使用GDB和VSCode调试内核
使用GDB和VSCode调试内核
背景
上一篇,已经搭建好QEMU的内核调试环境:https://notes.z-dd.online/2024/03/06/%E5%9F%BA%E4%BA%8EQEMU%E7%9A%84%E5%86%85%E6%A0%B8%E8%B0%83%E8%AF%95%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/
这篇主要在前面的基础上尝试用gdb来调试内核,躺了不少坑。
安装GDB
这里安装支持多种硬件体系架构的GDB版本,也可直接使用系统自带的默认gdb。如架构不同,需使用交叉编译工具链中的gdb,后面有时间会更新不同架构下的调试。
sudo apt-get install -y gdb-multiarch # 支持多种硬件体系架构的GDB版本
准备调试内核
在以前的基础上需修改一些内核配置才能调试:
- 打开
CONFIG_GDB_SCRIPTS
:在内核主目录下生成gdb脚本文件vmlinux-gdb.py
,该脚本实现了一些便于内核调试的命令,它们都以lx-开头,这个暂时先没用,后面再研究看看 - 打开
CONFIG_DEBUG_INFO
:该选项用于在内核编译时开启-g标志,保证编译的内核带有调试信息,这个很重要! - 关闭
CONFIG_DEBUG_INFO_REDUCED
- 关闭
CONFIG_RANDOMIZE_BASE
:该选项用于关闭KASLR
,或者可以在内核启动参数中添加nokaslr
,这个会导致地址随机化,从而无法调试,这个很重要!
运行qemu
这里只调试内核,就没有带根文件系统,也可以带上,这个看自己。
$ qemu-system-x86_64 -s -S \
-kernel ./bzImage \
-hda /dev/zero \
-append "root=/dev/zero console=ttyS0" \
-nographic
说明:
-s
选项是-gdb
的简写,会在本地的1234端口启动一个 GDB 服务-S
代表暂停虚拟机,等待 GDB 执行continue
指令
GDB命令行调试测试
# 重开一个shell,进入上面内核的源码目录
$ cd /path/to/your/linux
$ gdb-multiarch ./vmlinux
#以下进行调试
(gdb) target remote:1234
Remote debugging using :1234
0x000000000000fff0 in exception_stacks ()
#打断点,这里打在C语言入口函数(start_kernel),能看到后面的文件名及行数,说明内核可以调试
(gdb) b start_kernel
Breakpoint 1 at 0xffffffff83220960: file init/main.c, line 875.
(gdb) c
Continuing.
Breakpoint 1, start_kernel () at init/main.c:875
875 {
(gdb) c
Continuing.
VSCode图形化调试
VSCode打开上面运行内核的源码文件夹
修改VSCode调试配置
运行和调试 -> 创建launch.json文件 -> 添加配置 ->C/C++: gdb 启动
, 会自动生成相关配置,做一些相关修改如下:{ // 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "kernel-debug", "type": "cppdbg", "request": "launch", //主要添加修改下面3项 "program": "${workspaceFolder}/vmlinux", "miDebuggerServerAddress": "127.0.0.1:1234", "miDebuggerPath": "gdb-multiarch", "args": [], "stopAtEntry": true, "cwd": "${fileDirname}", "environment": [], "externalConsole": false, "MIMode": "gdb", "setupCommands": [ { "description": "为 gdb 启用整齐打印", "text": "-enable-pretty-printing", "ignoreFailures": true }, { "description": "将反汇编风格设置为 Intel", "text": "-gdb-set disassembly-flavor intel", "ignoreFailures": true } ] } ] }
启动调试
先打好断点,比如在init/main.c
中的start_kernel
函数中, 再QEMU启动内核,VSCode按“F5”或点击启动调试即可开始调试内核,比如单步运行等。
现在是手动先运行QEMU再启动VSCode调试,有没有办法在直接启动VSCode的时候自动启动QEMU呢?
可以使用VSCode的task功能,这里就不详述了,对于调试功能影响不大。
参考
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 DD'Notes!
评论