gdb(二)
八、反向调试
使用前输入$ target record命令,然后再使用各种反向调试命令
If you run into the error: Target child does not support this command. then try adding target record at the beginning of execution, after starting run.
Edit: Since GDB 7.6 target record is deprecated, use target record-full instead.
reverse-continue
反向运行程序知道遇到一个能使程序中断的事件(比如断点,观察点,异常)。
reverse-step
反向运行程序到上一次被执行的源代码行。
reverse-stepi
反向运行程序到上一条机器指令
reverse-next
反向运行到上一次被执行的源代码行,但是不进入函数。
reverse-nexti
反向运行到上一条机器指令,除非这条指令用来返回一个函数调用、整个函数将会被反向执行。
reverse-finish
反向运行程序回到调用当前函数的地方。
set exec-direction [forward | reverse]
设置程序运行方向,可以用平常的命令step和continue等来执行反向的调试命令。
九、内存与堆栈
help x
堆栈信息
- (gdb) bt(
backtrace) <-n>(只打印栈底下n层信息) - 查看某一层栈信息:
- (gdb) f(
frame) n(栈深度) - (gdb) i(info) f(
frame) - (gdb) up n(
向栈的上面移动) - (gdb) down n(
向栈的下面移动)
- (gdb) f(
内存信息
可以使用examine命令(简写是x)来查看内存地址中的值。x命令的语法如下所示:x/<n/f/u> <addr> n、f、u是可选的参数。
-
n是一个正整数,表示需要显示的内存单元的个数,也就是说从当前地址向后显示几个内存单元的内容,一个内存单元的大小由后面的u定义。
-
f 表示显示的格式,参见下面。如果地址所指的是字符串,那么格式可以是s,如果地十是指令地址,那么格式可以是i。
-
u 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4个bytes。u参数可以用下面的字符来代替,b表示单字节,h表示双字节,w表示四字节,g表示八字节。当我们指定了字节长度后,GDB会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来。
-
表示一个内存地址。
n/f/u三个参数可以一起使用。例如:
命令:x/3uh 0x54320 表示,从内存地址0x54320读取内容,h表示以双字节为一个单位,3表示输出三个单位,u表示按十六进制显示。
输出格式
一般来说,GDB会根据变量的类型输出变量的值。但你也可以自定义GDB的输出的格式。例如,你想输出一个整数的十六进制,或是二进制来查看这个整型变量的中的位的情况。要做到这样,你可以使用GDB的数据显示格式:
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
十、command
如果想在程序停止在断点的时候,打印信息,或给一些有价值的变量赋值以便定位bug,或者是激活其他断点,可以为这个断点设置一些指令集,完成这些操作。gdb的commands指令帮你实现这个功能能。
用法:
commands [range...] #breakpoint number
... command-list ...
end
eg1.
break foo if x>0
commands //指令集设置命令
silent //断点触发时不打印断点信息
printf "x is %d\n",x
continue
end //指令集设置结束时必须用end结束
eg2.
commands 3
silent
set x = y + 4
cont
end
十一、改变程序行为
gdb可以改变程序的执行
改变执行顺序
- jump line(file:line)
- jump +num
- jump
产生信号量
signal
signal命令与shell的kill命令区别:系统的kill命令发信号给被调试程序时,是由gdb截获;而signal命令则直接发给被调试程序。
强制函数返回
return
强制调用函数
call
expr可以是函数名,显示函数返回值(void不显示)。
attach到进程
如果程序已经运行,或者是调试陷入死循环而无法返回控制台进程,可以使用attach命令。
attach pid
通过ps aux可以查看进程的pid,然后使用bt查看栈帧。
以top为例操作步骤为:
\1. ps -aux查看进程pid,为16974.
\2. sudo gdb attach 16974,使用gdb 附着到top命令。
\3. 使用bt full查看,当前栈帧。此时使用print等查看信息。
\4. 还可以通过info proc查看进程信息。
当现实内容多的时候,GDB会强制分页,现实就会暂停。但是可能并不需要,可以通过set pagination off关闭。
十二、线程与进程
线程:https://www.cnblogs.com/xuxm2007/archive/2011/04/01/2002162.html
进程:https://blog.csdn.net/qq_34328833/article/details/60139291
多进程调试避免使用断点,可能出现内存越界问题。
十三、调试技巧
- 程序出错终止时,使用bt 与 f命令,查看栈帧信息,不断向上回溯,回到出错的地方。
- 使用tmux,运行程序a、b,若2个程序之间非血缘关系的进程,也非exec关系,则开启2个gdb调试。
- 内存错误(参考http://scottmcpeak.com/memory-errors/)
方法:
a. Making the bug more robust
I know of two main techniques for reducing the fragility of a memory bug:
- Don't re-use memory.
- Put empty space between memory blocks.
b. Using hardware watchpoints

浙公网安备 33010602011771号