views:

1372

answers:

7

GDB has a new version out that supports reverse debug (see http://www.gnu.org/software/gdb/news/reversible.html). I got to wondering how that works.

To get reverse debug to work it seems to me that you need to store the entire machine state including memory for each step. This would make performance incredibly slow, not to mention using a lot of memory. How are these problems solved?

+6  A: 
demoncodemonkey
This is installed on the programmer!
houman001
+1  A: 

Here is how another reverse-debugger called ODB works. Extract:

Omniscient Debugging is the idea of collecting "time stamps" at each "point of interest" (setting a value, making a method call, throwing/catching an exception) in a program and then allowing the programmer to use those time stamps to explore the history of that program run.

The ODB ... inserts code into the program's classes as they are loaded and when the program runs, the events are recorded.

I'm guessing the gdb one works in the same kind of way.

demoncodemonkey
So would this require directives in the code to tell the compiler and debugger where those interesting points are?
Nathan Fellman
No. There's a Java Web Start demo on www.LambdaCS.com/debugger/debugger.html which shows you how it works. It looks like a normal program. That's ODB anyway, don't know about gdb. It's very cool though :)
demoncodemonkey
Note that the gdb solution DOES NOT change the target program in any way. If you have to instrument a program to debug it, you have a fair chance of the problem disappearing due to timing difference and other disturbances. All commercial revexec tools are based on some form of external record that does not change the code of the program itself.
jakobengblom2
+1  A: 

Reverse debugging means you can run the program backwards, which is very useful to track down the cause of a problem.

You don't need to store the complete machine state for each step, only the changes. It is probably still quite expensive.

starblue
I see, but you still need to break execution at each change to save the changes.
Nathan Fellman
Yes, that's correct, but machines are quite fast now, and in human terms I don't believe the slow down is intollerable. It is comparable to valgrind, maybe not as slow as valgrind.
Michael Snyder
+29  A: 

Hi, I'm a gdb maintainer and one of the authors of the new reverse debugging. I'd be happy to talk about how it works. As several people have speculated, you need to save enough machine state that you can restore later. There are a number of schemes, one of which is to simply save the registers or memory locations that are modified by each machine instruction. Then, to "undo" that instruction, you just revert the data in those registers or memory locations.

Yes, it is expensive, but modern cpus are so fast that when you are interactive anyway (doing stepping or breakpoints), you don't really notice it that much.

Michael Snyder
But does reverse debugging only allow you to roll back `next` and `step` commands that you typed, or does it allow you to undo any number of instructions? For instance, if I set a breakpoint on an instruction and let it run until then, can I then roll back to the previous instruction, even though I skipped over it?
Nathan Fellman
> But does reverse debugging only allow you to roll back next and step commands that you typed or does it allow you to undo any number of instructionsYou can undo any number of instructions. Youre not restricted to, for instance only stopping at the points where you stopped when you were going forward. You can set a new breakpoint and run backwards to it> For instance if I set a breakpoint on an instruction and let it run until then, can I then roll back to the previous instruction, even though I skipped over itYes So long as you turned on recording mode before you ran to the breakpoint
Michael Snyder
Sorry for the unformatted text, don't know what's up with that.
Michael Snyder
How do you undo a syscall?
Longpoke
Most syscalls modify data in a buffer. You just record the contents of the boffer before and after.
Michael Snyder
+1  A: 

Nathan Fellman wrote:

But does reverse debugging only allow you to roll back next and step commands that you typed, or does it allow you to undo any number of instructions?

You can undo any number of instructions. You're not restricted to, for instance, only stopping at the points where you stopped when you were going forward. You can set a new breakpoint and run backwards to it.

For instance, if I set a breakpoint on an instruction and let it run until then, can I then roll back to the previous instruction, even though I skipped over it?

Yes. So long as you turned on recording mode before you ran to the breakpoint.

Michael Snyder
A crucial part of any reverse solution is that you turn it on at some point, and can only reverse up until that point. There is no magic that can run a machine in true reverse and find out what happened previously without some kind of record of what happened.
jakobengblom2
+3  A: 

There is now a tutorial to help you get started with gdb-7.0 reverse debugging: http://www.sourceware.org/gdb/wiki/ProcessRecord/Tutorial Good luck!

Michael Snyder
+1  A: 

Note that you must not forget the use of simulators, virtual machines, and hardware recorders to implement reverse execution.

Another solution to implement it is to trace execution on physical hardware, such as is done by GreenHills and Lauterbach in their hardware-based debuggers. Based on this fixed trace of the action of each instruction, you can then move to any point in the trace by removing the effects of each instruction in turn. Note that this assumes that you can trace all things that affect the state visible in the debugger.

Another way is to use a checkpoint + re-execution method, which is used by VmWare Workstation 6.5 and Virtutech Simics 3.0 (and later), and which seems to be coming with Visual Studio 2010. Here, you use a virtual machine or a simulator to get a level of indirection on the execution of a system. You regularly dump the entire state to disk or memory, and then rely on the simulator being able to deterministically re-execute the exact same program path.

Simplified, it works like this: say that you are at time T in the execution of a system. To go to time T-1, you pick up some checkpoint from point t < T, and then execute (T-t-1) cycles to end up one cycle before where you were. This can be made to work very well, and apply even for workloads that do disk IO, consist of kernel-level code, and performs device driver work. The key is to have a simulator that contains the entire target system, with all its processors, devices, memories, and IOs. See the gdb mailinglist and the discussion following that on the gdb mailing list for more details. I use this approach myself quite regularly to debug tricky code, especially in device drivers and early OS boots.

Another source of information is a Virtutech white paper on checkpointing (which I wrote, in full disclosure).

jakobengblom2