linux内核调试方法
我的机器配置如下:

所以就是在linux环境下用vscode + gdb + qemu (+busybox) 来调一下内核。
1.下载软件
哪里缺了下哪里,需要安装的有各种依赖,gdb,qemu,vscode等等。
2.下载内核源码并编译
在github上拉取linux内核源代码,然后对内核编译选项进行一些配置,至少要开启的有:
1 2 3 4 5 6
| CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_INFO=y CONFIG_GDB_SCRIPTS=y CONFIG_FRAME_POINTER=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y
|
并确保没有启用
1 2
| CONFIG_DEBUG_INFO_REDUCED CONFIG_DEBUG_INFO_NONE
|
然后编译内核
编译生成vmlinux和arch/x86/boot/bzImage,其中vmlinux包含 ELF 符号和调试信息,为gdb使用。bzImage是最终生成的内核映像文件,共qemu进行启动。
然后生成gdb辅助脚本。
3.使用busybox编译根文件系统
首先是在github上clone一下busybox的源代码,然后编译。
1 2 3
| make menuconfig make -j"$(nproc)" make install
|
之后制作根文件系统,在busybox目录下执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| dd if=/dev/zero of=disk bs=1M count=256 mkfs.ext2 disk mount -o loop disk /mnt/ mkdir -p /mnt/{dev,etc,proc,sys} sudo cp -r ./_install/* /mnt/ mkdir -p /mnt/etc/init.d/ cat > /mnt/etc/init.d/rcS << EOF #!bin/sh mount -t proc none /proc mount -t sysfs none /sys mount -t tmpfs none /dev /sbin/mdev -s EOF chmod +x /mnt/etc/init.d/rcS umount /mnt/
|
4.启动内核
qemu的启动脚本如下,在busybox路径下执行。
1 2 3 4 5 6 7 8 9 10
| sudo qemu-system-x86_64 \ -machine q35,accel=kvm \ -smp 4,sockets=1,cores=4,threads=1 \ -m 4G \ -kernel ~/czh/linux/arch/x86_64/boot/bzImage \ -append "root=/dev/vda rw init=/sbin/init console=ttyS0,115200n8 nokaslr" \ -drive file=disk,if=none,id=virtio-disk0,format=raw \ -device virtio-blk-pci,scsi=off,drive=virtio-disk0,id=virtio-blk0 \ -nographic \ -s -S
|
-s:在1234 端口开启 GDB 调试服务器。-S:启动时暂停 CPU 执行,等待 GDB 连接。nokaslr:禁用内核地址空间布局随机化,便于 GDB 调试。
5.1 在terminal中调试
启动qemu之后,打开另一个终端,进入Linux内核源码目录(vmlinux 所在的目录),输入:
然后
1
| target remote localhost:1234
|
之后就可以进行调试了。
5.2 vscode调试
也要先启动qemu!
在linux目录下输入code .进入vscode,然后在launch.json中配置以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| { "version": "0.2.0", "configurations": [ { "name": "Debug Linux Kernel", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/vmlinux", "cwd": "${workspaceFolder}", "MIMode": "gdb", "miDebuggerPath": "/usr/bin/gdb", "miDebuggerServerAddress": "localhost:1234", "stopAtEntry": false, "stopAtConnect": false, "externalConsole": false, "setupCommands": [ { "text": "set pagination off", "ignoreFailures": true }, { "text": "set breakpoint pending on", "ignoreFailures": true }, { "text": "hbreak start_kernel", "ignoreFailures": false } ] } ] }
|
然后按f5就可以进行调试了。
ebpf子模块调试方法