北冥有鱼 记录生活点滴,分享学习心得

gdb

gdb常用命令总结

Posted by YuChen on February 17, 2022

安装gdb-10

执行如下命令可在Ubuntu 18.04 LTS系统中安装自带源码高亮功能的gdb-10

1
2
3
4
5
6
apt install -y software-properties-common
# 若遇到ModuleNotFoundError: No module named 'apt_pkg'问题,只需
# 将/usr/bin/add-apt-repository中的`!/usr/bin/python3`改为`!/usr/bin/python3.6`
add-apt-repository ppa:ubuntu-toolchain-r/test -y
apt update -y
apt install -y gdb

加载调试程序

  • file:可以使用gdb [可执行文件]直接加载调试二进制文件,也可以先启动gdb再使用file [可执行文件]加载调试目标文件。

设置源码查找路径

  • set directories:一次设置多个源文件查找路径
    1
    
    set directories /work/study/jax/:/root/.cache/bazel/_bazel_root/42210d9a2e5c41f7817f753f6f92c412/
    
  • directory / dir:在源文件查找路径中添加一个路径,若已存在则不会重复添加
    1
    
    directory /work/study/tensorflow
    
  • gdb -d:如果希望在gdb启动时加载代码的位置,可以使用gdb的-d参数
    1
    
    gdb -q main -d /search/code/some
    

替换查找源文件的路径

  • shell readelf <target> -p .debug_str:可以用于查看原来的源码路径
  • set substitute-path:在调试时,如果源代码文件已经被移动到其它目录下,那么可以使用set substitute-path from to命令设置新的路径(to)替换旧的路径(from)
    1
    
    set substitute-path  /work/study/tensorflow /work/Develop/tensorflow
    
  • unset substitute-path [path]:可用于取消源码路径替换

打印源码

  • l:打印源码
  • l begin,end:列出begin到end行之间的源码
  • l <file>:<line>:列出指定文件指定行号的源码
  • l <file>:<line1>,<file>:<line2>:列出指定文件指定行号之间的源码
  • l <file>:<func_name>:列出指定文件指定函数的源码

设置源码一次列出行数

  • set listsize:设置源码一次列出的行数,默认是10行,可以使用该命令进行修改
    1
    2
    3
    
    set listsize 20
    # 一次列出20行源码
    # 若设置为0或者unlimited,则源码列出就无限制
    
  • show listsize:查看listsize所设置的大小

设置程序运行参数

存在三种方法指定程序运行的参数,以./main 1 2 3 4为例:

  1. gdb启动时直接设置程序运行参数,示例:gdb --args main 1 2 3 4
  2. gdb中启动程序运行时为程序传递参数,示例:r 1 2 3 4 或者 start 1 2 3 4
  3. gdb中使用set args设置所调试二进制文件的运行参数,示例:
    1
    
      set args 1 2 3 4
    

    注意: gdb中使用show args可查看所设置好的运行参数。

设置运行环境变量

  • set environment/set env可用于在gdb中设置环境变量,示例:
    1
    2
    
    set env LD_LIBRARY_PATH=.
    # set environment LD_LIBRARY_PATH=.
    

设置程序的运行路径

  • path <dir>可用于设定程序的运行路径
  • show paths可用于查看程序的运行路径

设置工作目录

  • cd <dir>:相当于shell的cd命令,可用于设置工作目录
  • pwd:用于显示当前所在的工作目录

完整打印字符串

  • set print elements 0:完整打印较长的字符串内容
    1
    2
    3
    
    set print elements 0
    show print elements
    # Limit on string chars or array elements to print is unlimited.
    

gdb日志重定向到文件

  • set logging可以用于将gdb的输出重定向到某个文件
    1
    2
    3
    4
    
    set logging file <file name>
    set logging on
    info functions
    set logging off
    

重定向程序的输入输出

  • r > outfile < inputfile或者run > outfile < inputfile可用于重定向程序的输入输出

设置观察点

  • watch:当所watch的变量值发生变化时,程序会停下来
    1
    
    watch var
    

启动断点设置

在程序入口处打断点的方法有两种,描述如下:

  • start:调试可执行文件时若希望启动时即在main函数处停住,则可以使用start启动运行
    • 说明:start命令在启动程序运行时会在main函数处设置一个临时断点
  • 先使用info files获取Entry point地址(如0x401050),再使用b *0x401050在入口地址处打断点

设置断点

  • b <file>:<line>:断点设置在指定文件指定行
  • 类成员函数设置断点的方法:
    • 需加上完整命名空间,写法如b tensorflow::DirectSession::Run
    • 若带有匿名命名空间,则需使用(anonymous namespace)表示匿名命名空间名称,如b tensorflow::(anonymous namespace)::ExecutorState::ScheduleReady(第二个命名空间即为namespace {}
  • 保存已经设置的断点
    • save breakpoints file-name-to-save保存已设置的断点
    • source file-name-to-save批量加载断点设置
  • tb用于设置临时断点,用法与b相同,但设置的断点只生效一次
  • ignore bnum count:在设置断点以后,可以忽略断点
    • ignore 1 5:接下来5次编号为1的断点触发都不会让程序中断,只有第6次断点触发才会让程序中断
  • del bnum: 删除第bnum号断点,del是删除所有断点

设置条件断点

  • break ifbreak [break-args] if (condition)可用于设置条件断点
    1
    2
    3
    
    break main if argc > 1
    break 180 if (str.empty() && i < 0)
    break test.c:34 if (x & y) == 1
    
  • condition:与break if类似, 但condition只能作用于已经存在的断点上,用法:condition <break_list> (condition)
    1
    
    cond 3 i == 3
    

    注意:条件表达式的返回值是int类型。

查看变量的类型

  • whatis:查看变量的类型
    1
    
    whatis var
    
  • ptype:查看变量的详细类型信息
    1
    
    ptype var
    

查看变量定义所在的文件

  • i variables:查看定义该变量的文件,gdb会显示匹配名称表达式的所有变量。
    1
    2
    
    i variables var
    i variables ^var$ # 特定只显示名称为var的变量
    

    info variables不会显示局部变量,即使是static变量所显示的有用信息亦不多。

查看函数调用堆栈

  • bt/backtrace:查看当前的堆栈信息,堆栈中的每个函数都被分配了一个编号,最近被调用的函数在0号帧中 (栈顶)
    • bt n表示只打印栈顶上n层的栈信息,bt -n:表示只打印栈底下n层的栈信息
  • f/frame:用于切换当前函数栈
    • f n命令表示在gdb中切换到编号为n的栈帧
    • f命令用于查看当前栈帧的编号、函数名、函数参数值、函数所在文件及行号、函数执行到的语句等信息
    • info f命令用于查看当前栈帧寄存器和参数信息
    • info f n命令用于查看编号为n的栈帧寄存器和参数信息
  • up/down:也可用于切换栈帧,down n命令表示往栈顶方向下移n层,up n命令表示往栈底方向上移n层

函数调用返回值赋值给gdb变量

  • set:可以使用set命令将某个函数调用结果赋值给一个gdb变量
    1
    2
    
    set $proto=test_module->ToProto()
    p $proto
    
  • 使用set命令可对某个变量进行强制类型转换,示例如下:
    1
    2
    3
    4
    5
    6
    7
    
    p cos(0.0)
    # $1 = -1073776640
    set $p = (double (*) (double)) cos
    p cos(0.0)
    # $2 = -1073776640
    p $p(0.0)
    # $3 = 1
    

继续执行到下一个断点

  • c/continue:继续执行程序,直到再次遇到断点处

继续运行到指定位置

  • u <line>/until <line>:继续执行到<line>行处

跳过执行

  • skip function <func_name>:step时跳过执行<func_name>函数
  • skip file <file_name>: step时跳过执行<file_name>文件中的所有函数

gdb中使用shell命令

  • shell <command>:command表示用户即将要执行的shell命令

参考资料





更多文章