Reverse Debugging using GDB
CodeProjectThe GNU Debugger is a feature-rich open source debugging suite. It's console based and can easily be extended using integrated development environments like Eclipse or Netbeans or with dedicated graphical interfaces like ddd.

Reverse debugging basics
What is reverse debugging
Reverse debugging is a technique where you cannot just move forward in your program, you can also move backward. Moving backward sounds simple, but GDB completely restores the state as it was when the code was executed in 'forward-debugging-mode'.Is it helpful for me?
I think that this can be helpful for everyone using GDB.
Imagine a program that crashes sometime. GDB catches the e.g. segmentation fault for you and jumps to the source. You can now examine the cause of the program crash, maybe because some value is wrong but you can not say where the faulty value was written. This is where reverse debugging comes in. Using reverse debugging you can step through your program in reverse order and examine where the value was written.
How to use it
The GDB command set gets extended by seven commands and a single variable explained below:- record: Start the reverse-debugging-record-recording. Needs to be called once for every debugging session to start recording the state of the program for every instruction.
- reverse-continue (short form: rc): Same as continue, but runs the program to the next event, e.g. breakpoint, end-(or should i say begin?)-of program or begin of reverse recording
- reverse-finish: Execute backward until the current stack frame is called
- reverse-next (short form: rn): Step program backward, and stop at the previous sourceline in the innermost stack frame
- reverse-nexti (short form: rni): Step backward for exactly one instruction, if the call is a subroutine call it breaks before the subroutine call and does not step into subroutine calls
- reverse-step (short form: rs): Step program backward until it reaches the beginning of a previous source line, this prevents multiple stops on a single line of code
- reverse-stepi: Step backward for exactly one instruction
- Var: exec_direction (forward/reverse): Seting this to reverse turns the normal step/next/continue/... commands to its reverse counterparts. eg. set exec-direction reverse
How does it work, not an Emacs tutorial
I will use Emacs to demonstrate how to use this feature, but this is not an Emacs Tutorial, i will show you the basics of the GDB mode for Emacs and how to use reverse debugging. If you are not familiar with the Emacs basics take a look at one of the following tutorials:- http://www2.lib.uchicago.edu/keith/tcl-course/emacs-tutorial.html
- http://www.gnu.org/software/emacs/tour/
- And last but not least an Emacs cheat-sheet
Before we start make sure that your gdb supports reverse debugging. It is supported since version 7.0 so check using
Code:
gdb --version |
Code:
GNU gdb (GDB) 7.2 |
|
Copyright (C) 2010 Free Software Foundation, Inc. |
Code:
emacs --version |
|
GNU Emacs 23.1.1 |
|
Copyright (C) 2009 Free Software Foundation, Inc. |
Once the requirements are met load our example file (attached):
Code:
emacs gdb_reverse_debugging_test.c |
Next we need to compile our application, we can do that right here in emacs, just hit META-x and type compile
Code:
META-x compile <ret> |
Code:
gcc -g -o gdb_reverse_debugging_test gdb_reverse_debugging_test.c <ret> |
Next is to invoke the gdb mode of Emacs with the following command:
Code:
META-x gdb <ret> |
Code:
META-x gdb-many-windows |

For this debugging session we will now set three breakpoints, one in each subroutine. Activate the gdb sub-window (top left) and enter the following
Code:
break main |
|
break foo |
|
break bar |
Code:
C-X SPACE<ret> |
Once the breakpoints are set let gdb run the application by typing run in the gdb sub-window
Code:
(gdb) run |
|
Starting program: gdb_reverse_debugging_test |
|
|
|
Breakpoint 1, main () at gdb_reverse_debugging_test.c:17 |
Code:
record |
Code:
(gdb) cont |
|
(gdb) cont |
|
|
|
Breakpoint 3, bar () at gdb_reverse_debugging_test.c:5 |
|
(gdb) s |
Code:
(gdb) display xyz |
|
1: xyz = 2 |
Code:
(gdb) bt |
|
#0 bar () at gdb_reverse_debugging_test.c:6 |
|
#1 0x00000000004004f1 in foo () at gdb_reverse_debugging_test.c:12 |
|
#2 0x000000000040050b in main () at gdb_reverse_debugging_test.c:18 |
Now it's getting more exciting, let's go back for a single step:
Code:
(gdb) reverse-step |
Code:
(gdb) display xyz |
|
1: xyz = 1 |
Now go back even further, to the breakpoint in the foo subroutine and take a look a the backtrace:
Code:
(gdb) reverse-continue |
|
(gdb) bt |
|
#0 foo () at gdb_reverse_debugging_test.c:11 |
|
#1 0x000000000040050b in main () at gdb_reverse_debugging_test.c:18 |
Problems with reverse debugging
- I think (correct me if im wrong) that it is not possible to effectively debug multi-threaded applications
- Another problem is that only a few architectures (i386-linux, amd64-linux) and some remote targets are supported. For me it is of special interest to support arm-targets.
- For other problems and future work visit the GDB reverse debugging page