gdb调试器(三)

        File/file 装入想要调试的可执行文件     run(r) 执行当前被调试的程序     kill(k) 终止正在调试的程序       quit(q)  退出gdb   shell 使用户不离开gdb就可以执行Linux的shell命令                  backtrace(bt) 回溯跟踪(当对代码进行调试时,run后出现错误,则可以使用bt命令查出详细的错误信息         frame n  定位到发生错误的代码段,n为backtrace命令的输出结果中的行号(位于行首)。   

(1) 设置断点(break)  

break <function>          在进入指定函数时被停住。C++可以使用class::function或function<type,type>格式来指定函数名。 //在该处停止(断点),该处不执行,下同

break <linenum> 在指定行号停住

break filename:linenum   在源文件filename的linenum行处停止

break filename:function   在源文件filename的function函数的入口处停止

break    没有参数,表示在下一条指令处停止

break *address 在程序运行的内存地址处停止

break与step结合使用时,step(s)确认后,执行上一次显示的未执行命令,并且显示出将要执行的下一行程序。使用单步调试命令step来跟踪程序,它一次只执行程序中的一行代码。

info break(i b)  命令  可以显示所有断点的信息

(2) 查看运行时的数据

在调试程序的过程中,需要查看程序中某些表达式或变量的值,以判断程序运行是否正确。

  •         print命令(p)

在调试程序时,当程序被停住时(如在断点处),可以使用print(p)命令或其同义命令inspect来查看当前程序的运行数据。

print <expr>  //输出表达式的值

print /<f> <expr>  //按某种格式输出表达式的值,如/x 则为16进制

(gdb) print n1

$1 = 4

(gdb) inspect n1

$2 = 4

(gdb) print n1

$3 = 4

(gdb) print n2

$4 = 5

(gdb) print $2

$5 = 4     //$2的值

(gdb) print $   //$5的值

$6 = 4

(gdb) print $ $  //$5的值    注意之间没有空格  这是防止CSDN编辑器转义而加上的空格

$7 = 4

(gdb) print $ $6 //$4的值

$8 = 5

每一个print都会被gdb记录下来,并且会以$1、$2、$3······这样的方式为每一个print命令编号。于是,可以使用这个编号访问以前的表达式。

另外要注意print命令的表达式中两个具有特殊意义的符号:$、$ $。print $表示显示当前序号的前一个序号的值;$ $表示给定序号的前两个序号,如果未给定序号,则默认当前序号为给定序号。

另外,info local命令可以显示当前本地的所有变量的值。

print命令的功能除了打印表达式或变量的值以外,还有对变量进行赋值和打印内存中某个变量开始的一段区域的内容。

  •         gdb的数据输出格式

x 十六进制格式     d 十进制格式   u 十六进制格式无符号整型

o 八进制格式       t 二进制格式    a 十六进制格式(等价x)

c  ASCII字符格式     f 浮点数格式     s字符串格式   i指令地址(指令文件)

p /x n1    //以十六进制格式显示n1的值

  •         自动显示命令display

当程序停住时,或单步跟踪时,这些变量会自动显示。

display <expr>        display /<f> <expr>   

display /<f> <addr>  addr表示内存地址

display /i $pc  $pc为gdb的环境变量,表示指令的地址,/i则表示输出格式为机器指令码,也就是汇编。该句指令表示,当程序停下后,就会出现源代码和机器指令码相对应的情形。 即输出当前指令的地址(程序运行到当前处),以机器指令码的格式输出,从而出现源代码和机器指令码(汇编代码)相对应的情形。

  •         查看内存examine(x)

examine(简写为x)指令可以查看内存地址中的值,格式:

x /<n/f/u> <addr>

n、f、u为可选的参数,可以独立使用,也可以联合使用。

n为一个正整数,表示显示内存的长度,即从当前地址向后显示几个地址的内容。

f表示显示的格式(即地址所指内容以什么样的格式显示出),s为字符串,如果所指的内容为指令地址,则为i。

u表示从当前地址往后请求的字节数,如果不指定则默认为4个Bytes。u参数可以用下面的字符代替:b表示单字节,h表示双字节,w表示四字节,g表示八字节。

<addr>表示一个内存地址

x /4uh 0x48723  // 从内存地址0x48723读取内容,h表示以双字节为1个单位,4表示4个单位,u表示按16进制显示。

  •         gdb的环境变量

可以在gdb的调试环境中定义自己的变量,用来保存一些调试程序中的运行数据。set命令用于定义gdb的环境变量,gdb的环境变量与Linux一样,都是以$起始。

set $foo=*object_ptr

第一次使用环境变量时,需要创建这个变量(set),以后使用直接对其赋值即可,环境变量没有类型,可以给环境变量定义任意的类型,包括结构体和数组。

在gdb的调试过程中,show convenience 命令用于查看当前设置的所有环境变量

  •         查看寄存器

在调试程序的过程中,有时需要查看某些寄存器中的值。寄存器存放了程序运行时的数据,比如程序当前运行时的指令地址(IP),程序的当前堆栈地址(SP)等。可以使用info命令来查看寄存器中的值。

info registers //查看寄存器的情况(不包括浮点寄存器)

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

info registers<name1,name2,······>  //查看指定寄存器的情况(name表示寄存器名)

也可以使用print命令来访问寄存器的情况,只需要在寄存器名字前加一个$就可以了,如:print $ip。

  •         查看源程序list(l)

在程序的调试过程中,有时需要查看源程序的内容,以及源代码在内存中的情况。用list命令可以显示程序的源代码。

list linenum 显示程序第linenum行周围的源程序

list filename:linenum  显示某个.c文件中的第linenum行周围的源程序(对于多个源文件的编译)

list function 显示函数名为function的函数的源程序

list filename:function

list 显示当前行后面的源程序

list - 显示当前行前面的源程序

list first,last 显示从first行到last行之间的源代码

list ,last 显示从当前行到last行之间的源代码

可以使用info line命令来查看源代码在内存中的地址,info line命令后面也可以跟行号、函数名、文件名:行号、文件名:函数名等,从而显示指定的源代码在内存中的地址。如要显示zsx.c源文件中calculate( )函数在内存中的地址:

info line zsx.c:calculate 

(3) 改变程序的执行

修改变量的值。print命令还可以修改被调试程序中运行时的变量值。如:

print x=9

跳转执行。可以修改程序的执行顺序,让程序执行随意跳跃。

jump <linespec>  <linespec>可以是文件的行号,可以是file:linenum格式,表示下一条运行语句从哪里开始。

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

注意jump命令不会改变当前的程序栈中的内容。

程序运行时,有一个寄存器用于保存当前代码所在的内存地址,所以jump命令也就是改变了这个寄存器中的值。可以使用set $pc来更改跳转执行的地址:set $pc=0x485。

(4) 具体事例

15           for (i = 0; i < len; ++i)

(gdb) b 15 if i==5

Breakpoint 1 at 0x4008d3: file ../src/main.c, line 15.

(gdb) b 27

Breakpoint 2 at 0x400936: file ../src/main.c, line 27.

(gdb) i b

Num     Type           Disp Enb               Address                      What

1       breakpoint     keep y        0x00000000004008d3  in main at ../src/main.c:15

                          stop only if i==5

2       breakpoint     keep y        0x0000000000400936  in main at ../src/main.c:27

//断点编号(id 断点类型    断点是否可用(y表示可用,n表示不可用) 断点地址  断点的详细信息

(5) 总结(重点内容)

运行程序:start(开始运行,只执行一步就停住);run(开始运行,在断点处停住);continue(c)继续运行,到下一个断点处停止,step(s)单步执行,进入函数内部;next(n)单步执行,不进入函数内部;u跳出循环体,执行循环体后面的第一个语句。

set var i=10  //将变量i的值设为10,比如在一个循环体中,i为控制变量,当单步执行时,i依次增加,如果想让变量i循环到10时,才停住,则可以:set var i = 10。

gdb调试:

              1. 启动gdb

                            start -- 只执行一步

                                   n -- next

                                   s -- step(单步) -- 可以进入到函数体内部

                                   c - continue -- 直接停在断点的位置

              2. 查看代码:

                            l -- list

                            l 10(或者函数名)

                            l filename:行号(或者函数名)

              3. 设置断点:

                            设置当前文件断点:

                                   b -- break

                                   b 10(或函数名)

                            设置指定文件断点:

                                b fileName:行号(或函数名)

                            设置条件断点:

                                   b 10 if value==19

                            删除断点:

                                   d 断点编号

                                获取编号:i b

              4. 查看设置的断点

                    info break   i b

              5. 开始 执行gdb调试

                            执行一步操作:  start

                                   继续执行:  n s

                            执行多步, 直接停在断点处:  continue

              5. 单步调试

                            进入函数体内部: s

                                   从函数体内部跳出: finish(如果在循环处有断点, 需要将断点删掉)

                            不进入函数体内部:n

                            退出当前循环: u //该退出是指,直接一次性执行完该循环体

              6. 查看变量的值: p -- print

              7. 查看变量的类型: ptype 变量名

              8. 设置变量的值:  set var 变量名 = 赋值  //注意,同理,不是硬性的

              9. 设置追踪变量

                            display

                            取消追踪变量

                            undisplay 编号

                            获取编号: info display

              10. 退出gdb调试

                                   quit

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值