gdb 使用手册
一、启动gdb
- gdb program 调试程序
- gdb program corefile 调试程序产生的coredump文件
- gdb attach pid 调试正在运行的程序
二、常用操作
- continue(c) 继续执行直到下一个中断点或结束
- step(s) 单步跟踪,如果有函数调用,会进入该函数。进入函数的前提是,此函数被编译有debug信息。
- step(s) count 执行后面的count条指令,然后停住
- next(n) 单步跟踪,如果有函数调用,不会进入该函数
- next(n) count 执行后面的count条指令,然后停住
- set step-mode on 打开 step-mode 模式,于是,在进行单步跟踪时,程序不会因为没有 debug 信息而不停住。这个参数有很利于查看机器码。
- set step-mod off 关闭 step-mode 模式
- finish 运行程序,直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值等信息
- return [expression] 取消当前函数的执行,并立即返回,如果指定了expression,那么该表达式的值会被认作函数的返回值。
- until(u) 执行一行程序,若此时程序是在 for/while/do loop 循环的最后一行,则一直执行到循环结束后的第一行程序后停止。
- nexti 单步执行一条指令,会跟踪进入子程序内部,但不打印出子程序内部的语句
- stepi 单步执行一条指令,会跟踪进入子程序内部,会提示下面要运行语句的代码
- backtrace(bt) 打印当前的函数调用栈的所有信息
- backtrace(bt) n n 是一个正整数,表示只打印栈顶上 n 层的栈信息
- backtrace(bt) -n -n 是一个负整数,表示只打印栈底下 n 层的栈信息
- frame (f) n 切换当前栈,n 是一个从 0 开始的整数,是栈中的层编号
- up n 表示向栈的上面移动 n 层,可以不打 n,表示向上移动一层
- down n 表示向栈的下面移动 n 层,可以不打 n,表示向下移动一层
三、断点
断点设置为函数入口
- break function
- break class::function
- break function(type,type)
- break class::function(type,type)
断点设置为文件行号
- break linenum 在当前文件中指定行打断点
- break filename:linenum 在指定文件指定行号打断点
设置条件断点
- break args if cond args为函数或行号,cond为条件
- condition bnum expression 修改断点号为bnum的条件为expression
- condition bnum 清除断点号为bnum的条件
- ignore bnum count 忽略断点号为bnum的条件count次
临时断点,仅生效一次
- tbreak args
根据正则匹配断点
- rbreak regex
查看断点,n 表示断点号
- info break [n]
设置观察点,监视变量或内存是否变化
-
watch 整型变量
-
watch 指针变量,监视的是指针变量本身;
-
watch *指针变量,监视的是指针所指的内容;
-
watch 数组变量或内存区间;
-
rwatch expr 当表达式(变量)expr 被读时,停住程序。
-
awatch expr 当表达式(变量)的值被读或被写时,停住程序
-
info watchpoints 查看所有观察点
设置捕捉点
- catch event
- tcatch event 设置临时捕捉点
- info break 列出当前所有捕捉点
捕捉的事件可以是如下:
- throw 一个 C++抛出的异常。(throw 为关键字)
- catch 一个 C++捕捉到的异常。(catch 为关键字)
- exec 调用系统调用 exec 时。(exec 为关键字,目前此功能只在 HP-UX 下有用)
- fork 调用系统调用 fork 时。(fork 为关键字,目前此功能只在 HP-UX 下有用)
- vfork 调用系统调用 vfork 时。(vfork 为关键字,目前此功能只在 HP-UX 下有用)
-load 或 load 载入共享库(动态链接库)时。(load 为关键字,目前此功能只在 HP-UX
下有用) - unload 或 unload 卸载共享库(动态链接库)时。(unload 为关键字,目前此功能只在
HP-UX 下有用)
断点启停
- clear function
- clear class::function
- clear function(type,type)
- clear class::function(type,type)
- disable 断点编号,禁用某个断点,使得断点不会被触发;
- enable 断点编号,启用某个被禁用的断点;
- delete 断点编号,删除某个断点
设置断点停止后的动作
- commands [bnum] ...command list... end 设置断点停止时执行的命令
- commands [bnum] end 取消断点停止时执行的命令
四、打印
info
- info frame 打印出更为详细的当前栈层的信息,比如:函数地址,调用函数的地址,被调用函数的地址,目前的函数是由什么样的程序语言写成的、函数参数地址及值、局部变量的地址等等
- info args 打印出当前函数的参数名及其值
- info locals 打印出当前函数中所有局部变量及其值
- info catch 打印出当前的函数中的异常处理信息
- info line 查看源代码在内存中的地址,后面可以跟“行号”,“函数名”,“文件名:行号”,“文件名:函数名”
- info registers 查看寄存器的情况。(除了浮点寄存器)
- info all-registers 查看所有寄存器的情况。(包括浮点寄存器)
- info registers regname 查看所指定的寄存器的情况
- info frame 查看当前函数的程序语言
- info sourc 查看当前文件的程序语言
- info signals 查看有哪些信号在被 GDB 检测中
- info handle 查看有哪些信号在被 GDB 检测中
- info terminal 显示你程序用到的终端的模式
- info break [n] 查看断点,n 表示断点号
- info watchpoints 列出当前所设置了的所有观察点
- info threads 查看正在运行程序中的线程信息
- info display 查看 display 设置的自动显示的信息。GDB 会打出一张表格,向你报告当前调试中设置了多少个自动显示设置,其中包括,设置的编号,表达式,是否 enable
- info macro 查看这个宏在哪些文件里被引用了,以及宏定义是什么样的,需要在编译的时候加-ggdb3参数。
- info inferiors 显示GDB调试的所有inferior,其中带有*的进程是正在调试的inferior
print(p)
- p global_var 打印全局变量(所有文件可见的),其中global_var为全局变量名
- p file::variable 打印静态全局变量,当前文件可见的
- p function::variable 打印局部变量
- p *array@len 打印一段连续的内存空间的值,@的左边是数组的首地址的值,也就是变量 array 所指向的内容,右边则是数据的长度,其保存在变量 len 中
- p array print 数组名,可以显示静态数组中所有数据的内容了
- p/x var 按十六进制格式显示变量, 可以指定的输出格式如下:
x 按十六进制格式显示变量
d 按十进制格式显示变量
u 按十六进制格式显示无符号整型
o 按八进制格式显示变量
t 按二进制格式显示变量
a 按十六进制格式显示变量
c 按字符格式显示变量
f 按浮点数格式显示变量
当用 GDB 的 print 查看程序运行时的数据时,每一个 print 都会被 GDB 记录下来。GDB会以$1, $2, $3 .....这样的方式为你每一个 print 命令编上号。
查看内存 examine(x)
-
x/nfu addr n、f、u 是可选的参数
n 是一个正整数,默认为 1,表示从 addr 开始显示内存的长度(按照units u 计数),也就是说从当前地址向后显示几个地址的内容
f 表示显示的格式,参见print。如果地址所指的是字符串,那么格式可以是 s,如果地址是指令地址,那么格式可以是 i。默认是'x'(十六进制)
u 表示从当前地址往后请求的字节数,如果不指定的话,GDB 默认是 w(4 个bytes)。u 参数可以用下面的字符来代替:
b (Bytes) 表示单字节
h (Halfwords) 表示双字节
w (Words) 表示四字节
g (Giant word)表示八字节当我们指定了字节长度后,GDB 会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。每次指定一个unit size,在你下一次使用 x 命令时这个 size 将变成默认的 unit。
自动显示 display
- display exp 程序停下后,自动显示表达式的值
- display/fmt expr 程序停下后,自动显示表达式的值, fmt表示显示的格式,见print
- display/fmt addr 程序停下后,自动显示内存地址的值, fmt表示显示的格式,见print
- display/i $pc 程序停下后,自动显示现源代码和机器指令码($pc 是 GDB 的环境变量,表示着指令的地址,i 则表示输出格式为机器指令码,也就是汇编。)
- undisplay dnums ... 删除自动显示,dnums 意为所设置好了的自动显式的编号。如果要同时删除几个,编号可以用空格分隔,如果要删除一个范围内的编号,可以用减号表示(如:2-5)
- delete display dnums ... 删除自动显示,同undisplay dnums
- disable display dnums ... 不删除自动显示的设置,而只是让其失效
- enable display dnums ... 恢复自动显示的设置
- info display 查看 display 设置的自动显示的信息
打印选项设置
- set print address 打开地址输出,当程序显示函数信息时,GDB 会显出函数的参数地址。系统默认为打开的
- set print address on 打开地址输出,同 set print address
- set print address off 关闭函数的参数地址显示
- show print address 查看当前地址显示选项是否打开
- set print array 打开数组显示,打开后当数组显示时,每个元素占一行,如果不打开的话,每个元素则以逗号分隔。这个选项默认是关闭的。
- set print array on 打开数组显示,同 set print array
- set print array off 关闭数组元素分行显示
- show print array 查看当前数组显示选项
- set print elements 主要是设置数组的, 指定数据显示的最大长度,当到达这个长度时,GDB 就不再往下显示了。如果设置为 0,则表示不限制
- show print elements 查看 print elements 的选项信息。
- set print null-stop 当显示字符串时,遇到结束符则停止显示。这个选项默认为off
- set print pretty on 打开 printf pretty 这个选项,美化结构体显示
- set print pretty off 关闭printf pretty 这个选项
- show print pretty 查看 GDB 是如何显示结构体的
- set print sevenbit-strings 设置字符显示,是否按“\nnn”的格式显示,如果打开,则字符串或字符数据按\nnn 显示,如“\065”
- show print sevenbit-strings 查看字符显示开关是否打开
- set print union 设置显示结构体时,是否显式其内的联合体数据
- show print union 查看联合体数据的显示方式
- set print object 在 C++中,如果一个对象指针指向其派生类,如果打开这个选项,GDB 会自动按照虚方法调用的规则显示输出,如果关闭这个选项的话,GDB 就不管虚函数表了。这个选项默认是off。
- show print object 查看对象选项的设置。
- set print static-members 这个选项表示,当显示一个 C++对象中的内容是,是否显示其中的静态数据成员。默认是on
- show print static-members 查看静态数据成员选项设置。
- set print vtbl 当此选项打开时,GDB 将用比较规整的格式来显示虚函数表时。其默认是关闭的。
- show print vtbl 查看虚函数显示格式的选项
五、查看源代码
显示源代码
- list linenum 显示程序第 linenum 行的周围的源程序
- list function 显示函数名为 function 的函数的源程序
- list 显示当前行后面的源程序
- list - 显示当前行前面的源程序(一般是打印当前行的上 5 行和下 5 行)
- set listsize count 设置一次显示源代码的行数
- show listsize 查看当前 listsize 的设置
- list first,last 显示从 first 行到 last 行之间的源代码
- list ,last 显示从当前行到 last 行之间的源代码
- list first, 显示从 first 行到当前行之间的源代码
- list <+offset> 显示从当前行号的正偏移量 周围的源代码
- list <-offset> 显示从当前行号的负偏移量 周围的源代码
- list <*address> 显示地址对应的代码行
搜索源代码
- forward-search (search) regexp 向前面搜索
- reverse-search regexp 全部搜索
指定源文件的路径
- directory (dir) dirname ... 指定源文件的路径(某些时候,用-g 编译过后的执行程序中只是包括了源文件的名字,没有路径名)
- directory 清除所有的自定义的源文件搜索路径信息
- show directories 显示定义了的源文件搜索路径
六、多线程
- break linespec thread threadno linespec 指定了断点设置在的源程序的行号。threadno 指定了线程的 ID。
- break linespec thread threadno if cond 为某线程指定断点条件
- info thread 查看当前调试程序启动了多少个线程,并打印出各个线程信息;
- thread(t) threadno 将该编号的线程切换为当前线程;
设置线程锁
- set scheduler-locking on 锁定线程,只有当前或指定线程可以运行;
- set scheduler-locking off 不锁定线程,会有线程切换;
- set scheduler-locking step 当单步执行某一线程时,其他线程不会执行,同时保证在调试过程中当前线程不会发生改变。但如果在该模式下执行 continue、until、finish 命令,则其他线程也会执行;
- show scheduler-locking 查看线程锁定状态;
- thread apply tid gdb_cmd 指定某线程执行某gdb命令;
- thread apply all gdb_cmd 全部的线程执行某gdb命令;
七、多进程
- set follow-fork-mode child 跟随子进程
- set follow-fork-mode parent 跟随父进程,默认行为
- set detach-on-fork on/off 调试进程时其他进程是否运行
- show follow-fork-mode 显示GDB跟踪的是父子哪个进程
- show detach-on-fork 显示调试时是否允许其他进程运行
- info inferiors 显示GDB调试的所有inferior,其中带有*的进程是正在调试的inferior
- inferior num 切换到ID是num的inferior进行调试
- remove-inferiors infno 删除一个infno号的inferior。如果inferior正在运行,则不能删除
- detach inferior infno detach掉infnum的inferior,注意(inferior仍然存在,可以用run等命令执行)
- kill inferior infno kill 掉infnum的inferior, 注意(inferior仍然存在,可以用run等命令执行)
- add-inferior[-copies n][-exec executable] 增加新的调试进程(可以用file+executable来分配给inferior可执行文件。+增加n个inferior并执行程序为executable。如果不指定n只增加一个inferior。如果不指定executable,则执行程序留空,增加后可使用file命令重新指定执行程序。这时候创建的inferior其关联的进程并没启动)
eg: add-inferior -copies 3 -exec /app/tmp/some
GDB将每一个被调试程序的执行状态记录在一个名为inferior的结构中。一般情况下一个inferior对应一个进程,每一个inferior都有自己的地址空间。inferior有时候会在进程没有启动时就存在。
八、环境变量
- set $foo = *object_ptr 设置环境变量值
- show convenience 查看当前所设置的所有的环境变量
九、信号
-
handle signal keywords
signal 参数表示要设定的目标信号,它通常为某个信号的全名(SIGINT)或者简称(去除‘SIG’后的部分,如 INT),可以用定义一个要处理信号的范围(如:SIGIO-SIGKILL,表示处理从 SIGIO 信号到 SIGKILL 的信号;如果要指定所有信号,可以用 all 表示
keywords 参数可以为以下:
nostop 当被调试的程序收到信号时,GDB 不会停住程序的运行,但会打出消息告诉你收到这种信号
stop 当被调试的程序收到信号时,GDB 会停住你的程序
print 当被调试的程序收到信号时,GDB 会显示出一条信息
noprint 当被调试的程序收到信号时,GDB 不会告诉你收到信号的信息
pass 当被调试的程序收到信号时,GDB 不处理信号。这表示,GDB 会把这个信号交给被调试程序
会处理
noignore 同pass
nopass 当被调试的程序收到信号时,GDB 不会让被调试程序来处理这个信号
ignore 同nopass -
info signals 查看有哪些信号在被 GDB 检测中
-
info handle 查看有哪些信号在被 GDB 检测中
-
signal <singal> 产生信号量(在希望发送信号的语句处设置断点,然后运行程序,当停止到断点所在位置后,用gdb的signal命令发送信号给调试目标程序)
十、其他
- print x=4 把变量 x 的值修改为 4
- set var width=47 使用 set var 命令来告诉 GDB,width 不是 GDB 的参数,而是程序的变
量名(可能有些情况,GDB 并不报告这种错误,所以保险起见,在你改变程序变量取值时,最好都使用 set var 格式的 GDB 命令) - show language 查看当前的语言环境
- set language 当 set language 命令后什么也不跟的话,可以查看 GDB 所支持的语言种类,在其后跟上被列出来的程序语言名,可设置当前的语言环境
- call expr 强制调用函数,并显示函数的返回值,如果函数返回值是 void,那么就不显示。表达式中可以一是函数
- jump 指定下一条语句的运行点。可以是文件的行号,可以是 file:line 格式,可以是+num 这种偏移量格式
- jump *address 修改程序的执行顺序, 下一条语句从address执行,address为代码行内存地址
- set $pc = 0x485 更改跳转执行的地址(等同jump,程序运行时,有一个寄存器用于保存当前代码所在的内存地址。所以,jump 命令也就是改变了这个寄存器中的值)
- disassemble func 查看源程序的当前执行时的机器码,这个命令会把目前内存中的指令 dump 出来
- macro 查看宏展开的样子
注意: jump 命令不会改变当前的程序栈中的内容,所以,当你从一个函数跳到另一个函数时,当函数运行完返回时进行弹栈操作时必然会发生错误,可能结果还是非常奇怪的,甚至于产生程序 Core Dump。所以最好是同一个函数中进行跳转。
本文来自博客园,作者:流翎,转载请注明原文链接:https://www.cnblogs.com/hjx168/p/17399648.html