摘自 GDB的那些奇淫技巧,补充了一些个人笔记。

启动 GDB

命令含义备注
gdb object正常启动,加载可执行
gdb object core对可执行 + core 文件进行调试
gdb object pid对正在执行的进程进行调试
gdb正常启动,启动后需要 file 命令手动加载
gdb -tui启用 gdb 的文本界面(或 ctrl-x ctrl-a 更换 CLI/TUI)

帮助信息

命令含义备注
help列出命令分类
help running查看某个类别的帮助信息
help run查看命令 run 的帮助
help info列出查看程序运行状态相关的命令
help info line列出具体的一个运行状态命令的帮助
help show列出 GDB 状态相关的命令
help show commands列出 show 命令的帮助

断点

命令含义备注
break main对函数 main 设置一个断点,可简写为 b main
break 101对源代码的行号设置断点,可简写为 b 101
break basic.c:101对源代码和行号设置断点
break basic.c:foo对源代码和函数名设置断点
break *0x00400448对内存地址 0x00400448 设置断点
info breakpoints列出当前的所有断点信息,可简写为 info break
delete 1按编号删除一个断点
delete删除所有断点
clear删除在当前行的断点
clear function删除函数断点
clear line删除行号断点
clear basic.c:101删除文件名和行号的断点
clear basic.c:main删除文件名和函数名的断点
clear *0x00400448删除内存地址的断点
disable 2禁用某断点,但是部删除
enable 2允许某个之前被禁用的断点,让它生效
rbreak {regexpr}匹配正则的函数前断点,如 ex_* 将断点 ex_ 开头的函数
tbreak function/line临时断点
hbreak function/line硬件断点
ignore {id} {count}忽略某断点 N-1 次
condition {id} {expr}条件断点,只有在条件生效时才发生
condition 2 i == 202号断点只有在 i == 20 条件为真时才生效
watch {*(int*)<addr>}/{expr}对变量设置监视点,监视写操作
rwatch {*(int*)<addr>}/{expr}对变量设置监视点,监视读操作
awatch {*(int*)<addr>}/{expr}对变量设置监视点,监视读写操作
info watchpoints显示所有观察点
catch exec断点在exec事件,即子进程的入口地址

运行程序

命令含义备注
run运行程序
run {args}以某参数运行程序
run < file以某文件为标准输入运行程序
run < <(cmd)以某命令的输出作为标准输入运行程序
run <<< $(cmd)以某命令的输出作为标准输入运行程序Here-String
set args {args} ...设置运行的参数
show args显示当前的运行参数
cont继续运行,可简写为 c
step单步进入,碰到函数会进去
step {count}单步多少次
next单步跳过,碰到函数不会进入
next {count}单步多少次
CTRL+C发送 SIGINT 信号,中止当前运行的程序
attach {process-id}链接上当前正在运行的进程,开始调试
detach断开进程链接
finish结束当前函数的运行
until持续执行直到代码行号大于当前行号(跳出循环)
until {line}持续执行直到执行到某行
kill杀死当前运行的函数

栈帧

命令含义备注
bt打印 backtrace
frame显示当前运行的栈帧
up向上移动栈帧(向着 main 函数)
down向下移动栈帧(远离 main 函数)
info locals打印帧内的相关变量
info args打印函数的参数

代码浏览

命令含义备注
list 101显示第 101 行周围 10行代码
list 1,10显示 1 到 10 行代码
list main显示函数周围代码
list basic.c:main显示另外一个源代码文件的函数周围代码
list -重复之前 10 行代码
list *0x22e4显示特定地址的代码
cd dir切换当前目录
pwd显示当前目录
search {regexpr}向前进行正则搜索
reverse-search {regexp}向后进行正则搜索
dir {dirname}增加源代码搜索路径
dir复位源代码搜索路径(清空)
show directories显示源代码路径

浏览数据

命令含义备注
print {expression}打印表达式,并且增加到打印历史
print /x {expression}十六进制输出,print 可以简写为 p
print array[i]@count打印数组范围
print $打印之前的变量
print *$->next打印 list
print $1输出打印历史里第一条
print ::gx将变量可视范围(scope)设置为全局
print 'basic.c'::gx打印某源代码里的全局变量,(gdb 4.6)
print /x &main打印函数地址
print /x 'A::B::C'打印不在当前 context 的函数地址好像没用
x *0x11223344显示给定地址的内存数据
x /nfu {address}打印内存数据,n是多少个,f是格式,u是单位大小
x /10xb *0x11223344按十六进制打印内存地址 0x11223344 处的十个字节
x/x &gx按十六进制打印变量 gx,x和斜杆后参数可以连写
x/4wx &main按十六进制打印位于 main 函数开头的四个 long
x/gf &gd1打印 double 类型
help x查看关于 x 命令的帮助
info locals打印本地局部变量
info functions {regexp}打印函数名称
info variables {regexp}打印全局变量名称
ptype name查看类型定义,比如 ptype FILE,查看 FILE 结构体定义
whatis {expression}查看表达式的类型
set var = {expression}变量赋值
display {expression}在单步指令后查看某表达式的值
undisplay删除单步后对某些值的监控
info display显示监视的表达式
show values查看记录到打印历史中的变量的值 (gdb 4.0)
info history查看打印历史的帮助 (gdb 3.5)

修改数据

命令含义备注
set {char}0x08048000=<value>按 char 大小修改内存地址这个大括号是命令里的,不代表它是个变量 ,同理可以修改 int 等
set $reg=<value>设置寄存器的值最通用的寄存器是 pc,所有架构都叫这个名字

文件操作

命令含义备注
file {object}加载新的可执行文件供调试
file放弃可执行和符号表信息
symbol-file {object}仅加载符号表
exec-file {object}指定用于调试的可执行文件(非符号表)
core-file {core}加载 core 用于分析

信号控制

命令含义备注
info signals打印信号设置
handle {signo} {actions}设置信号的调试行为
handle INT print信号发生时打印信息
handle INT noprint信号发生时不打印信息
handle INT stop信号发生时中止被调试程序
handle INT nostop信号发生时不中止被调试程序
handle INT pass调试器接获信号,不让程序知道
handle INT nopass调试起不接获信号
signal signo继续并将信号转移给程序
signal 0继续但不把信号给程序

线程调试

命令含义备注
info threads查看当前线程和 id
thread {id}切换当前调试线程为指定 id 的线程
break {line} thread {id}在 id 线程上下断点特定于线程的断点
break {line} thread all所有线程在指定行号处设置断点
thread apply {id..} cmd指定多个线程共同执行 gdb 命令
thread apply all cmd所有线程共同执行 gdb 命令
set schedule-locking ?调试一个线程时,其他线程是否执行
set non-stop on/off调试一个线程时,其他线程是否运行
set pagination on/off调试一个线程时,分页是否停止
set target-async on/off同步或者异步调试,是否等待线程中止的信息

进程调试

命令含义备注
info inferiors查看当前进程和 id
inferior {id}切换某个进程
kill inferior {id...}杀死某个进程注意这个 inferior 结构仍然存在,可以用 run 等命令再次执行它,如果想删除结构需要用 remove-inferior 命令。
detach inferior {id}detach 某个进程这个 inferior 仍然存在,可以再次用 run 等命令执行它,如果想删除结构需要用 remove-inferior 命令
remove-inferior {id...}删除某个进程如果 inferior 在运行,则不能删除 inferior,所以在删除以前需要先 kill 或者 detach 这个 inferior。
set detach-on-fork on/off设置当进程调用fork时gdb是否同时调试父子进程
set follow-fork-mode parent/child设置当进程调用fork时是否进入子进程
set print inferior-events on/off用来打开和关闭 inferior 状态的提示信息

汇编调试

命令含义备注
info registers打印普通寄存器
info all-registers打印所有寄存器
print/x $pc打印单个寄存器
stepi指令级别单步进入si
nexti指令级别单步跳过ni
display/i $pc监控寄存器(每条单步完以后会自动打印值)
x/x &gx十六进制打印变量
info line 22打印行号为 22 的内存地址信息
info line *0x2c4e打印给定内存地址对应的源代码和行号信息
disassemble {addr}对地址进行反汇编,比如 disassemble 0x2c4e

地址空间

命令含义备注
info proc mappings显示映射的内存区域仅 Unix 下可用
info files正在调试的目标和文件的名称
maintenance info sections列出可执行文件或 core 文件的 BFD(Binary File Descriptor)部分仅当前被调试文件的 BFD 部分
maintenance info target-sections列出 GDB 内部的 section table所有加载项的 section 都会被显示

其他命令

命令含义备注
show commands显示历史命令 (gdb 4.0)
info editing显示历史命令 (gdb 3.5)
ESC-CTRL-J切换到 Vi 命令行编辑模式
set history expansion on允许类 c-shell 的历史
break class::member在类成员处设置断点
list class:member显示类成员代码
ptype class查看类包含的成员/o可以看成员偏移,类似pahole
print *this查看 this 指针
define command ... end定义用户命令
<return>直接按回车执行上一条指令
shell {command} [args]执行 shell 命令
source {file}从文件加载 gdb 命令
quit退出 gdb

non-stop mode

开启方式为

set non-stop on

non-stop mode 一般搭配后台执行一起使用。

hook

可以定义用户命令,在某个命令前后执行其他命令

define hook-echo
echo <<<---
end

define hookpost-echo
echo --->>>\n
end

(gdb) echo Hello World
<<<---Hello World--->>>
(gdb)

参考 hellogcc/100-gdb-tips

加载脚本

gdb -x xxx.gdb

参考资料