GNU 的调试器 GDB 提供了许多有用的特性,支持机器级程序的运行时评估和分析。对于本书中的示例和练习,虽然可以通过阅读代码推断程序行为,但 GDB 能观察运行中的程序并控制其执行,使研究程序行为成为可能。
启动 GDB#
通常先运行 OBJDUMP 获取程序的反汇编版本。启动 GDB 的命令行格式如下:
Bash
linux> gdb progplaintext核心调试策略#
- 设置断点(Breakpoints) :可在函数入口处或具体的程序地址处设置。
- 暂停与控制 :程序执行遇到断点时会暂停,并将控制权返回给用户。
- 检查状态 :在断点处可以查看寄存器和内存位置的内容。
- 单步跟踪 :可以执行单条指令,或前进到下一个断点。
GDB 常用命令参考表(机器级调试)#
下表总结了用于研究机器级 x86-64 程序的常用 GDB 命令。
| 分类 | 命令 | 效果 |
|---|---|---|
| 开始和停止 | quit | 退出 GDB |
run | 运行程序(可在此处输入命令行参数) | |
kill | 停止当前正在运行的程序 | |
| 断点 | break multstore | 在函数 multstore入口处设置断点 |
break *0x400540 | 在地址 0x400540处设置断点 | |
delete 1 | 删除断点 1 | |
delete | 删除所有断点 | |
| 执行控制 | stepi | 执行 1 条指令 |
stepi 4 | 执行 4 条指令 | |
nexti | 类似于 stepi,但跳过函数调用(以函数为单位) | |
continue | 继续执行,直到遇到下一个断点 | |
finish | 运行直到当前函数返回 | |
| 检查代码 | disas | 反汇编当前函数 |
disas multstore | 反汇编函数 multstore | |
disas 0x400544 | 反汇编位于地址 0x400544附近的函数 | |
disas 0x400540, 0x40054d | 反汇编指定地址范围内的代码 | |
print /x $rip | 以十六进制输出程序计数器 %rip的值 | |
| 检查数据 | print $rax | 以十进制输出 %rax的内容 |
print /x $rax | 以十六进制输出 %rax的内容 | |
print /t $rax | 以二进制输出 %rax的内容 | |
print 0x100 | 输出 0x100的十进制表示 | |
print /x 555 | 输出 555的十六进制表示 | |
print /x ($rsp + 8) | 以十六进制输出 %rsp的内容加上 8 的结果 | |
print *(long *) 0x7ffffffe818 | 输出地址 0x7ffffffe818处的长整数 | |
print *(long *)($rsp + 8) | 输出内存地址 %rsp + 8处的长整数 | |
x/2g 0x7ffffffe818 | 检查从地址开始的 2 个双字(8字节/字)内容 | |
x/20b multstore | 检查函数 multstore的前 20 个字节 | |
| 有用信息 | info frame | 显示有关当前栈帧的信息 |
info registers | 显示所有寄存器的当前值 | |
help | 获取有关 GDB 命令的在线帮助 |
补充说明#
- 语法提示 :GDB 的命令语法初看较为晦涩,建议多使用
help命令查看详细用法。 - 格式说明 :
/x: 十六进制/d: 十进制/t: 二进制x命令格式:x/Nuf addr(N-数量,u-单位大小,f-格式)。例如x/2g中g代表 giant word(8 字节)。- 图形界面 :如果你不习惯命令行,可以使用 DDD (GDB 的图形化扩展)来观察数据结构和程序流。