注意:这篇文章上次更新于588天前,文章内容可能已经过时。
This article was last updated588 days ago, the content may be outdated.
使用 GDB 调试 Linux Kernel 需要以下几个步骤:
-
编译一个可以调试的内核
-
QEMU 启动内核
-
GDB 连接 QEMU
编译一个可以调试的内核
在前文 Linux Kernel 从编译到运行 中我们编译了一个内核,这个内核是没有调试信息的,我们需要重新编译一个带调试信息的内核。
首先使用 make mrproper 清理内核源码,然后使用 make menuconfig 配置内核,
Kernel hacking > Compile-time checks and compiler options > Debug information > 选择 Rely on the toolchain's implicit default DWARF version

和 debug 有关的内核配置项还包括:
- CONFIG_GDB_SCRIPTS
- CONFIG_DEBUG_INFO
- CONFIG_KGDB
- CONFIG_KGDB_SERIAL_CONSOLE
- CONFIG_KGDB_TESTS
它们大部分是默认开启的,我们只需要确认一下。
然后使用 make -j8 编译内核,这个过程比较慢,需要等待一段时间。
QEMU 启动内核
在前文 Linux Kernel 从编译到运行 中我们使用 QEMU 启动内核,这里我们需要修改一下启动命令,增加 -s -S 参数。
最好使用内核启动参数 nokaslr 来禁用内核地址空间随机化。
修改后的 Makefile 如下:
1 |
|
其中,-S 选项表示在启动时暂停 CPU,-s 选项表示在 1234 端口监听 GDB 连接。
-s 也可以使用 -gdb tcp::1234 代替。
把编译好的 bzImage 和 vmlinux 拷贝放到 QEMU 启动目录下
1 | cp arch/x86/boot/bzImage ../workspace/ |
我的 QEMU 启动目录是
../workspace/,你可以根据实际情况修改。
然后执行 make run 启动 QEMU。
GDB 连接 QEMU
使用 -S 选项启动 QEMU 后,QEMU 会暂停 CPU,等待 GDB 连接。

然后在另一个终端中使用 GDB 连接 QEMU
1 | gdb vmlinux |

然后在 GDB 中输入 target remote :1234 连接 QEMU

这时候就可以使用 GDB 调试内核了。
这里我们首先在 start_kernel 函数上打一个断点。
1 | (gdb) b start_kernel |

然后输入 c 继续执行,QEMU 会继续执行内核启动过程,直到遇到断点。
1 | (gdb) c |

这样就可以在内核启动的过程中使用 GDB 进行调试了。
Tips
当我们在真实的调试过程中,会反复执行某些命令,例如 target remote :1234,设置断点,查看变量等等。
对于这些命令,我们可以将它们写入 .gdbinit 文件中,这样每次启动 GDB 时会自动执行这些命令。
如果想使用当前目录下的 .gdbinit 文件,需要在 home 目录下的 gdbinit 文件中添加 set auto-load safe-path /,否则 GDB 会忽略当前目录下的 .gdbinit 文件。
例如:
1 | mkdir -p ~/.config/gdb |
此时,GDB 会自动连接 QEMU,设置断点,并继续执行至 start_kernel 函数。

The End…


