首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

GDB调试,转载一位大牛的东西

2023-11-09 来源:华拓网
 

本文是《手把手教你玩转GDB》系列的第二篇,主要内容是用GDB调试程序中比较常用到的断点(breakpoint)、监视点(watchpoint)和捕捉点(catchpoint)。虽然说这三类point的功能是不一样的,但它们的用法却极为相似。因此,本文将以断breakpoint为例,进行详细的介绍,关于watchpoint和catchpoint的介绍就相对比较粗略,相信读者朋友如果能够理解breakpoint的部分,那么便可以触类旁通,学会watchpoint和catchpoint的用法。

1. Breakpoint: 作用是让程序执行到某个特定的地方停止运行

  • (1)设置breakpoint:
  • a. break function: 在函数funtion入口处设置breakpointb. break +offset: 在程序当前停止的行向前offset行处设置breakpointc. break –offset: 在程序当前停止的行向衙offset行处设置breakpointd. break linenum: 在当前源文件的第linenum行处设置breakpointe. break filename:linenum: 在名为filename的源文件的第linenum行处设置breakpointf. break filename:function: 在名为filename的源文件中的function函数入口处设置breakpointg. break *address: 在程序的地址address处设置breakpointh. break … if cond: …代表上面讲到的任意一个可能的参数,在某处设置一个breakpoint, 但且仅但cond为true时,程序停下来i. tbreak args: 设置一个只停止一次的breakpoints, args与break命令的一样。这样的breakpoint当第一次停下来后,就会被自己删除k. rbreak regex: 在所有符合正则表达式regex的函数处设置breakpoint

  • (2)info breakpoints [n]:
  • 查看第n个breakpoints的相关信息,如果省略了n,则显示所有breakpoints的相关信息

  • (3)pending breakpoints:
  • 是指设置在程序开始调试后加载的动态库中的位置处的breakpointsa. set breakpoint pending auto: GDB缺省设置,询问用户是否要设置pending breakpointb. set breakpoint pending on: GDB当前不能识别的breakpoint自动成为pending breakpointc. set breakpoint pending off: GDB当前不能识别某个breakpoint时,直接报错d. show breakpoint pending: 查看GDB关于pending breakpoint的设置的行为(auto, on, off)

  • (4)breakpoints的删除:
  • a. clear: 清除当前stack frame中下一条指令之后的所有breakpointsb. clear function & clear filename:function: 清除函数function入口处的breakpointsc. clear linenum & clear filename:linenum: 清除第linenum行处的breakpointsd. delete [breakpoints] [range…]: 删除由range指定的范围内的breakpoints,range范围是指breakpoint的序列号的范围

  • (5)breakpoints的禁用、启用:
  • a. disable [breakpoints] [range…]: 禁用由range指定的范围内的breakpointsb. enable [breakpoints] [range…]: 启用由range指定的范围内的breakpointsc. enable [breakpoints] once [range…]: 只启用一次由range指定的范围内的breakpoints,等程序停下来后,自动设为禁用d. enable [breakpoints] delete [range…]: 启用range指定的范围内的breakpoints,等程序停下来后,这些breakpoints自动被删除

  • (6)条件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次后开始生效

  • (7)指定程序在某个breakpoint处停下来后执行一串命令:
  • a. 格式:commands [bnum]… command-list …endb. 用途:指定程序在第bnum个breakpoint处停下来后,执行由command-list指定的命令串,如果没有指定bnum,则对最后一个breakpoint生效c. 取消命令列表: commands [bnum]endd. 例子:break foo if x>0commandssilentprintf “x is %d”,xcontinueend上面的例子含义:当x>0时,在foo函数处停下来,然后打印出x的值,然后继续运行程序

    2. Watchpoint: 它的作用是让程序在某个表达式的值发生变化的时候停止运行,达到‘监视’该表达式的目的

  • (1)设置watchpoints:
  • a. watch expr: 设置写watchpoint,当应用程序写expr, 修改其值时,程序停止运行b. rwatch expr: 设置读watchpoint,当应用程序读表达式expr时,程序停止运行c. awatch expr: 设置读写watchpoint, 当应用程序读或者写表达式expr时,程序都会停止运行

  • (2)info watchpoints:
  • 查看当前调试的程序中设置的watchpoints相关信息

  • (3)watchpoints和breakpoints很相像,都有enable/disabe/delete等操作,使用方法也与breakpoints的类似
  • 3. Catchpoint: 的作用是让程序在发生某种事件的时候停止运行,比如C++中发生异常事件,加载动态库事件

  • (1)设置catchpoints:
  • a. catch event: 当事件event发生的时候,程序停止运行,这里event的取值有:

    1)throw: C++抛出异常2)catch: C++捕捉到异常3)exec: exec被调用4)fork: fork被调用5)vfork: vfork被调用6)load: 加载动态库7)load libname: 加载名为libname的动态库8)unload: 卸载动态库9)unload libname: 卸载名为libname的动态库10)syscall [args]: 调用系统调用,args可以指定系统调用号,或者系统名称

    b. tcatch event: 设置只停一次的catchpoint,第一次生效后,该catchpoint被自动删除

    (2)catchpoints和breakpoints很相像,都有enable/disabe/delete等操作,使用方法也与breakpoints的类似

    手把手教你玩转GDB(三)——常用命令2010年8月30日小武哥发表评论阅读评论 

    本文是手把手教你玩转GDB的第三篇,主要内容是介绍一些在程序调试过程中最常用的GDB命令,废话不多话,开始今天的正题。1.attach process-id/detach

  • (1)attach process-id: 在GDB状态下,开始调试一个正在运行的进程,其进程ID为process-id
  • (2)detach: 停止调试当前正在调试有进程,与attach配对试用
  • 2.kill

  • (1)基本功能:杀掉当前GDB正在调试的应用程序所对应的子进程
  • (2)如果想不退出GDB而对当前正在调试的应用程序重新编译、链接,可以在GDB中执行kill杀掉子进程,等编译、链接完后,再重新执行run,GDB便可加载新的可执行程序启动调试
  • 3.多线程程序调试相关:

  • (1)thread threadno:切换当前线程到由threadno指定的线程
  • (2)info threads:查看GDB当前调试的程序的各个线程的相关信息
  • (3)thread apply [threadno] [all] args:对指定(或所有)的线程执行由args指定的命令
  • 4.多进程程序调试相关(fork/vfork):

  • (1)缺省方式:fork/vfork之后,GDB仍然调试父进程,与子进程不相关
  • (2)set follow-fork-mode mode:设置GDB行为,mode为parent时,与缺省情况一样;mode为child时,fork/vfork之后,GDB进入子进程调试,与父进程不再相关
  • (3)show follow-fork-mode:查看当前GDB多进程跟踪模式的设置
  • 5.step & stepi

  • (1)step [count]: 如果没有指定count, 则继续执行程序,直到到达与当前源文件不同的源文件中时停止;如果指定了count, 则重复行上面的过程count
  • (2)stepi [count]: 如果没有指定count, 继续执行下一条机器指令,然后停止;如果指定了count,则重复上面的过程count
  • (3)step比较常见的应用场景:在函数func被调用的某行代码处设置断点,等程序在断点处停下来后,可以用step命令进入该函数的实现中,但前提是该函数编译的时候把调试信息也编译进去了,负责step会跳过该函数。
  • 6.next & nexti

  • (1)next [count]: 如果没有指定count, 单步执行下一行程序;如果指定了count,单步执行接下来的count行程序
  • (2)nexti [count]: 如果没有指定count, 单步执行下一条指令;如果指定了count, 音频执行接下来的count条执行
  • (3)stepi和nexti的区别:nexti在执行某机器指令时,如果该指令是函数调用,那么程序执行直到该函数调用结束时才停止。
  • 7.continue [ignore-count] 唤醒程序,继续运行,至到遇到下一个断点,或者程序结束。如果指定ignore-count,那么程序在接下来的运行中,忽略ignore-count次断点。8.finish & return

  • (1)finish: 继续执行程序,直到当前被调用的函数结束,如果该函数有返回值,把返回值也打印到控制台
  • (2)return [expression]: 中止当前函数的调用,如果指定了expression,把expresson值当做当前函数的返回值;如果没有,直接结束当前函数调用
  • 9.信号的处理

  • (1)info signals & info handle:打印所有的信号相关的信息,以及GDB缺省的处理方式:
  • 技术分享

  • (2)handle signal action: 设置GDB对具体某个信号的处理方式。signal可以为信号整数值,也可以为SIGSEGV这样的符号。action的取值有:
  • 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(四)——–函数调用栈(call stack)探密2010年9月23日小武哥发表评论阅读评论 

    本文是GDB系列的第四篇,感兴趣的朋友可以阅读本系列的前三篇。本文的主要内容是讲如何用GDB来查看C/C++程序中函数调用栈(call stack)的相关信息,通过介绍一些相关的命令及其用法,让读者朋友能够循序渐进了解调用栈的各个方面,更好的驾驭程序。下面开始今天的内容。

    我们知道,通常一个程序的运行,不外乎是A函数调用B,B函数调用C等等,等所有的调用都完成后,整个程序的运行也就ok了。在这个过程中,每当有新的函数调用,系统都会把该函数的一些信息,包括函数的参数,以及一些寄存器的值等,保存到调用栈(call stack)上。等该函数运行完成后,这些信息再从调用栈上弹出(pop)。如下图所示,是一个完整的调用栈:技术分享在上图中,整体叫做调用栈(call stack),每一行叫做一桢(frame)。我们来看看桢信息的组成有哪些:

  • (1)桢号:调用栈中对桢的一个编号,从0开始,依次增大
  • (2)PC:Program counter寄存器,指向当前桢中下一条要执行的指令的地址
  • (3)函数名:当前桢中被调用的函数的名字
  • (4)参数及传入的值:当前桢中被调用的函数在调用时传入的参数及其值
  • (5)源码位置:当前桢执行到的源码位置,格式为 file:linenum
  • 这里还有一点需要说明,不知道细心的读者朋友有没有发现,foo那一桢没有PC的地址,GDB通过这样来标示该桢是当前正在执行到的桢,因此我们通过看调用栈的信息,便可得知程序执行到哪里了。

    读者朋友有没有觉得原来函数调用的过程还有这么多信息可以知道啊,下面我就开始介绍一些GDB命令,通过这些命令你便可以查看到上面介绍的这些信息,甚至更加详细的信息。1. 查看调用栈信息:(具体信息的内容,与上面第二部分中介绍的相同)

  • (1)backtrace: 显示程序的调用栈信息,可以用bt缩写
  • (2)backtrace n: 显示程序的调用栈信息,只显示栈顶n桢(frame)
  • (3)backtrace –n: 显示程序的调用栈信息,只显示栈底部n桢(frame)
  • (4)set backtrace limit n: 设置bt显示的最大桢层数
  • (5)where, info stack:都是bt的别名,功能一样
  • 2. 查看桢信息:

  • (1)frame n: 查看第n桢的信息, frame可以用f缩写
  • (2)frame addr: 查看pc地址为addr的桢的相关信息
  • (3)up n: 查看当前桢上面第n桢的信息
  • (4)down n: 查看当前桢下面第n桢的信息
  • 3. 查看更加详细的信息:

  • (1)info frame、info frame n或者info frame addr
  • 查看指定桢的详细信息,关于详细信息的内容,这里有必要做一个介绍,如下图所示:技术分享上图中显示的信息有:a. 当前桢的地址: 0xbffff400b. 当前桢PC: eip = 0x8048516c. 当前桢函数: bar (test.cpp:16)d. caller桢的PC: saved eip 0x8048535e. caller桢的地址: called by frame at 0xbffff420f. callee桢的地址: caller of frame at 0xbffff3e0g. 源代码所用的程序的语言(c/c++): source language c++h. 当前桢的参数的地址及值: Arglist at 0xbffff3f8, args: name=0x8048621 “jessie”, myname=0x804861c “jack”i. 当前相中局部变量的地址:Locals at 0xbffff3f8, Previous frame’s sp is 0xbffff400k. 当前桢中存储的寄存器: Saved registers: ebp at 0xbffff3f8, eip at 0xbffff3fc

    (2)info args:查看当前桢中的参数

    (3)info locals:查看当前桢中的局部变量

    (4)info catch:查看当前桢中的异常处理器(exception handlers)

     

     

    再次申明,仅当转载自己mark,大家需要的可以去原来博客去看“小武哥的博客”里面有很多丰富的资料,再次也感谢小武哥提供这么丰富的姿势共享学习:http://www.wuzesheng.com/?p=1327,http://www.wuzesheng.com/?p=1362,http://www.wuzesheng.com/?p=1386,http://www.wuzesheng.com/?p=1409

    GDB调试,转载一位大牛的东西

    标签:

    小编还为您整理了以下内容,可能对您也有帮助:

    linuxgdb调试教程linuxgdb调试

    gdbserver和gdb如何通信?

    通过linux虚拟机里的gdb,来向开发板里的gdbserver发送命令,比如设置断点,运行setp等,然后开发板上的gdbserver收到命令后,便会执行应用程序做相应的动作,来实现调试的功能

    什么是GDB?

    GDB是GNU开源组织发布的一个强大的Unix/Linux下的程序调试工具

    gdb作用是:

    1、启动用户程序后,可以按照用户的要求随意运行程序

    2、可让被调试的程序在用户所设定的断点处停住

    3、当程序被停住时,可以检查此时用户程序中所发生的事。

    4、可动态改变用户程序的执行环境。

    gdb是什么意思?

    GDB是什么

    GDB全称“GNUsymbolicdebugger”,从名称上不难看出,它诞生于GNU计划(同时诞生的还有GCC、Emacs等),是Linux下常用的程序调试器。发展至今,GDB已经迭代了诸多个版本,当下的GDB支持调试多种编程语言编写的程序,包括C、C++、Go、Objective-C、OpenCL、Ada等。实际场景中,GDB更常用来调试C和C++程序。

    gcc,gdb,mingw,cygwin,的区别是什么,有什么联系。简单点写就可以了?

    gcc是linux下的编译器,gdb是linux下的调试工具,mingw是qt下的编译器,cwgwin是在windows下的交叉编译器

    GDB调试无法加载源码?

    编译的时候用-g的参数,初始的时候只能看到main所在的源码用l打开其它源码文件后在用b加断点

    【转】GDB中应该知道的几个调试方法GDB中应该知道的几个调试方法

    2011年02月10日陈皓评论40 条评论70,776 人阅读

    七、八年前写过一篇《用GDB调试程序》,于是,从那以后,很多朋友在MSN上以及给我发邮件询问我关于GDB的问题,一直到今天,还有人在问GDB的相关问题。这么多年来,有一些问题是大家反复在问的,一方面,我觉得我以前的文章可能没有说清楚,另一方面,我觉得大家常问的问题正是最有用的,所以,在这里罗列出来。希望大家补充。

    一、多线程调试

    多线程调试可能是问得最多的。其实,重要就是下面几个命令:

    info thread 查看当前进程的线程。

    thread <ID> 切换调试的线程为指定ID的线程。

    break file.c:100 thread all 在file.c文件第100行处为所有经过这里的线程设置断点。

    set scheler-locking off|on|step,这个是问得最多的。在使用step或者continue命令调试当前被调试线程的时候,其他线程也是同时执行的,怎么只让被调试程序执行呢?通过这个命令就可以实现这个需求。

    off 不锁定任何线程,也就是所有线程都执行,这是默认值。

    on 只有当前被调试程序会执行。

    step 在单步的时候,除了next过一个函数的情况(熟悉情况的人可能知道,这其实是一个设置断点然后continue的行为)以外,只有当前线程会执行。

    二、调试宏

    这个问题超多。在GDB下,我们无法print宏定义,因为宏是预编译的。但是我们还是有办法来调试宏,这个需要GCC的配合。

    在GCC编译程序的时候,加上-ggdb3参数,这样,你就可以调试宏了。

    另外,你可以使用下述的GDB的宏调试命令来查看相关的宏。

    info macro _ 你可以查看这个宏在哪些文件里被引用了,以及宏定义是什么样的。

    macro _ 你可以查看宏展开的样子。

    三、源文件

    这个问题问的也是很多的,太多的朋友都说找不到源文件。在这里我想提醒大家做下面的检查:

    编译程序员是否加上了-g参数以包含debug信息。

    路径是否设置正确了。使用GDB的directory命令来设置源文件的目录。

    下面给一个调试/bin/ls的示例(ubuntu下)

    1.2

    3.4

    5.6

    7.8

    9.10

    11.12

    13.14

    15.16

    17.18

    19.20

    $ apt-getsource coreutils

    $sudo apt-getinstall coreutils-dbgsym

    $gdb /bin/ls

    GNUgdb (GDB) 7.1-ubuntu

    (gdb) list main

    1192ls.c: No suchfile or directory.

    in ls.c

    (gdb) directory ~/src/coreutils-7.4/src/

    Source directories searched:/home/hchen/src/coreutils-7.4:$cdir:$cwd

    (gdb) list main

    1192 }

    1193 }

    1194

    1195 int

    1196 main (int argc, char **argv)

    1197 {

    1198 int i;

    1199 struct pending *thispend;

    1200 int n_files;

    1201

    四、条件断点

    条件断点是语法是:break [where] if [condition],这种断点真是非常管用。尤其是在一个循环或递归中,或是要监视某个变量。注意,这个设置是在GDB中的,只不过每经过那个断点时GDB会帮你检查一下条件是否满足。

    五、命令行参数

    有时候,我们需要调试的程序需要有命令行参数,很多朋友都不知道怎么设置调试的程序的命令行参数。其实,有两种方法:

    gdb命令行的 _args 参数

    gdb环境中 set args命令。

    六、gdb的变量

    有时候,在调试程序时,我们不单单只是查看运行时的变量,我们还可以直接设置程序中的变量,以模拟一些很难在测试中出现的情况,比较一些出错,或是switch的分支语句。使用set命令可以修改程序中的变量。

    另外,你知道gdb中也可以有变量吗?就像shell一样,gdb中的变量以$开头,比如你想打印一个数组中的个个元素,你可以这样:

    1.2

    3.4

    5.(gdb)set $i = 0

    (gdb) p a[$i++]

    ... #然后就一路回车下去了

    当然,这里只是给一个示例,表示程序的变量和gdb的变量是可以交互的。

    七、x命令

    也许,你很喜欢用p命令。所以,当你不知道变量名的时候,你可能会手足无措,因为p命令总是需要一个变量名的。x命令是用来查看内存的,在gdb中 “help x” 你可以查看其帮助。

    x/x 以十六进制输出

    x/d 以十进制输出

    x/c 以单字符输出

    x/i 反汇编 _ 通常,我们会使用x/10i $ip-20 来查看当前的汇编($ip是指令寄存器)

    x/s 以字符串输出

    八、command命令

    有一些朋友问我如何自动化调试。这里向大家介绍command命令,简单的理解一下,其就是把一组gdb的命令打包,有点像字处理软件的“宏”。下面是一个示例:

    1.2

    3.4

    5.6

    7.8

    9.10

    (gdb)break func

    Breakpoint 1 at 0x3475678:file test.c, line 12.

    (gdb)command 1

    Type commandsfor when breakpoint 1 is hit, one per line.

    End with a line saying just"end".

    >print arg1

    >print arg2

    >print arg3

    >end

    (gdb)

    当我们的断点到达时,自动执行command中的三个命令,把func的三个参数值打出来。

    (全文完)

    【转】GDB中应该知道的几个调试方法

    标签:字符串定义pad执行endharnexthref来源

    gdb调试命令是什么?

    gdb调试命令如下:

    1、启动gdb

    $gdb 

    这样可以和gdb进行交互了。 

    2、启动gdb,并且分屏显示源代码 

    $gdb -tui 

    这样,使用了'-tui'选项,启动可以直接将屏幕分成两个部分,上面显示源代码,比用list方便多了。这时候使用上下方向键可以查看源代码,想要命令行使用上下键就用[Ctrl]n和[Ctrl]p。

    3、启动gdb调试指定程序app

    $gdb app 

    这样就在启动gdb之后直接载入了app可执行程序,需要注意的是,载入的app程序必须在编译的时候有gdb调试选项,例如'gcc -g app app.c',注意,如果修改了程序的源代码,但是没有编译,那么在gdb中显示的会是改动后的源代码,但是运行的是改动前的程序,这样会导致跟踪错乱的。 

    4、启动程序之后,再用gdb调试

    $gdb <program> <PID> 

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

    5、启动程序之后,再启动gdb调试

    $gdb <PID> 

    这里,程序是一个服务程序,那么你可以指定这个服务程序运行时的进程ID,<PID>是要调试程序的PID.这样gdb就附加到程序上了,但是现在还没法查看源代码,用file命令指明可执行文件就可以显示源代码了。

    显示全文