摘自 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 == 20 | 2号断点只有在 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
参考资料