用途
本技能引导智能体完成 GDB 调试会话,从首次启动到高级工作流,涵盖崩溃诊断、反向调试、远程调试和多线程检查。
触发场景
- 程序发生段错误或崩溃,需要调试
- 需要在条件 X 上设置断点
- 需要在 GDB 中检查内存或变量
- 需要调试远程嵌入式目标
- GDB 显示 ?? 帧或无源码
- 需要确定性地重放 bug(记录/回放)
工作流
1. 前提:编译时带调试信息
始终使用 -g 编译(GCC/Clang)。大多数可调试代码使用 -Og 或 -O0。
gcc -g -Og -o prog main.c
发布构建:使用 -g -O2 并保留带符号的二进制文件(用 objcopy 单独剥离符号)。
2. 启动 GDB
gdb ./prog # 加载二进制文件
gdb ./prog core # 加载核心转储
gdb -p 12345 # 附加到运行中的进程
gdb --args ./prog arg1 arg2 # 传递参数
gdb -batch -ex 'run' -ex 'bt' ./prog # 非交互式(CI)
3. 基本命令
| 命令 | 快捷方式 | 效果 |
|---|---|---|
| run [args] | r | 启动程序 |
| continue | c | 断点后继续 |
| next | n | 单步跳过(源码行) |
| step | s | 单步进入 |
| nexti | ni | 单步跳过(指令) |
| stepi | si | 单步进入(指令) |
| finish | 运行到当前函数结束 | |
| until N | 运行到第 N 行 | |
| return [val] | 强制从函数返回 | |
| quit | q | 退出 GDB |
4. 断点和观察点
break main # 在函数处断点
break file.c:42 # 在行处断点
break *0x400abc # 在地址处断点
break foo if x > 10 # 条件断点
tbreak foo # 临时断点(触发一次)
rbreak ^mylib_.* # 对所有匹配函数使用正则断点
watch x # 观察点:x 变化时中断
watch *(int*)0x601060 # 观察内存地址
rwatch x # x 被读取时中断
awatch x # 读取或写入时中断
info breakpoints # 列出所有断点
delete 3 # 删除断点 3
disable 3 # 禁用而不删除
enable 3
5. 检查状态
print x # 打印变量
print/x x # 以十六进制打印
print *ptr # 解引用指针
print arr[0]@10 # 打印数组的 10 个元素
display x # 每次停止时自动打印 x
undisplay 1
info locals # 所有局部变量
info args # 函数参数
info registers # 所有 CPU 寄存器
info registers rip rsp rbp # 特定寄存器
x/10wx 0x7fff0000 # 检查地址处的 10 个字
x/s 0x400abc # 以字符串形式检查
x/i $rip # 检查当前指令
backtrace # 调用栈(bt)
bt full # bt + 局部变量
frame 2 # 切换到帧 2
up / down # 在栈中上移/下移
6. 多线程调试
info threads # 列出线程
thread 3 # 切换到线程 3
thread apply all bt # 所有线程的回溯
thread apply all bt full # 所有线程的完整回溯
set scheduler-locking on # 单步时暂停其他线程
7. 反向调试(记录/回放)
记录需要 target record-full 或 target record-btrace(Intel PT):
# 软件记录(慢但通用)
record # 开始记录
run
# ... 触发 bug ...
reverse-continue # 回到上一个断点
reverse-next # 向后单步
reverse-step
reverse-finish
# Intel Processor Trace(快速,硬件)
target record-btrace pt
run
# 查看指令历史
record instruction-history
8. 使用 gdbserver 进行远程调试
在目标机上:
gdbserver :1234 ./prog
# 或附加:
gdbserver :1234 --attach 5678
在主机上:
gdb ./prog
(gdb) target remote 192.168.1.10:1234
(gdb) break main
(gdb) continue
交叉编译时:在主机上使用 aarch64-linux-gnu-gdb。
9. 常见问题
| 症状 | 原因 | 修复 |
|---|---|---|
| 无符号表 | 二进制文件未使用 -g 编译 | 使用 -g 重新编译 |
| 回溯中出现 ?? 帧 | 缺少调试信息或栈损坏 | 安装 debuginfo 包;检查栈溢出 |
| 无法访问地址处的内存 | 空指针解引用/已释放内存 | 解引用前检查指针;使用 ASan |
| 回溯中出现 SIGABRT | abort() 或断言失败 | 向上查看帧以找到断言 |
| GDB 在运行时挂起 | 二进制文件等待输入 | 重定向 stdin:run < /dev/null |
| 断点位置错误 | 优化器移动了代码 | 使用 -Og 编译;或使用 nexti |
10. GDB 初始化文件(~/.gdbinit)
set history save on
set history size 1000
set print pretty on
set print array on
set print array-indexes on
set pagination off
set confirm off
命令速查表参见 references/cheatsheet.md。美化打印器和 Python 脚本参见 references/scripting.md。
相关技能
- 使用 skills/debuggers/core-dumps 加载核心文件
- 使用 skills/debuggers/lldb 进行基于 LLDB 的工作流
- 使用 skills/runtimes/sanitizers 在需要调试器之前捕获 bug
- 使用 skills/compilers/gcc 了解 -g 标志详情