您的位置:首页 > 其它

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: