- Published on
VSCode GDB 远程调试
- Authors
- Name
- Zhao Tao
- github
- @taoz27
需求
开发环境和程序实际运行环境不一样,又需要调试时,可以使用 GDB 远程调试。
例如我在 x86 上开发,在嵌入式 arm 板上运行程序,又或者单纯的想在 Windows 上开发,放到 Ubuntu 上运行,这些情况调试时都可以使用 gdb 进行远程调试。
基本原理
在远端(即需要运行程序的机器上)用gdbserver启动待调试程序,并监听指定端口。
在本地(即开发程序的机器上)用相应版本的 gdb连接远端 gdbserver 进行调试。
gdbserver + gdb 调试
所需工具:
| 工具 | 功能 |
|---|---|
| gnu-gcc | 编译可在目标远程机器上运行的程序。 |
| gnu-g++ | 编译可在目标远程机器上运行的程序。 |
| gnu-strip | 通常编译时,使用-g添加调试符号用于调试,但该运行程序体积较大,gnu-strip可以删除调试符号,生成体积较小的发布版本。 |
| gdbserver | 运行在目标远程机器上,用于启动调试服务。 |
| gnu-gdb | 用于连接远程机器上的 gdbserver。 |
这些工具应保持版本一致。
具体步骤:
目标远程机器上执行
# cd到要运行的程序目录下 $ cd /mnt/adas-rt/ # 启动调试服务,端口号2333按实际工作环境指定 $ gdbserver localhost:2333 ./hobot-adas-workflow config/global.json 1 # 服务启动成功 Listening on port 2333编译时需要编译两个可执行文件:
- hobot-adas-workflow:删除调试符号版本,文件体积较小,上传到远端;
- hobot-adas-workflow.gdb:带调试符号版本,文件体积很大,保留在本地。
本地机器执行
# cd到与编译所使用的gdb工具链目录下 $ cd toolchain/bin # 启动对应的gdb工具,而非默认gdb,并指定带有调试符号的可执行程序 $ ./aarch64-linux-gnu-gdb hobot-adas-workflow.gdb # 先指定本地机器代码目录,不指定将在运行时自动寻找,速度较慢 (gdb) set sysroot ~/SrcCode/ # 连接到目标远程机器上的调试服务,remote_ip:port按实际工作环境指定 (gdb) target remote remote_ip:port # 指定断点 (gdb) break main # 开始运行(要使用continue而不是run,可能是gdb版本原因) (gdb) c # 运行一段时间后,成功命中断点 Breakpoint 1, main (argc=3, argv =0x7ffffffc18) at ~/SrcCode/main.cpp:18 18 int main(int argc, char **argv) {
参考链接:gdb-remote-debugging-cant-seem-to-find-symbols
VSCode 配置
单纯使用 gdb 进行调试很不方便。接下来配置 VSCode,使用 VSCode 进行远程调试。
初步配置
使用 VSCode 打开工程文件夹,注意目录地址,指定不正确(如选择了父目录或子目录)将无法命中断点。
在.vscode目录下新建 launch.json,内容如下:
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb)Launch",
"type": "cppdbg",
"request": "launch",
// 指定带调试符号的可执行程序
"program": "build/hobot-adas-workflow.gdb",
"args": [],
"stopAtEntry": false,
// 当前工作环境
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
// 指定GDB调试工具
"miDebuggerPath": "~/SrcCode/toolchain/bin/aarch64-linux-gnu-gdb",
// 目标远程机器服务地址
"miDebuggerServerAddress": "remote_ip:port"
}
]
}
在代码中打好断点,按F5就可以愉快的调试啦~
全流程自动化
不太好的一点是,上述操作每次都需要在目标远程机器上启动服务,调试结束后服务会自动结束,下次调试需要重新启动服务。
接下来在 VSCode 中增加一个自动启动远程服务的命令。
在 launch.json 中新增两行:
// 开始调试前要执行的任务
"preLaunchTask": "before-debug-build",
// 调试结束后要执行的任务
"postDebugTask": "after-debug-kill"
添加好后如下:
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb)Launch",
"type": "cppdbg",
"request": "launch",
// 指定带调试符号的可执行程序
"program": "build/hobot-adas-workflow.gdb",
"args": [],
"stopAtEntry": false,
// 当前工作环境
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
// 指定GDB调试工具
"miDebuggerPath": "~/SrcCode/toolchain/bin/aarch64-linux-gnu-gdb",
// 目标远程机器服务地址
"miDebuggerServerAddress": "remote_ip:port",
// 开始调试前要执行的任务
"preLaunchTask": "before-debug-build",
// 调试结束后要执行的任务
"postDebugTask": "after-debug-kill"
}
]
}
在.vscode目录下新建一个 tasks.json:
{
"version": "2.0.0",
"tasks": [
{
// 任务名称
"label": "before-debug-build",
"type": "shell",
"command": "bash",
// 任务要执行的脚本
"args": ["${workspaceFolder}/start_server.sh"],
"options": {
"cwd": "${workspaceFolder}"
}
},
{
"label": "after-debug-kill",
"type": "shell",
"command": "bash",
"args": ["${workspaceFolder}/kill_server.sh"],
"options": {
"cwd": "${workspaceFolder}"
}
}
]
}
这样每次按F5后,都会自动执行 start_server.sh脚本,调试结束后,会自动执行kill_server.sh脚本。
新建一个 start_server.sh:
# ssh远程执行命令,启动gdbserver
ssh -fn -p port user@remote_ip "cd /mnt/adas-rt/; export LD_LIBRARY_PATH=/mnt/adas-rt/; gdbserver :2333 hobot-adas-workflow"
新建一个kill_server.sh:
# ssh远程执行命令,结束gdbserver
ssh -p 1034 root@10.136.68.101 "killall gdbserver"
这样就能够自动化的用 VSCode 进行远程调试了。