• GDB


    一、简介:

    GDB 是 GNU Debugger 的简称,是 GNU 软件系统中的标准调试器

    二、启动 GDB

    gdb 启动时,需要载入符号表文件(symbol table file)、可执行文件(executable file)、源代码文件。

    使用 gcc 编译程序时,使用 -g-ggdb-gdwarf-2 参数,生成的可执行文件内置了 gdb 调试用的符号表信息和源代码路径信息。启动 GDB 的方式有以下几种:

    1、gdb <program>

    默认使用 <program> 中记录的符号表信息和源代码路径信息,注意,如果源代码路径变化了,需要使用 -directory/-d 来重新指定源代码路径,否则 gdb 调试时无法 list ,此外该命令实际相当于 gdb -se <program> ,也可以使用 -s 单独指定符号表文件,或使用 -e 单独指定可执行文件。

    2、gdb -c <core dump> <program> 

    使用 core dump 文件来调试不易复现的问题。

    3、gdb <program> --pid=<pid>

    调试服务程序时,可以指定这个程序运行时的进程ID,gdb 会自动 attach 上去并调试它。

    还有一种方法:

    先 gdb <program> 运行起来,然后通过 attach PID 来关联上进程即可,并用 detach 来取消挂接的进程。

    启动带命令行参数的程序:

    -agrs  可以在启动时使用此参数,指定程序运行的命令行参数,如 gdb -args <program> [options],也可以启动 gdb 后,使用 set args [options],或使用 r [options] 带上命令行参数直接运行。

    三、查看命令

    info registers

    info all-registers

    info registers <regname,...>        //p $eax ,使用 print 的命令输出寄存器中的值,需要使用 $ 前缀。

    backtrace/bt  查看栈信息,还可以 bt <num>     num 可正可负,表示栈顶或栈底的 num 层信息。

    frame/f <num>  查看从栈顶(栈顶计为第0层)开始的第 n 层栈的信息。

    info args 打印出当前函数的参数的值

    info locals  打印出当前函数中所有的局部变量的值

    info catch 打印出当前的函数中的异常处理信息

    查看源代码:

    list +/-/<num>/<first,last>/<,last>/<filename:linenum>/<function>/<filename:function>/<class::function>/<* address>

    set/show listsize <count> 

    查看源代码中的内存:

    info line <num>/<function>

    disassemble <function>

    修改变量在运行时的值:

    p var=value ,或 set var=value

    whatis var  可查看变量的类型

    ptype:比whatis的功能更强,他可以提供一个结构的定义

    表达式:

    @ 和数组有关的操作符,左边是数组首地址的值,右边是想查看的长度。如果是静态数组,直接 p arrayname 就可以查看。

    :: 指定一个在文件或是一个函数中的变量

    {<type>}<addr> 表示一个指向内存地址<addr> 的类型为 <type> 的一个对象

    int *array = (int*) malloc(len*sizeof(int));

    p *array@len

    变量的自动显示:

    display <expr>

    display/i $pc  /i 表示输出格式为机器指令码即汇编,$pc 是 gdb 的环境变量,表示指令的地址。当程序停下来时,就会出现源代码和机器指令码相对应的情形。

    undisplay <dnums> 取消自动显示,<dnums> 表示 display 的编号,可以通过 display 命令查看。dnums 可以是一个值,也可以是多个用空格分开的值,也可以是范围值,使用 - 连接。

    delete display <dnums> 同上

    disable/enable display <dnums>  临时关闭/打开某些变量的自动显示

    GDB中有几种让程序暂停的方式:断点(BreakPoint)、观察点(WatchPoint)、捕捉点(CatchPoint)、信号(Signals)、线程停止(ThreadStops)

    break <arguments> ... if <condition>

    观察点一般用来观察某个变量或表达式的值是否发生变化,如果有变化,马上停住程序,而且也像 break 一样支持 if 条件。

    watch <expr>

    rwatch <expr>  当变量被读时,停住程序

    awatch <expr> 当变量被读或被写时,停住程序

    info watchpoints 列出所有观察点

    捕捉点一般用来捕捉程序运行时的一些事件,如载入动态链接库或是C++异常。

    catch <event> 当 <event> 发生时,停住程序,event 可以是 throwcatchexecforkvforkloadload <libname>unloadunload <libname>

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

    断点维护:

    clear 清除所有断点

    clear <function>/<filename:function>/<classname::function> 清除所有 function 上的断点

    clear <linenum>/<filename:linenum> 清除指定行上的断点

    delele breakpoint [num...]  按断点编号删除断点,如果不写 [num...],则删除所有断点

    disable/enable b [num...]  临时关闭/打开断点

    条件断点的维护:

    condition <bnum> <expr> 修改断点的停止条件,如果没有 <expr>,则表示清除断点的停止条件

    ignore <bnum> <count> 忽略停止条件几次

    断点的自动化操作:

    commands [bnum] command-list end

    如:

    break funif x>0

    commands 

    printf "x is %d ",x

    continue

    end

    如果要取消命令序列,只需要简单的执行一下 command 命令之后打个 end 即可。

    单步调试:

    step <count>

    next <count>

    continue/c/fg <ignore-count>

    finish  跳出函数

    until/u [num]  运行到哪一行,不使用 [num] 可以用来退出循环。

    stepi/si/nexti/ni  相当于 display/i $pc ,单步跟踪一条机器指令,即汇编代码。

    信号调试:

    handle <signal> <keywords ...> 

    keywords 可以为以下的关键字:

    nostop  收到信号时,不停止程序,但会打印出消息,通知收到这种信号

    stop  停止程序

    print  显示出信息 

    noprint  不显示信息

    pass/noignore  不处理信号,但会把信号交给调试程序处理

    nopass/ignore  处理信号,不会让调试程序处理

    可以通过 info signal /info handle 查看有哪些信号在被 gdb 检测中。

    signal <signal>  gdb提供的 signal 命令,可以产生一个信号量在被调试的程序,就可以在程序全速运行时在任意位置设置断点,并在该断点上用 gdb 产生一个信号量,可以精确的在某处产生信号。

    signal 命令和 shell的 kill 命令不同,前者是 gdb 发出给调试程序的,后者是 kill 命令发信息给调试程序,由 gdb 先截获的。

    多线程调试:

    break <line> thread <threadno> [if ...]

    注意,此处的线程ID是由 gdb 分配的,可以通过 info threads 来查看正在运行的程序的线程信息,如果不指定线程ID,则表示断点设在所有线程上面。

    跳转控制命令:

    jump <line>/<address> 修改程序的执行顺序,可以让程序执行随意跳跃。

    return <expr> 强制未执行完的函数返回,如果指定了 <expr> ,则其为指定的返回值。

    call <expr>  强制调用函数,并显示函数返回值,如果是 void ,则不显示。

    调试智能指针,如果智能指针是user_ptr,则:

    p user_ptr          //输出形如:$27 = {px = 0x826b370, pn = {pi_ = 0x826a008}}

    p user_ptr.px->userid    //查看智能智能指针指向对象中的成员值

    p *(user_ptr.pn.pi_)    //查看智能指针引用记数

    使用GDB调试数组和vector容器:

    int array[4] = {1,2,3,4}

    p array[0]@sizeof(array)/sizeof(array[0])

    p *(array+1)

    p *(vect._M_impl._M_start)@vect.size()

    p *(vect._M_impl._M_start + 3)  //查看第四个元素的值

    vector的源码,vector中只有一个成员变量_M_impl。这个成员变量是一个结构体,结构体又由三个类型指针构成:
          struct //伪代码
          {
               T* _M_start;
               T* _M_finish;
               T* _M_end_of_storage;
          }_M_impl;
        _M_start指向vector的开头,相当于v.begin()所返回的位置;
        _M_finish指向的是最后一个元素的结束位置之后,相当于v.end()所返回的位置。
        _M_end_of_storage指向所分配空间的末尾,相当于v.begin() + v.capacity()*sizeof(T)

    启动gdb的时候自动执行脚本

    gdb -x gdb_script

    gdb_script里面只能有gdb命令,但是 gdb命令里面有个 shell 指令,所以实际上这里可以做任何事。

    查看反汇编代码

    disassemble fun  查看 fun 函数的反汇编代码

    disassemble /r 0x401365,0x401370  查看一段内存地址

    info line fun   查看 fun 函数的起始地址

    gdb test -tui

    加上 -tui 参数后,就可以边调试边看代码了,实用。

    机器语言工具 
    有一组专用的gdb变量可以用来检查和修改计算机的通用寄存器,gdb提供了目前每一台计算机中实际使用的4个寄存器的标准名字: 
    $pc : 程序计数器 
    $fp : 帧指针(当前堆栈帧) 
    $sp : 栈指针 
    $ps : 处理器状态 

    up 上移栈帧,使另一函数成为当前函数

    down 下移栈帧,使得另一个函数成为当前函数

    make 不退出 gdb 就可以重新编译程序

    显示设置:

    set print address [on/off]  打开/关闭地址输出,当程序显示函数信息时,gdb 会显出函数的参数地址,默认为 on。show print address

    set print array [on/off]  打开数组显示,打开后每个元素占一行,如果不打开,则线个元素以逗号分隔,默认为 off。 show print array

    set print elements <number-of-elements>  设置数据显示的最大长度,如果设定为0,表示不限制。show print elements

    set print null-stop [on/off]  打开此选项时,当显示字符串时,遇到结束符就停止显示,默认为 off。

    set print pretty [on/off]  打开此选项时,当 gdb 显示结构体时会比较漂亮,会分行显示,否则显示在一行。show print pretty

    set print sevenbit-strings [on/off]  设置字符显示是否按 nn 的格式显示,如果打开,则字符串或字符数据按 nn 显示,如 65。show print sevenbit-strings

    set print object [on/off]  C++中,如果一个对象指针指向其派生类,打开此选项时,gdb 自动按照虚方法调用的规则显示输出,否则 gdb 不管虚函数表。默认是 off。show print object

    set print static-members [on/off]  显示一个 C++ 对象时,是否显示其中的静态数据成员,默认为 on。show print static-members

    set print vtbl [on/off]  当打开时,gdb 将使用比较规整的格式来显示虚函数表示,默认是关闭的。show print vtbl

  • 相关阅读:
    Deltix Round, Summer 2021
    CF1558F Strange Sort 题解
    将文本复制到粘贴板上
    Mac安装2021ps
    腾讯云TDSQL-C云原生数据库技术
    腾讯云分布式数据库TDSQL再获认可
    T-TDSQL的核心技术
    TDSQL原创技术的出发点
    拓路前行-TDSQL追求极致体验的这一路
    TDSQL多集群下的自动化和交付
  • 原文地址:https://www.cnblogs.com/tianyajuanke/p/3379977.html
Copyright © 2020-2023  润新知