gdb的使用总结

本文详细介绍了如何使用gdb工具分析core文件,包括核心配置、启动gdb、查看栈帧、定位问题等步骤,适用于软件开发和调试场景。

启动初始

gdb启动时默认从初始化文件中读取命令作些初始化工作,初始化文件顺序为

  1. system.gdbinit
  2. ~/.gdbinit
  3. ./.gdbinit

可以通过选项参数-nx或者-n设置不从初始化文件中作初始化工作

gdb启动时主要做了哪些事?

  1. 读取--with-system-gdbinit初始化文件,执行文件中的命令
  2. 读取主目录下的gdbinit文件,执行文件中的命令
  3. 执行-iex或者-ix指定的命令或者命令文件中的命令
  4. 处理命令行参数
  5. 当set auto-load local-gdbinit开启时,读取当前工作目录下的gdbini文件,执行文件中的命令
  6. 如果命令行指定的调试的进程或者进程id,则加载为程序提供的自动加载脚本
  7. 执行-ex或者-x指定的命令
  8. 读取历史文件中的命令历史

文件选择

主要包含符号文件 ,二进制文件 ,core文件。在没有指定选项情况下, 默认将第一个参数作为二进制文件,第二个参数作为core文件,如果第二个参数是以数字开始,则作为进程号,gdb调试附加到对应进程,如果失败,则当作core文件处理

符号文件使用选项-symbols file或者-s file

二进制文件使用选项-exec file或者-e file或者-se file(符号文件与二进制文件二合一)

core文件使用选项-core file或者-c file

命令文件使用选项-command file或者-x file

在加载执行gdbinit文件后执行的初始化命令文件选项用-init-command file或者-ix file

执行命令选项

选项有两种,其中-init-eval-command是在加载完gdbinit文件后才执行

  • -eval-command command或者-ex command
  • -init-eval-command command或者-iex command

core文件 

设置ulimit -c unlimited

echo "core" > /proc/sys/kernel/core_pattern

在程序core时,需要用到gdb分析问题出在哪里

1、gdb --core=core文件  程序名

2、bt(显示所有栈桢)

3、在知道问题出在哪个栈帧后,用up num向上进num个栈帧

4、用p来输出变量信息

gdb下启动程序

在gdb启动时指定程序名参数,或者使用命令file或者exec-file来指定程序名,启动程序使用run或者简写形式r

也可以使用start命令来启动,此时相当于在入口点设置了一个临时断点,然后运行run,如果使用start args相当于设置临时断点后,然后执行run args

start [args]

栈帧图

断点

设置断点

支持的格式有

  • break location:其中location与查看源文件中支持的location一致
  • break:表示在下一指令设置中断 
  • break ... if cond:表示条件中断,其中...表示location或者不带参数
  • tbreak args:表示设置临时中断点,只停止一次。即在第一次停止后自动删除该中断点
  • hbreak args:表示设置硬件中断点,要求支持硬件中断点,一些目标硬件可能不支持硬件中断点
  •  thbreak args:设置临时硬件中断点
  • rbreak regex:在匹配正则表达式的函数设置中断点
  • rbreak file:regex:限制在指定文件中匹配正则表达式的函数设置中断点

1、filename:linenum

2、function

3、function:label

4、filename:function

查看断点

info breakpoints [n...]
info break [n...]  //或者简写形式

gdb多线程调试的基本命令

1、info threads   显示当前可调试的线程,每个线程都有一个id

2、thread id       切换当前调试的线程为指定id的线程

3、set scheduler-locking on / off     设置当前线程执行,不会被其它线程干扰

查看数据

查看内存数据可以使用p或者x命令

x命令格式为

x/nfu addr

其中n表示查看多少个,f表示查看格式,u表示单元,支持b(字节),h(两字节),w(四字节),g(8字节)

查看格式

x:十六进制形式

d:十进制形式

u:无符号十进制形式

o:六进制形式

t:二进制形式

a:地址形式

c:字符形式

f:浮点数形式

s:作为字符串

z:与x相似,但是包含前导0

r:原始形式

i:主要针对代码,如$pc或者对应代码段的地址

文件各段地址分布情况 

显示数据段,代码段以及地址范围情况

使用info files或者info target

    设置搜索源文件或者脚本文件路径

    使用选项-directory directory或者-d directory

    执行shell脚本

    使用shell command-string或者!command-string

    编译脚本使用make make-args

    帮助命令

    查看总体帮助信息

    使用help或者简写形式h查找帮助类

    查看子类帮助

    使用help 子类信息,如help status

    查看具体的命令帮助信息

    使用help command

    info和show的差异

    info用于显示程序的状态,而show用于显示gdb的状态

    查看符号表

    配置

    设置/查看大小写敏感使用

    set case-sensitive on
    set case-sensitive off
    set case-sensitive auto
    show case-sensitive

    配置/查看输出类的方法名

    set print type methods
    set print type methods on
    set print type methods off
    show print type methods

    配置/查看类中的类型定义

    set print type typedefs 
    set print type typedefs on
    set print type typedefs off
    show print type typedefs

    查看符号

    查看符号存放的地址

    info address symbol

    查看地址对应的符号

    info symbol addr

    解构符号名

    demangle [-l language] [--] name

    查看变量类型

    whatis/ptype [/flags] [arg]

    当arg没有提供时,则输出$即值历史中的最后一个值的数据类型

    如果arg是变量或者表达式,则输出代码中的字面类型。如果类型是typedef定义的类型,whatis不会输出typedef背后的数据类型。如果 arg 是使用 typedef 定义的类型名称,则 whatis 仅展开该 typedef 的一个级别

    flags支持的参数有

    • r:显示原始类型
    • m:不会打印类中定义的方法
    • M:打印类中定义的方法
    • t:不打印类中定义的typedefs类型
    • T:打印类中定义的typedefs类型

    ptype与whatis相比,会输出更加详细的信息,同时对于typedef类型没有层级限制

    查看类型信息

    info types regexp
    info types

    在没有参数情况下,会输出程序的所有类型定义。在指定参数情况下,会输出类型名字中包含regexp的类型,其与whatis一样,不会输出详细信息,会列出类型定义所在的所有源文件

    类型打印机

    info type-printers
    enable type-printers name...
    disable type-printers name...

    查看某位置的局部变量

    info scope location

    查看源文件

    info source
    info sources

    info source查看当前执行点源文件的信息

    info sources查看当前程序所有源文件

    查看函数

    info functions
    info functions regexp

    查看变量

    info variables
    info variables regexp

    查看函数外定义的变量,不包含局部变量。查看虚函数表使用

    info variables vtable //查看所有的虚函数表
    info variables vtable.*class//查看class的虚函数表

    查看类

    info classes
    info classes regexp

    用在ojbect-c 

    查看选择器

    info selectors
    info selectors regexp

    用在ojbect-c

    配置模糊类型解析

    set opaque-type-resolution on
    set opaque-type-resolution off
    show opaque-type-resolution

    配置打印符号加载 

    set print symbol-loading
    set print symbol-loading full
    set print symbol-loading brief
    set print symbol-loading off
    show print symbol-loading

    输出符号信息到指定文件 

    maint print symbols filename
    maint print psymbols filename
    maint print msymbols filename

    其中 psymbols表示部分符号,msymbols表示最小符号

    查找符号信息

    maint info symbols [regexp]
    maint info psymbols [regexp]

    符号缓存

    maint set symbol-cache-size size
    maint show symbol-cache-size
    maint print symbol-cache
    maint print symbol-cache-statistics
    maint flush-symbol-cache

    查看源文件 

    使用list查找源文件,默认显示10行,可以通过set listsize来设置list的显示行数

    list linenum //显示当前源文件以行号linenum为中心的代码
    list function //显示以函数名function 为中心的代码
    list  //如果上次命令为list,此次打印紧跟上次打印的最后一行
    list - //打印上次的
    
    set listsize count //count为显示的行数
    set listsize unlimited 
    show listsize
    

    list支持的参数形式有

    • list location
    • list first,last
    • list ,last 表示显示直到last行
    • list first, 表示显示从first开始
    • list + 表示显示上次之后的
    • list - 表示显示上次之前的
    • list

    location支持的形式有

    • linenum 行号
    • -offset/+offset 当前行偏移前或者偏移后
    • filename:linenum 文件的哪一行
    • function 表示从函数体开始
    • function:label 表示从函数中的某标签开始
    • filename:function 表示从某文件的某函数开始
    • label 表示当前选择栈帧的某标签开始

    当文件、函数、标签有同名时,显示位置可以派上用场,支持的有

    • -source filename
    • -function function
    • -label label
    • -line number

    在当前文件中搜索特定匹配使用

    forward-search regexp //前向搜索regexp
    search regexp
    reverse-search regexp //反向搜索regexp
    

    源码目录默认是

    • cdir 表示当前目录
    • cwd 表示当前工作目录

    如果想要添加目录使用命令directory

    查看汇编代码

    使用disassemble或者简写形式disas

    支持的选项有,其中m,s参数表示混合形式,源代码+汇编形式,r表示以16进制原始形式

    • /m
    • /s
    • /r

    参数形式支持,开始结束地址形式和开始地址+指定长度。参数可以是表达式,如0x32c4, &main+10或者$pc-8

    • start,end
    • start,+length

    调试多进程 

    在使用gdb调试多进程时,默认调试的是父进程,如果想调试子进程,使用set follow-fork-mode mode命令,其中mode支持的参数有

    •  parent
    • child

    查看follow-fork-mode使用show follow-fork-mode

    在linux下,如果想父子进程都调试,使用set detach-on-fork即set detach-on-fork mode,其中mode支持的参数有

    • on:依赖于follow-fork-mode,子进程或者父进程在fork后会分离,即允许独立运行。默认情况下是on
    • off:父子进程都在gdb控制下,依赖于follow-fork-mode,gdb是调试哪个进程

    查看detach-on-fork模式使用show detach-on-fork

    多进程中有调用exec时,可以设置follow-exec-mode,即通过set follow-exec-mode mode,其中mode支持的参数有

    • new
    • same

    观察点

    用于观察内存变化

    设置观察点

    watch/rwatch/awatch [-l|-location] expr [thread threadnum] [mask maskvalue]

    watch表示关注写,rwatch表示关注读,awatch表示关注读写。expr不能是常量,在表示地址是使用*(type*)constValue。一般设置硬件观察点,硬件观察点比较快。

    查看观察点

    info watchpoints [n...]

    设置硬件观察点

    set can-use-hw-watchpoints 0/1
    show can-use-hw-watchpoints

    c++相关命令

    查看引用或者指针的虚函数表

    info vtbl ptr

    评论
    成就一亿技术人!
    拼手气红包6.0元
    还能输入1000个字符
     
    红包 添加红包
    表情包 插入表情
     条评论被折叠 查看
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包

    打赏作者

    kgduu

    你的鼓励将是我创作的最大动力

    ¥1 ¥2 ¥4 ¥6 ¥10 ¥20
    扫码支付:¥1
    获取中
    扫码支付

    您的余额不足,请更换扫码支付或充值

    打赏作者

    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

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

    余额充值