Replay debugger is a debugging tool that allows the user to go to any state of a program execution i.e it allows the user to execute the code line by line forwards or backwards. To allow this interaction , it has two stages:
1. Tracing :
In this stage the program is executed and enough information is generated to exactly reproduce the same execution of the program. A number of files are generated that store the program state. This dump of process state is called a checkpoint. This stage also stores rhat the program reads from the files and standard input, in order to replay it during the next stage.
2. Debugging session :
A read-only interactive debugging session allows the user to locate the bug by executing the program in forward and reverse direction.
The GDB-5.3 back-end and Insight-5.3 as a front-end have been extended to include replay features, and better code navigation facility.
One of the features, namely reverse watchpoints, allows the user to query the past execution of the program.
The Replay debugger is a source level debugger for single - threaded C programs.
It runs on Linux-i386 platform and allows the user only a read-only interaction , i.e user is not allowed to set program variable values as it could lead to change of program flow.
Breakpoints and watchpoints can be set as in GDB, and their forward semantics remain as they are. The semantics of breakpoints and watchpoints in reverse execution have been defined above.
This node describes how to run and start debugging your program.
Suppose your program is "foo.c". Then, run the following commands.
$ mkdir scratch $ cp foo.c scratch $ cd scratch $ export CHECKPOINT_INTERVAL=120 # in microseconds; you can change this number $ ~/replaydebugger/bin/run.sh $ ~/replaydebugger/bin/rd.sh
(Some sample programs can be found in the test-cases/ subdirectory of the distribution.)
The first three commands setup a new directory for running the program because many files are generated by the tracer etc. After debugging is over you can safely remove this directory.
The CHECKPOINT_INTERVAL environment variable controls how often the tracer checkpoints. A smaller interval makes tracing slower but replaying faster, and vice versa. Reverse watchpoints only work when this interval is set to zero.
The run.sh command analyses and traces the program.
The last command invokes the insight GUI. On the menubar, click Plugins -> Activation Tree to see the activation tree.
You can run any commands such as "jump_forward", "jump_backward", "fs", "bs", etc. These commands are documented in See section Commands.
The following commands can be executed at the GDB prompt.
+1
, or a function name.
By clicking on the menubar Plugin -> Activation Tree, a tree of the function activations can be displayed.
The activation tree of the debuggee's execution shows the nested structure of functions executed, where functions at the same level are ordered on time. When one function calls another, the callee becomes a child of the caller in the tree.
At every node of the tree, the name of the corresponding function is shown.
The activations on the current stack are colored with red dots, and the current activation is colored blue in the activation tree.
The user can click at any function activation, and the program state is restored to the beginning of that activation of the function, with the corresponding code appearing in the code browser window.
The data display window and stack window also get updated when you click on an activation.
A sample debugging session is as shown below.
The graphical front end is not shown. This session is shown to explain the use and semantics of the core commands provided by the debugger.
The code is ::
1 int main() 2 { 3 int x=2; 4 int y=5; 5 char buf[6]; 6 x++; 7 sub(3,5); 8 read(0 , buf , 5); 9 } 10 int sub(int x , int y) 11 { 12 return x-y; 13 } /////////////////////////////////////////// (gdb) start 1 int main() 2 { => int x=2; 4 int y=5; 5 char buf[6]; 6 x++; 7 sub(3,5); 8 read(0 , buf , 5); 9 } 10 int sub(int x , int y) 11 { 12 return x-y; 13 } /////////////////////////////////////////// (gdb) jump_forward 8 /* This takes the control to the line no 8 as shown */ 1 int main() 2 { 3 int x=2; 4 int y=5; 5 char buf[6]; 6 x++; 7 sub(3,5); => read(0 , buf , 5); 9 } 10 int sub(int x , int y) 11 { 12 return x-y; 13 } ///////////////////////////////////////////// (gdb) bs /* This causes the program to be executed backwards and so we stop at the previous line executed, which is inside the the function "sub", at the '}' */ 1 int main() 2 { 3 int x=2; 4 int y=5; 5 char buf[6]; 6 x++; 7 sub(3,5); 8 read(0 , buf , 5); 9 } 10 int sub(int x , int y) 11 { 12 return x-y; => } //////////////////////////////////////////////// (gdb) fs /* This causes the program to be executed forwards and so we stop at the previous line executed, which is inside the the function "main", at the line no. 8 */ 1 int main() 2 { 3 int x=2; 4 int y=5; 5 char buf[6]; 6 x++; 7 sub(3,5); => read(0 , buf , 5); 9 } 10 int sub(int x , int y) 11 { 12 return x-y; 13 } ///////////////////////////////////////////////////// (gdb) previous /* This causes the program to be executed backwards and so we stop at the previous line executed , but the previous function call is not stepped into.It steps across the function, back to line 7 */ 1 int main() 2 { 3 int x=2; 4 int y=5; 5 char buf[6]; 6 x++; => sub(3,5); 8 read(0 , buf , 5); 9 } 10 int sub(int x , int y) 11 { 12 return x-y; 13 } ///////////////////////////////////////////////////////////// (gdb) fn /* This causes the program to be executed forwards and so we stop at the next line executed , but the next function call is not stepped into.It steps across the function, to line 8 */ 1 int main() 2 { 3 int x=2; 4 int y=5; 5 char buf[6]; 6 x++; 7 sub(3,5); => read(0 , buf , 5); 9 } 10 int sub(int x , int y) 11 { 12 return x-y; 13 } //////////////////////////////////////////////////////////////////// (gdb) jump_backward 6 /* This causes the program to be executed backwards and so we stop at line no. 6 . Line numbers any where in the programs could have been given. Any breakpoints or watches set by user would be ignored. */ 1 int main() 2 { 3 int x=2; 4 int y=5; 5 char buf[6]; => x++; 7 sub(3,5); 8 read(0 , buf , 5); 9 } 10 int sub(int x , int y) 11 { 12 return x-y; 13 } ///////////////// (gdb) fs 1 int main() 2 { 3 int x=2; 4 int y=5; 5 char buf[6]; 6 x++; => sub(3,5); 8 read(0 , buf , 5); 9 } 10 int sub(int x , int y) 11 { 12 return x-y; 13 } //////////////// (gdb) reverse_watchpoint x /* The program is executed backwards and the state of program is restored to the one instruction after the last time value of expression "x" had changed from current value. Current value is "x=3".After command executes, state is restored to line 4, which is one instruction after the value of x was made 2. 1 int main() 2 { 3 int x=2; => int y=5; 5 char buf[6]; 6 x++; 7 sub(3,5); 8 read(0 , buf , 5); 9 } 10 int sub(int x , int y) 11 { 12 return x-y; 13 } /////////////////////////////////////////////// (gdb) q /* Quit the debugger */ //////////////////////////////////////////////
1. step 2. next 3. return 4. run 5. continue 6. finish 7. until 8. stepi 9. nexti 10. stop
In addition to mending all above mentioned bugs , we intend to do the following in the immediate next release :
1. Support replaying of system calls :: "brk" and "write" . This would enable programs to contain 'malloc' and 'printf' like functions.
2. Support replaying of signals :: Since we can trace the signals that a program recieves, we will be able to replay the signal at the exact place where that it was recieved.
Jump to: a - b - f - j - m - o - p - r - t
This document was generated on 28 February 2004 using texi2html 1.56k.