gdb: Reverse Execution
6 Running programs backward
***************************
When you are debugging a program, it is not unusual to realize that you
have gone too far, and some event of interest has already happened. If
the target environment supports it, GDB can allow you to "rewind" the
program by running it backward.
A target environment that supports reverse execution should be able
to "undo" the changes in machine state that have taken place as the
program was executing normally. Variables, registers etc. should revert
to their previous values. Obviously this requires a great deal of
sophistication on the part of the target environment; not all target
environments can support reverse execution.
When a program is executed in reverse, the instructions that have
most recently been executed are "un-executed", in reverse order. The
program counter runs backward, following the previous thread of
execution in reverse. As each instruction is "un-executed", the values
of memory and/or registers that were changed by that instruction are
reverted to their previous states. After executing a piece of source
code in reverse, all side effects of that code should be "undone", and
all variables should be returned to their prior values(1).
If you are debugging in a target environment that supports reverse
execution, GDB provides the following commands.
'reverse-continue [IGNORE-COUNT]'
'rc [IGNORE-COUNT]'
Beginning at the point where your program last stopped, start
executing in reverse. Reverse execution will stop for breakpoints
and synchronous exceptions (signals), just like normal execution.
Behavior of asynchronous signals depends on the target environment.
'reverse-step [COUNT]'
Run the program backward until control reaches the start of a
different source line; then stop it, and return control to GDB.
Like the 'step' command, 'reverse-step' will only stop at the
beginning of a source line. It "un-executes" the previously
executed source line. If the previous source line included calls
to debuggable functions, 'reverse-step' will step (backward) into
the called function, stopping at the beginning of the _last_
statement in the called function (typically a return statement).
Also, as with the 'step' command, if non-debuggable functions are
called, 'reverse-step' will run thru them backward without
stopping.
'reverse-stepi [COUNT]'
Reverse-execute one machine instruction. Note that the instruction
to be reverse-executed is _not_ the one pointed to by the program
counter, but the instruction executed prior to that one. For
instance, if the last instruction was a jump, 'reverse-stepi' will
take you back from the destination of the jump to the jump
instruction itself.
'reverse-next [COUNT]'
Run backward to the beginning of the previous line executed in the
current (innermost) stack frame. If the line contains function
calls, they will be "un-executed" without stopping. Starting from
the first line of a function, 'reverse-next' will take you back to
the caller of that function, _before_ the function was called, just
as the normal 'next' command would take you from the last line of a
function back to its return to its caller (2).
'reverse-nexti [COUNT]'
Like 'nexti', 'reverse-nexti' executes a single instruction in
reverse, except that called functions are "un-executed" atomically.
That is, if the previously executed instruction was a return from
another function, 'reverse-nexti' will continue to execute in
reverse until the call to that function (from the current stack
frame) is reached.
'reverse-finish'
Just as the 'finish' command takes you to the point where the
current function returns, 'reverse-finish' takes you to the point
where it was called. Instead of ending up at the end of the
current function invocation, you end up at the beginning.
'set exec-direction'
Set the direction of target execution.
'set exec-direction reverse'
GDB will perform all execution commands in reverse, until the
exec-direction mode is changed to "forward". Affected commands
include 'step, stepi, next, nexti, continue, and finish'. The
'return' command cannot be used in reverse mode.
'set exec-direction forward'
GDB will perform all execution commands in the normal fashion.
This is the default.
---------- Footnotes ----------
(1) Note that some side effects are easier to undo than others. For
instance, memory and registers are relatively easy, but device I/O is
hard. Some targets may be able undo things like device I/O, and some
may not.
The contract between GDB and the reverse executing target requires
only that the target do something reasonable when GDB tells it to
execute backwards, and then report the results back to GDB. Whatever
the target reports back to GDB, GDB will report back to the user. GDB
assumes that the memory and registers that the target reports are in a
consistant state, but GDB accepts whatever it is given.
(2) Unless the code is too heavily optimized.