调试内核需要配置defconfig或.config
defconfig文件需要放置在内核的receipt目录,需要在配置文件中使能
CONFIG_GDB_SCRIPTS=y
CONFIG_DEBUG_INFO_DWARF5=y
在配置调试Linux内核参数时可以使用 bitbake virtual/kernel -c menuconfig 使用Linux的menuconfig对内核参数进行配置
bitbake virtual/kernel
编译完成之后内核编译目录:
${yocto根目录}/build/tmp/work/qemux86_64-oe-linux/linux-yocto/7.0/build/
在此目录内有带有调试信息的 vmlinux
内核源代码保存在目录
${yocto根目录}/build/tmp/work-shared/qemux86-64/kernel-source/
在编译完成之后进入目录
${yocto根目录}/build/tmp/work/qemux86_64-oe-linux/linux-yocto/7.0/build/
使用 make scripts_gdb 编译调试脚本,在使用gdb配合qemu虚拟机调试内核时需要 vmlinux-gdb.py python调试脚本
- 使用qemu虚拟机启动yocto编译的内核和rootfs
qemu-system-x86_64 -device virtio-net-pci,netdev=net0,mac=52:54:00:12:34:02 -netdev tap,id=net0,ifname=tap0,script=no,downscript=no -object rng-random,filename=/dev/urandom,id=rng0 -device virtio-rng-pci,rng=rng0 -drive file=${yocto根目录}/build/tmp/deploy/images/qemux86-64/core-image-minimal-qemux86-64.rootfs.ext4,if=virtio,format=raw -usb -device usb-tablet -usb -device usb-kbd -cpu Skylake-Client -machine q35,i8042=off -smp 4 -m 1024 -vga std -serial mon:stdio -display sdl,show-cursor=on -gdb tcp::2345 -kernel ${yocto根目录}/build/tmp/deploy/images/qemux86-64/bzImage -append 'root=/dev/vda rw console=tty0 console=ttyS0,115200 ip=192.168.7.2::192.168.7.1:255.255.255.0::eth0:off:8.8.8.8 net.ifnames=0 oprofile.timer=1 tsc=reliable no_timer_check rcupdate.rcu_expedited=1 swiotlb=0 nokaslr'
此命令行中,制定gdb远程调试接口的指令为:
-gdb tcp::2345
如需debug启动,可以使用 -S 指定在启动之后停止
此命令行中,指定内核启动参数的指令为:
-append 'root=/dev/vda rw console=tty0 console=ttyS0,115200 ip=192.168.7.2::192.168.7.1:255.255.255.0::eth0:off:8.8.8.8 net.ifnames=0 oprofile.timer=1 tsc=reliable no_timer_check rcupdate.rcu_expedited=1 swiotlb=0 nokaslr'
需要关闭kaslr,即在启动参数末尾使用 nokaslr 禁用内核加载地址随机化,否则在使用GDB调试时需要先从/proc/kallsymc查询到内核的偏移地址,然后再使用调试修改内核起始地址
进入目录
${yocto根目录}/build/tmp/work/qemux86_64-oe-linux/linux-yocto/7.0/build/
使用命令
gdb ./vmlinux
打开gdb调试器
在gdb界面,使用命令:
a. 配置可加载的路径
(gdb) add-auto-load-safe-path ${yocto根目录}/build/tmp/work-shared/qemux86-64/kernel-source
b. 使能vmlinux-gdb.py调试插件
(gdb) source vmlinux-gdb.py
c. 配置当前内核的目录,gdb会从/usr/src/kernel 查找内核代码
(gdb) set substitute-path /usr/src/kernel ${yocto根目录}/build/tmp/work-shared/qemux86-64/kernel-source
d. 连接虚拟机调试器
(gdb) target remote :2345
e. 加载内核符号表
(gdb) lx-symbols
- 在未关闭kaslr的情况下可以重新定向内核的符号位置
未关闭kaslr,内核会启用内核加载地址随机化,重新定位内核符号的偏移
使用/proc/kallsyms 查找内核符号的实际内存位置
cat /proc/kallsyms
ffffffffadc00000 T _stext
ffffffffadc00000 T _text
ffffffffadc00000 T __pi__text
......
将内核的.text段重新定位到新的偏移,而不是直接使用vmlinux中定义的偏移
(gdb) add-symbol-file vmlinux 0xffffffffadc00000