当gdb启动时,会读取HOME
目录和当前目录下的的配置文件,执行里面的命令。配置文件名通常为.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自身命令的脚本,例如.gdbinit
文件,当gdb在启动时,就会执行.gdbinit
文件中的命令;此外,gdb还支持其它一些语言写的脚本文件(比如python)。
gdb用set script-extension
命令来决定按何种格式来解析脚本文件。它可以取3个值:
off
:所有的脚本文件都解析成gdb的命令脚本;soft
:根据脚本文件扩展名决定如何解析脚本。如果gdb支持解析这种脚本语言(比如python),就按这种语言解析,否则就按命令脚本解析;strict
:根据脚本文件扩展名决定如何解析脚本。如果gdb支持解析这种脚本语言(比如python),就按这种语言解析,否则不解析;写一个脚本文件(gdb.py
),但内容是一个gdb命令,不是真正的python脚本。用途是退出gdb时不提示:
# gdb.py
set confirm off
然后在gdb中按顺序执行以下命令:
# 查看script-extension的值,默认值是soft
show script-extension
# 因为soft会按照pyhton语言解析gdb.py文件,但是这个文件实质上是一个gdb命令脚本,所以解析会出错
set script-extension off
# 正确解析gdb.py文件,配置生效
source gdb.py
gdb [-tui] [execut_file] [| tee log_file]
,启动gdb-tui
选项,启动可以直接将屏幕分成两个部分,上面显示源代码;tee
命令可以将gdb调试时显示的所有信息输出到指定的文件中。gdb attach pid
,调试正在运行的进程// 查找所有正在运行的进程,筛选出名字中带有luarocks的,在筛选结果中剔除名字中带有auto的
// 找出筛选结果的第二列,作为gdb attach 后面跟的参数
gdb attach `ps -ef | grep "luarocks" | grep -v "auto" | awk '{print $2}'`
run
,简写r
:运行被调试的程序。如果此前没有下过断点,则执行完整个程序;如果有断点,则程序暂停在第一个可用断点处start
,开始调试,停在第一行代码处gdb -args ./a.out arg1 arg2 ...
,启动时设置被调试程序的参数set args
,修改发送给程序的参数(run后面跟的参数)## 也可以采用以下方式设置被调试程序的参数
gdb ./a.out
set args arg1 arg2 ...
## 还可以
gdb ./a.out
start arg1 arg2 ...
set var
,修改指定变量的值# assignment的语法跟随调试语言本身(= 、:=)
set var i = 10
# 也可以只用set,但可能会存在变量名(i)与gdb参数冲突的情况(print、args)
# 所以最好还是用set var
set i=10
set
,修改该指定寄存器中的值,如set $pc = 100
、set $r1 = 0
set [*|*(type*)|{type}]address = value
,修改指定地址处的值,如给存储地址在address,变量类型为type的变量赋值# 根据地址修改字符串的值
(gdb) p &p1
$1 = (char (*)[4]) 0x80477a4
(gdb) set {char [4]} 0x80477a4 = "Ace"
# 根据地址修改变量的值,有三种方式可选择
(gdb) p &i
$2 = (int *) 0x8047a54
(gdb) set *0x8047a54 = 8
(gdb) set *(int *)0x8047a54 = 8
(gdb) set {int}0x8047a54 = 8
# 缺省情况下,gdb是以只读方式加载程序的。可以通过以下命令行选项指定为可写
gdb -write ./a.out
# 或者
(gdb) set write on
(gdb) file ./a.out
# 将函数fun-name的每一行源码与其汇编指令和指令的具体值对应显示
disassemble /mr fun-name
# 修改二进制代码(注意大小端和指令长度)
# 如将0x0000000120000760处的指令改为:andi $r0,$r0,0x0
set *0x0000000120000760=0x03400000
set variable *(int*)0x0000000120000760=0x03400000
set {int}0x0000000120000760=0x03400000
next
,简写n
:执行一行源程序代码,此行代码中的函数调用也一并执行,(gdb) n
,(gdb) n line-number
step
,简写s
:执行一行源程序代码,如果此行代码中有函数调用,则进入该函数,(gdb) s
,(gdb) s line-number
step
进入(如系统库函数),但执行set step-mode on
即可。continue
,简写c
:继续执行被调试程序,直至下一个断点或程序结束,(gdb) c
,(gdb) c line-number
until [line-number]
,简写u [line-number]
:可以指定程序运行到某一行停下来,如当前程序停在第10行,使用(gdb) u 23
,则快速执行完中间代码,在23行停下来finish
,执行完当前函数的所有语句,然后正常退出该函数return [expression]
,立即结束当前正在执行的函数,不再执行函数的后面语句,并返回,expression是函数返回的值print[/f|等] [var|ptr|addr]
,简写p[/f|等] [var]
:显示指定变量的值,(gdb) p [var]
,(gdb) p [&var]
,(gdb) p [ptr]
,(gdb) p [*ptr]
,(gdb) p/x [var]
,参考自print打印。
其中f
表示显示方式, 可取如下值:
x
按十六进制格式显示变量
d
按十进制格式显示变量
u
按十六进制格式显示无符号整型
o
按八进制格式显示变量
t
按二进制格式显示变量
a
按十六进制格式显示变量
c
按字符格式显示变量
f
按浮点数格式显示变量
s
按字符串格式显示变量
打印数组前n个元素p *arr@n
,打印数组下标从m开始的n个元素p arr[m]@n
set print
,以指定的格式显示输出变量的值,在查看表达式(变量)信息时使用
set print address [on|off]
,打开地址输出,当程序显示函数信息时,GDB会显出函数的参数地址
set print array [on|off]
,打开数组显示,打开后当数组显示时,每个元素占一行,如果不打开的话,每个元素则以逗号分隔
set print elements [num|unlimited]
,指定数组显示的最大长度,,当到达这个长度时,GDB就不再往下显示了。如果设置为0,则表示不限制
set print null-stop [on|off]
,如果打开了这个选项,那么当显示字符串时,遇到结束符则停止显示。这个选项默认为off
set print union [on|off]
,设置显示结构体时,是否显式其内的联合体数据。
set print object [on|off]
,在C++中,如果一个对象指针指向其派生类,如果打开这个选项,GDB会自动按照虚方法调用的规则显示输出,如果关闭这个选项的话,GDB就不管虚函数表了
set print pretty [on|off]
,控制结构体输出格式,打开则会以如下形式显示:
$1 = {
next = 0x0,
flags = {
sweet = 1,
sour = 1
},
meat = 0x54 "Pork"
}
x /nfu
,查看指定内存中存放的值,addr
是个地址之,也可以用p *addr
,但是一次只能查看一个字节,没有x
好用
1)n
表示要显示的内存单元的个数
2)f
同上面print
指令中的f作用一样
3)u
表示一个地址单元的长度,可取如下值:
b
表示单字节
h
表示双字节
w
表示四字节
g
表示八字节
display [var]
,设置想要跟踪的变量,自动显示
display/[n]i $pc
,每次回到gdb命令行时,显示当前要执行的汇编指令,n为显示条数
info display
,简写i display
:显示所有跟踪变量
undisplay [varnum|varnum1-varnum2]
,取消禁用指定编号/范围的变量跟踪显示,(gdb) undisplay 1
disable display [varnum|varnum1-varnum2]
,禁用指定编号/范围的变量跟踪显示,(gdb) disable display 2-4
enable display [varnum|varnum1-varnum2]
,启用指定编号/范围的变量跟踪显示
delete display [varnum|varnum1-varnum2]
,删除指定编号/范围的变量跟踪显示
whatis [var]
和ptype [var]
,显示一个变量的类型
break
,简写b
:
b
,在下一条命令处停止运行
b [函数名]
,在某个函数的开始处设置断点,(gdb) b main
b [行号]
,在当前文件的指定行,(gdb) b 10
b [文件名:函数名/行号]
,指定文件的指定行
b [*address]
,在程序运行的内存地址处打断点
以上任意b命令 [if
,cond
为true
时,指定位置打断点,(gdb) b 10 if i==12
rbreak [REGEX|FILE:REGEX].
,REGEX
是正则表达式,程序中函数的函数名只要满足REGEX
条件,rbreak
命令就会其内部的开头位置打断点。如在所有函数上面打断点(gdb) rbreak .
,在main.c
文件中的所有函数上面打断电(gdb) rbreak main.c:.
tbreak
,简写tb
,临时断点,只生效一次,如(gdb) tb main.c:10
watch
,一般来观察某个表达式(变量也是表达式)或内存地址的值是否发生了变化,如果发生变化则程序立即暂停,自动断点
watch [exp|*addr]
,为exp
设置一个观察点,如果其值变化,程序暂停,(gdb) watch a
,(gdb) watch *(int *) 0xffffff318c
rwatch [exp|*addr]
,exp
被读时,程序暂停
awatch [exp|*addr]
,exp
的值被读或被写时,程序暂停
info watchpoints
,列出当前所设置的所有观察点
ignore N COUNT
,让N
断点执行COUNT
后停下,也就是前COUNT - 1
次该断点不会起效
(gdb) b lj_BC_JLOOP
Breakpoint 3 at 0x12003b020
(gdb) ignore 3 316
Will ignore next 316 crossings of breakpoint 3.
info breakpoints
,简写i b
:查看所有断点信息
disable [break-num]
,禁用某一个断点
enable [break-num]
,启用某一个断点
delete [break-num]
,简写d [break-num]
:删除某一个断点
save breakpoints [file-name]
,将设置的断点保存下来,等需要时(退出gdb再进入也ok),使用命令source [file-name]
批量设置被保存的断点,保存和使用的[file-name]
一致既可
list
命令,简写l
l
,显示当前行后面的代码l [-]
,继当前显示向前再显示10行l [行号]
,显示10行,指定行号处于中间位置l [fun-name]
,显示指定函数名的上下文backtrace
,简写bt
:查看当前程序的调用堆栈info frame
,简写i f
:查看当前栈帧信息frame [num]
,简写f [num]
:切换到其他堆栈处,通常与bt
一起使用,(gdb) f 2
。也可以用up [num]
和down [num]
向上或向下选择函数堆栈帧,其中n是层数show args
,查看发送给程序的参数(run
后面跟的参数)info registers
,简写i r
:查看除了浮点寄存器以外的寄存器info register [reg-name]
,简写i r [reg-name]
:查看指定寄存器reg-name
info all-registers
,简写: 查看所有的寄存器包括浮点寄存器p $reg-name
,可以查看寄存器的值info break
,简写i b
:查看所有断点信息info functions
查看所有的函数info watchpoints
,查看当前设置的所有观察点info signals info handle
,查看有哪些信号正在被gdb检测info line [currLineNum]
,查看源代码在内存中的地址info threads
,查看线程信息,只会输出线程的简短信息,通常只是一层栈(gdb) info threads
Id Target Id Frame
* 1 Thread 0xfff7c3ce70 (LWP 26956) "sysbench" main (argc=2, argv=0xffffff33b8) at sysbench.c:1405
info source
,查看当前所在的源代码文件信息,文件名称,程序语言等info files
,查看当前可执行文件的一些信息,如程序入口地址、各个段的内存布局等info frame
,查看当前函数栈的一些详细信息(gdb) info frame
Stack level 0, frame at 0xffffff2d40:
pc = 0xaaaab00e4c in sb_histogram_print (sb_histogram.c:321); saved pc = 0xaaaab85948
called by frame at 0xffffff2d40
source language c.
Arglist at 0xffffff2d40, args: h=0xaaaae46020
Locals at 0xffffff2d40, Previous frame's sp is 0xffffff2d40
Saved registers:
gp at 0xffffff2d28, s8 at 0xffffff2d30, ra at 0xffffff2d38, pc at 0xffffff2d38
b *fun-name
,在函数的第一条汇编指令打断点set disassemble-next-line auto
,当前代码没有源码(没有调试信息)时,自动反汇编执行到的每一行代码set disassemble-next-line on
,不管是否有源码,都自动反汇编执行到的每一行代码set disassemble-next-line off
,关闭自动反汇编功能display /[n]i $pc
,显示当前要执行的汇编指令,n为显示条数disassemble [/r] fun-name
,查看函数fun-name的反汇编代码/r
参数,以16进制显示每条汇编指令的值,下面指令都可以使用disassemble /m fun-name
,将函数的每一行源码与其汇编指令对应显示disassemble addr
:将addr所在函数的指令全部反汇编disassemble addr1, addr2
:反汇编[addr1, addr2)
处的指令,常与info line [currLineNum]
配合使用调试多进程常用命令。
set follow-fork-mode [child|parent]
,设置调试哪个进程child
,调试子进程parent
,调试父进程set detach-on-fork [off|on]
,GDB在fork之后是否断开(detach)某个进程的调试off
,同时调试父进程和子进程on
,只调试父进程set schedule-multiple on
,让父子进程都同时运行info inferiors
,查看所有进程信息inferiors
,切换到指定进程调试多线程。用gdb调试多线程程序时,一旦程序断住,所有的线程都处于暂停状态。此时当你调试其中一个线程时(比如执行“step”,“next”命令),所有的线程都会同时执行。
set print thread-events off
,当有线程产生和退出时,就不会打印提示信息
show scheduler-locking
, 查看控制其他线程执行的设置
set scheduler-locking [off|on|step]
on
,表示调试线程执行时,其余线程锁定,阻塞等待
off
,表示不锁定其他线程,也是默认值
step
,表示在step(单步)调试时,只有当前线程运行,其它线程不会执行,但是用其它命令(比如"next")调试线程时,其它线程也许会执行
info threads
,查看所有线程的信息
thread
,切换到指定线程
break
,在line行为指定tid的线程打断点
break
,在line行为所有的线程打断点
thread apply
,让tid线程执行gdb_cmd命令
Enter键
,复制上一条命令
help [cmd]
,指定命令帮助提示,(gdb) help list
quit
,简写q
,退出GDB调试环境
gcc -g
编译生成的程序,是不包含预处理器宏信息; 如果想在gdb中查看宏信息,可以使用gcc -g3
进行编译
set logging xxx
组合可以将调试信息输出到指定文件,下面将gdb调试的过程记录到thread_info.txt
文件中:
set height 0 ##设置在文件中的起始位置
set logging file thread_info.txt ##指定输出文件
set logging on ##此命令之后的所有调试信息将输出到thread_info.txt文件
## 开始gdb调试,会将过程记录
set logging off ##关闭到指定文件的输出
## 在启动gdb的时候加入tee命令也可以保存调试信息,不过这就没有上面的方式灵活
gdb ./a.out | tee log_file
info sharedlibrary regex
,显示程序加载的共享链接库信息,其中regex可以是正则表达式,意为显示名字符合regex的共享链接库。如果没有regex,则列出所有的库
(gdb) info sharedlibrary
From To Syms Read Shared Object Library
0x000000fff7fd2540 0x000000fff7feafd8 Yes /lib64/ld.so.1
0x000000fff7ef28f0 0x000000fff7f4e56c Yes /lib/loongarch64-linux-gnu/libm.so.6
0x000000fff7ed90b0 0x000000fff7eda064 Yes /lib/loongarch64-linux-gnu/libdl.so.2
0x000000fff7e91a90 0x000000fff7eb9300 Yes (*) /lib/loongarch64-linux-gnu/libgcc_s.so.1
0x000000fff7cfd040 0x000000fff7df7af8 Yes /lib/loongarch64-linux-gnu/libc.so.6
(*): 带“*”表示库缺少调试信息.
stack 20
,查看栈内20个值
vmmap
,查看映射状况 peda带有
readelf
,查看elf
文件中各个段的起始地址 peda
带有
parseheap
,显示堆状况 peda带有