现在的位置: 首页 > 综合 > 正文

GDB 单步调试

2013年03月10日 ⁄ 综合 ⁄ 共 13378字 ⁄ 字号 评论关闭

一、初始化
输入gdb进入gdb调试环境。或者直接输入gdb + progfile来加载文件。
注意该文件是使用gcc(或g++)编译得到的。为了使 gdb 正常工作, 必须
使你的程序在编译时包含调试信息,编译时必须使用-g参数来。
或者进入gdb环境后,通过命令file + progfile来加载需要调试的可
执行文件文件。

查看源代码:list [函数名][行数]

设置程序运行参数:set args

二、暂停程序   
gdb可以使用几种方式来暂停程序:断点,观察点,捕捉点,信号,线
程停止。当程序被暂停后,可以使用continue、next、step来继续执行程序。
continue         执行到下一暂停点或程序结束。
next         执行一行源代码但不进入函数内部。
step        执行一行源代码而且进入函数内部。

1、设置断点:
a、break + [源代码行号][源代码函数名][内存地址]
b、break ... if condition   ...可以是上述任一参数,condition
条件。例如在循环体中可以设置break ... if i = 100 来设置循环次数。

2、设置观察点:
a、watch + [变量][表达式]  当变量或表达式值改变时即停住程序。
b、rwatch + [变量][表达式] 当变量或表达式被读时,停住程序。
c、awatch + [变量][表达式] 当变量或表达式被读或被写时,停住程序。

3、设置捕捉点:
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 载入共享库(动态链接库)时。(load为关键字,
目前此功能只在HP-UX下有用)
7)、unload 或 unload 卸载共享库(动态链接库)时。(unload为关
键字,目前此功能只在HP-UX下有用)

4、捕捉信号:
handle + [argu] + signals
signals:是Linux/Unix定义的信号,SIGINT表示中断字符信号,也就是
Ctrl+C的信号,SIGBUS表示硬件故障的信号;SIGCHLD表示子进程状态改
变信号; SIGKILL表示终止程序运行的信号,等等。
argu:
nostop   当被调试的程序收到信号时,GDB不会停住程序的运行,但
会打出消息告诉你收到这种信号。
stop     当被调试的程序收到信号时,GDB会停住你的程序。
print    当被调试的程序收到信号时,GDB会显示出一条信息。
noprint  当被调试的程序收到信号时,GDB不会告诉你收到信号的信息。
pass or noignore    当被调试的程序收到信号时,GDB不处理信号。
这表示,GDB会把这个信号交给被调试程序会处理。
nopass or ignore     当被调试的程序收到信号时,GDB不会让被调
试程序来处理这个信号。

5、线程中断:
break [linespec] thread [threadno] [if ...]
linespec 断点设置所在的源代码的行号。如: test.c:12表示文件为
test.c中的第12行设置一个断点。
threadno 线程的ID。是GDB分配的,通过输入info threads来查看正在
运行中程序的线程信息。
if ...   设置中断条件。


三、查看信息
1、查看数据
print  variable        查看变量
print  *array@len      查看数组(array是数组指针,len是需要数据长度)
可以通过添加参数来设置输出格式:
/x 按十六进制格式显示变量。
/d 按十进制格式显示变量。
/u 按十六进制格式显示无符号整型。
/o 按八进制格式显示变量。
/t 按二进制格式显示变量。
/a 按十六进制格式显示变量。
/c 按字符格式显示变量。
/f 按浮点数格式显示变量。

2、查看内存
examine /n f u + 内存地址(指针变量)
n 表示显示内存长度
f 表示输出格式(见上)
u 表示字节数制定(b 单字节;h 双字节;w 四字节;g 八字节;默认为四字节)
如:
x /10cw pFilePath  (pFilePath为一个字符串指针,指针占4字节)
x 为examine命令的简写。

3、查看栈信息      
backtrace [-n][n]
n  表示只打印栈顶上n层的栈信息。
-n 表示只打印栈底上n层的栈信息。
不加参数,表示打印所有栈信息。
4、info

info address -- Describe where symbol SYM is stored
info all-registers -- List of all registers and their contents
info args -- Argument variables of current stack frame
info auxv -- Display the inferior's auxiliary vector
info breakpoints -- Status of user-settable breakpoints
info catch -- Exceptions that can be caught in the current stack frame
info checkpoints -- IDs of currently known forks/checkpoints
info classes -- All Objective-C classes
info common -- Print out the values contained in a Fortran COMMON block
info copying -- Conditions for redistributing copies of GDB
info dcache -- Print information on the dcache performance
info display -- Expressions to display when program stops
info extensions -- All filename extensions associated with a source language
info files -- Names of targets and files being debugged
info float -- Print the status of the floating point unit
info forks -- IDs of currently known forks/checkpoints
info frame -- All about selected stack frame
info functions -- All function names
info handle -- What debugger does when program gets various signals
info line -- Core addresses of the code for a source line
info linkmap -- Display the inferior's linkmap
info locals -- Local variables of current stack frame
info macro -- Show the definition of MACRO
info mem -- Memory region attributes
info proc -- Show /proc process information about any running process
info program -- Execution status of the program
info registers -- List of integer registers and their contents
info scope -- List the variables local to a scope
info selectors -- All Objective-C selectors
info set -- Show all GDB settings
info sharedlibrary -- Status of loaded shared object libraries
info signals -- What debugger does when program gets various signals
info source -- Information about the current source file
info sources -- Source files in the program
info stack -- Backtrace of the stack
info symbol -- Describe what symbol is at location ADDR
info target -- Names of targets and files being debugged
info terminal -- Print inferior's saved terminal status
info threads -- IDs of currently known threads
info tracepoints -- Status of tracepoints
info types -- All type names
info variables -- All global and static variable names
info vector -- Print the status of the vector unit
info warranty -- Various kinds of warranty you do not have
info watchpoints -- Synonym for ``info breakpoints''
info win -- List of all displayed windows

附注:
基本gdb命令:
---------------------------------------------------------------------
命令          简写         功能
---------------------------------------------------------------------
file                             装入想要调试的可执行文件.
kill             k              终止正在调试的程序.
list             l               列出产生执行文件的源代码的一部分.
next           n              执行一行源代码但不进入函数内部.
step          s              执行一行源代码而且进入函数内部.
continue  c               继续执行程序,直至下一中断或者程序结束。
run            r               执行当前被调试的程序.
quit           q               终止 gdb.
watch                        使你能监视一个变量的值而不管它何时被改变.
catch                         设置捕捉点.
thread       t               查看当前运行程序的线程信息.
break        b              在代码里设置断点, 这将使程序执行到这里时被挂起.
make                        使你能不退出 gdb 就可以重新产生可执行文件.
shell                         使你能不离开 gdb 就执行 UNIX shell 命令. 
print          p              打印数据内容。
examine  x               打印内存内容。
backtrace bt             查看函数调用栈的所有信息。



 

简述
一 列文件清单
二:执行程序
三:显示数据
四:断点(breakpoint)
五.断点的管理
六.变量的检查和赋值
七. 单步执行
八.函数的调用
九.机器语言工具
十.信号
GDB的使用方法

简述

一 列文件清单

  • List

    (gdb) list line1,line2
    

二:执行程序

要想运行准备调试的程序,可使用run命令,在它后面可以跟随发给该程序的任何参数,包括标准输入和标准输出说明符(< 和> )和外壳通配符(*、?、[、])在内。如果你使用不带参数的run命令,gdb就再次使用你给予前一条run命令的参数,这是很有用的。利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表。

(gdb)set args -b -x(gdb) show argsbacktrace命令为堆栈提供向后跟踪功能。Backtrace 命令产生一张列表,包含着从最近的过程开始的所以有效过程和调用这些过程的参数。

三:显示数据

  • 利用print 命令可以检查各个变量的值。

    (gdb) print p (p为变量名)
    

    print 是gdb的一个功能很强的命令,利用它可以显示被调试的语言中任何有效的表达式。表达式除了包含你程序中的变量外,还可以包含以下内容:

  1. 对程序中函数的调用

    (gdb) print find_entry(1,0)
    
  2. 数据结构和其他复杂对象
    (gdb) print *table_start$8={e=reference=’\000’,location=0x0,next=0x0}
    
  3. 值的历史成分
    (gdb)print $1 ($1为历史记录变量,在以后可以直接引用 $1 的值)
    
  4. 人为数组
    人为数组提供了一种去显示存储器块(数组节或动态分配的存储区)内容的方法。早期的调试程序没有很好的方法将任意的指针换成一个数组。就像对待参数一样, 让我们查看内存中在变量h后面的10个整数,一个动态数组的语法如下所示:
    base@length
    因此,要想显示在h后面的10个元素,可以使用h@10:

    (gdb)print h@10$13=(-1,345,23,-234,0,0,0,98,345,10)
    
  • whatis 命令可以显示某个变量的类型

    (gdb) whatis ptype = int *
    

四:断点(breakpoint)

break命令(可以简写为b)可以用来在调试的程序中设置断点,该命令有如下四种形式:

 

  • break line-number 使程序恰好在执行给定行之前停止。
  • break function-name 使程序恰好在进入指定的函数之前停止。
  • break line-or-function if condition 如果condition(条件)是真,程序到达指定行或函数时停止。
  • break routine-name 在指定例程的入口处设置断点

如果该程序是由很多原文件构成的,你可以在各个原文件中设置断点,而不是在当前的原文件中设置断点,其方法如下:

(gdb) break filename:line-number(gdb) break filename:function-name

要想设置一个条件断点,可以利用break if命令,如下所示:

(gdb) break line-or-function if expr例:(gdb) break 46 if testsize==100

从断点继续运行:countinue 命令

 

五.断点的管理

1.显示当前gdb的断点信息:

(gdb) info break

他会以如下的形式显示所有的断点信息:

Num Type Disp Enb Address What1 breakpoint keep y 0x000028bc in init_random at qsort2.c:1552 breakpoint keep y 0x0000291c in init_organ at qsort2.c:168
  1. 删除指定的某个断点:

    (gdb) delete breakpoint 1
    

    该命令将会删除编号为1的断点,如果不带编号参数,将删除所有的断点

    (gdb) delete breakpoint
    
  2. 禁止使用某个断点
    (gdb) disable breakpoint 1
    

    该命令将禁止断点 1,同时断点信息的 (Enb)域将变为 n

  3. 允许使用某个断点
    (gdb) enable breakpoint 1
    

    该命令将允许断点 1,同时断点信息的 (Enb)域将变为 y

  4. 清除原文件中某一代码行上的所有断点
    (gdb)clean number
    

    注:number 为原文件的某个代码行的行号

六.变量的检查和赋值

  • whatis:识别数组或变量的类型
  • ptype:比whatis的功能更强,他可以提供一个结构的定义
  • set variable:将值赋予变量
  • print 除了显示一个变量的值外,还可以用来赋值

七. 单步执行

  • next 不进入的单步执行
  • step 进入的单步执行如果已经进入了某函数,而想退出该函数返回到它的调用函数中,可使用命令finish

八.函数的调用

  • call name 调用和执行一个函数

    (gdb) call gen_and_sork( 1234,1,0 )(gdb) call printf(“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) handle SIGPIPE stop print

请注意,UNIX的信号名总是采用大写字母!你可以用信号编号替代信号名如果你的程序要执行任何信号处理操作,就需要能够测试其信号处理程 序,为此,就需要一种能将信号发送给程序的简便方法,这就是signal命令的任务。该命令的参数是一个数字或者一个名字,如SIGINT。假定你的程序 已将一个专用的SIGINT(键盘输入,或CTRL-C;信号2)信号处理程序设置成采取某个清理动作,要想测试该信号处理程序,你可以设置一个断点并使 用如下命令:

(gdb) signal 2continuing with signal SIGINT(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
3 int func(int n)
4 {
5 int sum=0,i;
6 for(i=0; i
7 {
8 sum+=i;
9 }
10 return sum;
11 }
12
13
14 main()
15 {
16 int i;
17 long result = 0;
18 for(i=1; i<=100; i++)
19 {
20 result += i;
21 }
22
23 printf("result[1-100] = %d \n", result );
24 printf("result[1-250] = %d \n", func(250) );
25 }
编译生成执行文件:
(Linux下)hchen/test> cc -g tst.c -o tst
使用GDB调试
hchen/test> gdb tst <---------- 启动GDBGNU 
gdb 5.1.1Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-suse-linux"...
(gdb) l <-------------------- l命令相当于list,从第一行开始例出原码。
1 #include
2
3 int func(int n)
4 {
5 int sum=0,i;
6 for(i=0; i
7 {
8 sum+=i;
9 }
10 return sum;
(gdb) <-------------------- 直接回车表示,重复上一次命令
11 }
12
13
14 main()
15 {
16 int i;
17 long result = 0;
18 for(i=1; i<=100; i++)
19 {
20 result += i;
(gdb) break 16 <-------------------- 设置断点,在源程序第16行处。
Breakpoint 1 at 0x8048496: file tst.c, line 16.
(gdb) break func <-------------------- 设置断点,在函数func()入口处。
Breakpoint 2 at 0x8048456: file tst.c, line 5.
(gdb) info break <-------------------- 查看断点信息。
Num Type Disp Enb Address What
1 breakpoint keep y 0x08048496 in main at tst.c:16
2 breakpoint keep y 0x08048456 in func at tst.c:5
(gdb) r <--------------------- 运行程序,run命令简写
Starting program: /home/hchen/test/tst
Breakpoint 1, main () at tst.c:17 <---------- 在断点处停住。
17 long result = 0;
(gdb) n <--------------------- 单条语句执行,next命令简写。
18 for(i=1; i<=100; i++)
(gdb) n
20 result += i;
(gdb) n
18 for(i=1; i<=100; i++)
(gdb) n
20 result += i;
(gdb) c <--------------------- 继续运行程序,continue命令简写。
Continuing.
result[1-100] = 5050 <----------程序输出。
Breakpoint 2, func (n=250) at tst.c:5
5 int sum=0,i;
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p i <--------------------- 打印变量i的值,print命令简写。
$1 = 134513808
(gdb) n
8 sum+=i;
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p sum
$2 = 1
(gdb) n
8 sum+=i;
(gdb) p i
$3 = 2
(gdb) n
6 for(i=1; i<=n; i++)
(gdb) p sum
$4 = 3
(gdb) bt <--------------------- 查看函数堆栈。
#0 func (n=250) at tst.c:5
#1 0x080484e4 in main () at tst.c:24
#2 0x400409ed in __libc_start_main () from /lib/libc.so.6
(gdb) finish <--------------------- 退出函数。
Run till exit from #0 func (n=250) at tst.c:5
0x080484e4 in main () at tst.c:24
24 printf("result[1-250] = %d \n", func(250) );
Value returned is $6 = 31375
(gdb) c <--------------------- 继续运行。
Continuing.
result[1-250] = 31375 <----------程序输出
Program exited with code 027. <--------程序退出,调试结束
(gdb) q <--------------------- 退出gdb。
hchen/test>
好了,有了以上的感性认识,还是让我们来系统地认识一下gdb吧。



  使用GDB
----

一般来说GDB主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,我们
必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数可以
做到这一点。如:

> cc -g hello.c -o hello
> g++ -g hello.cpp -o hello

如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。
当你用-g把调试信息加入之后,并成功编译目标代码以后,让我们来看看如何用
gdb来调试他。

启动GDB的方法有以下几种:

1、gdb
program也就是你的执行文件,一般在当然目录下。

2、gdb core
用gdb同时调试一个运行程序和core文件,core是程序非法执行后core dump后产生的文件。

3、gdb

如果你的程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID。
gdb会自动attach上去,并调试他。program应该在PATH环境变量中搜索得到。

GDB启动时,可以加上一些GDB的启动开关,详细的开关可以用gdb -help查看。我在下面只例举一些比较常用的参数:

-symbols
-s
从指定文件中读取符号表。

-se file
从指定文件中读取符号表信息,并把他用在可执行文件中。

-core
-c
调试时core dump的core文件。

-directory
-d
加入一个源文件的搜索路径。默认搜索路径是环境变量中PATH所定义的路径。

GDB的命令概貌
-------

启动gdb后,就你被带入gdb的调试环境中,就可以使用gdb的命令开始调试程序了,gdb的命令可以使用help命令来查看,如下所示:

/home/hchen> gdb
GNU gdb 5.1.1
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-suse-linux".
(gdb) help
List of classes of commands:

aliases -- Aliases of other commands
breakpoints -- Making program stop at certain points
data -- Examining data
files -- Specifying and examining files
internals -- Maintenance commands
obscure -- Obscure features
running -- Running the program
stack -- Examining the stack
status -- Status inquiries
support -- Support facilities
tracepoints -- Tracing of program execution without stopping the program
user-defined -- User-defined commands

Type "help" followed by a class name for a list of commands in that class.
Type "help" followed by command name for full documentation.
Command name abbreviations are allowed if unambiguous.
(gdb)

gdb的命令很多,gdb把之分成许多个种类。help命令只是例出gdb的命令种类,如果
要看种类中的命令,可以使用help 命令,如:help breakpoints,查看设置断点的所
有命令。也可以直接help 来查看命令的帮助。

gdb中,输入命令时,可以不用打全命令,只用打命令的前几个字符就可以了,当然,
命令的前几个字符应该要标志着一个唯一的命令,在Linux下,你可以敲击两次TAB
键来补齐命令的全称,如果有重复的,那么gdb会把其例出来。

示例一:在进入函数func时,设置一个断点。可以敲入break func,或是直接就是b func
(gdb) b func
Breakpoint 1 at 0x8048458: file hello.c, line 10.

示例二:敲入b按两次TAB键,你会看到所有b打头的命令:
(gdb) b
backtrace break bt
(gdb)

示例三:只记得函数的前缀,可以这样:
(gdb) b make_ <按TAB键>
(再按下一次TAB键,你会看到:)
make_a_section_from_file make_environ
make_abs_section make_function_type
make_blockvector make_pointer_type
make_cleanup make_reference_type
make_command make_symbol_completion_list
(gdb) b make_
GDB把所有make开头的函数全部例出来给你查看。

示例四:调试C++的程序时,有可以函数名一样。如:
(gdb) b 'bubble( M-?
bubble(double,double) bubble(int,int)
(gdb) b 'bubble(
你可以查看到C++中的所有的重载函数及参数。(注:M-?和“按两次TAB键”是一个意思)

要退出gdb时,只用发qu

抱歉!评论已关闭.