GDB调试入门简明指南
1. GDB简介
gdb是gnu debugger
的缩写, 是一款可以用于源码级和汇编级调试的无图形界面调试器, 虽然对新手并不算友好, 但是和vim一样, 都属于花时间学了就会真香的小工具,学费了就直接抛弃IDE和vscode吧…
2. 源码级调试
2.1 控制要调试的进程
gdb <executable_file_name>
可以启动调试器, 获得如下界面
run
可以启动待调试的可执行文件, 可以简写成r
. 如果启动需要带上命令行参数, 就直接加在后面.
例如r BV1zuCXYfE6z --resolution=1080p --downloader=/usr/bin/curl
start
可以自动启动程序, 并在main
函数的第一行停下, 若没有调试信息, 也会完成动态库加载等准备工作后之后停在入口处kill
可以杀死正在调试的进程continue
可以使程序继续运行, 直到遇到断点或崩溃finish
可以使程序运行到当前函数结束, 返回调用地点
gdb的几乎所有命令都能够简写, 在不具有二义性的情况下可以写尽量少的字母, 例如run
可以写成r
, continue
可以写成c
, 也可以使用TAB键补全命令
2.2 断点
gdb的断点指令是break
, 可以只简写成``.
b <function>
: 使程序在进入函数后的第一条语句处停下. 如果是C++代码, 可以写出作用域加函数原型, 保证断点在正确的重载处b <line-number>
: 将断点打在当前文件的对应行号处b <file_name>:<line_number>
: 将断点打在指定文件名称的指定行号处info breakpoints
: 查看断点信息delete breakpoints <breakpoint number>
: 删除对应标号的断点, 若没给出标号, 就删除所有断点
2.3 单步运行
单步不进入
next
可以单步运行代码(简写n
), 不进入下一层的函数内部
单步进入
step
可以单步运行代码(简写s
), 会进入下一层函数
例如: 当代码走到auto res...
这一行停下时, 键入n
会进入下一行std::fstream output_file;
, 而键入s
则会进入qrc_decode
函数内部
1 | // decode... |
2.4 查看信息
print
print
可以简写为p
, 可以打印变量的值或表达式的值
p
后面可以加一些修饰来表示以指定的格式输出内容
x
: 十六进制显示d
: 十进制显示u
: 十六进制无符号i
: 反汇编之后显示t
: 八进制显示c
: 字符格式显示f
: 浮点数格式显示s
: 按C风格字符串显示
使用案例: p/s str1
, 以字符串打印str1
变量
x
x
指令可以打印内存地址和寄存器中的值. 用法: x/nfu address
n
是一个正整数, 指定显示address
向高地址方向打印的内存单元的数量, 不给出就默认一个f
是指定显示格式的, 和上面p
的选项一致, 默认十六进制显示u
是指定内存单元长度的选项,b
表示单字节,h
表示双字节,w
表示四字节,h
表示八字节
使用案例: x/50wx char_ptr
就是十六机制查看char_ptr
指向的地址到char_ptr + 50 * 4
地址, 也就是char_ptr
指向地址偏移200字节内的内容
3. 汇编级调试
在没有调试信息时gdb仍然可以根据符号表进行调试
3.1 反汇编
disassemble <function>
可以反汇编指定的函数x/i $rip
可以反汇编指令寄存器指向的指令
3.2 汇编级单步执行
ni
: 汇编级单步不进入(遇到call指令不进入函数)si
: 汇编级单步进入(遇到call指令进入函数)
3.3 查看内存与寄存器
info register
: 简写i r
, 查看所有寄存器信息
- 使用
x
指令查看寄存器和其指向内容–例:x/50wx $rsp
查看栈顶指针寄存器向高地址方向的200字节, 4字节一组十六进制显示
大部分常用的调试技巧其实只有寥寥几条指令, 读者稍加练习就能掌握, 并体验到命令行调试器的优势.
如果需要更详细的gdb调试技巧, 可以看看100个gdb小技巧.