GDB
本笔记基于陈皓大神的笔记
启动GDB
调试程序
gdb <program>
调试core
gdb <program> core
调试运行中的进程
gdb <program> <PID>
gdb attach <PID>
启动时常用参数
-s/-symbols <file>
:指定符号表-se file
:指定文件中读取符号表信息-directory\-d <directory>
:加入一个源文件的搜索路径,默认搜索路径是环境变量中PATH所定义的路径。-core/-c <file>
:调试时core dump的core文件
启动时常用指令
程序运行参数
1 | set args #可指定运行时参数。(如:set args 10 20 30 40 50) |
设置运行环境
1 | path <dir> #可设定程序的运行路径。 |
设置工作目录
1 | cd <dir> #相当于shell的cd命令。 |
程序的输入输出
1 | info terminal #显示你程序用到的终端的模式。 |
运行shell命令
shell <command string>
可以在gdb中直接make,rebuild 程序
make <make-args>
= shell make <make-args>
暂停/恢复
设置断点
函数
break <function>/<filename:function>
c++中可以使用class::function或function(type,type)格式来指定函数名。
行号
break <linenum>/<filename:linenum>
内存:
break *address
在程序运行的内存地址处停住
条件
break ... if <condition>
…可以是上述的参数,condition表示条件
打印断点
info breakpoints/break [n]
设置观察点
观察某个表达式(变量也是一种表达式)的值是否有变化了
expr值有变化时,马上停住程序
watch <expr>
expr被读时,停住程序
rwatch <expr>
expr被读或被写时,停住程序
awatch <expr>
打印观察点
info watchpoints
设置捕获事件
捕捉程序运行时的一些事件
格式
catch <event>
tcatch <event>
:设置捕捉点,当停住后自动删除。
事件
- throw :C++抛出的异常
- catch:C++捕捉到的异常
- exec/fork/vfork:exec/fork/vfork被调用
- load/unload:载入/卸载动态库
维护停止点与停止条件
clear
:清除所有的停止点clear <function>/<filename:function>
: 清除该函数上所有的停止点clear <linenum>/<filename:linenum>
:清除该行上所有的停止点delete/disable/enable [breakpoints] [range...]
:删除/禁用/使能指定断点condition <bnum> <expression>
:修改断点停止条件,bnum—断点号condition <bnum>
:删除断点停止条件ignore <bnum> <count>
:忽略断点的停止条件count次
恢复运行与单步调试
继续:
continue/fg [ignore-count]
ignore-count:跳过断点次数
逐语句:
step <count>
逐过程:
next <count>
step-mode模式:
set step-mode on/off
单步跟踪时,程序不会因为没有debug信息而不停住
离开当前函数:
finish
离开当前循环体:
until/u
单步一条机器指令:
stepi/si/nexti/ni
运行:
run/r
信号
指令
handle <signal> <keywords...>
keywords
- nostop:不停止运行,但会打印信息
- stop:停止运行。
- print:打印信息
- noprint:不打印信息
- pass/noignore:信号下发给程序
- nopass/ignore:信号不下发给程序
查看有哪些信号在被GDB检测
info signals/handle
多线程调试
当你的程序被GDB停住时,所有的运行线程都会被停住
查看线程
info threads
切换线程
thread <ID>
特定线程打断点
break <linespec> thread <threadno> [if ...]
控制其他线程
set scheduler-locking off|on|step
- off:不锁定任何线程,也就是所有线程都执行,这是默认值。
- on:只有当前被调试程序会执行。
- step:在单步的时候,除了next过一个函数的情况以外,只有当前线程会执行。
查看信息
查看栈信息
- 栈的所有信息
bt
:调用栈的所有信息bt <n>
:打印栈顶上n层的栈信息bt <-n>
:打印栈底下n层的栈信息
- 切换当前栈
- 默认当前层:栈顶层
f <n>
:切换至第n层up/down <n>
:向上/下面移动n层,可以不打n,表示向上/下移动一层
- 信息打印
info f
:当前栈层的详情info args
:入参及其值info locals
:所有局部变量及其值。
查看源程序
显示源代码
list <linenum>/<function>/<first>, <last>/ , <last>/<+|-offset>
:显示周围代码/函数代码/行区域代码/向前|后便宜set listsize <count>
:设置一次显示源代码的行数
搜索源代码
- 向前搜索:
forward-search/search <regexp>
,regexp为正则表达式 - 全部搜索:
reverse-search <regexp>
源文件路径
设置路径
directory <dirname ... >
dir <dirname ... >
清除路径
directory
显示路径
show directories
源代码的内存
查看源码在内存中的地址
info line <function>/<filename:function>/<linenum>/<filename:linenum>
查看函数的汇编代码
disassemble <function>/<filename:function>
查看变量
指令格式
命令
print <expr>
print /<f> <expr>
:f 输出格式操作符
@
:是一个和数组有关的操作符::
:指定一个在文件或是一个函数中的变量。{<type>} <addr>
:表示一个指向内存地址\的类型为type的一个对象。
数组
p *array@len
输出格式
- x:按十六进制格式显示变量
- d:按十进制格式显示变量
- u:按十六进制格式显示无符号整型
- o:按八进制格式显示变量
- t:按二进制格式显示变量
- a:按十六进制格式显示变量
- c:按字符格式显示变量
f:按浮点数格式显示变量
查看内存
指令
examine 简写 x
x/<n/f/u> <addr>
例子:
x/3uh 0x54320
参数
- n:表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容
- f:表示显示的格式,参上
- u:表示数据宽度,默认是4B。u参数可以用下面的字符来代替
- b表示单字节
- h表示双字节
- w表示四字节
- g表示八字节
自动显示
设置自动显示的变量,当程序停住时,或单步时,这些变量会自动显示
display <expr>
/display/<fmt> <expr>
/display/<fmt> <addr>
undisplay/delete <dnums...>
:删除自动显示disable/enable display <dnums...>
:禁用/使能自动显示info display
:展示自动显示表
打印的历史记录
每一个print都会被GDB记录下来。GDB会以$1, $2, $3 …..这样的方式为你每一个print命令编上号。于是,你可以使用这个编号访问以前的表达式,如$1
定义环境变量
和shell一样使用$
- 定义:
set $i = 0
- 显示:
show convenience
- 使用:
$i
显示选项
略,个人觉得默认的挺好用的
查看寄存器
略,目前从事服务器开发,不大可能接触。
改变程序的执行
修改变量值
print x=4
跳转执行
jump <linespec>
\
:文件的行号,可以是file:line格式,可以是+num这种偏移量格式 jump <address>
\
:代码行的内存地址注意事项:jump不会改变当前的程序栈中的内容,所以,当你从一个函数跳到另一个函数时,当函数运行完返回时进行弹栈时必然会发生错误,所以最好是同一个函数中进行跳转。
产生信号量
signal <singal>
\
:UNIX的系统信号量通常从1到15。所以\ 取值也在这个范围 - single命令和shell的kill命令不同,系统的kill命令发信号给被调试程序时,是由GDB截获的,而single命令所发出一信号则是直接发给被调试程序的
强制函数返回
return
return <expression>
强制调用函数
call <expr>
设置生成dump
Windows
SetUnhandledExceptionFilter()
:崩溃时触发的回调函数- 使用dbghelp.lib的
MiniDumpWriteDump()
,生成dump文件 - 使用在VS工程中,打开dmp文件
- 使用仅限本机经
1 |
|
Linux
如果无目录名,则core生成在命令运行目录
core 文件大小
ulimit -c unlimited
要永久生效需要,加到shell初始化文件 /etc/profile 中
unlimited
:不限制、0: 关闭单位block,默认值1KB,查看
stat -fc %s .
core 文件路径
查看:
cat /proc/sys/kernel/core_pattern
临时设置:
echo '%e.core.%p' > /proc/sys/kernel/core_pattern
永久设置:
sysctl -w kernel.core_pattern=%e.core.%p
路径参数
未设置绝对路径,默认使用进程所在目录
当core_uses_pid=1时,若core_pattern无设置%p
,则会自动在末尾跟上
关闭core_uses_pid:sysctl -w kernel.core_uses_pid=0
- %p:进程id
- %u:用户id
- %g:用户组id
- %s:导致产生core的信号
- %t:core文件生成时的unix时间
- %h:主机名
- %e:进程名
GDB 指令缩写
缩写 | 原义 | 意义 |
---|---|---|
b | break | 打断点 |
c | continue | 继续 |
d | delete | 删除断点 |
f | frame | 栈层跳转 |
i | info | 查看信息 |
j | jump | 程序跳转 |
l | list | 展示源码 |
n | next | 单步-过程 |
p | 打印与设置变量 | |
r | run | 运行 |
s | step | 单步-语句 |
u | until | 离开循环体 |
ni | nexti | 机器级单步 |
si | stepi | 机器级单步 |
bt | backtrace | 所有栈信息 |
wa | watch | 设置观察点 |
ig | ignore | 忽略断点 |
fin | finish | 离开函数 |