GDB调试

GDB是一个GNU开源项目,用户unix/linux下的程序调试,基于命令行,功能十分强大。一个简单的调试过程如下:

g++ -g test.cpp  #编译加入调试信息
gdb <可执行文件名>  #调试程序
run  #运行程序

# 设置断点
b <源代码行号>
info b  #显示断点

# 调试
n  #单步步过,如果遇到函数调用,则跳过函数的具体执行,直接到下一步
s  #单步步入,如果遇到函数调用,跳到函数内部
c  #继续运行程序,直到遇到断点位置

# 显示源码窗口
layout src

启动gdb

要调试某一程序,需要在编译程序是,加入-g参数,如:g++ -g hello.cpp,接下来,就可以启动调试了。
gdb <program>
<program>为生成的可执行文件

调试core文件(core是程序非法执行后core dump后产生的文件):
gdb <program> <core dump file>
$ gdb program core.11127

调试服务程序:
gdb <program> <PID>
$gdb hello 11127

运行

run
简记为:r,作用是运行程序,当遇到程序断电时,停止运行等待用户的下一步操作。

continue
简记为: c,继续执行到下一个断点处。

next
简记为:n,单步跟踪程序,当遇到函数调用时,也不进入此函数体;此命令同 step 的主要区别是,step 遇到用户自定义的函数,将步进到函数中去运行,而 next 则直接调用函数,不会进入到函数体内。

step
简记为:s,单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的。

until
简记为:u,在一个循环体内单步跟踪时,该命令可以运行程序直到退出循环体。
until + 行号
运行至某行,运行过程中可以退出循环体。

finish
运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。

call 
call <expr>
强制调用某函数,也可以传递参数,如:call gdb_test(55)。

jump
GDB可以修改程序的执行顺序,从而让程序随意跳跃。
jump <linespec>
指定下一条语句的运行点。<linespec>可以是文件的行号,可以是file:line格式,也可以是+num这种偏移量格式,表示下一条运行语句从哪里开始。
jump <address>
这里的<address>是代码行的内存地址。
注意,jump命令不会改变当前的程序栈中的内容,所以,如果使用jump从一个函数跳转到另一个函数,当跳转到的函数运行完返回,进行出栈操作时必然会发生错误,这可能导致意想不到的结果,所以最好只用jump在同一个函数中进行跳转。

set
设定运行时的参数。
修改寄存器:
(gdb) set $v0 = 0x004000000
(gdb) set $epc = 0xbfc00000
修改内存:
(gdb) set {unsigned int}0x8048a51=0x0

quit
简记为:q,退出gdb。

设置断点

break
简记为:b。
b n
在第n行处设置断点。
break <func>
在函数<func>的入口处设置断点。
break +offset / break -offset
在当前行的前offset或后offset的行处,设置断点。
break *address
在程序运行的内存地址处设置断点。
break if <condition>
在满足条件时,停止执行,比如:break if i>100

delete
删除断点
delete n
删除第n个断点
delete breakpoints
删除所有断点

disable
disable n
暂停第n个断点

clear
clear n
删除第n行的断点

查看

list
简记为:l。列出程序的代码。
list <n>
列出当前行的前后n行代码。
list <func>
列出函数<func>的源代码。

print
简记为:p。
print <expr>
print a
显示变量a的值。
print ++a
将a的加1显示出来。
print gdb_test(a)
将以变量 a 作为参数调用 gdb_test() 函数
print /<f> <expr>
/f表示print的输出格式,格式如下:
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。

watch
设置一个监视点,一旦被监视的“表达式”的值改变,gdb将强行终止正在被调试的程序,如: watch a,a为一个变量。watch只有在程序运行时,才可设置

info
info watchpoints
列出当前所设置了的所有观察点。
info registers
查看除了浮点寄存器以外的寄存器
info all-registers
查看所有寄存器,包括浮点寄存器
info breakpoints
查看所有的断点
info signals
查看有哪些信号正在被GDB检测
info threads
可以看多线程

show
show ars
查看设置好的运行参数
show environment
查看环境变量

display
在单步运行时将非常有用,使用display命令设置一个表达式后,它将在每次单步进行指令后,紧接着输出被设置的表达式及值,如: display a。

examine
简记为:x,查看内存地址中的值。
x/<n/f/u> <addr>
<addr>表示一个内存地址。“x/”后的n、f、u都是可选的参数,n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容;f 表示显示的格式,如果地址所指的是字符串,那么格式可以是s,如果地址是指令地址,那么格式可以是i;u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4字节。u参数可以被一些字符代替:b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,GDB会从指定的内存地址开始,读写指定字节,并把其当作一个值取出来。n、f、u这3个参数可以一起使用,例如命令“x/3uh 0x54320”表示从内存地址0x54320开始以双字节为1个单位(h)、16进制方式(u)显示3个单位(3)的内存。

分割窗口

layout
该命令可以分割窗口,可以一边查看代码,一边测试:
layout src
显示源代码窗口
layout asm
显示反汇编窗口
layout regs
显示源代码/反汇编和CPU寄存器窗口
layout split
显示源代码和反汇编窗口
Ctrl + L
刷新窗口

gdb 调试利器 
调试器gdb的基本使用方法(1)

还可利用gdb调试PostgreSQL。

用GDB 调试 PostgreSQL 
Linux下gdb调试及显示变量的值 
100个gdb小技巧