本篇以调试 rust_shyper 为例:

写在开头

阅读本篇前假定您目前已有正确配置如下:

  • Qemu
  • aarch64-none-elf 交叉工具链(特别是aarch64-none-elf-gdb)
  • VSCode

阅读本篇前假定您目前可以正确做到如下:

  • make debug 无报错
  • make gdb 无报错

即您可以到达这个界面:

原有调试环境.png

左为 make debug
右为 make gdb

配置 VsCode 调试

第一步

  • 运行 VsCode,安装扩展 GDB Debug

GDB Debug.png

第二步

  • 配置 .vscode/launch.json 或者点击调试下的齿轮打开 .vscode/launch.json

launch.png

  • 内容填写格式如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "kernel debug",
"type": "cppdbg",
"request": "launch",
"program": rust_shyper 目录,
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"miDebuggerPath":aarch64-none-elf-gdb 目录,
"miDebuggerServerAddress": "127.0.0.1:1234",
}
]
}
  1. program 是要 debug 的可执行文件目录
  2. miDebuggerPath 是 gdb 的目录
  3. miDebuggerServerAddress 是调试程序服务器的网络地址

一定要注意 miDebuggerPath 的路径是交叉编译 gdb(aarch64-none-elf-gdb) 的位置,而不是普通 gdb 的位置
否则就会报错:truncated register 37 in remote g packet 是架构不支持的报错
详见:qemu-gdb debug

  • 例如我的格式如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "kernel debug",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/target/aarch64/release/rust_shyper",
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"miDebuggerPath":"/usr/local/arm/gcc-arm-11.2-2022.02-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gdb",
"miDebuggerServerAddress": "127.0.0.1:1234",
}
]
}
如果 cppdbg 报错,安装 C/C++ Runner 插件 和 C/C++ Extension Pack

C++ Runner.png

C++ Extension.png

第三步

打开工作目录,在任意位置设置断点。

在 rust-shyper 目录下打开 shell,输入 make debug打开 qemu

尝试在 VSCode 运行调试,如果运行正确就会跳到断点

调试界面.png

如图,左边可以查看 变量,寄存器,堆栈,断点。

可以单步执行,逐过程等等,做到如同写简单代码一样的调试。

debug 时自动启动 qemu

如果觉得每次需要手动在 shell 输入 make debug 打开 qemu 觉得麻烦,可以做到运行调试时自动打开 qemu。

第一步

  • 配置 .vscode/tasks.json 或者在 VSCode 界面选择终端——运行任务——使用模板创建 tasks.json 文件——Ohters

配置任务-1

配置任务-2

  • 配置写入如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "qemu",
"type": "shell",
"command": "make debug",
"presentation": {
"echo": true,
"clear": true,
"group": "qemu"
},
"isBackground": true,
"problemMatcher": []
}
]
}

第二步

.vscode/launch.json下添加一项新属性:"preLaunchTask": "qemu"

即最终的 launch.json 内容为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "kernel debug",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/target/aarch64/release/rust_shyper",
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"miDebuggerPath":"/usr/local/arm/gcc-arm-11.2-2022.02-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gdb",
"miDebuggerServerAddress": "127.0.0.1:1234",
"preLaunchTask": "qemu"
}
]
}
之后点击 debug 就会自动运行该任务,自动启动 qemu。

可能问题

如果设置后运行调试提示如下内容,则点击仍然调试即可,此问题不致命、不影响调试

无法跟踪.png

最终效果

最终效果.png

  • 点击调试自动执行 make debug 和 make gdb
  • qemu 的输出在 VSCode 的终端即可查看
  • 调试在 VSCode 进行

附录

提供另一种可视化调试的方法,可以方便的查看汇编,安装也十分简单方便,效果如下:

board-1.png

一个 shell 显示所有寄存器。

board-2.png

一个 shell 显示堆栈、当前汇编、执行语句。

原汁原味的 gdb 调试命令,但可视化寄存器、汇编指令、执行语句

资料参考:神仙GDB调试工具 gdb-dashboard

第一步

在工作目录下(Rust-Shyper)下下载脚本

wget -P ~ https://git.io/.gdbinit

如果超时、挂梯子自己去下载一下,然后复制进工作目录即可。

第二步

~/.gdbinit.d/ 目录创建配置文件 ~/.gdbinit.d/init,写入内容如下:

1
2
3
set breakpoint pending on
set confirm off
dashboard -layout registers assembly source !variables stack

第三步

正常执行 make debug 和 make gdb 即可。

多窗口调试

参考前述:神仙GDB调试工具 gdb-dashboard