GDB
GDB(GNU Debugger)是一个命令行调试工具,可用于调试使用各种编程语言编写的程序。它允许在被调试的代码中检查内存、控制代码的执行状态、检测代码特定部分的执行等。
gdb [选项] [可执行文件] [core文件]| 参数 | 说明 |
|---|---|
| 可执行文件 | 需要调试的程序 |
| core 文件 | 程序崩溃时生成的 core dump |
| 命令 | 说明 |
|---|---|
gdb ./prog |
启动时加载程序 |
gdb ./prog core |
调试崩溃程序(core dump) |
gdb -tui ./prog |
TUI 模式(图形化界面) |
TUI 模式下程序输出可能导致界面错乱,可通过
refresh手动刷新。
layout 命令可在终端中创建多窗口布局:
layout src:显示源代码窗口和命令行窗口layout asm:显示汇编代码窗口和命令行窗口layout split:上下分屏显示源代码和汇编代码layout regs:在代码窗口下方显示寄存器窗口
| 命令 | 说明 |
|---|---|
break [LOCATION] |
设置断点 |
info breakpoints |
查看断点列表 |
delete <编号> |
删除断点 |
disable <编号> |
禁用断点 |
enable <编号> |
启用断点 |
LOCATION 可以是函数名、行号、文件名:行号、地址等,还可附加条件表达式:
(gdb) break main # 在 main() 开头断点(gdb) break *0x804000 # 在地址断点(反汇编时常用)(gdb) break 123 # 在当前文件第 123 行断点(gdb) break file.c:20 # 在 file.c 第 20 行断点(gdb) break my_loop if i > 10 # 条件断点:当 i > 10 时触发删除与启用/禁用示例:
(gdb) delete 1 # 删除断点 1(gdb) delete # 删除所有断点(gdb) delete 2-5 # 删除断点 2 到 5(gdb) disable 2 # 禁用断点 2(gdb) enable 2 # 启用断点 2(gdb) enable delete 3 # 启用断点 3 并在触发后删除| 命令 | 说明 |
|---|---|
run / r |
启动程序(可带参数) |
continue / c |
继续运行直到下一个断点 |
step / s |
单步进入函数(会进入被调用函数内部) |
next / n |
单步执行但不进入函数内部 |
finish |
直接运行到当前函数结束(快速跳出函数) |
(gdb) run arg1 arg2 # 带参数启动(gdb) run # 不带参数启动(gdb) continue(gdb) step(gdb) next(gdb) finish打印变量与寄存器
Section titled “打印变量与寄存器”(gdb) print x # 打印变量值(gdb) print array[10] # 打印数组元素(gdb) print *ptr # 打印指针指向的值(gdb) info registers # 查看所有寄存器的值(gdb) p $eax # 查看特定寄存器x/[n][f][u] address:检查内存
n:显示的单元数(可选,默认 1)f:输出格式(x十六进制、d十进制、s字符串、i指令)u:单元大小(b字节、h半字 2 字节、w字 4 字节、g双字 8 字节)address:内存地址(变量名、指针值、表达式等)
(gdb) x/16xb &array # 查看数组前 16 字节(十六进制)(gdb) x/10dw ptr # 查看 ptr 指向的 10 个 4 字节整数(十进制)(gdb) x/s 0x8040000 # 查看地址处的字符串(gdb) x/8i $pc # 查看当前指令附近的 8 条汇编指令set {TYPE}<address> = <value>:直接修改内存
(gdb) set {int}0xffffd000 = 42 # 修改内存为整数 42(gdb) set {char[5]}0x804000 = "ABCD" # 写入字符串| 命令 | 说明 |
|---|---|
backtrace / bt |
查看调用栈(崩溃时特别有用) |
frame <编号> |
切换到指定栈帧 |
(gdb) backtrace(gdb) frame 2(gdb) watch x # 当变量 x 被修改时暂停编译带调试信息的程序并启动调试:
gcc -g -o prog prog.cgdb ./prog在 main 函数设置断点并运行:
(gdb) break main(gdb) run(gdb) next(gdb) print x(gdb) continue调试崩溃程序:
gdb ./prog core(gdb) backtrace(gdb) frame 0(gdb) print *ptr