SDK 应用调试指南
SDK 烧录到开发板之后需要进行开发调试,本文将介绍在开发调试中常用的工具,方便开发流程。一般开发环境如下图所示,PC 与开发板通过串口线与 USB 线连接。通过串口线访问开发板控制终端,通过 USB 执行下载烧录、ADB 等功能。
概述
调试工具简介
V861 SDK 提供了多种调试工具,各有特点和适用场景。下表帮助您快速选择合适的调试工具:
| 工具 | 功能概述 | 学习难度 | 推荐使用场景 |
|---|---|---|---|
| ADB | 命令行交互、文件传输、远程执行 | ★☆☆ 低 | 日常开发、快速验证、简单调试 |
| GDB | 断点调试、单步执行、变量查看 | ★★★ 高 | 深入分析程序逻辑、复杂问题定位 |
| VSCode | 图形化调试环境、断点、变量监视 | ★★☆ 中 | 大型项目开发、日常开发首选 |
| Coredump | 事后分析崩溃问题、内存转储 | ★★☆ 中 | 无法实时调试的场景、崩溃分析 |
章节导航
- 初次使用:建议从「使用 ADB 辅助调试」开始,熟悉基本的命令行操作
- 深入调试:阅读「使用 GDB 远程调试」,掌握命令行调试技巧
- 提升效率:配置「使用 VSCode 开发调试」,享受图形化调试体验
- 崩溃分析:学习「使用 Coredump 文件调试」,处理无法实时调试的问题
使用 ADB 辅助调试
工具简介
ADB(Android Debug Bridge)原本是 Android 平台的调试工具,V861 SDK 将其移植到了 Linux 平台。通过 ADB,您可以:
- 远程执行命令:无需串口,直接在 PC 上执行开发板命令
- 文件传输:方便地在 PC 和开发板之间传输文件
- 端口转发:为 GDB 等工具提供网络通道
- 系统控制:重启设备、进入烧写模式等
前置条件
执行 m menuconfig,勾选 ADB 软件包:
Allwinner --->
USB --->
<*> adbd................................................. adbd for Tina Linux

环境搭建
在使用 ADB 之前,需要在 PC 上搭建 ADB 环境。
Windows 环境:
- 下载 ADB 工具包:SDK 平台工具版本说明
- 解压到任意目录(如
C:\platform-tools) - 将该目录添加到系统环境变量 PATH 中
- 打开命令提示符,输入
adb version验证安装
Linux 环境:
# Ubuntu/Debian
sudo apt-get install android-tools-adb
# 验证安装
adb version
更多详细信息请参考 Android 调试桥官方文档。
连接方式
USB 连接
USB 连接是最简单、最稳定的连接方式。
步骤:
- 开发板烧录固件后,使用 USB 线连接 PC 和开发板
- 在 PC 命令行中检查连接状态:
adb devices
- 看到设备列表后,进入 ADB 控制台:
adb shell

网络连接
网络连接适用于开发板与 PC 距离较远,或需要无线调试的场景。
步骤:
(1)开发板连接网络
开发板通过串口连接,输入命令搜索 Wi-Fi 网络:
wifi -s

搜索到目标网络后,连接:
wifi -c <SSID> <密码>
连接成功后,使用 ifconfig 查看分配的 IP 地址:

(2)配置开发板无线 ADB
设置 ADB 监听端口(默认使用 5555):
export ADB_TRANSPORT_PORT=5555
重启 ADB 服务:
kill $(pgrep adbd) && adbd -D &
(3)PC 端连接
使用 IP 地址和端口连接:
adb connect <IP>:5555

(4)默认开启网络 ADB(可选)
如需开机自动启动网络 ADB,修改文件 openwrt/openwrt/package/subpackage/allwinner/usb/adbd/adbd.init,取消 ADB_TRANSPORT_PORT 的注释:

常用命令详解
设备管理
| 命令 | 说明 | 示例 |
|---|---|---|
adb devices | 列出已连接设备 | adb devices |
adb connect <ip>:<port> | 网络连接设备 | adb connect 192.168.1.100:5555 |
adb disconnect | 断开网络连接 | adb disconnect |
adb kill-server | 终止 ADB 服务 | adb kill-server |
adb start-server | 启动 ADB 服务 | adb start-server |
文件传输
| 命令 | 说明 | 示例 |
|---|---|---|
adb push <local> <remote> | 推送文件到设备 | adb push sample_virvi /mnt/extsd |
adb pull <remote> <local> | 从设备拉取文件 | adb pull /mnt/extsd/log.txt ./ |
示例:推送可执行文件和配置文件到开发板
adb push sample_virvi /mnt/extsd
adb push sample_virvi.conf /mnt/extsd
远程执行命令
| 命令 | 说明 | 示例 |
|---|---|---|
adb shell | 进入交互式 Shell | adb shell |
adb shell <command> | 执行单条命令 | adb shell ls /mnt/extsd |
示例:查看开发板文件列表
adb shell ls -la /mnt/extsd
系统控制
| 命令 | 说明 | 示例 |
|---|---|---|
adb reboot | 重启设备 | adb reboot |
adb reboot efex | 进入烧写模式 | adb reboot efex |
adb reboot recovery | 进入恢复模式 | adb reboot recovery |
端口转发
| 命令 | 说明 | 示例 |
|---|---|---|
adb forward tcp:<local> tcp:<remote> | 端口转发 | adb forward tcp:2241 tcp:2241 |
常见问题排查
Q: adb devices 看不到设备?
可能原因及解决方案:
- USB 线问题:更换 USB 线或换一个 USB 接口
- 驱动问题(Windows):安装 ADB 驱动,或使用「设备管理器」手动安装驱动
- ADB 服务问题:尝试重启 ADB 服务
adb kill-server
adb start-server
adb devices - 开发板 ADB 未启动:检查开发板是否正确烧录固件,ADB 服务是否运行
Q: 网络连接失败?
可能原因及解决方案:
- IP 地址错误:确认开发板 IP 地址正确,使用
ifconfig验证 - 端口未开放:确认开发板已执行
export ADB_TRANSPORT_PORT=5555并重启 adbd - 网络不通:使用
ping测试网络连通性 - 防火墙阻止:检查 PC 或网络防火墙设置
Q: 权限被拒绝?
解决方案:
Linux 环境下可能需要配置 udev 规则:
# 创建 udev 规则文件
sudo vim /etc/udev/rules.d/51-android.rules
# 添加以下内容(vendor ID 根据实际情况修改)
SUBSYSTEM=="usb", ATTR{idVendor}=="18d1", MODE="0666"
# 重载规则
sudo udevadm control --reload-rules
sudo udevadm trigger
使用远程 GDB 辅助调试
GDB 简介
什么是 GDB?
GDB(GNU Debugger)是 GNU 项目开发的调试器,支持多种编程语言(C/C++、Go、Rust 等)。它可以:
- 启动程序并指定任何可能影响其行为的参数
- 在指定条件下使程序停止
- 检查程序停止时发生了什么
- 修改程序中的内容以便纠正错误
为什么嵌入式需要远程调试?
在嵌入式开发中,目标设备(开发板)资源有限:
- 内存有限:无法运行完整的 GDB
- 存储有限:无法存储调试符号信息
- 性能受限:调试会严重影响系统性能
因此,采用「GDB Server + GDB Client」的架构:
┌─────────────────┐ ┌─────────────────┐
│ PC Side │ │ Board Side │
│ │ │ │
│ ┌───────────┐ │ Network │ ┌───────────┐ │
│ │ GDB │◄─┼────────────────────┼──│ GDB Server│ │
│ │ (Client) │ │ │ │ │ │
│ └───────────┘ │ │ └───────────┘ │
│ │ │ │ │
│ Debug Symbols │ │ Target Program │
│ Source Code │ │ │
└─────────────────┘ └─────────────────┘
GDB Server 运行在开发板上,体积小、资源占用少;GDB Client 运行在 PC 上,拥有完整的调试能力。
前置条件
编译调试信息
要让 GDB 正常工作,需要编译带调试信息的程序。
步骤:
- 编辑
openwrt/package/allwinner/eyesee-mpp/middleware/Makefile,在 FLAGS 中增加-g选项:
CFLAGS="-I -fstack-protector $(TARGET_CFLAGS) -g" \
CXXFLAGS="-I -fstack-protector $(TARGET_CXXFLAGS) -g" \
CPPFLAGS="-I -fstack-protector $(TARGET_CPPFLAGS) -g" \

- 重新编译 MPP:
cleanmpp && mkmpp
说明:
-g选项告诉编译器在可执行文件中包含调试信息(如变量名、函数名、源代码行号等)。没有调试信息,GDB 只能进行汇编级别的调试。
配置 GDB Server
进入 menuconfig 勾选 gdbserver:
Development --->
<*> gdbserver................................. Remote server for GNU Debugger

端口转发配置
ADB 端口转发
由于 GDB Client 和 GDB Server 通过网络通信,而开发板通常没有公网 IP,需要使用 ADB 端口转发。
原理图:
┌────────────────┐ USB ┌────────────────┐
│ PC │◄──────────────────►│ Board │
│ │ │ │
│ localhost │ adb forward │ localhost │
│ :2241 ───────┼────────────────────┼──► :2241 │
│ │ │ │ │
│ │ │ gdbserver │
│ │ │ listen 2241 │
└────────────────┘ └────────────────┘
命令格式:
adb forward tcp:<local_port> tcp:<device_port>
local_port:PC 端监听端口device_port:开发板端监听端口
示例:转发端口 2241
adb forward tcp:2241 tcp:2241
转发到编译服务器(可选)
在企业开发环境中,编译通常在远程服务器进行,需要额外一层端口转发。
拓扑图:
┌──────────────┐ SSH Tunnel ┌──────────────┐ ADB Forward ┌──────────────┐
│ Build Server │◄────────────────────►│ PC │◄────────────────────►│ Board │
│ │ │ │ │ │
│ GDB │ PuTTY/SSH │ adb │ USB │ gdbserver │
│ :2241 ◄─────┼──────────────────────┼─── :2241 ◄───┼──────────────────────┼──► :2241 │
│ │ │ │ │ │
└──────────────┘ └──────────────┘ └──────────────┘
配置步骤:
- 打开 PuTTY,配置编译服务器地址
- 点击 Connection → SSH → Tunnels
- 配置端口转发:

- 按图中顺序配置:

- 点击
Open建立连接
此后,在编译服务器上访问 localhost:2241 即可连接开发板的 GDB Server。
连接与调试
启动 GDB Server
在开发板上启动 GDB Server:
gdbserver --multi 0:2241 &


参数说明:
--multi:启用扩展模式,允许 GDB 控制程序加载和运行0:2241:监听所有网络接口的 2241 端口&:后台运行
使用 GDB 连接
(1)启动 GDB
进入工具链目录(根据使用的 libc 选择):
cd prebuilt/rootfsbuilt/riscv/Xuantie-900-gcc-linux-6.6.36-musl32-x86_64-V3.3.0/bin
启动 GDB:
./riscv32-unknown-linux-musl-gdb

(2)加载被调试程序
(gdb) file ../../../../../platform/allwinner/eyesee-mpp/middleware/sun252iw1/sample/bin/sample_virvi

说明:
file命令加载可执行文件的符号表,使 GDB 能够将机器码映射到源代码。
(3)配置动态库搜索路径
GDB 需要知道动态库的位置才能加载符号:
(gdb) set sysroot ../../../../../out/v861/bga_perf1/openwrt/staging_dir/target/root-v861-bga_perf1/
(gdb) set solib-search-path ../../../../../out/v861/bga_perf1/openwrt/staging_dir/target/root-v861-bga_perf1/usr/lib
(gdb) info sharedlibrary

说明:
sysroot:设置库文件的根目录前缀solib-search-path:设置库文件的搜索路径info sharedlibrary:显示已加载的共享库信息
(4)连接 GDB Server
(gdb) target extended-remote :2241

说明:
extended-remote模式允许 GDB 控制程序加载和运行,比普通的remote模式功能更强大。
(5)推送可执行文件
将编译好的可执行文件推送到开发板:
adb push sample_virvi /mnt/extsd
adb push sample_virvi.conf /mnt/extsd
在 GDB 中设置远端执行文件:
(gdb) set remote exec-file /mnt/extsd/sample_virvi
断点操作详解
设置断点
按函数名设置断点:
(gdb) break main
按文件和行号设置断点:
(gdb) break sample_virvi/sample_virvi.c:1113

按条件设置断点:
(gdb) break sample_virvi/sample_virvi.c:1113 if pContext->mSaveBufMgrConfig.mSavePicDev >= 0

只有当条件满足时,程序才会暂停。
按内存地址设置断点:
(gdb) break *0x0001e136

适用于没有源代码时的调试。
管理断点
查看所有断点:
(gdb) info breakpoints

启用断点:
(gdb) enable 1

禁用断点:
(gdb) disable 1

删除断点:
(gdb) delete 1

单步调试详解
启动程序
(gdb) run -path /mnt/extsd/sample_virvi.conf
程序将在第一个断点处暂停。
查看代码
(gdb) list

继续执行
(gdb) continue
程序将继续执行,直到下一个断点或程序结束。
单步执行
next(不进入函数):
(gdb) next
执行当前行,如果当前行是函数调用,则执行完整个函数。
step(进入函数):
(gdb) step
执行当前行,如果当前行是函数调用,则进入函数内部。
变量查看详解
查看变量值
(gdb) print pContext->mSaveBufMgrConfig.mSavePicDev

查看局部变量
(gdb) info locals

查看结构体内容
(gdb) p *pContext

GDB 命令速查表
| 功能 | 命令 | 说明 |
|---|---|---|
| 断点操作 | ||
| 设置断点(函数) | break main | 在函数入口设置断点 |
| 设置断点(行号) | break file.c:100 | 在指定文件的指定行设置断点 |
| 设置断点(条件) | break file.c:100 if var > 0 | 条件断点 |
| 设置断点(地址) | break *0x12345678 | 在内存地址设置断点 |
| 查看断点 | info breakpoints | 显示所有断点 |
| 启用断点 | enable 1 | 启用编号为 1 的断点 |
| 禁用断点 | disable 1 | 禁用编号为 1 的断点 |
| 删除断点 | delete 1 | 删除编号为 1 的断点 |
| 执行控制 | ||
| 启动程序 | run [args] | 启动程序执行 |
| 继续执行 | continue | 继续执行到下一个断点 |
| 单步(不进入) | next | 执行一行,不进入函数 |
| 单步(进入) | step | 执行一行,进入函数 |
| 执行到指定行 | until 100 | 执行到第 100 行 |
| 变量查看 | ||
| 打印变量 | print var | 打印变量值 |
| 打印结构体 | print *ptr | 打印指针指向的结构体 |
| 查看局部变量 | info locals | 显示当前函数的局部变量 |
| 查看参数 | info args | 显示当前函数的参数 |
| 查看调用栈 | bt | 显示函数调用栈 |
| 其他 | ||
| 查看代码 | list | 显示当前位置的源代码 |
| 查看线程 | info threads | 显示所有线程 |
| 切换线程 | thread 2 | 切换到线程 2 |
| 退出 GDB | quit | 退出调试 |
常见问题排查
Q: 连接 GDB Server 超时?
错误信息:
Remote connection closed
could not connect: Connection timed out.
排查步骤:
- 检查开发板 gdbserver 是否运行:
ps | grep gdbserver - 检查端口转发是否正确:
adb forward --list - 检查防火墙设置
- 尝试重新建立连接:
adb kill-server
adb start-server
adb forward tcp:2241 tcp:2241
Q: 符号表加载失败?
错误信息:
Reading symbols from /lib/libc.so...
(no debugging symbols found)
解决方案:
- 确认编译时添加了
-g选项 - 检查
sysroot和solib-search-path路径是否正确 - 使用
info sharedlibrary检查库加载状态
Q: 动态库找不到?
错误信息:
Cannot find new threads: generic error
解决方案:
确保 sysroot 指向正确的根文件系统路径:
(gdb) set sysroot /path/to/rootfs
使用 VSCode 开发调试
VSCode 简介
Visual Studio Code(VSCode)是微软开发的开源代码编辑器,具有以下优势:
- 跨平台:支持 Windows、Linux、macOS
- 插件丰富:拥有庞大的插件生态系统
- 调试功能强大:支持断点、变量监视、调用栈查看
- 远程开发:支持 SSH 远程连接服务器开发
对于嵌入式开发,VSCode 可以替代命令行 GDB,提供更直观的图形化调试体验。
前置条件
编译调试信息
要让 VSCode 调试正常工作,需要编译带调试信息的程序。
步骤:
- 编辑
openwrt/package/allwinner/eyesee-mpp/middleware/Makefile,在 FLAGS 中增加-g选项:
CFLAGS="-I -fstack-protector $(TARGET_CFLAGS) -g" \
CXXFLAGS="-I -fstack-protector $(TARGET_CXXFLAGS) -g" \
CPPFLAGS="-I -fstack-protector $(TARGET_CPPFLAGS) -g" \

- 重新编译 MPP:
cleanmpp && mkmpp
GDB 环境配置
确保已完成「使用远程 GDB 辅助调试」章节中的以下步骤:
- GDB Server 已配置并运行
- ADB 端口转发已建立
- 可执行文件已推送到开发板
环境配置
安装 VSCode
从官网下载安装:https://code.visualstudio.com/
配置远程开发(可选)
如果 SDK 在远程服务器上,需要安装 Remote-SSH 扩展:
- 在 VSCode 中按
Ctrl+Shift+X打开扩展面板 - 搜索并安装
Remote - SSH - 按
F1,输入Remote-SSH: Connect to Host连接服务器
更多详情参考 VSCode 远程 SSH 文档。
安装 C/C++ 扩展
- 点击扩展图标
- 搜索
C/C++ - 安装 Microsoft 的 C/C++ 扩展

扩展地址:https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools
launch.json 配置详解
创建 launch.json
- 点击调试图标
- 点击「创建 launch.json 文件」

- 选择调试器类型(任意选择一个即可)
配置内容
以下是完整的 launch.json 配置(以调试 sample_virvi 为例):
{
"version": "1.0.0",
"configurations": [
{
"name": "(gdb) Launch sample_virvi",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/platform/allwinner/eyesee-mpp/middleware/sun252iw1/sample/sample_virvi/sample_virvi",
"args": [
"-path",
"/mnt/extsd/sample_virvi.conf"
],
"symbolLoadInfo": {
"loadAll": true,
"exceptionList": ""
},
"additionalSOLibSearchPath": "${workspaceFolder}/out/v861/bga_perf1/openwrt/staging_dir/target/root-v861-bga_perf1;${workspaceFolder}/out/v861/bga_perf1/openwrt/staging_dir/target/root-v861-bga_perf1/usr/lib",
"stopAtEntry": true,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "${workspaceFolder}/prebuilt/rootfsbuilt/riscv/Xuantie-900-gcc-linux-6.6.36-musl32-x86_64-V3.3.0/bin/riscv32-unknown-linux-musl-gdb",
"miDebuggerServerAddress": "localhost:2241",
"useExtendedRemote": true,
"postRemoteConnectCommands": [
{
"description": "Set remotetimeout for gdb",
"text": "set remotetimeout 20",
"ignoreFailures": true
},
{
"description": "Set remote exec-file for gdb",
"text": "set remote exec-file /mnt/extsd/sample_virvi",
"ignoreFailures": false
},
{
"description": "Set sysroot for gdb",
"text": "set sysroot ${workspaceFolder}/out/v861/bga_perf1/openwrt/staging_dir/target/root-v861-bga_perf1",
"ignoreFailures": false
},
{
"description": "Set solib-search-path for gdb",
"text": "set solib-search-path ${workspaceFolder}/out/v861/bga_perf1/openwrt/staging_dir/target/root-v861-bga_perf1/usr/lib",
"ignoreFailures": false
}
],
"setupCommands": [
{
"description": "Enable pretty-printing for GDB",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set disassembly-flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
}
]
}

配置字段说明
| 字段 | 说明 |
|---|---|
name | 配置名称,显示在调试面板中 |
type | 调试器类型,C/C++ 使用 cppdbg |
request | 请求类型,launch 表示启动调试 |
program | 要调试的程序路径(本地带符号表的程序) |
args | 程序运行参数 |
MIMode | 调试器模式,使用 GDB |
miDebuggerPath | GDB 可执行文件路径 |
miDebuggerServerAddress | GDB Server 地址 |
useExtendedRemote | 使用扩展远程模式 |
postRemoteConnectCommands | 连接后执行的 GDB 命令 |
修改配置
针对不同的调试需求,需要修改以下字段:

program:修改为要调试的程序路径args:修改程序参数miDebuggerPath:根据工具链类型修改postRemoteConnectCommands中的路径:修改为对应的板级路径
调试演示
准备工作
-
开发板启动 GDB Server:
gdbserver --multi 0:2241 & -
PC 端配置端口转发:
adb forward tcp:2241 tcp:2241 -
推送可执行文件:
adb push sample_virvi /mnt/extsd
adb push sample_virvi.conf /mnt/extsd
开始调试
- 打开源代码文件,在需要暂停的行点击左侧设置断点:

- 切换到调试面板,点击「开始调试」:

- 程序将在断点处暂停:

- 查看调试信息:

调试面板提供以下功能:
- 变量:查看当前作用域的变量
- 监视:添加表达式监视
- 调用堆栈:查看函数调用栈
- 线程:切换线程
常见问题排查
Q: launch.json 配置错误?
检查要点:
- 路径使用正斜杠
/或双反斜杠\\ ${workspaceFolder}表示工作区根目录- JSON 格式正确(无多余逗号、引号匹配)
Q: 断点不生效?
可能原因:
- 编译时未添加
-g选项 - 源代码与编译时的代码不一致
- 优化级别过高(尝试添加
-O0)
Q: 无法连接 GDB Server?
排查步骤:
- 检查 GDB Server 是否运行
- 检查端口转发是否正确
- 检查
miDebuggerServerAddress配置是否正确
使用 Coredump 文件调试
Coredump 简介
什么是 Coredump?
Coredump(核心转储)是程序崩溃时操作系统生成的一个文件,它包含了程序崩溃时的内存映像、寄存器状态、堆栈信息等。通过分析 Coredump 文件,可以定位程序崩溃的原因。
工作原理
Program Crash
│
▼
OS captures exception signal
│
▼
Generate Coredump file (memory image + registers + stack)
│
▼
Load Coredump with GDB for analysis
│
▼
Locate crash cause
适用场景
- 程序偶发性崩溃,难以复现
- 生产环境问题分析
- 无法使用 GDB 实时调试的场景
前置条件
编译调试信息
要让 Coredump 分析有意义,需要编译带调试信息的程序。
步骤:
- 编辑
openwrt/package/allwinner/eyesee-mpp/middleware/Makefile,在 FLAGS 中增加-g选项:
CFLAGS="-I -fstack-protector $(TARGET_CFLAGS) -g" \
CXXFLAGS="-I -fstack-protector $(TARGET_CXXFLAGS) -g" \
CPPFLAGS="-I -fstack-protector $(TARGET_CPPFLAGS) -g" \
- 重新编译 MPP:
cleanmpp && mkmpp
配置 Coredump 环境
内核配置
内核需要启用 CONFIG_COREDUMP 配置(默认已启用):

配置 Coredump 文件大小
系统默认可能限制 Coredump 文件大小,需要取消限制:
ulimit -c unlimited
说明:
unlimited表示不限制大小。也可以指定具体数值,如ulimit -c 1000000(单位:KB)。
配置 Coredump 文件路径和格式
设置 Coredump 文件的保存路径和命名格式:
echo '/mnt/extsd/core.%e.%p' > /proc/sys/kernel/core_pattern
格式说明:
| 参数 | 含义 |
|---|---|
%e | 程序文件名 |
%p | 进程 ID |
%t | 时间戳 |
%h | 主机名 |
示例:
/mnt/extsd/core.%e.%p→/mnt/extsd/core.sample_virvi.1234/mnt/extsd/core.%e.%t→/mnt/extsd/core.sample_virvi.1700000000
触发与生成 Coredump
人为触发 Coredump(测试)
为了演示 Coredump 分析流程,可以人为添加一个会导致崩溃的代码。
编辑 platform/allwinner/eyesee-mpp/middleware/sun252iw1/sample/sample_virvi/sample_virvi.c,在某个线程函数中添加空指针访问:
int *ptr = NULL;
printf("Value at ptr: %d\n", *ptr); // 访问空指针,触发段错误

重新编译并运行,程序将崩溃并生成 Coredump 文件。
运行程序生成 Coredump
在开发板上执行:
ulimit -c unlimited
echo '/mnt/extsd/core.%e.%p' > /proc/sys/kernel/core_pattern
./sample_virvi -path sample_virvi.conf
程序崩溃后,将看到类似输出:

检查生成的 Coredump 文件:

使用 Coredump 定位问题
准备分析文件
将 Coredump 文件和对应的可执行文件(带调试信息)放到同一目录:

启动 GDB 分析
进入工具链目录:
cd prebuilt/rootfsbuilt/riscv/Xuantie-900-gcc-linux-6.6.36-musl32-x86_64-V3.3.0/bin
启动 GDB 并加载程序和 Coredump 文件:
./riscv32-unknown-linux-musl-gdb ../../../../../platform/allwinner/eyesee-mpp/middleware/sun252iw1/sample/bin/sample_virvi ../../../../../platform/allwinner/eyesee-mpp/middleware/sun252iw1/sample/bin/core.sample_virvi.212

加载符号表
如果看到库符号表加载失败的警告,需要配置库搜索路径:
(gdb) set sysroot ../../../../../out/v861/bga_perf1/openwrt/staging_dir/target/root-v861-bga_perf1/
(gdb) set solib-search-path ../../../../../out/v861/bga_perf1/openwrt/staging_dir/target/root-v861-bga_perf1/usr/lib
(gdb) info sharedlibrary

查看崩溃位置
使用 bt(backtrace)命令查看调用栈:
(gdb) bt

从输出可以看到崩溃发生在 sample_virvi.c 的第 565 行。
查看源代码
使用 list 命令查看崩溃位置附近的代码:
(gdb) list

查看变量值
查看局部变量:
(gdb) info locals

查看指针指向的内容:
(gdb) p *pContext

查看出错原因
查看导致崩溃的指针:
(gdb) p *ptr
可以看到 ptr 是空指针,访问空指针导致了段错误。
常见问题排查
Q: Coredump 文件未生成?
可能原因:
-
ulimit -c限制为 0- 解决:执行
ulimit -c unlimited
- 解决:执行
-
core_pattern配置指向管道而非文件- 检查:
cat /proc/sys/kernel/core_pattern - 解决:重新配置为文件路径
- 检查:
-
磁盘空间不足
- 检查:
df -h
- 检查:
-
程序没有崩溃信号
- 检查程序是否真的崩溃了
Q: Coredump 文件过大?
解决方案:
-
使用压缩:
echo '|/bin/gzip > /mnt/extsd/core.%e.%p.gz' > /proc/sys/kernel/core_pattern -
限制程序内存使用,减小 Coredump 大小
Q: GDB 分析失败?
可能原因:
-
可执行文件与 Coredump 不匹配
- 确保使用同一版本的可执行文件
-
符号表缺失
- 确保编译时添加了
-g选项
- 确保编译时添加了
-
库路径配置错误
- 检查
sysroot和solib-search-path
- 检查
附录
常见问题汇总
ADB 相关
| 问题 | 解决方案 |
|---|---|
| 看不到设备 | 检查 USB 线、驱动、ADB 服务 |
| 网络连接失败 | 检查 IP、端口、防火墙 |
| 权限被拒绝 | 配置 udev 规则 |
GDB 相关
| 问题 | 解决方案 |
|---|---|
| 连接超时 | 检查 gdbserver、端口转发 |
| 符号表加载失败 | 检查 -g 选项、sysroot 路径 |
| 断点不生效 | 检查优化级别、源代码一致性 |
VSCode 相关
| 问题 | 解决方案 |
|---|---|
| launch.json 错误 | 检查 JSON 格式、路径格式 |
| 无法连接 | 检查 GDB Server、端口转发 |
| 变量显示异常 | 检查符号表、优化级别 |
Coredump 相关
| 问题 | 解决方案 |
|---|---|
| 文件未生成 | 检查 ulimit、core_pattern |
| 文件过大 | 使用压缩、限制内存 |
| 分析失败 | 检查可执行文件版本、符号表 |
调试技巧
- 使用日志:在关键位置添加日志输出,帮助定位问题
- 逐步缩小范围:先用简单方法(如打印)定位大致位置,再用 GDB 精确定位
- 保存现场:遇到崩溃时,及时保存 Coredump 文件
- 版本管理:保留带调试信息的可执行文件,便于后续分析
- 工具组合:ADB + GDB + VSCode 配合使用,提高调试效率