1. 启动方法
>gdb program
program是可执行文件的名字,一般在当前目录下。
2. 为可执行程序设定运行参数
运行参数的设置在进入gdb环境后。
<gdb>set args 参数列表
可用show args查看设定的参数。
3.启动GDB后,首先就是要设置断点。在gdb中,断点通常有三种形式:
断点(BreakPoint):
在代码的指定位置中断,这个是我们用得最多的一种。设置断点的命令是break,它通常有如下方式:
break <function> 在进入指定函数时停住
break <linenum> 在指定行号停住。
break +/-offset 在当前行号的前面或后面的offset行停住。offiset为自然数。
break filename:linenum 在源文件filename的linenum行处停住。
break ... if <condition> ...可以是上述的参数,condition表示条件,在条件成立时停住。比如在循环境体中,可以设置break if i=100,表示当i为100时停住程序。
可以通过info breakpoints [n]命令查看当前断点信息。此外,还有如下几个配套的常用命令:
delete 删除所有断点
delete breakpoint [n] 删除某个断点
disable breakpoint [n] 禁用某个断点
enable breakpoint [n] 使能某个断点
观察点(WatchPoint):
在变量读、写或变化时中断,这类方式常用来定位bug。
watch <expr> 变量发生变化时中断
rwatch <expr> 变量被读时中断
awatch <expr> 变量值被读或被写时中断
可以通过info watchpoints [n]命令查看当前观察点信息
捕捉点(CatchPoint):
捕捉点用来补捉程序运行时的一些事件。如:载入共享库(动态链接库)、C++的异常等。通常也是用来定位bug。
捕捉点的命令格式是:catch <event>,event可以是下面的内容
throw C++抛出的异常时中断
catch C++捕捉到的异常时中断
exec 调用系统调用exec时(只在某些操作系统下有用)
fork 调用系统调用fork时(只在某些操作系统下有用)
vfork 调用系统调用vfork时(只在某些操作系统下有用)
load 或 load <libname> 载入共享库时(只在某些操作系统下有用)
unload 或 unload <libname> 卸载共享库时(只在某些操作系统下有用)
另外,还有一个tcatch <event>,功能类似,不过他只设置一次捕捉点,当程序停住以后,应点被自动删除。
捕捉点信息的查看方式和代码断点的命令是一样的,这里就不多介绍了。
在gdb中,和调试步进相关的命令主要有如下几条:
continue 继续运行程序直到下一个断点(类似于VS里的F5)
next 逐过程步进,不会进入子函数(类似VS里的F10)
setp 逐语句步进,会进入子函数(类似VS里的F11)
until 运行至当前语句块结束
finish 运行至函数结束并跳出,并打印函数的返回值(类似VS的Shift+F11)
PS:这些命令大部分可以简写为第一个字母,在日常使用过程中,往往只会输入第一个字符即可执行该命令,我标红的即是通常的使用方式。这几条命令使用非常频繁,并且可以带一些附加参数以实现高级功能,需要熟练掌握。
将可执行程序用gdb program_name调用到内存中后,就可以利用gdb的反汇编命令调试程序了。常用命令如下:
(1)设置反汇编的代码为intel格式
gdb默认反汇编为att格式的指令。可以通过show disassembly-flavor查看。如果习惯intel格式的,用命令set disassembly-flavor intel设置。
(2)反汇编命令disas/disass/disassemble
功能:将内存中的机器码程序以指令助记符的形式显示出来。
格式: disas/disass/disassemble 函数名/起始地址[,结束地址]
例如:
disas main,显示main函数对应的汇编代码
(3)info line
功能:查看某个line的相关信息。
格式:info line 函数名/*内存地址
说明:如果参数为函数名,则显示该函数在源文件中的行号及在内存中的起始地址和结束地址。例如:
如果参数为*内存地址,则显示该内存地址的指令对应的语句所在的函数在源文件中的行号及在内存中的起始地址和结束地址。例如:
(4)r 开始/重新执行 r means run
(5)b设置断点 b means break
格式:b *内存地址
delete:删除所有断点
delete num:删除编号为num的断点
info break:列出所有断点
(6)ni 单步步过,相当于debug命令中的p (跟进 相当于OD中的F8)
(7)si 单步步入,相当于debug命令中的t (跟进 相当于OD中的F7)
(8)finish 执行到返回
(9)display 显示某寄存器的值
格式:display /x $寄存器名字。例如:display /x $eax
(10)x查看内存单元
格式:x /nfu 内存地址 x means examine
说明:
n表示要显示的内存单元的个数
f表示显示方式, 可取如下值:
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a按十六进制格式显示变量。
i 指令地址格式。
c 按字符格式显示变量。
s 按字符串格式显示变量。
f 按浮点数格式显示变量。
u表示一个地址单元的长度,其中:
b表示单字节,
h表示双字节,
w表示四字节,
g表示八字节。
(11)p查看变量值
格式: p 变量名
如果要查看变量的地址,用p &变量名
格式:x /nfu 内存地址 x means examine
x/i $pc 查看当前执行到了哪一条语句。
x/x $esp 显示esp寄存器的值
x/4wx $esp 显示4个word
display /x $esp 一直显示esp寄存器的值
i reg 显示所有的寄存器值还有状态。
call + 函数名称 直接调用这个函数
比较好的参考:
http://blog.csdn.net/yechonglaile/article/details/44888623