实用gdb命令

1.启动与退出gdb

一般有三种方式启动gdb:

第一种--->gdb  a.out           与先运行gdb再file  a.out等价

第二种--->gdb   a.out   core.pad    这里,我们得预先获取了被调试程序的core文件core.pid(core文件是程序崩溃时所生成的内存转储文件,通过该文件可以还原程序崩溃时的情景。如果程序崩溃时没有生成core文件,可以运行“-ulimit  -c  50000”命令后再试试)

第三种--->gdb   a.out   pid   调试已运行的程序,其中pid是通过ps命令获得的进程号。

使用quit命令可以退出gdb


2.获取帮助

进入gdb后,运行help可以获取帮助,如果不指定参数,则gdb输出分类帮助信息。可以以类名作为参数,则获取哪些命令属于在分类,例:help  stack

通过这种循环渐进的方式,我们能很快地获得需要的命令,进而以具体命令为参数通过help命令获得更详细的帮助信息。

另外有两点需要注意,如果命令的开头几个字符能唯一的标识该命令,则后面的字符可以不输入。<Tab>键能让gdb自动为我们完成整个命令的输入,或则通过<Tab>让gdb告诉我们哪些参数可选。

gdb中,对于大多数命令都可以通过直接按Enter键的方式运行前面执行过的命令。


3.调试程序

使用gdb调试程序,需要被调试程序的符号表。符号表可以是直接来源于被调试的程序文件,或则一个独立的符号文件。(使用strip命令的--only-keep-debug选项,可以生成只包含符号表的文件)

-----------------·断点设置:

软件程序断点,硬件程序断点和数据断点,gdb中设置这三种断点的命令不同。此外gdb还提供了捕获事件的断点和断点设置命令。

软件程序断点

break命令可以设置软件断点。有多种形式

break    main    以函数名为break命令参数

break    main.c : 147   指定文件名和行号来指定断点位置

当使用break不带任何参数时,gdb会在程序指针寄存器所指的位置处设置一个断点。

可以后带if设置先决条件,即满足if后的表达式,断点才会被设置,如break   mpool.c:147   if   index = 3

当调试的是一个多线程的程序时,可以在break命令中指定使断点有效的线程号。

break命令完整的语法格式。其中方括号内的参数是可选的:

break    location   [thread   threadnum]   [if  condition]

如果希望设置一次有效的断点,可以使用tbreak命令。其使用方法与break命令完全相同。(temporary break)。程序一旦在使用tbreak命令设置的断点处停下后,gdb就会自动删除该断点。

使用rbreak命令可以以正则表达式的方式在多个函数中设置断点。

设置断点时,gdb会对每一个断点赋予一个唯一的标识符(我们称之为断点号)。通过使用“info  breakpoints”命令可以查看已设置的(所有类型)断点。

使用disable和enable命令可以分别使任一个断点无效和有效。这两个输入参数都是断点号,这两个命令会影响“info  breakpoints”命令输出结果中的“Enb”列的值。

删除一个断点使用“delete”命令,使用“delete breakpoints”可以删除所有断点。“delete breakpoints  断点号”的命令效果和“delete  断点号”是一样的,删除某个断点。

使用ignore命令可以让gdb忽略程序碰到某断点的次数,使用“help  ignore”命令,读者可以获获取其使用帮助。


硬件程序断点:

使用hbreak命令可以设置硬件程序断点,其命令格式与break是完全一样的。通过show命令可以了解处理器所支持的硬件断点数。

show    can-use-hw-watchpoints

结果:Debugger`s  willingness  to  use  watchpoint  hardware   is  1

使用thbreak命令可以设置一次有效的硬件断点


数据断点:

数据断点需要使用watch命令,其参数是我们所希望观察的被改变的变量名,或则一个已知的内存地址。注意,如果想对局部变量使用watch命令,则需要程序已经停止在变量所在的函数中,对于全局变量没有限制。读者可以想想为什么?此外对于32的处理器,数据断点只能用于监视类型大小为32的数据。


事件断点:

除上面三种外,gdb还提供了catch命令以便我们捕获调试期间的事件,事件包括信号,程序开始,程序终止和C++中的异常(exception)等。读者可以通过gdb在线帮助了解catch命令可以用于捕获哪些事件。使用tcatch可以设置一次有效事件断点。


-----------------控制程序的运行:

使用run运行被调试的程序,被调试程序所需要的输入参数可以通过run命令加以指定。在run不带参数的情况下,以最后一次指定的参数为准。

被调试程序的输入参数除了通过run的参数指定外,还可以使用set命令设置args参数。

set       args  -v    -h

show    args

Argument   list  to  give  program  being  debugged   when   it   is  started   is  "-v  -h"

除了run命令,start命令也可以用于启动被调试程序,但程序会停在mian()函数的开始处。这一命令等效于在mian()函数的入口处设置一个一次性断点,然后运行run。

程序一旦停止,可以使用continue让它继续运行。

使用next单步调试,后面可以带一个参数,指示命令的运行次数,如:next  3  等价于连续运行三次next

如果要跟踪进入函数体内,则需要使用step命令。step也可以像next一样携带运行命令的次数。

跟踪代码时,可以使用不带参数的list显示跟踪点附近的代码。

如果想让程序运行到某行可以用until命令,它的参数是我们所希望的停止点,如果不带参数则和next命令一样。(用例:跳过for循环)until  115 到115行。

如果想让程序运行完某函数并返回,则可以使用finish命令。

如果希望在某函数内直接返回某一值而不真正运行完函数,则需要使用return命令。例:程序正在system_up()函数中,使用return  -1

在C语言中如果想以汇编指令的方式调试程序,则需要用到stepi命令和nexti命令。

在调试过程中,还可以人为的改变程序中的变量的值,这需要set命令。格式为:“set   变量名   =  表达式”



4.程序检查

调试程序时,如果要查看相关变量或寄存器的值,则需要使用print命令。格式:print    /f     expression   

其中f表示显示格式,可以是x(十六进制),d(有符号的十进制,这是默认格式),u(无符号十进制),o(八进制),t(二进制),a(地址),c(字符)和f(浮点)中的任一个;expression是指变量,函数等表达式。

每次执行print命令时,gdb都会为输出结果分配一个编号,我们在之后可以使用“$n”的形式加以回访,其中的n就是gdb所分配的编号。

另外,与print相似的一个命令时call命令,唯一区别是,当调用函数时如果某函数的返回值为void,则它不打印出返回结果。

如果需要检查某一内存区域中的数据,则需要使用x命令。格式:x     /Nuf    expression    其中N表示需要打印的单元个数;u表示单元的大小;而f表示打印格式。u可以是b(字节),h(双字节),w(四字节),或g(八字节)。f除了包含print命令中的格式外,还可以是s(以NUL为结束的字符串)或大写i(汇编指令)。

使用info和print可以查看寄存器的值,info reg  $ebp                   print   $ebp

使用backtrace命令可以查看程序的调用栈。当程序因为崩溃而获得core文件时,我们可以通过使用backtrace命令了解程序的出错点(前提假设是栈没有被破坏)。backtrace命令的输出结果为每一个栈帧提供一个标号,这个编号可用于切换栈帧。

使用info  locals 可以查看函数的所有局部变量的值,使用info  args 可以查看函数参数的值,使用info   frame  可以看到当前栈帧的信息。

info  locals 和 info frame 与栈帧是紧密相关的,通过使用frame命令可以在不同的栈帧中进行切换。frame命令的参数是backtrace命令所输出的各栈帧的编号。

另一种切换栈帧的方法是使用up命令和down命令。这两个命令的参数是一样的,用于指示希望向上或向下移动几个栈帧。

前面说了使用list查看源码,再说明其他四种使用形式,默认情况下list显示10行代码,list- 用于显示前10行代码。如果想要修改list命令每次显示的行数,则可以使用set命令改变listsize参数的值。

如果要查看反汇编代码,则可以使用disassemble命令。在不带参数的情形下,disassemble显示程序计数器寄存器所指向地址附近的汇编代码。如果给disassemble指定程序地址,它将显示该地址附近的代码。/m指示显示汇编指令的同时,显示相应的程序源码;/r指示显示十六进制的计算机指令(raw instruction)。


5.提高调试效率

调试效率的提供啊除了正确设置断点外,还需要使用gdb的其他功能。第一个可以考虑的功能是使用display命令,命令参数和print是相同的,格式:display   /f    expression

使用display命令设置的表达式在程序每次碰到断点停止时都会自动打印出其值。同过这种方式可以省去每次手工检查的麻烦。使用display不带参数时,将获得已设置了哪些自动显示内容;去除自动显示内容需要使用undisplay命令。

提高效率的第二种方式是,可以通过在gdb中编辑和编译程序的方式,省去启动和退出gdb的动作。可以使用edit命令编辑源程序,edit命令的参数可以是文件,函数名和行号;也可以运行cd,pwd和make命令进行工作目录切换和程序编译。gdb一旦发现被调试程序有更新,就会自动的重新加载程序(和符号表)。此外,如果需要在gdb中运行其他的shell命令,则可以使用gdb中的shell命令。


6.查看符号表

通过使用info,ptype和whatis三个命令来查看程序中的符号表。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值