1. 编译Kernel
先按照https://www.kernel.org/doc/html/latest/dev-tools/gdb-kernel-debugging.html说明的config设定编译内核并且安装到guest上。
menuconfig中按“/”是可以搜索的,例如要找“CONFIG_GDB_SCRIPTS”,按“/”输入“GDB_SCRIPTS”。
qemu启用了virtio的话,记得选上VIRTIO_BLK和VIRTIO_NET。
2. QEMU
2.1 关闭KVM
关闭KVM,关闭KVM,关闭KVM,重要的事情说三次!不然step by step的时候,会无限跳到arch/x86/kernel/apic/apic.c的sysvec_apic_timer_interrupt。要关闭KVM,运行qemu时去掉–enalbe-kvm参数,用libvirt的话,domain的type值置qemu:
1 2 3 |
<domain type='qemu' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'> ... </domain> |
2.2 启用gdbserver
运行QEMU时加上参数-s,或者通过“-gdb tcp::端口号”参数手动指定端口,libvirt xml的设定如下:
1 2 3 4 5 6 7 |
<domain type='qemu' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'> ... <qemu:commandline> <qemu:arg value='-s'/> </qemu:commandline> ... </domain> |
或者:
1 2 3 4 5 6 7 8 |
<domain type='qemu' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'> ... <qemu:commandline> <qemu:arg value='-gdb'/> <qemu:arg value='tcp::1235'/> </qemu:commandline> ... </domain> |
3. CLion
点击右上角的“Select Run/Debug Configuration”,添加个GDB Remote Debug:
‘targer remote’ args填入qemu监听的gdbserver IP和端口,Symbol file选编译出的vmlinux(在源码根目录下)。
5. 调试
断点的设定跟平常无异。
Debug标签页,pause后可以调用gdb console,如果kernel在运行,点左侧的“| |”即可:
栈、变量以及源码通过IDE浏览会直观许多:
6. <optimized out>
提醒下:通过-O0参数是无法成功编译Kernel的。
gdb console通过disassemble可以反汇编当前函数:
优化后的汇编其实不太好跟实际写的C代码联系起来,如果实在不行,就printk吧……