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。所以最好是同一个函数中进行跳转。

posted @ 2023-05-14 17:11  流翎  阅读(547)  评论(0编辑  收藏  举报