GDB调试器基础
GDB常用命令:
命令 | 含义描述 |
---|---|
file | 装入想要调试的可执行文件 |
run | 执行当前被调试的程序 |
kill | 终止正在调试的程序 |
step | 执行一行源代码并进去函数内部 |
next | 执行一行源代码但不进入函数内部 |
break | 在代码里设置断点,这将使程序执行到这里被挂起 |
| 打印表达式或变量的值,或打印内存中某个变量开始的一段连续区域的值,还以用来对变量进行赋值 |
display | 设置自动显示的表达式或变量,当程序停住或在单步跟踪时,这些变量会自动显示当前值 |
list | 列出产生执行文件的源代码的一部分 |
quit | 退出gdb |
watch | 使你能监视一个变量的值而不管它何时被改变 |
backtrace | 回溯跟踪 |
frame n | 定位到发生错误的代码段,n为backtrace命令的输出结果的行号 |
examine | 查看内存地址中的值 |
jump | 使程序跳转执行 |
signal | 产生信号量 |
return | 强制函数返回 |
call | 强制函数调用 |
make | 使用户不退出gdb就可以重新产生可执行文件 |
shell | 使用户不离开gdb就执行Linux的shell命令 |
使用断点,break命令的用法:
命令 | 函数描述 |
break <function> | 在进入指定函数时停住。C++中可以使用class::function或function(type,type)格式来指定函数名 |
break <linenum> | 在指定行号停住 |
break+offset | 在当前行号前面的offset行停住 |
break-offset | 在当前行号后面的offset行停住 |
break filename:linenum | 在源文件filename的linenum行停住 |
break filename:function | 在源文件filename的function函数入口处停住 |
break *address | 在程序运行的内存地址处停住 |
brak | 该命令没有参数时,表示在下一条指令处停住 |
break ... if<condition> | condition表示条件,在条件成立时停住。比如在循环体中,可以设置brak if i=100,表示i为100时暂停程序 |
GDB常用命令的参数:
参数 | 含义名称 |
| 行号 |
| 函数名 |
<+offset> | 当前行号的正偏移量 |
<-offset> | 当前行号的负偏移量 |
<filename:linenum> | 某个文件的某一行 |
<filename:function> | 某个文件的某个子函数 |
<*address> | 程序运行时的语句在内存中的地址 |
查看运行时数据:
1、print命令:
print <expr>
print /<f> <expr>
<expr>是表达式或变量,<f>是输出的格式,如8、16进制
print $表示当前序号的前一个序号,$代表序号
2、输出格式:
gdb的数据显示格式
符号 | 含义 |
x | 十六进制 |
d | 十进制 |
u | 十六进制显示无符号整数 |
o | 八进制 |
t | 二进制 |
a | 十六进制 |
c | 字符格式 |
f | 浮点格式 |
3、自动显示命令
display <expr>
display /<fmt> <expr>
display /<fmt> <addr>
expr是表达式,fmt表示显示的格式,addr表示内存地址
display /i $pc:$pc是gdb的环境变量,表示指令的地址;/i表示输出格式为机器指令码,就是汇编
display相关命令
命令 | 含义描述 |
undisplay <dnums...> delete display <dnums...> | 删除自动显示,dnums为已经设置好了的自动显示的编号。如果要同时删除几个编号,可以用空格分割;如果要删除一个范围内的编号,可以用减号表示 |
disable display <dnums...> enable display <dnums...> | 不删除自动显示的设置,而只是让其失效或恢复 |
info display | 查看display设置的自动显示的信息,gdb会显示处一张表格,报告调试中设置了多少个自动显示设置,其中包括已经设置的编号、表达式及是否enable |
4、查看内存
可以用examine命令(简写是x)来查看内存地址中的值。
x /<n/f/u> <addr>
-
n,f,u是可选参数,可以独立使用,也可以联合使用
-
n是一个正整数,表示显示内存的长度,也就时从当前地址向后显示几个地址的值
-
f表示显示的格式,如果地址时字符串,可以是s;如果时指令地址,格式可以是i
-
u表示从当前地址往后请求的字节数,如果不指定默认是4B,u可以替代:b表示字节;h表示双字节;w表示四字节;g表示八字节;
-
<addr>表示一个内存地址
5、gdb的环境变量
设置环境变量:set $foo = *object_ptr
查看当前所设置的所有环境变量:show convenience
6、查看寄存器
命令 | 含义描述 |
Info registers | 查看寄存器的情况(除了浮点寄存器) |
Info all-registers | 查看所有寄存器的情况(包括浮点寄存器) |
Info registers <regname>... | 查看所指定的寄存器的情况,regname表示寄存器名,多个寄存器之间用逗号隔开 |
查看源程序
1、显示源代码
可以用list命令来显示程序的源代码:
list命令
命令 | 含义描述 |
list<linenum> | 显示程序linenum行周围的源程序 |
list<function> | 显示名为function的函数的源程序 |
list | 显示当前行后面的源程序 |
list- | 显示当前行前面的源程序。一般时显示当前行的上5行和下5行,或者显示当前行的上2行和下8行,默认总共是10行。 |
set listsize <count> | 设置一次显示源代码的行数。 |
show listsize | 查看当前listsize的设置 |
list<first>,<last> | 显示从first行到last行之间的源代码。 |
list,<last> | 显示从当前行到last行之间的源代码。 |
list + | 向后显示源代码。 |
2、源代码的内存
可以用info line命令来查看源代码在内存中的地址。info line后面可以跟“行后”,“函数名”,“文件名:行号”,“文件名:函数名”的参数形式,这个命令会显示处所在的源代码在运行时的内存地址。
例如:info line square_sum.c:Calculate
可以用disassemble命令查看源代码当前执行时的机器码,这个命令会把目前内存中的指令dump出来。
例如:disassemble Calculate
改变程序的执行
1、修改变量值
print x=8
x=8是C/C++语言意为把变量x的值修改为8
2、跳转执行
用jump命令实现程序执行的跳跃
jump <linespec>
指定下一条语句的运行点。<linespec>是文件的行号,可以时file:line格式,可以是+num这种偏移量格式,表示下一条运行语句从哪里开始。
jump <address>
这里<address>是代码行的内存地址。
【最好在同一个函数中进行跳转】
3、产生信号量
使用signal命令可以产生一个信号量给被调试的程序。如中断信号Ctrl+C。
signal <signal>(signal介于1~15)
4、强制函数返回
如果调试断点在某个函数中,还有语句没有执行完,可以用return命令强制函数忽略还没有执行的语句并返回。
return
return <expression>
使用return命令取消当前函数时,并立即返回;如果指定了<expression>,那么该表达式的值会被当作函数的返回值。
5、强制调用函数
强制调用函数使用call命令,格式如下:
call <expr>
表达式中也可以是函数,以达到强制调用函数的目的,显示函数的返回值,如果函数返回值时void,那么就不显示。
当然也可=可以用print命令。
6、gdb的语言环境命令
命令 | 含义描述 |
show language | 查看当前的语言环境。如果gdb不能识别所调试的编程语言,那么C 语言被认为是默认的环境 |
info frame | 查看当前函数的程序语言 |
info source | 查看当前文件的程序语言 |
可以set language <l>命令手动设置当前的程序语言,<l>是语言。