Cài đặt kernel (nếu cần):
Ở bài viết này mình sẽ chuẩn bị 2 máy chạy linux, và mình làm trên hai máy ảo luôn.
Set up:
- 2 máy ảo linux
Ở đây mình muốn debug kernel cũ cho nên trước khi vào phần debug mình sẽ hướng dẫn cài đặt kernel cũ
mình sẽ tải kernel trên mạng về và cài đặt:
Link : http://old-releases.ubuntu.com/ubuntu/pool/main/l/linux/
Hoặc có thể tải từ https://packages.ubuntu.com/
Hoặc từ: https://kernel.ubuntu.com/~kernel-ppa/mainline/
bạn tùy chọn phiên bản mình cần tải với format version là x.x.xx-xx thì mình sẽ tải 3 file
linux-headers-x.x.xx-xx-generic_x.x.xx-xx.yy_amd64.deb
linux-headers-x.x.xx-xx-generic_x.x.xx-xx.yy_all.deb
linux-image-x.x.xx-xx-generic_x.x.xx-xx.yy_amd64.deb
Sau khi tải về, các bạn vào Linux, trên command shell gõ:
wget <đường dẫn>
ví dụ : wget http://old-releases.ubuntu.com/ubuntu/pool/main/l/linux/linux-headers-3.16.0-36-generic_3.16.0-36.48_amd64.deb
Nên để 3 file .deb trong 1 thư mục riêng cho dễ quản lý. Sau khi tải xong các bạn gõ lệnh để cài đặt:
sudo dpkg -i *.deb
Tiếp đến ta cần dừng màn hình boot để chọn kernel cần boot, các bạn gõ
sudo nano /etc/default/grub
comment dòng GRUB_HIDDEN_TIMEOUT (nếu có) và set GRUB_TIMEOUT thành -1
sau đó update lại grub
sudo update-grub
sau khi boot lên, các bạn chọn Advanced options for Ubuntu
rồi chọn kernel bạn muốn boot.
DEBUG:
Để tiện cho việc debug bạn có thể download symbol và source về sau đó tiến hành debug
SYMBOLS:
- GPG key import
- #16.04 and higher
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C8CAB6595FDFF622
#older distributions
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys ECDCAD72428D7C01
- #16.04 and higher
- NOTE: import key vào để nó verify khi bạn install symbol. Nếu cách import key trên không được thì thử:
wget -O - http://ddebs.ubuntu.com/dbgsym-release-key.asc | sudo apt-key add -
- Add repository config ( copy cẩn thận dấu “–” với dấu “ ‘ ” )
- codename=$(lsb_release -c | awk ‘{print $2}’)
sudo tee /etc/apt/sources.list.d/ddebs.list << EOF
deb http://ddebs.ubuntu.com/ ${codename} main restricted universe multiverse
deb http://ddebs.ubuntu.com/ ${codename}-security main restricted universe multiverse
deb http://ddebs.ubuntu.com/ ${codename}-updates main restricted universe multiverse
deb http://ddebs.ubuntu.com/ ${codename}-proposed main restricted universe multiverse
EOF - sudo apt-get update
sudo apt-get install linux-image-$(uname -r)-dbgsym
- codename=$(lsb_release -c | awk ‘{print $2}’)
- file symbol của bạn sẽ nằm trong /usr/lib/debug/boot/
- Nếu như bạn không tải được thì các bạn có thể extract vmlinuz ra file vmlinux (vmlinuz là file nén, còn vmlinux là file không nén)
- Giải nén bằng lệnh: ( giả sử version của mình là 4.15.0-51)
- Tham khảo thêm tại: https://wiki.ubuntu.com/Debug%20Symbol%20Packages
sudo /usr/src/linux-headers-4.15.0-51-generic/scripts/extract-vmlinux /boot/vmlinuz-4.15.0-51-generic > vmlinux
source :
check version:
uname -r
Ví dụ của mình là 4.10.0
sudo apt-get install linux-source-4.10.0
Cài xong vào /usr/src/linux-source-4.10.0 để giải nén
NOTE:
- Lưu ý là lsb_release không có ở bản thấp hơn 18.04 nên thay vào đó các bạn có thể dùng lệnh
cat /etc/os-releasevà lấy tênubuntu_codenamera cũng được - các lệnh ở trên chỉ áp dụng cho kernel hiện tại đang boot
Debug:
Sửa file .vmx, thêm 2 dòng như sau:
- debugStub.listen.guest64 = “TRUE”
- debugStub.listen.guest64.remote = “TRUE”
Sau đó lưu lại và thực hiện tiếp cách dưới đây
Cách 1:
Copy file vmlinux và thư mục source qua máy host
- Chỉnh setting của máy target như sau:

- Name pipe các bạn đặt theo cấu trúc : \\.\pipe\<tên pipe> (ở đây mình dùng name là debug)
- target thì mình để là This end is the server
- còn lại để như trong hình
- Máy host làm tương tự khác ở chỗ là mình sẽ để là This end is the client
- Sau đó start máy target lên
- Qua máy host, start lên, rồi mở gdb ( root nha )
- Chúng ta làm như sau
$ chmod +x <tên file vmlinux>
$ gdb <tên file vmlinux>
$ target remote <ip>:8864 (file 64 bit hoặc 8832 với file 32bit) – (IP là IP VMnet8 trên máy chính xem bằng lệnh ipconfig)
Cách 2: Nếu cách trên không được thì thử remote bằng cách dưới nha
Bên target(root): $ cat /dev/ttyS0
Bên host(root): $ echo ‘abcd’ > /dev/ttyS0
Nếu bên target mà nhận được tức là communicate được rồi đó, nếu không được thì thử ttyS1 xem sao, sau khi được rồi thì xuống bước phía dưới
Bên target: $sudo nano /etc/default/grubThêm vào dòng GRUB_CMDLINE_LINUX=”kgdbwait kgdboc=ttyS0,115200″
Lưu lại và gõ lệnh: $sudo update-grub
NOTE: ttyS0 hay ttyS1 thì tùy bạn test nhé
Sau đó các bạn restart lại máy target, khi máy reboot thì sẽ dừng lại cho các bạn attach vào
Lúc đó sang host(root) dùng gdb attach vào:
$ gdb <vmlinux>
$ target remote /dev/ttyS0
$continue
Sau khi attach vô xong thì continue để máy target tiếp tục boot
Để break kernel thì ta có thể dùng lệnh
$ echo g > /proc/sysrq-trigger
hoặc nhấn Alt + sysrq + g
Lúc này kernel dừng lại để mình debug bên host
Để debug với source ta làm như sau:
(gdb) dir <path>
Tiếp đến là list xem mình đang dùng path mặc định là gì rồi thay thế nó
(gdb) info source Current source file is /build/linux-hwe-lyR8gz/linux-hwe-4.10.0/init/version.c
(gdb) set substitute-path /build/linux-hwe-lyR8gz/linux-hwe-4.10.0/ /home/todhudson/kernel/linux-source-4.10.0/
Rồi giờ thì debug thôi.
Attach
Sau khi remote tới thì các bạn đặt breakpoint ở hàm mình cần debug, sau đó gõ
(gdb) continue
sang target ta run file, khi file được run nó sẽ đến chỗ mình breakpoint và dừng lại, mình sẽ sang host để debug như bình thường.
REF:
debug on vmware player
deubg on virtual box