GDB精简手册

获取到一份GDB的使用说明(作者署名个人信息753640,MSN: haoel@hotmail.com

出于查阅目的,稍做裁剪和章节调整


章1. GDB运行流程控制 -------------------------------------------------------------

  编译时 cc ,gcc 选型中加 -g 参数,目标代码中会有函数和地址的映射

I. gdb -d <program>;   

II, gdb <program> core;(core是程序非法执行后core dump后产生的文件) 

III. gdb <program> <PID>(ps进程ID。gdb会自动attach上去,detach来取消)

运行中任意时刻ctr+c,发出中断信号,可以进入gdb命令行状态

(gdb)r(run)//开始运行程序

(gdb)n(next)//单步跟踪

(gdb)s(step)//单步跟踪,会进入子函数调用 (gdb) set step-mode on/off   开启关闭单步跟踪模式:程序不会因为没有debug信息停住,便于查看机器码

(gdb)c(continue)  //继续执行

(gdb)finish//当前函数执行结束后打印出堆栈地址,返回值等

(gdb)u(until)//运行直到结束当前循环体

(gdb)si(stepi)//指令级单步跟踪

(gdb)ni(nexti)//指令级单步跟踪

(gdb)q(quit) //退出gdb


jump <linespec>//<linespce>可以是文件的行号;可以是file:line格式可以是+num这种偏移量格式

jump <address>//这里的<address>是代码行的内存地址

jump 命令最好是同一个函数中进行跳转,以为junmp不会改变当前的程序栈中的内容;

当你从一个函数跳到另一个函数时,当函数运行完返回时进行弹栈操作时必然会发生错误,可能结果还是非常奇怪的,甚至于产生程序Core Dump。

熟悉汇编的人都知道,程序运行时,有一个寄存器用于保存当前代码所在的内存地址。

所以,jump命令也就是改变了这个寄存器中的值。于是,你可以使用“set $pc”来更改跳转执行的地址。如:

  set $pc = 0x485

return <expression>

return命令强制函数忽略还没有执行的语句并返回。如果指定了<expression>,那么该表达式的值会被认作函数的返回值。

call <expr> 强制调用函数,print后面可以跟函数表达式,所以也可以代替这个功能

运行前可以做的设置:

1、程序运行参数。set args 可指定运行时参数。(如:set args 10 20 30 40 50)show args 命令可以查看设置好的运行参数。

2、程序的输入输出。info terminal 显示你程序用到的终端的模式。使用重定向控制程序输出。如:run > outfile ;tty命令可以指写输入输出的终端设备。如:tty /dev/ttyb

3、运行环境。path <dir> 可设定程序的运行路径。show paths 查看程序的运行路径。

(gdb)set environment varname [=value] 设置环境变量。如:set env USER=hchen ;

(gdb)show environment [varname] 查看环境变量。

GDB的环境变量和UNIX一样,也是以$起头。如:set $foo = *object_ptr,GDB会在你第一次使用时创建这个变量,而在以后的使用中,则直接对其賦值。

环境变量没有类型,你可以给环境变量定义任一的类型。包括结构体和数组。

set $i = 0

print bar[$i++]->contents 

于是,当你就不必,print bar[0]->contents, printbar[1]->contents地输入命令了。

输入这样的命令后,只用敲回车,重复执行上一条语句,环境变量会自动累加,从而完成逐个输出的功能


章2. 断点 breakpoint -------------------------------------------------------------

断点设置方式

(gdb)b(break) function

(gdb)b filename:function//可能会有相同函数名,gdb会给出你选择项,c++多态情况,可以用function<type>的方法确定,或class:function的方法

(gdb)b filename:linenumber

(gdb)b +offset/-offset //在当前行号的前面或后面的offset行停住

        (gdb)b  addr if<condition>//addr 为上述某种断点位置,condition是需要满足的条件

i(info) b  列出所有断点

beakpoint 的编辑:

(gdb)d(delete) [breakpoints] [range...]      //breakpoints 可以是i b 命令列出的对应断点序号,range可以是比如3-7之间的所有断点

(gdb)clear //清除所有断点

(gdb)clear function / clear filename:function//删除某函数上的所有断点

(gdb) disable [breakpoints] [range...]//暂停断点

(gdb) enable [breakpoints] [range...]//使能断点

(gdb) enable [breakpoints] once range...//enable所指定的停止点一次,当程序停止后,该停止点马上被GDB自动disable

(gdb) enable [breakpoints] delete range...//enable所指定的停止点一次,当程序停止后,该停止点马上被GDB自动删除

还有一些附加的功能停止断点

...condition <bnum> <expression>//修改断点号为bnum的停止条件为expression。

...condition <bnum> //清除断点号为bnum的停止条件。

...ignore <bnum> <count>//表示忽略断点号为bnum的停止条件count次。

断点停止时,可以自动执行一些命令,这对于自动化测试时很关键的

//通式

commands [bnum]

... command-list ...

end

//举例

break foo if x>0

commands

printf "x is %d\n",x

continue

end


章3. 观察点 watchpoint -------------------------------------

观察某个表达式或值是否变化了,变化则停住程序

watch <expr> 表达式有变化,马上停止

rwatch <expr>表达式被读,停住程序

awatch <expr>表达式被读或者被写,停住程序

info watchpoints 列出错有观察点


章4.捕捉点 catchpoint -------------------------------------------------------------

--- 捕捉某一事件,载入共享库(动态链接库)或是C++的异常(不支持if)

catch <event>当event发生时,停住程序。event可以是下面的内容:

1、throw 一个C++抛出的异常。(throw为关键字)

2、catch 一个C++捕捉到的异常。(catch为关键字)

3、exec 调用系统调用exec时。(exec为关键字,目前此功能只在HP-UX下有用)

4、fork 调用系统调用fork时。(fork为关键字,目前此功能只在HP-UX下有用)

5、vfork 调用系统调用vfork时。(vfork为关键字,目前此功能只在HP-UX下有用)

6、load 或 load <libname> 载入共享库(动态链接库)时。(load为关键字,目前此功能只在HP-UX下有用)

7、unload 或 unload <libname> 卸载共享库(动态链接库)时。(unload为关键字,目前此功能只在HP-UX下有用)

  tcatch <event>            设置一次捕捉点,当程序停住以后,该点被自动删除。



章5. 信号 signal ----------------------------------------------------------------------------

使用singal命令,可以产生一个信号量给被调试的程序。

 single命令和shell的kill命令不同,系统的kill命令发信号给被调试程序时,是由GDB截获的,而single命令所发出一信号则是直接发给被调试程序的

  语法是:signal <singal>,UNIX的系统信号量通常从1到15。所以<singal>取值也在这个范围。

(gdb)handle <signal> <keywords...> 

(gdb)handle 13 nostop noprint//一般会在开始的时候设置

<signal>表示要处理信号范围,常见信号:

SIGINT表示中断字符信号,也就是Ctrl+C的信号;

SIGBUS表示硬件故障的信号

SIGCHLD表示子进程状态改变信号; SIGKILL表示终止程序运行的信号

<keywords>:nostop / stop / print / noprint / nopass / pass / noignore / ignore

stop表示要不要停止,print表示要不要显示,pass/ignore需不需要忽略

(gdb)info signals

(gdb)info handle查看哪些信号在被gdb中


章6. 线程 thread -  -------------------------------------------------------------

你可以定义你的全局性断点在哪些线程中起作用

(gdb) break <linespec> thread <threadno>

(gdb) break <linespec> thread <threadno>if ...

< linespec> 指定了断点设置在的源程序的行号。

<threadno> 指定了线程的ID,注意,这个ID是GDB分配的,你可以通过“info threads命令来查看正在运行程序中的线程信息。

如果你不指定thread<threadno>则表示你的断点设在所有线程上面。你还可以为某线程指定断点条件。如:

  (gdb) break frik.c:13 thread 28 if bartab > lim


章7. 查看运行数据-------------------------------------------------------------

gdb)bt(backtrace) 查看堆栈信息

(gdb)bt n//只打印栈顶n层

(gdb)bt -n//打印栈底n层

默认你都是出于栈顶的,但是你可以切换当前栈

(gdb)f(frame) <n>//切到第几层栈

(gdb)up<n>//向上移动栈

(gdb)down<n>//向下移动栈

上面的命令,都会打印出移动到的栈层的信息,你可以使用这三个命令:

(gdb) select-frame <n> 对应于 frame 命令。

(gdb) up-silently <n> 对应于 up 命令。

(gdb) down-silently <n> 对应于 down 命令。

(gdb)info f(frame)//详细的当前栈信息,包括函数地址,局部变量等

(gdb)info args//只打印当前的局部变量

(gdb)info catch//打印当前函数中的异常处理信息

显示源代码内存

(gdb)info line命令来查看源代码在内存中的地址; info line后面可以跟“行号”,“函数名”,“文件名:行号”,“文件名:函数名”

(gdb)disassemble func查看函数func的汇编代码; disassemble 查看源程序的当前执行时的机器码,这个命令会把目前内存中的指令dump出来

查看当前运行栈中的数据

(gdb)p(print) /<f> <expr>//<f>是显示的格式 /x /a是16进制,/d 十进制,/u 十六进制无符号 ,/o 八进制,/t 二进制 ,/c 字符格式,/f 浮点格式

可以查看一些变量,全局变量,局部变量; 但是有时候可能某些变量可能被编译优化掉,编译参数“-gstabs”可以解决类似问题

(gdb)p file::variable

(gdb)p function::variable

(gdb) p *array@len

x( examine)命令 查看内存

x /<n/f/u> <addr> n 是一个正整数,表示显示内存的长度;

f 表示显示的格式,参见上面。

u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4 个bytes。

u参数可以用下面的字符来代替,b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,

GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。
<addr>表示一个内存地址

display 自动显示变量

(gdb)display/<fmt> <addr>

(gdb)display/i $pc$pc是GDB的环境变量,表示着指令的地址,/i则表示输出格式为机器指令码,也就是汇编。

于是当程序停下后,就会出现源代码和机器指令码相对应的情形,这是一个很有意思的功能

(gdb)undisplay <dnums...>

(gdb)delete display<dnums...>

(gdb)disable display<dnums...>

(gdb)enable display <dnums...>

(gdb)info display

以上这些和break的使用就很类似了,不过多解释

可以设置一些显示选项

(gdb)set print address off//当程序显示函数信息时,GDB会显出函数的参数地址,默认打开

(gdb)set print addr off

(gdb)show print address//查看当前地址显示选项是否打开

(gdb)set print array on//设置数组显示每个元素占一行,默认关闭,显示元素逗号分隔

(gdb)set print array off

(gdb)show print array

(gdb)set print elements<number-of-elements>//指定数据显示的最大长度

(gdb)show print elements

(gdb)set print null-stop<on/off>//显示字符串结束符停止,默认打开,但是你可能想看看出错时字符串后面还有什么,那么关闭

(gdb)set print sevenbit-strings <on/off>//设置字符显示,是否按“\nnn”的格式显示 如“\065” (gdb)show print sevenbit-strings

一些对象的显示:

(gdb)set print pretty on//显示结构体时会比较漂亮(gdb)show print pretty查看GDB是如何显示结构体的

(gdb)set print union <on/off>//设置显示结构体时,是否显式其内的联合体数据

(gdb)set print object <on/off>//对象指针指向其派生类自动按照虚方法调用的规则显示输出;(gdb)show print object查看对象选项的设置

(gdb)set print static-members <on/off>//C++对象中是否显示其中的静态数据成员。默认是on;(gdb)show print static-members查看静态数据成员选项设置

(gdb)set print vtbl <on/off>//GDB用比较规整的格式来显示虚函数表。其默认是关闭的 (gdb)show print vtbl查看虚函数显示格式的选项

查看寄存器

寄存器中放置了程序运行时的数据,比如程序当前运行的指令地址(ip)程序的当前堆栈地址(sp)等等

你同样可以使用print命令来访问寄存器的情况,只需要在寄存器名字前加一个$符号就可以了如:p$eip

(gdb)info registers //查看寄存器的情况。(除了浮点寄存器)

(gdb)info all-registers//查看所有寄存器的情况。(包括浮点寄存器)

(gdb)info registers <regname ...>//查看所指定的寄存器的情况

关键字冲突

(gdb) set width=47

Invalid syntax in expression

(gdb) set var width=47//width和gdb关键字冲突,则显示告诉gdb这是个应用程序的变量


print编号的访问编号:当你p 显示后,以$1, $2, $3 .....递增,那么当你回头再看这个变量时,就不需要用原来那么复杂的表达式了



章8. 显示源程序-------------------------------------------------------------

list

(gdb)l(list <linenum>)//显示程序第linenum行的周围的源程序

(gdb) list <function> //显示函数名为function的函数的源程序

(gdb) list + //显示当前行后面的源程序

(gdb) list - //显示当前行前面的源程序

(gdb) set listsize <count> //设置一次显示源代码的行数;默认:一般是打印当前行的上5行和下5行,如果显示函数是是上2行下8行,默认是10行

(gdb) show listsize //查看当前listsize的设置

(gdb) list <first>, <last>//显示从first行到last行之间的源代码, first 缺省的话,代表从当前行到last行之间

search 搜索源代码

(gdb) search <regexp>   

(gdb) forward-search <regexp> 向前面搜索。

(gdb) reverse-search <regexp> 全部搜索

其中,<regexp>就是正则表达式,也主一个字符串的匹配模式,关于正则表达式,请查阅相关资料。

dir 指定源文件路径,暂时没看到实际使用作用:

(gdb) dir(directory)<dirname ... >//加一个源文件路径到当前路径的前面,多个路径使用 ":" (windows是“; ”)

(gdb) directory//清除所有的自定义的源文件搜索路径信息

(gdb) show directories//显示定义了的源文件搜索路径


章9. 多语言支持-------------------------------------------------------------

GDB 支持下列语言:C, C++, Fortran, PASCAL, Java, Chill,assembly, 和Modula-2

GDB会根据你所调试的程序的语言,来设置自己的语言环境,并让GDB的命令跟着语言环境的改变而改变

例如C/C++中对指针的语法是*p,而在Modula-2中则是p^

下面是几个相关于GDB语言环境的命令:

show language 查看当前的语言环境。如果GDB不能识为你所调试的编程语言,那么,C语言被认为是默认的环境。

(gdb)info frame 查看当前函数的程序语言。

(gdb)info source 查看当前文件的程序语言。

(gdb)

set language

手动设置当前的程序语言,不跟参数则

查看GDB所支持的语言种类。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值