标签:style class blog c code tar
(1)gdb program ///最常用的用gdb启动程序,开始调试的方式
(2)gdb program
core ///用gdb查看core
dump文件,跟踪程序core的原因
(3)gdb program
pid ///用gdb调试已经开始运行的程序,指定pid即可
(1)启动GDB的时候,加上–args选项,然后把应用程序和其命令行参数带在后面,具体格式为:gdb –args
program args
(2)先按1中讲的方法启动GDB, 然后再执行run命令的时候,后面加上参数
(1)End-of-File(Ctrl+d)
(2)quit或者q
(1)shell command
args(也可以先执行shell命令,GDB会退出到当前shell,
执行完command后,然后在shell中执行exit命令,便可回到GDB)
(2)make make-args(等同于shell
make make-args)
(1)在GDB中执行help命令,可以得到如图1所示的帮助信息:
图1
GDB帮助菜单
由图1可以看出,GDB中的命令可以分为八类:别名(aliases)、断点(breakpoints)、数据(data)、文件(files)、内部(internals)、隐含(obscure)、运行(running)、栈(stack)、状态(status)、支持(support)、跟踪点(tracepoints)和用户自定义(user-defined)。
(2)help class-name:查看该类型的命令的详细帮助说明
(3)help
all:列出所有命令的详细说明
(4)help command:列出命令command的详细说明
(5)apropos word:列出与word这个词相关的命令的详细说明
(6)complete args:列出所有以args为前辍的命令
(1)info:用来获取和被调试的应用程序相关的信息
(2)show:用来获取GDB本身设置相关的一些信息
1. Breakpoint: 作用是让程序执行到某个特定的地方停止运行
a. break function:
在函数funtion入口处设置breakpoint
b. break +offset:
在程序当前停止的行向前offset行处设置breakpoint
c. break –offset:
在程序当前停止的行向衙offset行处设置breakpoint
d. break linenum:
在当前源文件的第linenum行处设置breakpoint
e. break filename:linenum:
在名为filename的源文件的第linenum行处设置breakpoint
f. break filename:function:
在名为filename的源文件中的function函数入口处设置breakpoint
g. break *address:
在程序的地址address处设置breakpoint
h. break … if cond:
…代表上面讲到的任意一个可能的参数,在某处设置一个breakpoint,
但且仅但cond为true时,程序停下来
i. tbreak args:
设置一个只停止一次的breakpoints, args与break命令的一样。这样的breakpoint当第一次停下来后,就会被自己删除
k. rbreak regex:
在所有符合正则表达式regex的函数处设置breakpoint
查看第n个breakpoints的相关信息,如果省略了n,则显示所有breakpoints的相关信息
是指设置在程序开始调试后加载的动态库中的位置处的breakpoints
a. set breakpoint pending
auto: GDB缺省设置,询问用户是否要设置pending breakpoint
b. set
breakpoint pending on: GDB当前不能识别的breakpoint自动成为pending breakpoint
c.
set breakpoint pending off:
GDB当前不能识别某个breakpoint时,直接报错
d. show breakpoint pending:
查看GDB关于pending breakpoint的设置的行为(auto, on, off)
a. clear: 清除当前stack
frame中下一条指令之后的所有breakpoints
b. clear function & clear filename:function:
清除函数function入口处的breakpoints
c. clear linenum & clear filename:linenum:
清除第linenum行处的breakpoints
d. delete [breakpoints]
[range…]:
删除由range指定的范围内的breakpoints,range范围是指breakpoint的序列号的范围
a. disable [breakpoints]
[range…]:
禁用由range指定的范围内的breakpoints
b. enable [breakpoints]
[range…]:
启用由range指定的范围内的breakpoints
c. enable [breakpoints] once [range…]:
只启用一次由range指定的范围内的breakpoints,等程序停下来后,自动设为禁用
d. enable [breakpoints] delete [range…]:
启用range指定的范围内的breakpoints,等程序停下来后,这些breakpoints自动被删除
a. 设置条件breakpoints可以通过break … if cond来设置,也可以通过condition bnum
expression来设置,在这里首先要通过(1)中介绍的命令设置好breakpoints,然后用condition命令来指定某breakpoint的条件,该breakpoint由bnum指定,条件由expression指定
b. condition bnum:
取消第bnum个breakpoint的条件
c. ignore bnum count:
第bnum个breakpoint跳过count次后开始生效
a. 格式:commands [bnum]
… command-list
…
end
b.
用途:指定程序在第bnum个breakpoint处停下来后,执行由command-list指定的命令串,如果没有指定bnum,则对最后一个breakpoint生效
c.
取消命令列表: commands [bnum]
end
d.
例子:
break foo if x>0
commands
silent
printf “x is
%d\n”,x
continue
end
上面的例子含义:当x>0时,在foo函数处停下来,然后打印出x的值,然后继续运行程序
2. Watchpoint: 它的作用是让程序在某个表达式的值发生变化的时候停止运行,达到‘监视’该表达式的目的
a. watch expr:
设置写watchpoint,当应用程序写expr,
修改其值时,程序停止运行
b. rwatch expr:
设置读watchpoint,当应用程序读表达式expr时,程序停止运行
c. awatch expr:
设置读写watchpoint, 当应用程序读或者写表达式expr时,程序都会停止运行
查看当前调试的程序中设置的watchpoints相关信息
3. Catchpoint: 的作用是让程序在发生某种事件的时候停止运行,比如C++中发生异常事件,加载动态库事件
a. catch event: 当事件event发生的时候,程序停止运行,这里event的取值有:
b. tcatch event: 设置只停一次的catchpoint,第一次生效后,该catchpoint被自动删除
本文是手把手教你玩转GDB的第三篇,主要内容是介绍一些在程序调试过程中最常用的GDB命令,废话不多话,开始今天的正题。
1.attach
process-id/detach
2.kill
3.多线程程序调试相关:
4.多进程程序调试相关(fork/vfork):
5.step & stepi
6.next & nexti
7.continue
[ignore-count] 唤醒程序,继续运行,至到遇到下一个断点,或者程序结束。如果指定ignore-count,那么程序在接下来的运行中,忽略ignore-count次断点。
8. finish
& return
9.信号的处理
a. stop和nostop: nostop表示当GDB收到指定的信号,不会应用停止程序的执行,只会打印出一条收到信号的消息,因此,nostop也暗含了下面的print;
而stop则表示,当GDB收到指定的信号,停止应用程序的执行。
b. print和noprint: print表示如果收到指定的信号,打印出一条信息; noprint与print表示相反的意思
c. pass和nopass:pass表示如果收到指定的信号,把该信号通知给应用程序; nopass表示与pass相反的意思
d. ignore和noignore: ignore与nopass同义,同理,noignore与pass同义
==================================================================
GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具,GDB主要可帮助工程师完成下面4个方面的功能:
不管是调试Linux内核空间的驱动还是调试用户空间的应用程序,掌握gdb的用法都是必须。而且,调试内核和调试应用程序时使用的gdb命令是完全相同的,下面以代码清单22.2的应用程序为例演示gdb调试器的用法。
使用命令gcc –g gdb_example.c –o gdb_example编译上述程序,得到包含调试信息的二进制文件example,执行gdb gdb_example命令进入调试状态:
在gdb中运行list命令(缩写l)可以列出代码,list的具体形式包括:
下面演示了使用gdb中的run(缩写r)、break(缩写b)、next(缩写n)命令控制程序的运行,并使用print(缩写p)命令打印程序中的变量sum的过程:
(gdb)break add Breakpoint1 at 0x80482f7: file gdb_example.c, line 3.(gdb) run Starting program:/driver_study/gdb_example Breakpoint1, add (a=48, b=85) at gdb_example.c:3 warning:Source file is more recent than executable.3 return a + b;(gdb)next4 }(gdb)next main () at gdb_example.c:2323 for(i =0; i <10; i++)(gdb)next25 sum[i]= add(array1[i], array2[i]);(gdb)print sum $1 ={133,0,0,0,0,0,0,0,0,0}
在gdb中,运行程序使用run命令。在程序运行前,我们可以设置如下4方面的工作环境:
set args 可指定运行时参数,如:set args 10 20 30 40 50;show args 命令可以查看设置好的运行参数。
path <dir> 可设定程序的运行路径;how paths可查看程序的运行路径;set environment varname [=value]用于设置环境变量,如set env USER=baohua;
show environment [varname]则用于查看环境变量。
cd <dir> 相当于shell的cd命令;pwd 显示当前所在的目录。
info terminal 用于显示程序用到的终端的模式;gdb中也可以使用重定向控制程序输出,如run > outfile;
tty命令可以指定输入输出的终端设备,如:tty /dev/ttyS1。
在gdb中用break命令来设置断点,设置断点的方法包括:
在进入指定函数时停住,C++中可以使用class::function或function(type, type)格式来指定函数名。
在指定行号停住。
在当前行号的前面或后面的offset行停住,offiset为自然数。
在源文件filename的linenum行处停住。
在源文件filename的function函数的入口处停住。
在程序运行的内存地址处停住。
break命令没有参数时,表示在下一条指令处停住。
“...”可以是上述的break <linenum>、break +offset / break –offset中的参数,condition表示条件,在条件成立时停住。比如在循环体中,可以设置break if i=100,表示当i为100时停住程序。
查看断点时,可使用info命令,如info breakpoints [n]、info break [n](n表示断点号)。
在调试过程中,next命令用于单步执行,类似VC++中的step
over。next的单步不会进入函数的内部,与next对应的step(缩写s)命令则在单步执行一个函数时,会进入其内部,类似VC++中的step
into。下面演示了step命令的执行情况,在23行的add()函数调用处执行step会进入其内部的“return
a+b;”语句:
单步执行的更复杂用法包括:
单步跟踪,如果有函数调用,则进入该函数(进入函数的前提是,此函数被编译有debug信息)。step后面不加count表示一条条地执行,加表示执行后面的count条指令,然后再停住。
单步跟踪,如果有函数调用,它不会进入该函数。同样地,next后面不加count表示一条条地执行,加表示执行后面的count条指令,然后再停住。
set step-mode on用于打开step-mode模式,这样,在进行单步跟踪时,程序不会因为没有debug信息而不停住,这个参数的设置可便于查看机器码。set step-mod off用于关闭step-mode模式。
运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。
一直在循环体内执行单步,退不出来是一件令人烦恼的事情,until命令可以运行程序直到退出循环体。
stepi和nexti用于单步跟踪一条机器指令,一条程序代码有可能由数条机器指令完成,stepi和nexti可以单步执行机器指令。 另外,运行“display/i $pc”命令后,单步跟踪会在打出程序代码的同时打出机器指令,即汇编代码。
当程序被停住后,可以使用continue命令(缩写c,fg命令同continue命令)恢复程序的运行直到程序结束,或到达下一个断点,命令格式为:
ignore-count表示忽略其后多少次断点。
假设我们设置了函数断点add(),并watch
i,则在continue过程中,每次遇到add()函数或i发生变化,程序就会停住,如:
在调试程序时,当程序被停住时,可以使用print命令(缩写为p),或是同义命令inspect来查看当前程序的运行数据。print命令的格式是:
<expr>是表达式,是被调试的程序中的表达式,<f>是输出的格式,比如,如果要把表达式按16进制的格式输出,那么就是/x。在表达式中,有几种GDB所支持的操作符,它们可以用在任何一种语言中,“@”是一个和数组有关的操作符,“::”指定一个在文件或是函数中的变量,“{<type>}
<addr>”表示一个指向内存地址<addr>的类型为type的一个对象。
下面演示了查看sum[]数组的值的过程:
当需要查看一段连续内存空间的值的时间,可以使用GDB的“@”操作符,“@”的左边是第一个内存地址,“@”的右边则是想查看内存的长度。例如如下动态申请的内存:
int*array =(int*) malloc (len *sizeof(int));
在GDB调试过程中这样显示出这个动态数组的值:
p *array@len
print的输出格式包括:
我们可用display命令设置一些自动显示的变量,当程序停住时,或是单步跟踪时,这些变量会自动显示。 如果要修改变量,如x的值,可使用如下命令:
print x=4
当用GDB的print查看程序运行时的数据时,每一个print都会被GDB记录下来。GDB会以$1,$2,$3 …这样的方式为每一个print命令编号。我们可以使用这个编号访问以前的表达式,如$1。
watch一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序。我们有下面的几种方法来设置观察点: watch <expr>:为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序。rwatch <expr>:当表达式(变量)expr被读时,停住程序。awatch <expr>:当表达式(变量)的值被读或被写时,停住程序。info watchpoints:列出当前所设置了的所有观察点。 下面演示了观察i并在连续运行next时一旦发现i变化,i值就会显示出来的过程:
我们可以使用examine命令(缩写为x)来查看内存地址中的值。examine命令的语法如下所示:
x/<n/f/u><addr>
<addr>表示一个内存地址。“x/”后的n、f、u都是可选的参数,n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容;f 表示显示的格式,如果地址所指的是字符串,那么格式可以是s,如果地址是指令地址,那么格式可以是i;u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4字节。u参数可以被一些字符代替:b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,GDB会从指定的内存地址开始,读写指定字节,并把其当作一个值取出来。n、f、u这3个参数可以一起使用,例如命令“x/3uh 0x54320”表示从内存地址0x54320开始以双字节为1个单位(h)、16进制方式(u)显示3个单位(3)的内存。 ==
譬如下面的例子:
我们在
下一行设置断点后:
可以通过多种方式看C指向的字符串:
方法1:
方法2:
方法3:
将第一个字符改为大写:
再看看C:
修改寄存器:
修改内存:
譬如对于第8节的例子:
一般来说,被调试程序会按照程序代码的运行顺序依次执行,但是GDB也提供了乱序执行的功能,也就是说,GDB可以修改程序的执行顺序,从而让程序随意跳跃。这个功能可以由GDB的jump命令:jump <linespec> 来指定下一条语句的运行点。<linespec>可以是文件的行号,可以是file:line格式,也可以是+num这种偏移量格式,表示下一条运行语句从哪里开始。jump <address> 这里的<address>是代码行的内存地址。 注意,jump命令不会改变当前的程序栈中的内容,所以,如果使用jump从一个函数跳转到另一个函数,当跳转到的函数运行完返回,进行出栈操作时必然会发生错误,这可能导致意想不到的结果,所以最好只用jump在同一个函数中进行跳转。
使用singal命令,可以产生一个信号量给被调试的程序,如中断信号“Ctrl+C”。这非常方便于程序的调试,可以在程序运行的任意位置设置断点,并在该断点用GDB产生一个信号量,这种精确地在某处产生信号的方法非常有利于程序的调试。 signal命令的语法是:signal <signal>,UNIX的系统信号量通常从1到15,所以<signal>取值也在这个范围。
如果在函数中设置了调试断点,在断点后还有语句没有执行完,这时候我们可以使用return命令强制函数忽略还没有执行的语句并返回。
上述return命令用于取消当前函数的执行,并立即返回,如果指定了<expression>,那么该表达式的值会被作为函数的返回值。
call命令用于强制调用某函数: call <expr> 表达式中可以一是函数,以此达到强制调用函数的目的,它会显示函数的返回值(如果函数返回值不是void)。 其实,前面介绍的print命令也可以完成强制调用函数的功能。
info命令可以在调试时用来查看寄存器、断点、观察点和信号等信息。要查看寄存器的值,可以使用如下命令: info registers (查看除了浮点寄存器以外的寄存器)info all-registers (查看所有寄存器,包括浮点寄存器)info registers <regname ...> (查看所指定的寄存器) 要查看断点信息,可以使用如下命令:info break 列出当前所设置的所有观察点,使用如下命令:info watchpoints 查看有哪些信号正在被GDB检测,使用如下命令:info signals info handle 也可以使用info line命令来查看源代码在内存中的地址。info threads可以看多线程。info line后面可以跟行号、函数名、文件名:行号、文件名:函数名等多种形式,例如下面的命令会打印出所指定的源码在运行时的内存地址:
off 不锁定任何线程,也就是所有线程都执行,这是默认值。
on 只有当前被调试程序会执行。
step
在单步的时候,除了next过一个函数的情况以外,只有当前线程会执行。
与多线程调试相关的命令还包括:
thread ID
切换当前调试的线程为指定ID的线程。
break
thread_test.c:123 thread all
在所有线程中相应的行上设置断点
thread apply ID1
ID2 command
让一个或者多个线程执行GDB命令command。
thread apply
all command
让所有被调试线程执行GDB命令command。
disassemble命令用于反汇编,它可被用来查看当前执行时的源代码的机器码,其实际上只是把目前内存中的指令dump出来。下面的示例用于查看函数func的汇编代码:
标签:style class blog c code tar
原文地址:http://www.cnblogs.com/wliangde/p/3736868.html