听说GDB 7.0中有一个很酷的功能,那就是所谓Reverse Debuggin(RD),简单的说是程序可以倒着调试。一下子也想不到特别有用的地方,但感觉上确实是很酷的功能。
从发布的信息中看,GDB主要支持以下几种Reverse命令:
- reverse-continue ('rc') -- Continue program being debugged but run it in reverse
- reverse-finish -- Execute backward until just before the selected stack frame is called
- reverse-next ('rn') -- Step program backward, proceeding through subroutine calls.
- reverse-nexti ('rni') -- Step backward one instruction, but proceed through called subroutines.
- reverse-step ('rs') -- Step program backward until it reaches the beginning of a previous source line
- reverse-stepi -- Step backward exactly one instruction
- set exec-direction (forward/reverse) -- Set direction of execution.
而且Breakpoint和Watch也是支持逆向的。
写个HelloWorld来试试。
1 #include <iostream>
2
3 using namespace std;
4
5 int main()
6 {
7 for (int i = 0; i < 100; ++i)
8 cout << i << endl;
9 return 0;
10 }
编译:
g++ hello.cpp -o hello -g
调试:
gdb hello
(gdb) b 8 // 第8行加断点
(gdb) r // 运行
Breakpoint 1, main () at hello.cpp:8
8 cout << i << endl;
(gdb) // 好,停下了。
(gdb) watch i // Watch i 变量
开始我以为,现在应该可以使用rc, rn之类的了。
可一试,会有这样的提示。
(gdb) rc
Target child does not support this command.
查了一下才知道,要先用一个命令,作用好像是录制调试的过程
(gdb) target record
然后你就可以前前后后了,Breakpoint和watch都能正常工作。
(gdb) target record
(gdb) n
Hardware watchpoint 2: i
Old value = 0
New value = 1
0x080486e0 in main () at hello.cpp:7
7 for (int i = 0; i < 100; ++i)
(gdb)
Breakpoint 1, main () at hello.cpp:8
8 cout << i << endl;
(gdb)
1
7 for (int i = 0; i < 100; ++i)
(gdb)
Hardware watchpoint 2: i
Old value = 1
New value = 2
0x080486e0 in main () at hello.cpp:7
7 for (int i = 0; i < 100; ++i)
(gdb)
Breakpoint 1, main () at hello.cpp:8
8 cout << i << endl;
(gdb)
2
7 for (int i = 0; i < 100; ++i)
(gdb)
Hardware watchpoint 2: i
Old value = 2
New value = 3
0x080486e0 in main () at hello.cpp:7
7 for (int i = 0; i < 100; ++i)
(gdb) rn
Hardware watchpoint 2: i
Old value = 3
New value = 2
main () at hello.cpp:7
7 for (int i = 0; i < 100; ++i)
(gdb)
Breakpoint 1, main () at hello.cpp:8
8 cout << i << endl;
(gdb)
Hardware watchpoint 2: i
Old value = 2
New value = 1
main () at hello.cpp:7
7 for (int i = 0; i < 100; ++i)
(gdb)
Breakpoint 1, main () at hello.cpp:8
8 cout << i << endl;
但是你不能回到target record命令之前,否则会有一个提示。
No more reverse-execution history.
这也是很自然的。
总得说来这个功能确实不错,可能在调试某局部代码时,做录制,再前前后后的看非常方便。
当然,网上也有人说这方便了很多Cracker。