GDB.docx
《GDB.docx》由会员分享,可在线阅读,更多相关《GDB.docx(51页珍藏版)》请在冰豆网上搜索。
![GDB.docx](https://file1.bdocx.com/fileroot1/2023-2/2/64bc3054-c208-41cd-859f-ee61e02441ce/64bc3054-c208-41cd-859f-ee61e02441ce1.gif)
GDB
简述
一列文件清单
二:
执行程序
三:
显示数据
四:
断点(breakpoint)
五.断点的管理
六.变量的检查和赋值
七.单步执行
八.函数的调用
九.机器语言工具
十.信号
GDB的使用方法
简述
一列文件清单
∙List
∙(gdb)listline1,line2
二:
执行程序
要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(<和>)和外壳通配符(*、?
、[、])在内。
如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的。
利用setargs命令就可以修改发送给程序的参数,而使用showargs命令就可以查看其缺省参数的列表。
(gdb)setargs–b–x
(gdb)showargs
backtrace命令为堆栈提供向后跟踪功能。
Backtrace命令产生一张列表,包含着从最近的过程开始的所以有效过程和调用这些过程的参数。
三:
显示数据
∙利用print命令可以检查各个变量的值。
∙(gdb)printp(p为变量名)
print是gdb的一个功能很强的命令,利用它可以显示被调试的语言中任何有效的表达式。
表达式除了包含你程序中的变量外,还可以包含以下内容:
1.对程序中函数的调用
2.(gdb)printfind_entry(1,0)
3.数据结构和其他复杂对象
4.(gdb)print*table_start
5.$8={e=reference=’\000’,location=0x0,next=0x0}
6.值的历史成分
7.(gdb)print$1($1为历史记录变量,在以后可以直接引用$1的值)
8.人为数组
人为数组提供了一种去显示存储器块(数组节或动态分配的存储区)内容的方法。
早期的调试程序没有很好的方法将任意的指针换成一个数组。
就像对待参数一样,让我们查看内存中在变量h后面的10个整数,一个动态数组的语法如下所示:
base@length
因此,要想显示在h后面的10个元素,可以使用h@10:
9.(gdb)printh@10
10.$13=(-1,345,23,-234,0,0,0,98,345,10)
∙whatis命令可以显示某个变量的类型
∙(gdb)whatisp
∙type=int*
四:
断点(breakpoint)
break命令(可以简写为b)可以用来在调试的程序中设置断点,该命令有如下四种形式:
∙breakline-number使程序恰好在执行给定行之前停止。
∙breakfunction-name使程序恰好在进入指定的函数之前停止。
∙breakline-or-functionifcondition如果condition(条件)是真,程序到达指定行或函数时停止。
∙breakroutine-name在指定例程的入口处设置断点
如果该程序是由很多原文件构成的,你可以在各个原文件中设置断点,而不是在当前的原文件中设置断点,其方法如下:
(gdb)breakfilename:
line-number
(gdb)breakfilename:
function-name
要想设置一个条件断点,可以利用breakif命令,如下所示:
(gdb)breakline-or-functionifexpr
例:
(gdb)break46iftestsize==100
从断点继续运行:
countinue命令
五.断点的管理
1.显示当前gdb的断点信息:
(gdb)infobreak
他会以如下的形式显示所有的断点信息:
NumTypeDispEnbAddressWhat
1breakpointkeepy0x000028bcininit_randomatqsort2.c:
155
2breakpointkeepy0x0000291cininit_organatqsort2.c:
168
1.删除指定的某个断点:
2.(gdb)deletebreakpoint1
该命令将会删除编号为1的断点,如果不带编号参数,将删除所有的断点
(gdb)deletebreakpoint
3.禁止使用某个断点
4.(gdb)disablebreakpoint1
该命令将禁止断点1,同时断点信息的(Enb)域将变为n
5.允许使用某个断点
6.(gdb)enablebreakpoint1
该命令将允许断点1,同时断点信息的(Enb)域将变为y
7.清除原文件中某一代码行上的所有断点
8.(gdb)cleannumber
注:
number为原文件的某个代码行的行号
六.变量的检查和赋值
∙whatis:
识别数组或变量的类型
∙ptype:
比whatis的功能更强,他可以提供一个结构的定义
∙setvariable:
将值赋予变量
∙print除了显示一个变量的值外,还可以用来赋值
七.单步执行
∙next不进入的单步执行
∙step进入的单步执行如果已经进入了某函数,而想退出该函数返回到它的调用函数中,可使用命令finish
八.函数的调用
∙callname调用和执行一个函数
∙(gdb)callgen_and_sork(1234,1,0)
∙(gdb)callprintf(“abcd”)
∙$1=4
∙finish结束执行当前函数,显示其返回值(如果有的话)
九.机器语言工具
有一组专用的gdb变量可以用来检查和修改计算机的通用寄存器,gdb提供了目前每一台计算机中实际使用的4个寄存器的标准名字:
∙$pc:
程序计数器
∙$fp:
帧指针(当前堆栈帧)
∙$sp:
栈指针
∙$ps:
处理器状态
十.信号
gdb通常可以捕捉到发送给它的大多数信号,通过捕捉信号,它就可决定对于正在运行的进程要做些什么工作。
例如,按CTRL-C将中断信号发送给gdb,通常就会终止gdb。
但是你或许不想中断gdb,真正的目的是要中断gdb正在运行的程序,因此,gdb要抓住该信号并停止它正在运行的程序,这样就可以执行某些调试操作。
Handle命令可控制信号的处理,他有两个参数,一个是信号名,另一个是接受到信号时该作什么。
几种可能的参数是:
∙nostop接收到信号时,不要将它发送给程序,也不要停止程序。
∙stop接受到信号时停止程序的执行,从而允许程序调试;显示一条表示已接受到信号的消息(禁止使用消息除外)
∙print接受到信号时显示一条消息
∙noprint接受到信号时不要显示消息(而且隐含着不停止程序运行)
∙pass将信号发送给程序,从而允许你的程序去处理它、停止运行或采取别的动作。
∙nopass停止程序运行,但不要将信号发送给程序。
例如,假定你截获SIGPIPE信号,以防止正在调试的程序接受到该信号,而且只要该信号一到达,就要求该程序停止,并通知你。
要完成这一任务,可利用如下命令:
(gdb)handleSIGPIPEstopprint
请注意,UNIX的信号名总是采用大写字母!
你可以用信号编号替代信号名如果你的程序要执行任何信号处理操作,就需要能够测试其信号处理程序,为此,就需要一种能将信号发送给程序的简便方法,这就是signal命令的任务。
该命令的参数是一个数字或者一个名字,如SIGINT。
假定你的程序已将一个专用的SIGINT(键盘输入,或CTRL-C;信号2)信号处理程序设置成采取某个清理动作,要想测试该信号处理程序,你可以设置一个断点并使用如下命令:
(gdb)signal2
continuingwithsignalSIGINT
(2)
该程序继续执行,但是立即传输该信号,而且处理程序开始运行.
GDB的使用方法
GDB是一个强大的命令行调试工具。
大家知道命令行的强大就是在于,其可以形成
执行序列,形成脚本。
UNIX下的软件全是命令行的,这给程序开发提代供了极大的
便利,命令行软件的优势在于,它们可以非常容易的集成在一起,使用几个简单的已
有工具的命令,就可以做出一个非常强大的功能。
于是UNIX下的软件比Windows下的软件更能有机地结合,各自发挥各自的长处,组合
成更为强劲的功能。
而Windows下的图形软件基本上是各自为营,互相不能调用,很
不利于各种软件的相互集成。
在这里并不是要和Windows做个什么比较,所谓“寸有
所长,尺有所短”,图形化工具还是有不如命令行的地方。
用GDB调试程序
GDB概述
————
GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。
或许,各位比较喜欢
那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在UNIX平台下做软件,你
会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。
所谓“寸有所
长,尺有所短”就是这个道理。
一般来说,GDB主要帮忙你完成下面四个方面的功能:
1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。
(断点可以是条件表达式)
3、当程序被停住时,可以检查此时你的程序中所发生的事。
4、动态的改变你程序的执行环境。
从上面看来,GDB和一般的调试工具没有什么两样,基本上也是完成这些功能,不过
在细节上,你会发现GDB这个调试工具的强大,大家可能比较习惯了图形化的调试工
具,但有时候,命令行的调试工具却有着图形化工具所不能完成的功能。
让我们一
一看来。
一个调试示例
——————
源程序:
tst.c
1#include
2
3intfunc(intn)
4{
5intsum=0,i;
6for(i=0;i
7{
8sum+=i;
9}
10returnsum;
11}
12
13
14main()
15{
16inti;
17longresult=0;
18for(i=1;i<=100;i++)
19{
20result+=i;
21}
22
23printf("result[1-100]=%d\n",result);
24printf("result[1-250]=%d\n",func(250));
25}
编译生成执行文件:
(Linux下)
hchen/test>cc-gtst.c-otst
使用GDB调试:
hchen/test>gdbtst<----------启动GDB
GNUgdb5.1.1
Copyright2002FreeSoftwareFoundation,Inc.
GDBisfreesoftware,coveredbytheGNUGeneralPublicLicense,andyouare
welcometochangeitand/ordistributecopiesofitundercertainconditions.
Type"showcopying"toseetheconditions.
ThereisabsolutelynowarrantyforGDB.Type"showwarranty"fordetails.
ThisGDBwasconfiguredas"i386-suse-linux"...
(gdb)l<--------------------l命令相当于list,从第一行开始例出原码。
1#include
2
3intfunc(intn)
4{
5intsum=0,i;
6for(i=0;i
7{
8sum+=i;
9}
10returnsum;
(gdb)<--------------------直接回车表示,重复上一次命令
11}
12
13
14main()
15{
16inti;
17longresult=0;
18for(i=1;i<=100;i++)
19{
20result+=i;
(gdb)break16<--------------------设置断点,在源程序第16行处。
Breakpoint1at0x8048496:
filetst.c,line16.
(gdb)breakfunc<--------------------设置断点,在函数func()入口处。
Breakpoint2at0x8048456:
filetst.c,line5.
(gdb)infobreak<--------------------查看断点信息。
NumTypeDispEnbAddressWhat
1breakpointkeepy0x08048496inmainattst.c:
16
2breakpointkeepy0x08048456infuncattst.c:
5
(gdb)r<---------------------运行程序,run命令简写
Startingprogram:
/home/hchen/test/tst
Breakpoint1,main()attst.c:
17<----------在断点处停住。
17longresult=0;
(gdb)n<---------------------单条语句执行,next命令简写。
18for(i=1;i<=100;i++)
(gdb)n
20result+=i;
(gdb)n
18for(i=1;i<=100;i++)
(gdb)n
20result+=i;
(gdb)c<---------------------继续运行程序,continue命令简写。
Continuing.
result[1-100]=5050<----------程序输出。
Breakpoint2,func(n=250)attst.c:
5
5intsum=0,i;
(gdb)n
6for(i=1;i<=n;i++)
(gdb)pi<---------------------打印变量i的值,print命令简写。
$1=134513808
(gdb)n
8sum+=i;
(gdb)n
6for(i=1;i<=n;i++)
(gdb)psum
$2=1
(gdb)n
8sum+=i;
(gdb)pi
$3=2
(gdb)n
6for(i=1;i<=n;i++)
(gdb)psum
$4=3
(gdb)bt<---------------------查看函数堆栈。
#0func(n=250)attst.c:
5
#10x080484e4inmain()attst.c:
24
#20x400409edin__libc_start_main()from/lib/libc.so.6
(gdb)finish<---------------------退出函数。
Runtillexitfrom#0func(n=250)attst.c:
5
0x080484e4inmain()attst.c:
24
24printf("result[1-250]=%d\n",func(250));
Valuereturnedis$6=31375
(gdb)c<---------------------继续运行。
Continuing.
result[1-250]=31375<----------程序输出。
Programexitedwithcode027.<--------程序退出,调试结束。
(gdb)q<---------------------退出gdb。
hchen/test>
好了,有了以上的感性认识,还是让我们来系统地认识一下gdb吧。
使用GDB
————
一般来说GDB主要调试的是C/C++的程序。
要调试C/C++的程序,首先在编译时,我们
必须要把调试信息加到可执行文件中。
使用编译器(cc/gcc/g++)的-g参数可以
做到这一点。
如:
>cc-ghello.c-ohello
>g++-ghello.cpp-ohello
如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。
当你用-g把调试信息加入之后,并成功编译目标代码以后,让我们来看看如何用
gdb来调试他。
启动GDB的方法有以下几种:
1、gdb
program也就是你的执行文件,一般在当然目录下。
2、gdbcore
用gdb同时调试一个运行程序和core文件,core是程序非法执行后coredump后产生的文件。
3、gdb
如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。
gdb会自动attach上去,并调试他。
program应该在PATH环境变量中搜索得到。
GDB启动时,可以加上一些GDB的启动开关,详细的开关可以用gdb-help查看。
我在下面只例举一些比较常用的参数:
-symbols
-s
从指定文件中读取符号表。
-sefile
从指定文件中读取符号表信息,并把他用在可执行文件中。
-core
-c
调试时coredump的core文件。
-directory
-d
加入一个源文件的搜索路径。
默认搜索路径是环境变量中PATH所定义的路径。
GDB的命令概貌
———————
启动gdb后,就你被带入gdb的调试环境中,就可以使用gdb的命令开始调试程序了,gdb的命令可以使用help命令来查看,如下所示:
/home/hchen>gdb
GNUgdb5.1.1
Copyright2002FreeSoftwareFoundation,Inc.
GDBisfreesoftware,coveredbytheGNUGeneralPublicLicense,andyouare
welcometochangeitand/ordistributecopiesofitundercertainconditions.
Type"showcopying"toseetheconditions.
ThereisabsolutelynowarrantyforGDB.Type"showwarranty"fordetails.
ThisGDBwasconfiguredas"i386-suse-linux".
(gdb)help
Listofclassesofcommands:
aliases--Aliasesofothercommands
breakpoints--Makingprogramstopatcertainpoints
data--Examiningdata
files--Specifyingandexaminingfiles
internals--Maintenancecommands
obscure--Obscurefeatures
running--Runningtheprogram
stack--Examiningthestack
status--Statusinquiries
support--Supportfacilities
tracepoints--Tracingofprogramexecutionwithoutstoppingtheprogram
user-defined--User-definedcommands
Type"help"followedbyaclassnameforalistofcommandsinthatclass.
Type"help"followedbycommandnameforfulldocumentation.
Commandnameabbreviationsareallowedifunambiguous.
(gdb)
gdb的命令很多,gdb把之分成许多个种类。
help命令只是例出gdb的命令种类,如果
要看种类中的命令,可以使用help命令,如:
helpbreakpoints,查看设置断点的所
有命令。
也可以直接help来查看命令的帮助。
gdb中,输入命令时,可以不用打全命令,只用打命令的前几个字符就可以了,当然,
命令的前几个字符应该要标志着一个唯一的命令,在Linux下,你可以敲击两次TAB
键来补齐命令的全称,如果有重复的,那么gdb会把其例出来。
示例一:
在进入函数func时,设置一个断点。
可以敲入breakfunc,或是直接就是bfunc
(gdb)bfunc
Breakpoint1at0x8048458:
filehello.c,line10.
示例二:
敲入b按两次TAB键,你会看到所有b打头的命令:
(gdb)b
backtracebreakbt
(gdb)
示例三:
只记得函数的前缀,可以这样:
(gdb)bmake_<按TAB键>
(再按下一次TAB键,你会看到:
)
make_a_section_from_filemake_environ
make_abs_sectionmake_function_type
make_blockvectormake_pointer_type
make_cleanupmake_reference_type
make_commandmake_symbol_completion_list
(gdb)bmake_
GDB把所有make开头的函数全部例出来给你查看。
示例四:
调试C++的程序时,有可以函数名一样。
如:
(gdb)b'bubble(M-?
bubble(double,double)bubble(int,int)
(gdb)b'bubble(
你可以查看到C++中的所有的重载函数及参数。
(注:
M-?
和“按两次TAB键”是一个意思)
要退出gdb时,只用发quit或命令简称q就行了。
GDB中运行UNIX的shell程序
————————————
在gdb环境中,你可以执行UNIX的shell的命令,使用gdb的shell