gdb 与 gdbserver 是 GNU 提供的远程调试工具,gdb 运行在主机上,gdbserver 运行在目标设备上,通过网络连接实现远程调试。本文介绍如何为开源鸿蒙哪吒开发板配置 gdbserver 进行程序调试,并在 vscode 中进行可视化调试。
NOTE被调试的程序需要是
debug模式编译的可执行文件,以包含调试信息,在编译时需要加入-g参数。
编译 gdbserver
首先依照 为开源鸿蒙哪吒开发板编写程序 中的步骤,下载并解压 剑池开发工具集 中的 GCC工具链-900系列。本文以 Linux 系统为例,使用 Xuantie-900-gcc-elf-newlib-x86_64-V3.2.0-20250627.tar.gz。
打开终端,首先下载并解压 gdb 源码:
wget https://ftp.gnu.org/gnu/gdb/gdb-16.3.tar.xz
tar -xvf gdb-16.3.tar.xz
NOTE也可以从 GNU FTP 站点 直接下载
gdb源码。下载速度较慢时,可以使用国内镜像站点,例如 清华大学开源软件镜像站。
因为 gdb 在之前下载的编译工具链中已经包含,我们只需要编译 gdbserver 部分。进入解压后的 gdb-16.3 目录,并新建 build 文件夹:
cd gdb-16.3
mkdir build
cd build
使用以下命令进行编译,注意替换 TOOL 路径为实际的编译器路径:
export TRIPLE=riscv64-unknown-linux-musl
export TOOL=/home/wely/Xuantie-900-gcc-linux-6.6.0-musl64-x86_64-V3.2.0/bin/
export CC="$TOOL$TRIPLE-gcc"
export CXX="$TOOL$TRIPLE-g++"
export AR="$TOOL$TRIPLE-ar"
export RANLIB="$TOOL$TRIPLE-ranlib"
export CFLAGS="-O2 -DELF_NFPREG=33"
export CXXFLAGS="-O2 -DELF_NFPREG=33"
export LDFLAGS="-static -Wl,--gc-sections -static-libgcc -static-libstdc++"
../configure --host="$TRIPLE" --disable-gdb --disable-werror --without-python --without-guile --disable-inprocess-agent
make -j"$(nproc)" all-gdbserver
编译完成后,gdbserver 可执行文件位于 gdb-16.3/build/gdbserver/gdbserver。
将 gdbserver 可执行文件传输到开源鸿蒙哪吒开发板上,作为服务端运行。建议复制到 /bin/ 目录下,以便全局使用。
使用 gdb 连接 gdbserver 进行调试
首先在开源鸿蒙哪吒开发板上启动 gdbserver,监听指定端口(例如 23456):
gdbserver --multi :23456
在主机上,使用编译工具链中的 riscv64-unknown-linux-musl-gdb,连接到哪吒开发板上的 gdbserver,注意将 /host/test-cpp-debug 替换为主机实际的可执行文件路径,将 x.x.x.x 替换为哪吒开发板的实际 IP 地址,并设置远程执行文件路径为哪吒开发板上的实际路径 /remote/test-cpp-debug:
./riscv64-unknown-linux-musl-gdb /host/test-cpp-debug
(gdb) target extended-remote x.x.x.x:23456
(gdb) set remote exec-file /remote/test-cpp-debug
现在可以使用 gdb 命令进行调试,例如设置断点、单步执行等:
(gdb) break main
(gdb) continue
(gdb) step
(gdb) print variable_name
在 vscode 中配置可视化调试
首先在开源鸿蒙哪吒开发板上启动 gdbserver,监听指定端口(例如 23456):
gdbserver --multi :23456
在主机上,在 vscode 中安装 C/C++ 扩展,然后创建或修改项目中的 .vscode/launch.json 文件,添加以下配置,注意替换 program 为实际的主机可执行文件路径,替换 miDebuggerPath 为实际的 riscv64-unknown-linux-musl-gdb 路径,替换 -target-select extended-remote x.x.x.x:23456 中的 IP 地址和端口号为实际的哪吒开发板地址和端口号,替换 set remote exec-file /remote/test-cpp-debug 为实际的哪吒开发板可执行文件路径:
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 远程",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/test-cpp-debug",
"args": [],
"stopAtEntry": true,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "riscv64-unknown-linux-musl-gdb",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "将反汇编风格设置为 Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
},
{ "text": "-target-select extended-remote x.x.x.x:23456" },
{ "text": "set remote exec-file /remote/test-cpp-debug" },
{ "text": "skip file /musl/" },
{ "text": "skip function exit" },
{ "text": "skip function _Exit" }
]
}
]
}
保存后,在 vscode 中启动调试,即可通过图形界面进行断点设置、单步执行和变量查看等操作。
进阶:在 vscode 中一键编译、上传与调试
可以在开发板上运行 ssh 服务,使 vscode 能够通过 scp 自动上传编译后的可执行文件,实现一键调试。
编译 dropbear
dropbear 是一个轻量级的 ssh 服务器,适合资源受限的嵌入式设备。
还是依照 为开源鸿蒙哪吒开发板编写程序 中的步骤,下载并解压 剑池开发工具集 中的 GCC工具链-900系列。本文以 Linux 系统为例,使用 Xuantie-900-gcc-elf-newlib-x86_64-V3.2.0-20250627.tar.gz。
获取 dropbear 源码:
git clone https://github.com/mkj/dropbear.git
cd dropbear
创建 build 目录并进入:
mkdir build
cd build
使用以下命令进行编译,注意替换 TOOL 路径为实际的编译器路径:
export TRIPLE=riscv64-unknown-linux-musl
export TOOL=/home/wely/Xuantie-900-gcc-linux-6.6.0-musl64-x86_64-V3.2.0/bin/
export CC="$TOOL$TRIPLE-gcc"
export CXX="$TOOL$TRIPLE-g++"
export AR="$TOOL$TRIPLE-ar"
export RANLIB="$TOOL$TRIPLE-ranlib"
export CFLAGS="-O2 -DELF_NFPREG=33"
export CXXFLAGS="-O2 -DELF_NFPREG=33"
export LDFLAGS="-static -Wl,--gc-sections -static-libgcc -static-libstdc++"
../configure --host=riscv64-linux-musl --disable-pam --disable-zlib --disable-shadow --disable-lastlog --disable-wtmp --disable-utmp
make MULTI=1 PROGRAMS="dropbear dbclient dropbearkey scp" LDFLAGS="-static" -j$(nproc)
编译完成后,dropbearmulti 可执行文件位于 dropbear/build/dropbearmulti,它是一个多合一可执行文件,包含 dropbear、dbclient、dropbearkey 和 scp 四个程序。
将 dropbearmulti 可执行文件传输到开源鸿蒙哪吒开发板上,作为 ssh 服务器运行。建议复制到 /bin/ 目录下,以便全局使用。
配置 dropbear 服务器
为方便使用,创建符号链接:
ln -s /bin/dropbearmulti /bin/dropbear
ln -s /bin/dropbearmulti /bin/dbclient
ln -s /bin/dropbearmulti /bin/dropbearkey
ln -s /bin/dropbearmulti /bin/scp
生成主机密钥:
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
dropbearkey -t ecdsa -f /etc/dropbear/dropbear_ecdsa_host_key
修改 root 用户配置使其可登录:
cp /etc/passwd /etc/passwd.bak
sed -i '/^root:/c root:x:0:0:root:/root:/bin/sh' /etc/passwd
配置 root 用户密码,此时在本地生成密码的哈希值(注意不是在开发板上):
openssl passwd -6
按提示输入两次你想要的密码,得到一串形如 $6$6$xxxxx$yyyy 的哈希,复制备用。在开发板上将此哈希值设置为变量:HASH='$6$......'(以下回到开发板上运行):
HASH='$6$......'
计算 最后修改日期(单位为天,自 1970-01-01 起):
DAYS=$(($(date +%s)/86400))
重建 /etc/shadow 文件:
printf 'root:%s:%s:0:99999:7:::\n' "$HASH" "$DAYS" > /etc/shadow
chmod 600 /etc/shadow
chown 0:0 /etc/shadow
同时写入 /etc/passwd 文件:
sed -i "s#^root:[^:]*:#root:${HASH}:#" /etc/passwd
创建 root 用户的家目录:
mkdir -p /root && chmod 700 /root
创建 .ssh 目录并设置权限:
mkdir -p /root/.ssh && chmod 700 /root/.ssh
此时可启动 dropbear 服务器,测试密码登录:
dropbear -E -F -R -p 22
可在主机上使用 ssh 连接到哪吒开发板,输入密码测试登录。
配置密钥登录
在主机上生成 ssh 密钥对(注意不是在开发板上):
sh-keygen -t rsa
运行后会提示输入文件名和密码,可直接回车使用默认文件名且不设置密码。生成的公钥文件为 ~/.ssh/id_rsa.pub,私钥文件为 ~/.ssh/id_rsa。
使用 ssh-copy-id 将公钥复制到哪吒开发板的 root 用户下(注意替换 x.x.x.x 为实际 IP 地址):
ssh-copy-id -i ~/.ssh/id_rsa.pub root@x.x.x.x
注:也可以手动将公钥内容追加到哪吒开发板的 /root/.ssh/authorized_keys 文件中。
# 在客户端查看公钥
cat ~/.ssh/id_rsa.pub
# 在服务器上添加到 authorized_keys
mkdir -p root/.ssh
chmod 700 root/.ssh
echo "粘贴公钥内容" >> root/.ssh/authorized_keys
chmod 600 root/.ssh/authorized_keys
上传完成后,即可使用密钥登录:
ssh -i ~/.ssh/id_rsa root@x.x.x.x
在 vscode 中配置一键上传与调试
配置 .vscode/launch.json 文件,注意修改 miDebuggerPath、x.x.x.x 以及 set remote exec-file 中的 IP 地址和可执行文件路径:
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) 远程",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}/${fileBasenameNoExtension}-debug",
"args": [],
"stopAtEntry": true,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "riscv64-unknown-linux-musl-gdb",
"preLaunchTask": "build+upload",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "将反汇编风格设置为 Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
},
{ "text": "-target-select extended-remote x.x.x.x:23456" },
{ "text": "set remote exec-file ${fileBasenameNoExtension}-debug" },
{ "text": "skip file /musl/" },
{ "text": "skip function exit" },
{ "text": "skip function _Exit" }
]
}
]
}
配置 .vscode/tasks.json 文件,添加编译与上传任务,注意修改 riscv64-unknown-linux-musl-g++ 编译器路径与 scp 使用的 id_rsa 私钥、x.x.x.x IP 和 / 上传路径:
{
"version": "2.0.0",
"tasks": [
{
"label": "build-static-riscv",
"type": "shell",
"command": "riscv64-unknown-linux-musl-g++",
"args": [
"${fileBasename}",
"-static",
"-g",
"-o",
"${fileBasenameNoExtension}-debug"
],
"options": {
"cwd": "${fileDirname}"
},
"group": "build",
"problemMatcher": ["$gcc"]
},
{
"label": "upload-to-target",
"type": "shell",
"command": "scp",
"args": [
"-i",
"id_rsa",
"-O",
"${fileDirname}/${fileBasenameNoExtension}-debug",
"root@x.x.x.x:/"
]
},
{
"label": "build+upload",
"dependsOrder": "sequence",
"dependsOn": [
"build-static-riscv",
"upload-to-target"
]
}
// 可选:调试结束后清理远端文件
// {
// "label": "cleanup-remote",
// "type": "shell",
// "command": "ssh",
// "args": ["root@192.168.31.200", "rm -f /test/${fileBasenameNoExtension}-debug"]
// }
]
}
在开发板上启动 dropbear 和 gdbserver:
dropbear -p 22 -R
gdbserver --multi :23456
现在在 vscode 中启动调试,选择 (gdb) 远程,即可实现一键编译、上传与调试功能,大大提升开发效率。
