GDB调试使用的命令

1、目前线上问题出现内存泄露, 怎样使用shell脚本 执行gdbattach 后 break bt quit等快速执行呢?

2、多进程 多线程一般会用到那些命令?

对于第一个问题:

以前文章有:gdb快速打印线程堆栈

 目前可以参考脚本:

 

##############################################################################
# 帮助信息
##############################################################################

help                      # 列出命令分类
help running              # 查看某个类别的帮助信息
help run                  # 查看命令 run 的帮助
help info                 # 列出查看程序运行状态相关的命令
help info line            # 列出具体的一个运行状态命令的帮助
help show                 # 列出 GDB 状态相关的命令
help show commands        # 列出 show 命令的帮助


##############################################################################
# 断点
##############################################################################

break main                # 对函数 main 设置一个断点,可简写为 b main
break 101                 # 对源代码的行号设置断点,可简写为 b 101
break basic.c:101         # 对源代码和行号设置断点
break basic.c:foo         # 对源代码和函数名设置断点
break *0x00400448         # 对内存地址 0x00400448 设置断点
info breakpoints          # 列出当前的所有断点信息,可简写为 info break
delete 1                  # 按编号删除一个断点
delete                    # 删除所有断点
clear                     # 删除在当前行的断点
clear function            # 删除函数断点
clear line                # 删除行号断点
clear basic.c:101         # 删除文件名和行号的断点
clear basic.c:main        # 删除文件名和函数名的断点
clear *0x00400448         # 删除内存地址的断点
disable 2                 # 禁用某断点,但是不删除
enable 2                  # 允许某个之前被禁用的断点,让它生效
rbreak {regexpr}          # 匹配正则的函数前断点,如 ex_* 将断点 ex_ 开头的函数
tbreak function|line      # 临时断点
hbreak function|line      # 硬件断点
ignore {id} {count}       # 忽略某断点 N-1 次
condition {id} {expr}     # 条件断点,只有在条件生效时才发生
condition 2 i == 20       # 2号断点只有在 i == 20 条件为真时才生效
watch {expr}              # 对变量设置监视点
info watchpoints          # 显示所有观察点
catch exec                # 断点在exec事件,即子进程的入口地址


##############################################################################
# 运行程序
##############################################################################

run                       # 运行程序
run {args}                # 以某参数运行程序
run < file                # 以某文件为标准输入运行程序
run < <(cmd)              # 以某命令的输出作为标准输入运行程序
run <<< $(cmd)            # 以某命令的输出作为标准输入运行程序
set args {args} ...       # 设置运行的参数
show args                 # 显示当前的运行参数
continue                  # 继续运行,可简写为 c 或 cont
step                      # 单步进入,碰到函数会进去(Step in)
step {count}              # 单步多少次
next                      # 单步跳过,碰到函数不会进入(Step Over)
next {count}              # 单步多少次
finish                    # 运行到当前函数结束(Step Out)
until                     # 持续执行直到代码行号大于当前行号(跳出循环)
until {line}              # 持续执行直到执行到某行
CTRL+C                    # 发送 SIGINT 信号,中止当前运行的程序
attach {process-id}       # 链接上当前正在运行的进程,开始调试
detach                    # 断开进程链接
kill                      # 杀死当前运行的函数


##############################################################################
# 栈帧
##############################################################################

bt                        # 打印 backtrace (命令 where 是 bt 的别名)
frame                     # 显示当前运行的栈帧
up                        # 向上移动栈帧(向着 main 函数)
down                      # 向下移动栈帧(远离 main 函数)
info locals               # 打印帧内的相关变量
info args                 # 打印函数的参数


##############################################################################
# 代码浏览
##############################################################################

list 101                  # 显示第 101 行周围 10行代码
list 1,10                 # 显示 110 行代码
list main                 # 显示函数周围代码
list basic.c:main         # 显示另外一个源代码文件的函数周围代码
list -                    # 重复之前 10 行代码
list *0x22e4              # 显示特定地址的代码
cd dir                    # 切换当前目录
pwd                       # 显示当前目录
search {regexpr}          # 向前进行正则搜索
reverse-search {regexp}   # 向后进行正则搜索
dir {dirname}             # 增加源代码搜索路径
dir                       # 复位源代码搜索路径(清空)
show directories          # 显示源代码路径


##############################################################################
# 浏览数据
##############################################################################

print {expression}        # 打印表达式,并且增加到打印历史
print /x {expression}     # 十六进制输出,print 可以简写为 p
print array[i]@count      # 打印数组范围
print $                   # 打印之前的变量
print *$->next            # 打印 list
print $1                  # 输出打印历史里第一条
print ::gx                # 将变量可视范围(scope)设置为全局
print 'basic.c'::gx       # 打印某源代码里的全局变量,(gdb 4.6)
print /x &main            # 打印函数地址
x *0x11223344             # 显示给定地址的内存数据
x /nfu {address}          # 打印内存数据,n是多少个,f是格式,u是单位大小
x /10xb *0x11223344       # 按十六进制打印内存地址 0x11223344 处的十个字节
x/x &gx                   # 按十六进制打印变量 gx,x和斜杆后参数可以连写
x/4wx &main               # 按十六进制打印位于 main 函数开头的四个 long 
x/gf &gd1                 # 打印 double 类型
help x                    # 查看关于 x 命令的帮助
info locals               # 打印本地局部变量
info functions {regexp}   # 打印函数名称
info variables {regexp}   # 打印全局变量名称
ptype name                # 查看类型定义,比如 ptype FILE,查看 FILE 结构体定义
whatis {expression}       # 查看表达式的类型
set var = {expression}    # 变量赋值
display {expression}      # 在单步指令后查看某表达式的值
undisplay                 # 删除单步后对某些值的监控
info display              # 显示监视的表达式
show values               # 查看记录到打印历史中的变量的值 (gdb 4.0)
info history              # 查看打印历史的帮助 (gdb 3.5)


##############################################################################
# 目标文件操作
##############################################################################

file {object}             # 加载新的可执行文件供调试
file                      # 放弃可执行和符号表信息
symbol-file {object}      # 仅加载符号表
exec-file {object}        # 指定用于调试的可执行文件(非符号表)
core-file {core}          # 加载 core 用于分析


##############################################################################
# 信号控制
##############################################################################

info signals              # 打印信号设置
handle {signo} {actions}  # 设置信号的调试行为
handle INT print          # 信号发生时打印信息
handle INT noprint        # 信号发生时不打印信息
handle INT stop           # 信号发生时中止被调试程序
handle INT nostop         # 信号发生时不中止被调试程序
handle INT pass           # 调试器接获信号,不让程序知道
handle INT nopass         # 调试器不接获信号
signal signo              # 继续并将信号转移给程序
signal 0                  # 继续但不把信号给程序


##############################################################################
# 线程调试
##############################################################################

info threads              # 查看当前线程和 id
thread {id}               # 切换当前调试线程为指定 id 的线程
break {line} thread all   # 所有线程在指定行号处设置断点
thread apply {id..} cmd   # 指定多个线程共同执行 gdb 命令
thread apply all cmd      # 所有线程共同执行 gdb 命令
set schedule-locking ?    # 调试一个线程时,其他线程是否执行,off|on|step
set non-stop on/off       # 调试一个线程时,其他线程是否运行
set pagination on/off     # 调试一个线程时,分页是否停止
set target-async on/off   # 同步或者异步调试,是否等待线程中止的信息


##############################################################################
# 进程调试
##############################################################################

info inferiors                       # 查看当前进程和 id
inferior {id}                        # 切换某个进程
kill inferior {id...}                # 杀死某个进程
set detach-on-fork on/off            # 设置当进程调用fork时gdb是否同时调试父子进程
set follow-fork-mode parent/child    # 设置当进程调用fork时是否进入子进程


##############################################################################
# 汇编调试
##############################################################################

info registers            # 打印普通寄存器
info all-registers        # 打印所有寄存器
print/x $pc               # 打印单个寄存器
stepi                     # 指令级别单步进入,可以简写为 si
nexti                     # 指令级别单步跳过,可以简写为 ni
display/i $pc             # 监控寄存器(每条单步完以后会自动打印值)
x/x &gx                   # 十六进制打印变量
info line 22              # 打印行号为 22 的内存地址信息
info line *0x2c4e         # 打印给定内存地址对应的源代码和行号信息
disassemble {addr}        # 对地址进行反汇编,比如 disassemble 0x2c4e

 

set disassemble-next-line on:自动反汇编后面要执行的代码  
si:

maint info program-spaces:打印当前所有被调试的进程信息
用“display /i $pc” :命令显示当程序停止时,将要执行的汇编指令;取消显示可以用undisplay命令。
“disas /m fun”(disas是disassemble命令缩写)命令将函数代码和汇编指令映射起来
info  line 13 只想查看某一行所对应的地址范围

set print elements number-of-elements--
set print elements 0
set print elements unlimited
    打印大数组的内容,
    
    
p array[60]@10  打印了array数组第60~69个元素的值

set print array-indexes on      打印数组的索引下标
“set print pretty on”命令,这样每行只会显示结构体的一名成员,而且还会根据成员的定义层次进行缩进:     
     
用“bt full”命令显示各个函数的局部变量值
info locals 只是想打印当前函数局部变量的值
想查看进程的内存映射信息,可以使用“info proc mappings”命令(i是info命令缩写)
可以用"i files"(还有一个同样作用的命令:“i target”)命令,它可以更详细地输出进程的内存信息,包括引用的动态链接库等等,
whatis xxx 或者 ptype xxx  打印变量的类型和所在文件
info variables xxx  查看定义该变量的文件:

gdb中使用“x”命令来打印内存的值,格式为“x/nfu addr”。含义为以f格式打印从addr开始的n个长度单元为u的内存值。参数具体含义如下:
a)n:输出单元的个数。
b)f:是输出格式。比如x是以16进制形式输出,o是以8进制形式输出,等等。
c)u:标明一个单元的长度。b是一个byte,h是两个byte(halfword),w是四个byte(word),g是八个byte(giant word)。 
 以16进制格式打印数组前a16个byte的值:(gdb)  x/16xb a
 
可以显式地指定文件名(上下文):
(gdb) p 'static-1.c'::var
$1 = 1
(gdb) p 'static-2.c'::var
$2 = 2

list(简写为l)命令来显示源代码以及行号

使用“watch a”命令以后,当a的值变化:由0变成1,由1变成2,程序都会停下来。

此外也可以使用“watch *(data type*)address”这样的命令,
 使用“watch expr thread threadnum”命令设置观察点只针对特定线程生效,也就是只有编号为threadnum的线程改变了变量的值,
 程序才会停下来,其它编号线程改变变量的值不会让程序停住
 
可以使用“rwatch”命令设置读观察点,也就是当发生读取变量行为时,程序就会暂停住 
使用“awatch”命令设置读写观察点,也就是当发生读取变量或改变变量值的行为时,




当gdb启动时,会读取HOME目录和当前目录下的的配置文件,执行里面的命令。这个文件通常为“.gdbinit”。
这里给出了本文档中介绍过的,可以放在“.gdbinit”中的一些配置:
# 打印STL容器中的内容
python
import sys
sys.path.insert(0, "/home/xmj/project/gcc-trunk/libstdc++-v3/python")
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)
end

# 保存历史命令
set history filename ~/.gdb_history
set history save on

# 退出时不显示提示信息
set confirm off

# 按照派生类型打印对象
set print object on

# 打印数组的索引下标
set print array-indexes on

# 每行打印一个结构体成员
set print pretty on

 

 

对于第二个:

看以前问题文章

GDB使用    GDB符号表

进程:

gdb catch功能

set follow-fork-mode child
catch exec

Catch Point真是个好东西,支持很多有用的事件:

  • 常规的C++异常事件
  • 系统调用事件(可直接指定系统调用号)
  • 动态库的加载/卸载事件
  • exec/fork/vfork

2.2 set detach-on-fork on
      只调试父进程或子进程的其中一个(根据follow-fork-mode来决定),这是默认的模式。

 

2.3 set detach-on-fork off
       父子进程都在gdb的控制之下,其中一个进程正常调试(根据follow-fork-mode来决定),另一个进程会被设置为暂停状态。

 

1.2 set follow-fork-mode parent
      gdb只跟踪父进程,不跟踪子进程,这是默认的模式。

 

1.3 set follow-fork-mode child
      gdb在子进程产生以后只跟踪子进程,放弃对父进程的跟踪。

 

 如果想让父子进程都同时运行,可以使用“set schedule-multiple on

  show follow-fork-mode
   set follow-fork-mode child
   show detach-on-fork
   set detach-on-fork off

 

  gdb调试多进程时,如果想要在进程间进行切换,那么就需要在fork调用前设置: set detach-on-fork off ,
然后使用 info inferiors 来查看进程信息,得到的信息可以看到最前面有一个进程编号,使用 inferior num 来进行进程切换。
那么为什么要使用 set detache-on-fork off 呢?它的意思是在调用fork后相关进程的运行行为是怎么样的,是detache on/off ?
也就是说分离出去独立运行,不受gdb控制还是不分离,被阻塞住。这里还涉及到一个设置 set follow-fork-mode [parents/child] ,
就是fork之后,gdb的控制落在谁身上,如果是父进程,那么分离的就是子进程,反之亦然。如果detache-on-fork被off了,
那么未受控的那个进程就会被阻塞住,进程状态为T,即处于调试状态。

r 运行调试 display 显示变量追踪
n 下一步 watch

监控变量,当变量发生修改时,打印显示。删除对应监控变量,

可以先 info watch,然后 delete 对应的号码。

c 继续运行 info registers / register <reg> 查看寄存器
ctrl + c 中断信号 info win

窗口切换fs cmd   fs src
c/continue 中断后继续运行 display 追踪查看具体变量值。
s 进入一个函数 undisplay 取消追踪观察变量。
finish 退出函数 i watch 显示观察点。
l 列出代码行 thread apply all bt 显示线程所有堆栈
b 断点
显示断点列表 info b
删除断点 delete
清除断点 clear
info threads 查看多个线程
until 跳至行号
until number
thread <thread id> 调试某个线程。
p 打印
打印数组信息 p *array@len
p/x 按十六进制格式显示变量
attach 绑定进程调试
attach -p pid
bt/backtrace 堆栈bt <-n>
-n表一个负整数,表示只打印栈底下n层的栈信息。
detach 取消绑定调试进程
f/frame 进入指定堆栈层
f number
disassemble 看二进制数据
disassemble func
x 查看内存 focus 显示源码界面

查看源代码

  • list(l):查看最近十行源码
  • list fun:查看fun函数源代码
  • list file:fun:查看flie文件中的fun函数源代码

设置断点与观察断点

  • break 行号/fun设置断点。
  • break file:行号/fun设置断点。
  • break if<condition>:条件成立时程序停住。
  • info break(缩写:i b):查看断点。
  • watch expr:一旦expr值发生改变,程序停住。
  • delete n:删除断点。

多线程下:

thread apply ID1 ID2 IDN command:让线程编号是ID1,ID2…等等的线程都执行command命令。

thread apply all command:所有线程都执行command命令。

set scheduler-locking off|on|step:在调式某一个线程时,其他线程是否执行。在使用step或continue命令调试当前被调试线程的时候,其他线程也是同时执行的,如果我们只想要被调试的线程执行,而其他线程停止等待,那就要锁定要调试的线程,只让他运行。
off:不锁定任何线程,默认值。
on:锁定其他线程,只有当前线程执行。


step:在step(单步)时,只有被调试线程运行。

set non-stop on/off:当调式一个线程时,其他线程是否运行。

set pagination on/off:在使用backtrace时,在分页时是否停止。

set target-async on/ff:同步和异步。同步,gdb在输出提示符之前等待程序报告一些线程已经终止的信息。而异步的则是直接返回。


show scheduler-locking:查看当前锁定线程的模式

 

gdb调试时可以使用以下方式打印变量,

  • print
  • x
  • whatis
  • ptype
  • info
命令作用
whatis variable 查看变量的类型
ptype variable 查看变量详细数据结构信息
info variables var 查看定义该变量的文件,不支持局部变量

 

打印字符串

命令作用
x/s str 打印字符串str
set print elements 0 打印不限制字符串长度/或不限制数组长度
call printf("%s\n", xxx) 这是打印出的字符串不会含有多余的转义字、符
printf("%s\n", xxx)  

 

打印数组

命令作用
print *array@10 打印从数组开头连续10个元素的值
print array[60]@10 打印第60~69个元素
set print array-indexes on 打印数组元素时,同时打印数组下标
*(float *)(addr)@num 打印地址值 将addr转换成float*类型,并打印num个值

 

打印指针/结构体

命令作用
print ptr 查看该指针指向的类型及指针地址
print *(struct xxx *)ptr 查看指向的结构体内容

打印指定内存地址的值

使用x命令来打印内存的值,格式为x/nfu addr,以f格式打印从addr开始的n个长度单元为u的内存值。

  • n:输出单元的个数
  • f : 输出格式,如x表示以16进制输出,o表示以8进制数处,默认x
  • u:一个单元的长度,b表示1byte,h表示2byte(half word),w表示4byte,g表示8byte(giant word)。
命令作用
x/8xb 16进制形式打印8byte
x/8xw 16进制形式打印8个单字(word)
x/10sg 字符串形式打印10个双字

 

打印局部变量

命令作用
info locals 打印当前函数局部变量
backtrace full 打印当前栈帧各个函数的局部变量,缩写bt f
bt full n 从内到外显示n个栈帧及其局部变量
bt full -n 从外到内显示n个栈帧及其局部变量

 

设置打印格式

命令作用
set print pretty on 每行只显示结构体的一名成员
set print null-stop 不显示'\000\

 

 

 

posted @ 2022-11-19 14:49  codestacklinuxer  阅读(186)  评论(0)    收藏  举报