当前位置: 首页 > backend >正文

Linux 下使用 VS Code 远程 GDB 调试 ARM 程序

Linux 下使用 VS Code 远程 GDB 调试 ARM 程序

在嵌入式 Linux 开发中,调试是开发过程中至关重要的一环。由于嵌入式设备资源有限,直接在设备上进行调试往往不方便。因此,远程调试成为了一种高效的调试方式。

本文将详细介绍如何在 Linux 环境下使用 VS Code 进行远程 GDB 调试 ARM 程序,包括:

  1. 使用 gdbserver 和交叉 GDB 进行远程调试
  2. 使用本地模拟的根文件系统(rootfs)解决环境差异问题
  3. 在 VS Code 中配置图形化调试界面
  4. 如何根据系统字节数选择模拟器
  5. 提供完整的调试流程、常见问题解答和实用建议
  6. 一个完整的自动化脚本(build + deploy + debug)
  7. 一个最小可运行的示例项目结构
  8. VS Code 配置模板

一、远程调试原理

远程调试的基本原理是:

目标设备(Target):运行 gdbserver,负责启动被调试程序,接收 GDB 客户端的调试命令。

主机(Host):运行 GDB 客户端,负责发送调试命令,显示调试信息。

[主机] <—> [网络] <—> [目标设备]

GDB客户端 gdbserver

二、准备工作

1. 安装 VS Code

2. 安装插件:

  • C/C++ Extension Pack
  • CMake Tools(可选)
  • GDB Debug

3. 安装交叉编译工具链

sudo apt install gcc-<arch>-linux-gnu

4.验证安装:

<arch>-linux-gnu-gcc --version

3. 准备目标设备的 rootfs

你可以从以下途径获取:

  • 从设备厂商提供的 SDK 中提取
  • 使用 debootstrap 或 multistrap 构建最小系统
  • 从设备的固件镜像中提取

假设你获得了 rootfs.tar.xz,解压:

tar -xJf rootfs.tar.xz
cd rootfs

4. 安装 QEMU 模拟器

sudo apt install qemu-user-static

1.根据目标系统的字节数选择模拟器:

  • 32位 ARM 系统:使用 qemu-arm-static
  • 64位 ARM 系统:使用 qemu-aarch64-static

2.将对应的模拟器拷贝到 rootfs 中:

# 对于 64 位系统
cp /usr/bin/qemu-aarch64-static ./usr/bin/# 对于 32 位系统
cp /usr/bin/qemu-arm-static ./usr/bin/

3.验证 QEMU:

qemu-aarch64-static --version
# 或
qemu-arm-static --version

三、配置远程调试环境

1. 在目标设备上启动 gdbserver

gdbserver :1234 ./your_app

2. 在本地主机上启动 GDB 并连接

<arch>-linux-gnu-gdb ./your_app
(gdb) target remote <设备IP>:1234

四、使用 VS Code 进行远程调试

1. 配置 launch.json

在项目根目录下创建 .vscode/launch.json:

{"version": "0.2.0","configurations": [{"name": "Remote Debug","type": "cppdbg","request": "launch","program": "${workspaceFolder}/build/your_app","args": [],"stopAtEntry": false,"cwd": "${workspaceFolder}","environment": [],"externalConsole": false,"MIMode": "gdb","miDebuggerPath": "/usr/bin/<arch>-linux-gnu-gdb","miDebuggerServerAddress": "192.168.1.100:1234","setupCommands": [{"description": "Enable pretty-printing for gdb","text": "-enable-pretty-printing","ignoreFailures": true}]}]
}

2. 配置 tasks.json(可选)

用于自动编译:

{"version": "2.0.0","tasks": [{"label": "build","type": "shell","command": "<arch>-linux-gnu-gcc","args": ["-g","-o","${workspaceFolder}/build/your_app","${workspaceFolder}/src/main.c"],"group": {"kind": "build","isDefault": true}}]
}

3. 启动调试

  • 按 F5 或点击"运行和调试"
  • 选择"Remote Debug"配置
  • VS Code 将连接远端 gdbserver 并开始调试

五、使用本地模拟的 rootfs 进行调试(chroot + QEMU)

适用于本地与远端环境差异较大的情况。

1. 进入模拟环境

sudo chroot ./rootfs /usr/bin/qemu-aarch64-static /bin/sh
# 或
sudo chroot ./rootfs /usr/bin/qemu-arm-static /bin/sh

2. 挂载工具链(可选)

mount --bind /opt/toolchain ./toolchain
export PATH=$PATH:/toolchain/bin

3. 编译并调试

<arch>-linux-gnu-gcc -g -o your_app main.c
gdbserver :1234 ./your_app

4.在主机上连接:

<arch>-linux-gnu-gdb ./your_app
(gdb) target remote localhost:1234

5. 退出模拟环境

exit

6. 卸载挂载:

sudo umount ./dev ./proc ./sys ./toolchain

六、常见问题与解决方案

1. GDB 提示 “remote target does not support run”

  • 原因:远程调试不支持 run 命令,程序已由 gdbserver 启动。
  • 解决:使用 continue 替代 run。

2. 断点无效或无法命中

  • 原因:
    • 本地文件与远端文件不一致
    • 本地文件未带 -g 编译
    • 文件被 strip
  • 解决:
    • 确保本地文件带 -g
    • 使用 md5sum 或 file 命令比对文件
    • 本地使用未 strip 文件,远端可用 strip 文件

3. 连接失败或中断

  • 原因:
    • 网络不通
    • 防火墙阻止端口
    • gdbserver 未启动
  • 解决:
    • 检查 IP 和端口
    • 使用 ping 和 telnet 测试连接
    • 确保 gdbserver 正常运行

七、实用建议

1.使用自动化脚本

建议写一个脚本自动完成:

  1. 编译
  2. 拷贝到远端
  3. 启动 gdbserver
  4. 启动 GDB 并连接

使用 rsync 替代 scp

2.更高效同步文件:

rsync -avz ./build/ root@<ip>:/home/root/build/

3.使用 tmux 保持远端会话

避免 SSH 断开导致 gdbserver 中断:

tmux new -s debug
gdbserver :1234 ./your_app

八、总结

调试方式适用场景优点缺点
远程调试(gdbserver)真实设备调试真实硬件环境上传慢、环境不一致
模拟调试(chroot + QEMU)本地模拟调试环境一致、调试快性能低、硬件功能受限
VS Code 图形化调试提高开发效率可视化、易用性强需配置插件和JSON

使用 VS Code + 交叉 GDB + gdbserver,可以在本地高效调试远端 ARM 程序,结合模拟 rootfs 可解决环境差异问题,提升开发体验。

九、附录

A. 自动化脚本(build + deploy + debug)

#!/bin/bash# 配置
TARGET_IP="192.168.1.100"
TARGET_USER="root"
TARGET_PATH="/home/root"
APP_NAME="your_app"
CROSS_COMPILE="<arch>-linux-gnu-"# 编译
echo "Building..."
${CROSS_COMPILE}gcc -g -o build/${APP_NAME} src/main.c# 部署
echo "Deploying..."
rsync -avz build/${APP_NAME} ${TARGET_USER}@${TARGET_IP}:${TARGET_PATH}/# 启动 gdbserver
echo "Starting gdbserver on target..."
ssh ${TARGET_USER}@${TARGET_IP} "cd ${TARGET_PATH} && gdbserver :1234 ./${APP_NAME}" &# 等待 gdbserver 启动
sleep 2# 启动 GDB
echo "Starting GDB..."
${CROSS_COMPILE}gdb build/${APP_NAME} -ex "target remote ${TARGET_IP}:1234"

B. 最小可运行示例项目结构

my_project/
├── src/
│   └── main.c
├── build/
├── .vscode/
│   ├── launch.json
│   └── tasks.json
├── rootfs/
│   ├── bin/
│   ├── lib/
│   └── ...
├── debug.sh
└── README.md

src/main.c 示例:

#include <stdio.h>int main() {int a = 10;int b = 20;int sum = a + b;printf("Sum: %d\n", sum);return 0;
}

C. VS Code 配置模板

.vscode/launch.json:

{"version": "0.2.0","configurations": [{"name": "Remote Debug","type": "cppdbg","request": "launch","program": "${workspaceFolder}/build/your_app","args": [],"stopAtEntry": false,"cwd": "${workspaceFolder}","environment": [],"externalConsole": false,"MIMode": "gdb","miDebuggerPath": "/usr/bin/<arch>-linux-gnu-gdb","miDebuggerServerAddress": "192.168.1.100:1234","setupCommands": [{"description": "Enable pretty-printing for gdb","text": "-enable-pretty-printing","ignoreFailures": true}]}]
}

.vscode/tasks.json:

{"version": "2.0.0","tasks": [{"label": "build","type": "shell","command": "<arch>-linux-gnu-gcc","args": ["-g","-o","${workspaceFolder}/build/your_app","${workspaceFolder}/src/main.c"],"group": {"kind": "build","isDefault": true}}]
}
http://www.xdnf.cn/news/15173.html

相关文章:

  • 探索飞算 JavaAI 进阶:解锁高效Java开发的新维度
  • Selenium 自动化实战技巧【selenium】
  • springboot生成pdf方案之dot/html/图片转pdf三种方式
  • PDF 转图助手 PDF2JPG 绿色版:免安装直接用,急处理文件的救急小天使
  • 技术突破与落地应用:端到端 2.0 时代辅助驾驶TOP10 论文深度拆解系列【第九篇(排名不分先后)】
  • GPT和MBR分区
  • 云蝠智能 VoiceAgent重构企业呼入场景服务范式
  • 重学前端004 --- html 表单
  • 从二维到三维:数字孪生如何重塑UI前端设计
  • 【Git】git的回退功能
  • Flutter优缺点
  • 港科大 NMPC 控制下的高效自主导航!SkyVLN:城市环境无人机视觉语言导航与非线性模型预测控制
  • 哪些因素会影响NMR杂质检测的准确性
  • 全面掌控 Claude Code:命令 + 参数 + 快捷键一文全整理(建议收藏)
  • Linux的基础I/O
  • 如何在 PyCharm 批量调整代码缩进?PyCharm 调整代码格式化和代码缩进的快捷键有哪些?
  • S7-1200 与 S7-300 CPS7-400 CP UDP 通信 Step7 项目编程
  • 最常用的JS加解密场景MD5
  • Vue 3 入门——自学习版本
  • 分布式推客系统全栈开发指南:SpringCloud+Neo4j+Redis实战解析
  • C#事件:从原理到实践的深度剖析
  • 微软语音合成标记语言SSML文档结构和事件(详细文档和实例)
  • 基于Python的豆瓣图书数据分析与可视化系统【自动采集、海量数据集、多维度分析、机器学习】
  • Ubuntu20.04运行openmvg和openmvs实现三维重建(未成功,仅供参考)
  • AI金融风控:识别欺诈,量化风险的新利器
  • 批量合并全国地理信息资源目录服务系统下载的全国基础地理数据
  • JAVA JVM垃圾收集
  • JavaScript 异步编程指南:async/await 与 Promise 该怎么选?
  • 中国银联豪掷1亿采购海光C86架构服务器
  • 第十五章 STL(stack、queue、list、set、map容器使用)