基于 VSCode 的 Linux 内核图形化调试

1,101 阅读2分钟

背景

上一篇文章介绍了如何调试树莓派 Linux 内核 基于 J-Link + openocd + gdb 调试树莓派 4B Linux 内核 ,其中笔者基于 gdb + openocd + jlink 实现了内核调试。对于 gdb 老手来说,这样就已经足够了。然而,并不是人人都是 gdb 老手,笔者这个从上到下学习 Linux 的人也不是,图形化调试可能才是比较适合新手的方式。

经过一番研究后,笔者实现了通过 VSCode 来调试 Linux 内核,并将步骤分享在本文中。

步骤

准备源码 & 符号

将内核源码和符号拷贝到主机上,笔者在这里使用的是 Win 11 PC。源码和符号的获取可见上一篇文章。

配置 VSCode

安装 VSCode C 相关拓展

image.png

编写调试配置文件

将源码文件夹拖入到 VSCode 中后,在源码根目录的 .vscode 目录创建文件 launch.json,内容如下:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Linux Kernel Debug",
            "type": "cppdbg",
            "request": "launch",
            "program": "C:\\Users\\xxx\\vmlinux",
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerServerAddress": "localhost:3333",
            "hardwareBreakpoints": { "require": true, "limit": 6 },
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                },
                {
                    "description": "将反汇编风格设置为 Intel",
                    "text": "-gdb-set disassembly-flavor intel",
                    "ignoreFailures": true
                }
            ],
            "miDebuggerPath": "C:\\SysGCC\\raspberry64\\bin\\aarch64-linux-gnu-gdb.exe"
        }
    ]
}

其中 miDebuggerServerAddress是上一篇文章中 openocd 开启的 gdb server 的调试端口,miDebuggerPath 是上一篇文章中安装的 gdb 的路径,hardwareBreakpoints 是强制使能硬件断点的配置。

开始调试

开启上一篇文章提到的 openocd 后,点击 VSCode 调试选项卡的如下按钮后就可以开始调试了。

image.png

效果展示

调试启动后,点击下图中右上角的暂停按钮即可让系统停下来:

image.png 停下来之后可以查看各 CPU 上的 CALL STACK:

image.png 可以看到目前停在 cpu_do_idle,符合预期。

下面展示了笔者研究【cat /proc/[pid]/maps 中匿名内存映射(如下图下方展示的 [heap] [vvar] 等 vma)的名字是怎么得到的】过程中的调试截图。

screenshot-20230405-181533.png

$ sudo cat /proc/497/maps
55803e0000-55804b4000 r-xp 00000000 b3:02 17803                          /usr/sbin/sshd
55804c3000-55804c7000 r--p 000d3000 b3:02 17803                          /usr/sbin/sshd
55804c7000-55804c8000 rw-p 000d7000 b3:02 17803                          /usr/sbin/sshd
55804c8000-55804cc000 rw-p 00000000 00:00 0
55a04a9000-55a04eb000 rw-p 00000000 00:00 0                              [heap]
......
7f9cc0c000-7f9cc0e000 r--p 00000000 00:00 0                              [vvar]
7f9cc0e000-7f9cc0f000 r-xp 00000000 00:00 0                              [vdso]
......
7feee1e000-7feee3f000 rw-p 00000000 00:00 0                              [stack]

从结果来看效果还是可以的,局部变量、调用栈、点击调用栈跳转源码等功能都正常工作。