加入你正在使用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程序:
- int main(int argc, const char *argv[])
- {
- int a = 0;
- a = 1;
- a = 2;
- return 0;
- }
將它編譯並加上調試符號:
- $ gcc -Wall -g a.c
開始調試:
- $ gdb a.out
查看一下源代碼:
- (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 }
接下來設置一個斷點在第三行:
- (gdb) b 3
- Breakpoint 1 at 0x804839a: file a.c, line 3.
運行,程序會在第三行的地方停下來:
- (gdb) r
- Starting program: /home/cheryl/a.out
- Breakpoint 1, main (argc=1, argv=0xbffff3e4) at a.c:3
- 3 int a = 0;
給變量a設置監視點方便我們觀察:
- (gdb) watch a
- Hardware watchpoint 2: a
啟動進程記錄回放:
- (gdb) record
現在每運行一步調試器都會記錄下變化,以便回溯。我們連續執行3條語句。
- (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命令:
- (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:
- (gdb) record stop
- Process record is stoped and all execution log is deleted.
參考:《Reverse Debugging with GDB》 --- http://sourceware.org/gdb/wiki/ReverseDebug