GDB 反向调试(Reverse Debugging)
2016-04-06 18:07
323 查看
使用调试器时最常用的功能就是step, next, continue,这几个调试命令都是“往下执行”的, 但是很多时候会有这种需求:你在调试的过程中多跳过了几步而错过中间过程,这时候不得不重头调试一遍,非常麻烦。而GDB从7.0版本开始支持反向调试功能,也就是允许你倒退着运行程序,或者说撤销程序执行的步骤从而会到以前的状态。
直观地来看,加入你正在使用GDB7.0以上版本的调试器并且运行在支持反向调试的平台,你就可以用以下几条命令来调试程序:
reverse-continue
反向运行程序知道遇到一个能使程序中断的事件(比如断点,观察点,异常)。
reverse-step
反向运行程序到上一次被执行的源代码行。
reverse-stepi
反向运行程序到上一条机器指令
reverse-next
反向运行到上一次被执行的源代码行,但是不进入函数。
reverse-nexti
反向运行到上一条机器指令,除非这条指令用来返回一个函数调用、整个函数将会被反向执行。
reverse-finish
反向运行程序回到调用当前函数的地方。
set exec-direction [forward | reverse]
设置程序运行方向,可以用平常的命令step和continue等来执行反向的调试命令。
上面的反向运行也可以理解为撤销后面运行的语句所产生的效果,回到以前的状态。
好的,接下来我们来试试看如何反向调试。
首先确认自己的平台支持进程记录回放(Process Record and Replay),当在调试器启用进程记录回放功能时,调试器会记录下子进程,也就是被调试进程的每一步的运行状态与上一步运行状态的差异,需要撤销的时候就可以很方便回到上一步。
假设我们有以下C程序:
[cpp] view
plain copy
print?
int main(int argc, const char *argv[])
{
int a = 0;
a = 1;
a = 2;
return 0;
}
将它编译并加上调试符号:
[python] view
plain copy
print?
$ gcc -Wall -g a.c
开始调试:
[python] view
plain copy
print?
$ gdb a.out
查看一下源代码:
[python] view
plain copy
print?
(gdb) l
1 int main(int argc, const char *argv[])
2 {
3 int a = 0;
4 a = 1;
5 a = 2;
6 return 0;
7 }
接下来设置一个断点在第三行:
[python] view
plain copy
print?
(gdb) b 3
Breakpoint 1 at 0x804839a: file a.c, line 3.
运行,程序会在第三行的地方停下来:
[python]
view plain
copy
print?
(gdb) r
Starting program: /home/cheryl/a.out
Breakpoint 1, main (argc=1, argv=0xbffff3e4) at a.c:3
3 int a = 0;
给变量a设置监视点方便我们观察:
[python] view
plain copy
print?
(gdb) watch a
Hardware watchpoint 2: a
启动进程记录回放:
[python] view
plain copy
print?
(gdb) record
现在每运行一步调试器都会记录下变化,以便回溯。我们连续执行3条语句。
[python] view
plain copy
print?
(gdb) n
4 a = 1;
(gdb)
Hardware watchpoint 2: a
Old value = 0
New value = 1
main (argc=1, argv=0xbffff3e4) at a.c:5
5 a = 2;
(gdb)
Hardware watchpoint 2: a
Old value = 1
New value = 2
main (argc=1, argv=0xbffff3e4) at a.c:6
6 return 0;
可以看到,a的值先是从0变为了1,然后变为2,如果想让程序倒退回到以前的状态怎么办?可以用reverse-next命令:
[python]
view plain
copy
print?
(gdb) reverse-next
Hardware watchpoint 2: a
Old value = 2
New value = 1
main (argc=1, argv=0xbffff3e4) at a.c:5
5 a = 2;
(gdb)
Hardware watchpoint 2: a
Old value = 1
New value = 0
main (argc=1, argv=0xbffff3e4) at a.c:4
4 a = 1;
(gdb)
No more reverse-execution history.
main (argc=1, argv=0xbffff3e4) at a.c:3
3 int a = 0;
(gdb)
这样程序就倒退到了我们启动进程记录回放的地方,a的值经过两步回到了最初的状态。
若需要关闭进程记录回放,可以使用record stop:
[python] view
plain copy
print?
(gdb) record stop
Process record is stoped and all execution log is deleted.
参考:《Reverse Debugging with GDB》 --- http://sourceware.org/gdb/wiki/ReverseDebug
直观地来看,加入你正在使用GDB7.0以上版本的调试器并且运行在支持反向调试的平台,你就可以用以下几条命令来调试程序:
reverse-continue
反向运行程序知道遇到一个能使程序中断的事件(比如断点,观察点,异常)。
reverse-step
反向运行程序到上一次被执行的源代码行。
reverse-stepi
反向运行程序到上一条机器指令
reverse-next
反向运行到上一次被执行的源代码行,但是不进入函数。
reverse-nexti
反向运行到上一条机器指令,除非这条指令用来返回一个函数调用、整个函数将会被反向执行。
reverse-finish
反向运行程序回到调用当前函数的地方。
set exec-direction [forward | reverse]
设置程序运行方向,可以用平常的命令step和continue等来执行反向的调试命令。
上面的反向运行也可以理解为撤销后面运行的语句所产生的效果,回到以前的状态。
好的,接下来我们来试试看如何反向调试。
首先确认自己的平台支持进程记录回放(Process Record and Replay),当在调试器启用进程记录回放功能时,调试器会记录下子进程,也就是被调试进程的每一步的运行状态与上一步运行状态的差异,需要撤销的时候就可以很方便回到上一步。
假设我们有以下C程序:
[cpp] view
plain copy
print?
int main(int argc, const char *argv[])
{
int a = 0;
a = 1;
a = 2;
return 0;
}
将它编译并加上调试符号:
[python] view
plain copy
print?
$ gcc -Wall -g a.c
开始调试:
[python] view
plain copy
print?
$ gdb a.out
查看一下源代码:
[python] view
plain copy
print?
(gdb) l
1 int main(int argc, const char *argv[])
2 {
3 int a = 0;
4 a = 1;
5 a = 2;
6 return 0;
7 }
接下来设置一个断点在第三行:
[python] view
plain copy
print?
(gdb) b 3
Breakpoint 1 at 0x804839a: file a.c, line 3.
运行,程序会在第三行的地方停下来:
[python]
view plain
copy
print?
(gdb) r
Starting program: /home/cheryl/a.out
Breakpoint 1, main (argc=1, argv=0xbffff3e4) at a.c:3
3 int a = 0;
给变量a设置监视点方便我们观察:
[python] view
plain copy
print?
(gdb) watch a
Hardware watchpoint 2: a
启动进程记录回放:
[python] view
plain copy
print?
(gdb) record
现在每运行一步调试器都会记录下变化,以便回溯。我们连续执行3条语句。
[python] view
plain copy
print?
(gdb) n
4 a = 1;
(gdb)
Hardware watchpoint 2: a
Old value = 0
New value = 1
main (argc=1, argv=0xbffff3e4) at a.c:5
5 a = 2;
(gdb)
Hardware watchpoint 2: a
Old value = 1
New value = 2
main (argc=1, argv=0xbffff3e4) at a.c:6
6 return 0;
可以看到,a的值先是从0变为了1,然后变为2,如果想让程序倒退回到以前的状态怎么办?可以用reverse-next命令:
[python]
view plain
copy
print?
(gdb) reverse-next
Hardware watchpoint 2: a
Old value = 2
New value = 1
main (argc=1, argv=0xbffff3e4) at a.c:5
5 a = 2;
(gdb)
Hardware watchpoint 2: a
Old value = 1
New value = 0
main (argc=1, argv=0xbffff3e4) at a.c:4
4 a = 1;
(gdb)
No more reverse-execution history.
main (argc=1, argv=0xbffff3e4) at a.c:3
3 int a = 0;
(gdb)
这样程序就倒退到了我们启动进程记录回放的地方,a的值经过两步回到了最初的状态。
若需要关闭进程记录回放,可以使用record stop:
[python] view
plain copy
print?
(gdb) record stop
Process record is stoped and all execution log is deleted.
参考:《Reverse Debugging with GDB》 --- http://sourceware.org/gdb/wiki/ReverseDebug
相关文章推荐
- 问题1:javascript的函数对象问题
- mybatis generator maven-plugin 集成
- numpy 学习,里面有converters参数的使用方法
- IP格式合法问题研究
- mysql两大存储引擎的区别与选择
- Qt Quick实现的涂鸦程序
- LUA IO库
- 使用word模板生成pdf文件
- python为什么有私有方法和变量
- Android 发送广播更加方便快捷高效的方式
- 数据库索引
- In App Purchase(应用内购)
- shell if手册
- .bar : 嵌入子元素
- Ubuntu 15.10安装ns2.35+nam
- 通过一个实例理解 offsetLeft,offsetTop; offsetWidth , offsetHeight
- xUtils 3.0
- YARN DistributedShell源码分析与修改
- 四则运算终结版
- swift学习笔记