GDB 用法记录

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

    bt                 // 打印当前的函数调用栈的所有信息
    bt full

    backtrace <n>
    bt <n>
        n是一个正整数,表示只打印栈顶上n层的栈信息。

    backtrace <-n>
    bt <-n>
        -n表一个负整数,表示只打印栈底下n层的栈信息

/*
 * info
 */
    info line        // 查看源代码在内存中的地址。

    info line后面可以跟"行号","函数名","文件名:行号","文件名:函数名",这个命令会打印出所指定的源码在运行时的内存地址
        (gdb) info line tst.c:func
        Line 5 of "tst.c" starts at address 0x8048456 <func+6> and ends at 0x804845d <func+13>.

    info f            // 这个命令会打印出更为详细的当前栈层的信息,只不过,大多数都是运行时的内内地址。
    info args        // 打印出当前函数的参数名及其值。
    info locals        // 打印出当前函数中所有局部变量及其值。
    info catch        // 打印出当前的函数中的异常处理信息。
    info terminal    // 显示你程序用到的终端的模式
    info registers
    info break
    info signals
    info handle
    info threads

/*
 * 查看某一层的信息
 */
    frame <n>
    f <n>
        n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。
   
    up <n>
        表示向栈的上面移动n层,可以不打n,表示向上移动一层。
       
    down <n>
        表示向栈的下面移动n层,可以不打n,表示向下移动一层。

/*
 * 显示寄存器
 */
    info reg可以显示寄存器内容。

    在寄存器名之前加$可以显示寄存器内容,

        p $寄存器:显示寄存器内容

        p/x $寄存器:十六进制显示寄存器内容。

    用x命令可以显示内容内容,"x/格式 地址"。

        x $pc:显示程序指针内容

        x/i $pc:显示程序指针汇编。

        x/10i $pc:显示程序指针之后10条指令。

        x/128wx 0xfc207000:从0xfc20700开始以16进制打印128个word。

        x/10w $esp        // 显示栈里的10个数据,其中左边第一列是栈地址。
        
        x/s 0x080484f0    // 栈中字符串格式的内存地址(指针)
        x/s $rdi

        x/5i 0x0804844a    // 显示出这个地址开始的指令

        x/10g $rsp        // 显示栈中的数值,g 代表 giant words.

/*
 * x : 查看内存
 */
    examine 命令(简写是 x )来查看内存地址中的值。

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

    n、f、u是可选的参数。

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

    f 表示显示的格式,参见上面。如果地址所指的是字符串,那么格式可以是s,如果地十是指令地址,那么格式可以是i。

    u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,b表示单字节,h表示双字节,w表示四字节,
        g表示八字节。当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。

    <addr>表示一个内存地址。

    n/f/u三个参数可以一起使用。
        
        命令:x/3uh 0x54320 表示,从内存地址0x54320读取内容,h表示以双字节为一个单位,3表示三个单位,u表示按十六进制显示。
    
    x /nfu 0x<addr>:查看内存地址中的值。

n表示要显示的内存单元的个数

f表示显示方式, 可取如下值

x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
i 指令地址格式
c 按字符格式显示变量。
f 按浮点数格式显示变量。

u表示一个地址单元的长度

b表示单字节,

h表示双字节,

w表示四字节,

g表示八字节

可以用来查看当前汇编代码:
        x/5i $pc
        x/5ih $pc

    char *c = "hi";

    (gdb) p c
    $1 = 0x075f4688 "hi"

    (gdb) x/s 0x075f4688
    0x075f4688:     "hi"

    (gdb) p (char *)0x075f4688
    $3 = 0x075f4688 "hi"

    (gdb) p *(char *)0x075f4688='H'        // 将第一个字符改为大写
    $4 = 72 'H'

    (gdb) p c
    $5 = 0x075f4688 "Hi"


/*
 * disassemble
 */
    disassemble

    disassemble 程序计数器 :反汇编pc所在函数的整个函数。

    disassemble addr-0x40,addr+0x40:反汇编addr前后0x40大小。

    disassemble function-name

/*
 * 监视点
 */
    要想找到变量在何处被改变,可以使用watch命令设置监视点watchpoint。

    watch <表达式>:表达式发生变化时暂停运行

    awatch <表达式>:表达式被访问、改变是暂停执行

    rwatch <表达式>:表达式被访问时暂停执行

    info watchpoints    列出当前所设置了的所有观察点

    watch counter>15    // 当counter>15的时候程序终止

/*
 * 设置捕捉点(CatchPoint)
 */
    设置捕捉点来捕捉程序运行时的一些事件。如:载入共享库(动态链接库)或是C++的异常。设置捕捉点的格式如下:
             
    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 <libname> 载入共享库(动态链接库)时。(load为关键字,目前此功能只在HP-UX下有用)
    7、unload 或 unload <libname> 卸载共享库(动态链接库)时。(unload为关键字,目前此功能只在HP-UX下有用)

    tcatch <event>
    只设置一次捕捉点,当程序停住以后,应点被自动删除。


/*
 * 带有命令行参数
 */    
    gdb binary-operation
    set args 6

    使用两种方法输入命令行参数
        1)run  命令行参数
        2)set args  命令行参数

/*
 * list:显示程序中的代码,常用使用格式有:
 */
    list
        输出从上次调用list命令开始往后的10行程序代码。
    list -
        输出从上次调用list命令开始往前的10行程序代码。
    list n
        输出第n行附近的10行程序代码。
    list function
        输出函数function前后的10行程序代码。

/*
 * layout : 显示源码窗口
 */
    可以使用"layout src"命令,或者按Ctrl-X再按A(重复按一遍则可以关闭),就会出现一个窗口可以查看源代码。

    也可以使用 -tui参数,这样进入gdb里面后就能直接打开代码查看窗口。

    窗口相关命令    功能
    info win    显示窗口的大小
    layout next    切换到下一个布局模式
    layout prev    切换到上一个布局模式
    layout src    只显示源代码
    layout asm    只显示汇编代码
    layout split    显示源代码和汇编代码
    layout regs    增加寄存器内容显示
    focus cmd/src/asm/regs/next/prev    切换当前窗口
    refresh    刷新所有窗口
    tui reg next    显示下一组寄存器
    tui reg system    显示系统寄存器
    update    更新源代码窗口和当前执行点
    winheight name +/- line    调整name窗口的高度
    tabset nchar    设置tab为nchar个字符

/*
 * condition:设置断点在一定条件下才能生效。
 */
    前面在说到设置断点时,提到过可以设置一个条件,当条件成立时,程序自动停止,这是一个非常强大的功能,

    一般来说,为断点设置一个条件,我们使用if关键词,后面跟其断点条件。并且,条件设置好后,
    我们可以用condition命令来修改断点的条件。
    (只有break和 watch命令支持if,catch目前暂不支持if)

condition 断点号 条件表达式

* cont/continue:使程序在暂停在断点之后继续运行。使用格式:
cont
跳过当前断点继续运行。
cont n
跳过n次断点,继续运行。
    当n为1时,cont 1即为cont。

    condition <bnum> <expression>
        修改断点号为bnum的停止条件为expression。

    condition <bnum>
        清除断点号为bnum的停止条件。

    ignore <bnum> <count>
        指定程序运行时,忽略断点号为bnum的停止条件count次。

/*
 * ptype and whatis :显示数据类型
 */
* 和whatis类似,用于显示数据类型,但是它还可以显示typedef定义的类型等。使用格式:
ptype 变量或表达式
    
* whatis 命令可以显示某个变量的类型
    "(gdb) whatis p
    type = int *

/*
 * set:设置程序中变量的值。
 */
    set 变量=表达式
    set 变量:=表达式

    set prompt $把gdb的提示符设为$.
    set args 可指定运行时参数。(如:set args 10 20 30 40 50)
    show args 命令可以查看设置好的运行参数。
    "(gdb)set args –b –x
    "(gdb) show args    

    set width 70        // 设置gdb的列宽,以下为将屏幕设置为70列

    gdb a.out core
    where                // 查看导致崩溃的原因

    (gdb) set $epc = 0xbfc00000                    // 修改寄存器
    (gdb) set {unsigned int}0x8048a51=0x0        // 修改内存

    set print address                // 地址输出
    set print address on
    set print address off
    show print address                // 查看当前地址显示选项是否打开
    打开地址输出,当程序显示函数信息时,GDB会显出函数的参数地址。系统默认为打开的,如:
    
    (gdb) frame
        #0 set_quotes (lq=0x34c78 "<<", rq=0x34c88 ">>")    // print address on

    (gdb) f
        #0 set_quotes (lq="<<", rq=">>") at input.c:530        // print address off

    set print array                // 数组显示
    set print array on
    set print array off
    show print array
    打开数组显示,打开后当数组显示时,每个元素占一行,如果不打开的话,每个元素则以逗号分隔。这个选项默认是关闭的。

    set print elements <number-of-elements>        // 更改打印字符串的长度
    show print elements                            // 查看print elements的选项信息
    这个选项主要是设置数组的,如果你的数组太大了,那么就可以指定一个<number-of-elements>来指定数据显示的最大长度,
    当到达这个长度时,GDB就不再往下显示了。如果设置为0,则表示不限制。

        set print elements 300            ; 300 char
        set print elements 0            ; set unlimted

    set print null-stop <on/off>
    如果打开了这个选项,那么当显示字符串时,遇到结束符则停止显示。这个选项默认为off。

    set print pretty on
    set print pretty off
    show print pretty                        // 查看GDB是如何显示结构体的
    如果打开printf pretty这个选项,那么当GDB显示结构体时会比较漂亮。
    
    set print sevenbit-mains <on/off>
    show print sevenbit-mains                // 查看字符显示开关是否打开
    设置字符显示,是否按"\nnn"的格式显示,如果打开,则字符串或字符数据按\nnn显示,如"\065"。

    set print union <on/off>
    show print union                        // 查看联合体数据的显示方式
    设置显示结构体时,是否显式其内的 union 联合体数据

    set print object <on/off>
    show print object                        // 查看对象选项的设置
    在C++中,如果一个对象指针指向其派生类,如果打开这个选项,GDB会自动按照虚方法调用的规则显示输出,
    如果关闭这个选项的话,GDB就不管虚函数表了。这个选项默认是off。

    set print static-members <on/off>
    show print static-members                // 查看静态数据成员选项设置
    这个选项表示,当显示一个C++对象中的内容是,是否显示其中的静态数据成员。默认是on。

    set print vtbl <on/off>
    show print vtbl                            // 查看虚函数显示格式的选项
    当此选项打开时,GDB将用比较规整的格式来显示虚函数表时。其默认是关闭的。

    用不带任何参变量的'set'命令可以显示所有可以设置的变量的值

/*
 * show
 */
    show命令用来显示gdb自身的状态。

    使用'set'命令可以改变绝大多数由'show'显示的信息
    
    show radix        // 显示基数
    show version    // 显示gdb的版本号
    show copying    // 显示版权信息
    show warranty    // 显示担保信息

    path <dir>  设定程序的运行路径。
    show paths  查看程序的运行路径。

    tty         指写输入输出的终端设备。如:tty /dev/ttyb

/*
 * display
 */
    你可以设置一些自动显示的变量,当程序停住时,或是在你单步跟踪时,这些变量会自动显示。相关的GDB命令是display。

    display <expr>
    display/<fmt> <expr>
    display/<fmt> <addr>

    expr是一个表达式,fmt表示显示的格式,addr表示内存地址

    格式i和s同样被display支持    
    
    display/i $pc        // $pc 是GDB的环境变量,表示着指令的地址,/i 则表示输出格式为机器指令码,也就是汇编。
                        // 于是当程序停下后,就会出现源代码和机器指令码相对应的情形,这是一个很有意思的功能。

    undisplay <dnums...>
    delete display <dnums...>
    删除自动显示,dnums意为所设置好了的自动显式的编号。如果要同时删除几个,编号可以用空格分隔,
    如果要删除一个范围内的编号,可以用减号表示(如:2-5)

    disable display <dnums...>
    enable display <dnums...>
    disable和enalbe不删除自动显示的设置,而只是让其失效和恢复。

    info display
    查看display设置的自动显示的信息。GDB会打出一张表格,向你报告当然调试中设置了多少个自动显示设置,
    其中包括,设置的编号,表达式,是否enable。

    delete display num    // num 为前面变量前的编号,不带num时清除所有。

    disable display num // num 为前面变量前的编号,不带num时去使能所有

    (gdb) display a        // 在每个断点或是每执行一步时显示该叙述值

    display *node@10    // 数组

/*
 * print 显示数据
 */
    (print 指令可简写为 p)

    print <expr>
    print /<f> <expr>
    
    <expr>是表达式,是被调试的程序中的表达式,<f>是输出的格式,比如,如果要把表达式按16进制的格式输出,那么就是/x。
    在表达式中,有几种GDB所支持的操作符,它们可以用在任何一种语言中,
    "@"是一个和数组有关的操作符,
    "::"指定一个在文件或是函数中的变量,
    "{<type>} <addr>"表示一个指向内存地址<addr>的类型为type的一个对象。

    (gdb) print a => 显示 a 变量的内容.
    (gdb) print sizeof(a) => 显示 a 变量的长度.
    (gdb) print (a=10) => 将变量 a 的值设定为 10.    // 更改变量值:
    (gdb) print find_entry(1,0)                        // 对程序中函数的调用
    (gdb) print *table_start                        // 数据结构和其他复杂对象
        $8={e=reference=’\000’,location=0x0,next=0x0}
        
    (gdb)print $1 ($1为历史记录变量,在以后可以直接引用 $1 的值)    // 值的历史成分
    
    x 按十六进制格式显示变量。
    d 按十进制格式显示变量。
    u 按十六进制格式显示无符号整型。
    o 按八进制格式显示变量。
    t 按二进制格式显示变量。
    a 按十六进制格式显示变量。
    c 按字符格式显示变量。
    f 按浮点数格式显示变量。

    print  variable            // 查看变量
    print  *array@len        // 查看数组(array是数组指针,len是需要数据长度)
    print(p)                // 查看运行时的变量以及表达式。
    print(p) array            // 查看数组,
    print(p) array[1],        // 查看数组第2个元素。
    print(p) *array@len        // 查看动态内存。
    print(p) x=5            // 改变运行时数据。
    print xxx                // 打印变量
    p /x xxx                // 16进制显示
    p str@str_len            // 打印字符串
    printf "%2.2s/n",(char*)0x120100fa0

    /*
     * 数组
     */    
        p *array@len            
        p *node@10    

/*
 * 函数的调用
 */
    call name 调用和执行一个函数
    (gdb) call gen_and_sork( 1234,1,0 )
    (gdb) call printf("abcd")
    $1=4
    
    finish 结束执行当前函数,显示其返回值(如果有的话)

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

    利用set args 命令就可以修改发送给程序的参数,而使用show args 命令就可以查看其缺省参数的列表。

/*
* 设置临时断点
*/
* tbreak :设置临时断点,在设置之后只起作用一次。使用格式:
tbreak 要设置临时断点的行号

/*
 * 断点(breakpoint)
 */
    break命令(可以简写为b)可以用来在调试的程序中设置断点,该命令有如下四种形式:
    break line-number 使程序恰好在执行给定行之前停止。
    break function-name 使程序恰好在进入指定的函数之前停止。
    break line-or-function if condition 如果condition(条件)是真,程序到达指定行或函数时停止。
    break routine-name 在指定例程的入口处设置断点

    如果该程序是由很多原文件构成的,你可以在各个原文件中设置断点,而不是在当前的原文件中设置断点,其方法如下:
    (gdb) break filename:line-number    // b single_link.c:300
    (gdb) break filename:function-name    // b single_link.c:init

    要想设置一个条件断点,可以利用break if命令,如下所示:
    (gdb) break line-or-function if expr
    (gdb) break 46 if testsize==100

    从断点继续运行:countinue 命令

    break <function>
    在进入指定函数时停住,C++中可以使用class::function或function(type, type)格式来指定函数名。

    break <linenum>
    在指定行号停住。

    break +offset / break -offset
    在当前行号的前面或后面的offset行停住,offiset为自然数。

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

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

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

    break
    break命令没有参数时,表示在下一条指令处停住。

    break ... if <condition>
    "..."可以是上述的break <linenum>、break +offset / break –offset中的参数,condition表示条件,在条件成立时停住。
    比如在循环体中,可以设置break if i=100,表示当i为100时停住程序。

    break *ADDRESS
    在地址ADDRESS上设置断点,这个命令允许你在没有调试信息的程序中设置断点

    hbreak ARGS
    设置一个由硬件支持的断点。这个命令的主要目的是用于对EPROM/ROM程序的调试    因为这条命令可以在不改变代码的情况下设置断点。
    这可以同SPARCLite DSU一起使用。当程序访问某些变量和代码时,DSU将设置"陷井"。
    注意:你只能一次使用一个断点,在新设置断点时,先删除原断点

    rbreak REGEX
    在所有满足表达式REGEX的函数上设置断点。这个命令在所有相匹配的函数上设置无条件断点,当这个命令完成时显示所有被设置的断点信息。
    这个命令设置的断点和break命令设置的没有什么不同。当调试C++程序时这个命令在重载函数上设置断点时非常有用。

    查看断点时,可使用info命令,如info breakpoints [n]、info break [n](n表示断点号)。

    /*
     * 断点的管理
     */
        1. 显示当前gdb的断点信息:
        "(gdb) info break
        2.删除指定的某个断点:
        "(gdb) delete breakpoint 1
        该命令将会删除编号为1的断点,如果不带编号参数,将删除所有的断点
        "(gdb) delete breakpoint
        3.禁止使用某个断点
        "(gdb) disable breakpoint 1
        该命令将禁止断点 1,同时断点信息的 (Enb)域将变为 n
        4.允许使用某个断点
        "(gdb) enable breakpoint 1
        该命令将允许断点 1,同时断点信息的 (Enb)域将变为 y
        5.清除原文件中某一代码行上的所有断点
        "(gdb)clean number
        注:number 为原文件的某个代码行的行号

    /* info breakpoints */
    *Breakpoint Numbers*----断点号
    *Type*----断点类型(断点或是观察点)
    *Disposition*---显示断点的状态
    *Enabled or Disabled*---使能或不使能。'y'表示使能,'n'表示不使能。
    *Address*----地址,断点在你程序中的地址(内存地址)
    *What*---地址,断点在你程序中的行号。

    如果断点是条件断点,此命令还显示断点所需要的条件。带参数N的'info break'命令只显示由N指定的断点的信息。
    此命令还显示断点的运行信息(被执行过几次),这个功能在使用'ignore' 命令时很有用。你可以'ignore'一个断点许多次。使用这个命令可以查看断点
    被执行了多少次。这样可以更快的找到错误。

    /* maint info breakpoints */        
        显示所有的断点,无论是你设置的还是gdb自动设置的。

    /* 断点的含义 */
        breakpoint:断点,普通断点
        watchpoint:普通观察点
        longjmp:内部断点,用于处理'longjmp'调用
        longjmp resume:内部断点,设置在'longjmp'调用的目标上
        until:'until'命令所使用的内部断点
        finish:finish'命令所使用的内部断点

    /*
     * 断点菜单
     */
        在 C++中,可能会重复出现同一个名字的函数若干次(函数重载),在这种情况下,break <function>不能告诉GDB要停在哪个函数的入口。
        这时可以使用break <function(type)>也就是把函数的参数类型告诉GDB,以指定一个函数。
        否则的话,GDB会给你列出一个断点菜单供你选择你所需要的断点。
        你只要输入你菜单列表中的编号就可以了。
           
        (gdb) b main::test
        [0] cancel
        [1] all
        [2] file:main.cpp; line number:77
        [3] file:main.cpp; line number:160
        [4] file:main.cpp; line number:175
        [5] file:main.cpp; line number:153
        [6] file:main.cpp; line number:146
        [7] file:main.cpp; line number:135
        > 2 4 6
        Breakpoint 1 at 0xb26c: file main.cpp, line 77.
        Breakpoint 2 at 0xb344: file main.cpp, line 175.
        Breakpoint 3 at 0xafcc: file main.cpp, line 146.
        Multiple breakpoints were set.
        Use the "delete" command to delete unwanted
        breakpoints.
        (gdb)
               
        可见,GDB列出了所有test的重载函数,你可以选一下列表编号就行了。0表示放弃设置断点,1表示所有函数都设置断点。

/*
 * commands
 */
* commands:设置在遇到断点后执行特定的指令。使用格式有:
commands
设置遇到最后一个遇到的断点时要执行的命令
commands n
设置遇到断点号n时要执行的命令
注意,commands后面跟的是断点号,而不是断点所在的行号。
在输入命令后,就可以输入遇到断点后要执行的命令,每行一条命令,在输入最后一条命令后输入end就可以结束输入。

    /*
     * 为停止点设定运行命令
     */
        GDB提供 command 命令来设置停止点的运行命令。也就是说,当运行的程序被停止住时,可以让其自动运行一些别的命令,
        这很有利行自动化调试。

        对基于GDB的自动化调试是一个强大的支持。详细如下:
                    
        commands [bnum]
        ... command-list ...
        end

        为断点号bnum指写一个命令列表。当程序被该断点停住时,gdb会依次运行命令列表中的命令。
                    
        例如:
        break foo if x>0
        commands
        printf "x is %d\n",x
        continue
        end

        断点设置在函数foo中,断点条件是x>0,如果程序被断住后,也就是,一旦x的值在foo函数中大于0,GDB会自动打印出x的值,
        并继续运行程序。
                    
        如果你要清除断点上的命令序列,那么只要简单的执行一下commands命令,并直接在打个end就行了。

/*
 * continue
 */
    程序被停住后用continue命令恢复程序的运行直到程序结束,或下一个断点到来。也可以使用step或next命令单步跟踪程序。
           
    continue [ignore-count]
    c [ignore-count]

    fg [ignore-count]
        恢复程序运行,直到程序结束,或是下一个断点到来。
        ignore-count表示忽略其后的断点次数。continue,c,fg三个命令都是一样的意思。

    step <count>
        单步跟踪,有函数调用时进入该函数。进入函数的前提是,此函数被编译有debug信息。
        后面可以加count也可以不加,不加表示一条条地执行,加表示执行后面的count条指令,然后再停住。

    next <count>
        单步跟踪,有函数调用不会进入该函数。后面可以加count也可以不加,不加表示一条条地执行,
        加表示执行后面的count条指令,然后再停住。

    set step-mode
    set step-mode on
        打开step-mode模式,于是,在进行单步跟踪时,程序不会因为没有debug信息而不停住。这个参数有很利于查看机器码。

    set step-mod off
        关闭step-mode模式。

    finish
        运行程序,直到当前函数完成返回。并打印函数返回时的堆栈地址和返回值及参数值等信息。

    until 或 u
        在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体。

    stepi 或 si
    nexti 或 ni
        单步跟踪一条机器指令!一条程序代码有可能由数条机器指令完成,stepi和nexti可以单步执行机器指令。
        与之一样有相同功能的命令是"display/i $pc" ,当运行完这个命令后,
        单步跟踪会在打出程序代码的同时打出机器指令(也就是汇编代码)

/*
 * 单步执行
 */
* next:继续执行语句,但是跳过子程序的调用。使用格式:
next
执行一条语句
next n
执行n条语句

* nexti:单步执行语句,但和next不同的是,它会跟踪到子程序的内部,但不打印出子程序内部的语句。使用格式同上。
* step:与next类似,但是它会跟踪到子程序的内部,而且会显示子程序内部的执行情况。使用格式同上。
* stepi:与step类似,但是比step更详细,是nexti和step的结合。使用格式同上。

    单步执行有两个命令next和step,两者的区别是next遇到函数不会进入函数内部,step会执行到函数内部。

    如果需要逐条汇编指令执行,可以分别使用nexti和stepi。

    s : Step Into (单步跟踪进入)
    n : Step Over (单步跟踪)
        "si"命令用于执行一条汇编代码——区别于"s"执行一行C代码

/*
 * 维护停止点
 */  
    delete、clear、disable、enable这几个命令来进行维护。

    clear                            // 清除所有的已定义的停止点。
    clear <function>
    clear <filename:function>        // 清除所有设置在函数上的停止点。
                        
    clear <linenum>
    clear <filename:linenum>        // 清除所有设置在指定行上的停止点。                        

/*
 * 命令的历史
 */
    为了允许使用历史命令,可使用 set history expansion on 命令 (gdb) set history expansion on

    当你用GDB的print查看程序运行时的数据时,你每一个print都会被GDB记录下来。
    GDB会以$1, $2, $3 .....这样的方式为你每一个print命令编上号。

    于是,你可以使用这个编号访问以前的表达式,如$1。这个功能所带来的好处是,
    如果你先前输入了一个比较长的表达式,如果你还想查看这个表达式的值,你可以使用历史记录来访问,省去了重复输入。

/*
 * -g 等级
 */
    如果不打开-g或者-ggdb(GDB专用)调试开关,GCC编译时不会加入调试信息,因为这会增大生成代码的体积。GCC采用了分级调试,
    通过在-g选项后附加数字1、2或3来指定在代码中加入调试信息量。

    默认的级别是2(-g2),此时调试信息包括扩展的符号表、行号、局部或外部变量信息。

    级别3(- g3)包含级别2中的调试信息和源代码中定义的宏。
    级别1(- g1)不包含局部变量和与行号有关的调试信息,只能用于回溯跟踪和堆栈转储之用。
    [ 回溯跟踪指的是监视程序在运行过程中的函数调用历史,
    堆栈转储则是一种以原始的十六进制格式保存程序执行环境的方法,两者都是经常用到的调试手段。] 。

/*
 * GDB的启动:
 */
    1、 gdb <program>

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

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

    make <make-args> 不退出GDB就重新编译程序


/*
 * 调试已运行的程序
 */
    两种方法:
    1.在UNIX下用ps查看正在运行的程序的PID(进程ID),然后用gdb <program> PID格式挂接正在运行的程序。
    2.先用gdb <program>关联上源代码,并进行gdb,在gdb中用attach命令来挂接进程的PID。并用detach来取消挂接的进程。

/*
 * 原文件的搜索
 */
    search text:该命令可显示在当前文件中包含text串的下一行。
    Reverse-search text:该命令可以显示包含text 的前一行。

/*
 * UNIX接口
 */
    "shell 命令可启动UNIX外壳,CTRL-D退出外壳,返回到 gdb.

/*
 * GDB环境变量
 */
    你可以在GDB的调试环境中定义自己的变量,用来保存一些调试程序中的运行数据。要定义一个GDB的变量很简单只需。使用GDB的set命令。
    GDB的环境变量和UNIX一样,也是以$起头。如:

    set $foo = *object_ptr

    使用环境变量时,GDB会在你第一次使用时创建这个变量,而在以后    的使用中,则直接对其賦值。环境变量没有类型,
    你可以给环境变量定义任一的类型。包括结构体和数组。

    show convenience
    该命令查看当前所设置的所有的环境变量。

    这是一个比较强大的功能,环境变量和程序变量的交互使用,将使得程序调试更为灵活便捷。例如:

    set $i = 0
    print bar[$i++]->contents

    于是,当你就不必,print bar[0]->contents, printbar[1]->contents地输入命令了。
    输入这样的命令后,只用敲回车,重复执行上一条语句,环境变量会自动累加,从而完成逐个输出的功能。

/*
 * 改变程序的执行
 */
    一旦使用GDB挂上被调试程序,当程序运行起来后,你可以根据自己的调试思路来动态地在GDB中更改当前被调试程序的运行线路
    或是其变量的值,这个强大的功能能够让你更好的调试你的程序,比如,你可以在程序的一次运行中走遍程序的所有分支。

/*
 * 修改变量值
 */
    修改被调试程序运行时的变量值,在GDB中很容易实现,使用GDB的print命令即可完成。如:

    (gdb) print x=4

    x=4这个表达式是C/C++的语法,意为把变量x的值修改为4,如果你当前调试的语言是Pascal,那么你可以使用Pascal的语法:x:=4。

    在某些时候,很有可能你的变量和GDB中的参数冲突,如:

    (gdb) whatis width
    type = double
    (gdb) p width
    $4 = 13
    (gdb) set width=47
    Invalid syntax in expression.

    因为,set width是GDB的命令,所以,出现了"Invalid syntax inexpression"的设置错误,此时,你可以使用set var命令来告诉GDB,
    width不是你GDB的参数,而是程序的变量名,如:

    (gdb) set var width=47

    另外,还可能有些情况,GDB并不报告这种错误,所以保险起见,在你改变程序变量取值时,最好都使用set var格式的GDB命令。

/*
 * 跳转执行
 */
    一般来说,被调试程序会按照程序代码的运行顺序依次执行。GDB提供了乱序执行的功能,也就是说,GDB可以修改程序的执行顺序,
    可以让程序执行随意跳跃。这个功能可以由GDB的jump命令来完:

    jump <linespec>
    指定下一条语句的运行点。<linespce>可以是文件的行号,可以是file:line格式,可以是+num这种偏移量格式。
    表式着下一条运行语句从哪里开始。

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

    注意,jump命令不会改变当前的程序栈中的内容,所以,当你从一个函数跳到另一个函数时,
    当函数运行完返回时进行弹栈操作时必然会发生错误,

    可能结果还是非常奇怪的,甚至于产生程序Core Dump。所以最好是同一个函数中进行跳转。

    熟悉汇编的人都知道,程序运行时,有一个寄存器用于保存当前代码所在的内存地址。所以,jump命令也就是改变了这个寄存器中的值。
    于是,你可以使用"set $pc"来更改跳转执行的地址。如:

    set $pc = 0x485

/*
 * 强制函数返回
 */
    如果你的调试断点在某个函数中,并还有语句没有执行完。你可以使用return命令强制函数忽略还没有执行的语句并返回。

    return
    return <expression>
    使用return命令取消当前函数的执行,并立即返回,如果指定了<expression>,那么该表达式的值会被认作函数的返回值。

/*
 * 强制调用函数
 */
    call <expr>
    表达式中可以一是函数,以此达到强制调用函数的目的。并显示函数的返回值,如果函数返回值是void,那么就不显示。

    另一个相似的命令也可以完成这一功能——print,print后面可以跟表达式,所以也可以用他来调用函数,print和call的不同是,
    如果函数返回void,call则不显示,print则显示函数返回值,并把该值存入历史数据中。

    在不同语言中使用GDB支持下列语言:C, C++, Fortran, PASCAL, Java, Chill,assembly, 和 Modula-2。
    一般说来,GDB会根据你所调试的程序来确定当然的调试语言,比如:发现文件名后缀为".c"的,GDB会认为是C程序。
    文件名后缀为 ".C, .cc, .cp, .cpp, .cxx, .c++"的,GDB会认为是C++程序。
    而后缀是".f, .F"的,GDB会认为是Fortran程序,还有,后缀为如果是".s, .S"的会认为是汇编语言。

    也就是说,GDB会根据你所调试的程序的语言,来设置自己的语言环境,并让GDB的命令跟着语言环境的改变而改变。比如一些GDB命令需
    要用到表达式或变量时,这些表达式或变量的语法,完全是根据当前的语言环境而改变的。例如C/C++中对指针的语法是*p,而在
    Modula-2中则是p^。并且,如果你当前的程序是由几种不同语言一同编译成的,那到在调试过程中,GDB也能根据不同的语言自动地切换
    语言环境。这种跟着语言环境而改变的功能,真是体贴开发人员的一种设计。

    下面是几个相关于GDB语言环境的命令:

    show language
    查看当前的语言环境。如果GDB不能识为你所调试的编程语言,那么,C语言被认为是默认的环境。

    info source
    查看当前文件的程序语言。

    如果GDB没有检测出当前的程序语言,那么你也可以手动设置当前的程序语言。使用set language命令即可做到。

    当set language命令后什么也不跟的话,你可以查看GDB所支持的语言种类:

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《debugging with gdb》是一本关于使用GDB进行调试的指南。GDB(GNU调试器)是一个强大的调试工具,可以用于调试各种编程语言,如C、C++、Fortran等。 这本书详细介绍了GDB的安装和配置,并提供了许多示例来说明如何使用它来调试程序。它从基本的调试命令开始,如设置断点、单步执行、查看变量的值等。然后,它介绍了更高级的调试功能,如条件断点、观察点、跟踪函数调用等。 书中还介绍了如何使用GDB来调试多线程程序和动态库。它解释了如何设置线程断点、查看线程状态和跟踪线程的执行路径。此外,它还介绍了如何对动态链接库进行调试,包括加载和卸载库、查看库中的符号和调用库中的函数等。 此外,《debugging with gdb》还介绍了如何使用GDB进行内存调试。它涵盖了诸如检测内存泄漏、跟踪指针问题和查找内存错误等主题。通过这本书,读者可以学习如何使用GDB来诊断和解决各种程序错误和问题。 总之,《debugging with gdb》是一本全面而详细的关于使用GDB进行调试的指南。无论是有经验的开发人员还是初学者,都可以从中学习到如何使用GDB来快速定位和解决程序中的错误。 ### 回答2: GDB是一个调试器,用于帮助开发者在程序中找出错误并进行调试。它提供了许多功能和命令,可以让开发者在程序运行过程中获取各种有用的信息。 在使用GDB进行调试之前,首先需要将程序编译成可调试的二进制文件。可以使用编译器的参数“-g”来生成包含调试信息的可执行文件。编译完成后,可以通过终端命令"gdb <可执行文件名>"启动GDB,并载入要调试的程序。 一旦进入GDB调试界面,可以使用各种命令来控制程序的执行。例如,可以使用"break <函数名>"命令在特定的函数内设置断点,当程序执行到该函数时会触发断点,并暂停程序的执行。可以使用"run"命令来运行程序,当程序遇到断点时会暂停,并在终端显示相关的调试信息。 一旦程序暂停在断点处,就可以使用GDB提供的许多命令来检查程序状态和寻找错误。例如,可以使用"print <变量名>"命令来打印特定变量的值,以确定其是否符合预期。还可以使用"step"命令来逐行执行程序,并跟踪程序的执行流程,以查找错误所在。 在调试过程中,还可以使用其他命令来查看函数调用栈,设置条件断点,监视特定变量的值等。通过这些命令的使用,可以逐步分析程序的执行过程,找出其中的问题,并进行修复。 在调试完成后,可以使用"quit"命令退出GDB调试界面。调试信息和步骤可以记录下来并与其他开发者共享,以便更好地协作解决问题。 总之,GDB是一个功能强大的调试器,它可以帮助开发者定位和修复程序中的错误。通过使用GDB,开发者可以更加高效地进行程序调试,提高开发效率。 ### 回答3: 《debugging with gdb》是一本介绍使用GDB进行调试的书籍。GDB是GNU工具链中的一个强大的调试工具,用于分析和修复程序中的错误。 该书详细介绍了GDB的各种功能和用法,并通过实例演示了如何利用GDB进行程序调试。它提供了许多实用技巧和建议,帮助读者快速定位和解决程序中的bug。 书中首先介绍了GDB的基本用法,包括启动程序、设置断点、执行程序、查看变量值等。接着,它详细阐述了GDB的高级功能,例如条件断点、观察点、内存调试等。 此外,书中还介绍了GDB调试多线程程序、动态链接程序和嵌入式程序的方法。针对不同的调试需求,它还介绍了GDB的执行控制、堆栈跟踪和源代码级别的调试等高级特性。 《debugging with gdb》还提供了一些常见问题的解决方案,如内存泄漏、数组越界、死锁等。它还解释了一些常见错误的原因和调试技巧,帮助读者更好地理解和定位程序中的问题。 通过阅读《debugging with gdb》,读者可以更好地理解和掌握GDB的使用方法,提高程序调试的效率和准确性。无论是新手还是有经验的程序员,都可以从中受益,提升自己的调试能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值