获取到一份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所支持的语言种类。