Instruction-level Reverse Execution for Debugging Tankut Akgul and Vincent J. Mooney School of Electrical and Computer Engineering Georgia Institute of Technology November 2002
Background Detect an Determine error the bug location(s) Run the program Remove the Error-free bug(s) from Restart the program the program program Debugging is a repetitive process! 2
Motivation • State constructed during forward execution • At least one (typically more than � � one) re-execution required for locating a bug in a program • Re-executions localized around erroneous program points by reverse execution • Time saved by preventing re- � � executions starting from the beginning of the program • Assembly-level reverse execution as a first step 3
Motivation 4
Previous Work � Periodic state saving � Save whole processor state periodically � Incremental state saving � Save modified processor state � Program animation � Construct a virtual machine with reversible instructions which are usually stack operations � Source transformation � Transform the source code to a reversible source code version � Apply state saving for destructive statements All above methods use state saving heavily! State saving = time time and memory memory overheads introduced during forward execution 5
Methodology We define the state of a processor as follows: S = ( PC , M , R ) PC : program counter M : memory values R : r egister values In order to reverse execute a program do the following: � Construct a reverse program T' for an input program T � Recover M and R by executing T' in place of T � Recover the program counter value with the help of the debugger tool 6
Program Execution Model � � � � � � � � � � � � � � � � � � � � � � � � � � � � Execution 1: I 1 = ( � , 2 , 3 , � , 5 ) : a non-branch instruction Execution 2: I 2 = ( � , 2 , 6 ) : a branch instruction 7
Reverse Execution Take a specific execution of T � � � � � Execution 1: S 0 S 1 S 2 S 3 S 4 S 5 Generate a set of one or more reverse instructions , a reverse instruction group (RIG), for every non-branch instruction such that RIG x reverses the effect of x � ) � ( RIG 1 , RIG 3 , RIG 5 ) ( 1 , 3 , Execute RIGs in the order opposite to the completion order of the instructions during forward execution and have the debugger tool recover the rest of the state debugger RIG 5 RIG 1 RIG 3 debugger Reverse Execution: S 0 S 1 S 2 S 3 S 4 S 5 8
Reverse Execution (Continued) Problem: Dynamic control flow of T may change! Solution: � Find out a condition set C (predicate expressions) which determines control flow of T � Combine the RIGs in such a way that the execution order of the RIGs is bound to C 9
Reverse Execution (Continued) ����� Instructions in a basic block (BB) � ? complete in lexical order � Confluence points are the only � decision points on the path to follow during reverse execution � � Reverse � � Execution ? � � ? � ���� 10
Reverse Code Generation (RCG) Algorithm Step 1: Constructs a control flow graph ( CFG ) for every procedure/function (intra-procedural analysis) and labels the CFG edges for Step2 Step 2: Determines the predicate expressions (condition set C ) at the confluence points in the CFG of each procedure/function Step 3: Constructs the RIGs Step 4: Combines the RIGs via conditional branch instructions with the determined predicates at the confluence points to generate the reverse of each procedure/function Step 5: Combines the reverse procedures/functions 11
Step 1: CFG Construction and Labeling BB 1 in start : j th incoming forward edge of BB i L i, j [0,255] [0,255] out L : j th outgoing forward edge of BB i i, j BB 2 � [0,255] [0,255] L out 1,1 = [0,255] BB 3 � BB i CFG {exit start}, do { ∀ ∈ − ∧ � InFwdEdges (BB ) n � i � � = = temp in L [x , y ] L [0,127] [0,127] k k i, j = = k 1 j 1 for k 1 to n { = BB 4 � [128,255] [128,255] == if( OutFwdEdge s(BB ) 2) { i � out = out ∪ + + − L L [x , (x y 1)/2 1], [0,63] [0,63] [64,127] [64,127] i,1 i,1 k k k out = out ∪ + + L L [(x y 1)/2, y ] i,2 i,2 k k k � BB 5 } else if |OutFwdEdges(BB i )|==1) � = ∪ out out L L [x , y ] � BB 6 i,1 i,1 k k exit } �� } 12
Step 2: Predicate Expression Determination BB 1 start CFI1 CFI2 CFI3 [0,255] [0,255] 255 BB 2 0 63 64 127 128 addi r 2 , r 1 , 8 [0,255] [0,255] false true p( cb 1 ) BB 3 lwz r 4 , 0(r 2 ) false true cmpi r 4 , 97 p( cb 2 ) cb 1 blt exit p( x ): predicate of x [0,127] [0,127] true cb: conditional branch false [128,255]: p(cb 1 ) [128,255] [128,255] BB 4 cmpi r 4 , 122 [64,127]: [p ( cb 1 )]' · [ p(cb 2 )] ≡ [p(cb 1 )]' bgt exit cb 2 [0,63] [0,63] [64,127] [64,127] P : Reverse code for P if p(cb 1 ) BB 5 subi r 4 , r 4 , 32 reverse of BB 3 stw r 4 , 0(r 2 ) P P BB 6 else addi r 2 , r 2 , 4 exit b loop reverse of BB 4 13
Step 3: Construction of the RIGs � Rename Values start � Generate a directed acyclic graph ( DAG ) 0 < 0 r 2 � Find the definition of r 1 reaching P P false true � Recover r 1 using available nodes 1 = r 2 0 + r 3 2 = r 2 0 r 1 0 r 1 at P P' ' 1 r 4 + 3 = S ( r 1 1 ,r 1 2 ) r 1 3 r 1 r 2 1 = r 1 3 + r 3 0 < 0 0 0 � 0 r 4 S r 2 P P 4 = r 2 0 - 4 r 1 2 4 1 r 1 r 1 r 1 P' ' P + 0 0 r 1 0 r 4 r 2 0 r 3 exit if r 2 < 0 RIG for : r 1 = r 4 – r 3 or r 1 = r 2 else r 1 = r 2 + r 3 14
Step 3: Construction of the RIGs (Example) BB 1 2 start m 1 2 r 4 S 1 m 1 BB 2 1: addi r 2 , r 1 , 8 4 r 4 2 m 0 BB 3 2: lwz r 4 , 0(r 2 ) S 1 r 4 1 m 0 3: cmpi r 4 , 97 3 r 4 4 r 2 4: blt exit 0 m 0 S 3 r 2 0 m 1 1 r 2 BB 4 5: cmpi r 4 , 122 2 r 2 6: bgt exit 0 m 0 0 0 r 2 r 1 0 0 r 4 m 1 BB 5 7: subi r 4 , r 4 , 32 8: stw r 4 , 0(r 2 ) BB 6 9: addi r 2 , r 2 , 4 exit 10: b loop 15
Step 4: Combination of the RIGs BB 1 start (BB 6 )' start subi r LC , r LC , 1 (BB 5 )' BB 2 subi r 2 , r 2 , 4 stw r 2 , mem1 addi r t , r 4 , 32 addi r 2 , r 1 , 8 stw r t , 0(r 2 ) li r LC , 0 addi r 4 , r 4 , 32 stw r 4 , mem2 (BB 3 )' cmpi r LC , 0 BB 3 lwz r 4 , 0(r 2 ) bne L1 cmpi r 4 , 97 blt exit L1: subi r t , r 2 , 4 lwz r 4 , mem2 lwz r 4 , 0(r t ) b L2 BB 4 cmpi r 4 , 122 cmpi r LC , 0 bgt exit bne loop BB 5 subi r 4 , r 4 , 32 (BB 2 )' lwz r 2 , mem1 stw r 4 , 0(r 2 ) addi r 2 , r 2 , 4 BB 6 exit addi r LC , r LC , 1 (BB 1 )' exit b loop 16
Step 5: Combination of Reverse Procedures/functions m 1 m start void main(void) { 1 A 2 if (…) A 2 g(); A 0 // call g g 1 m 1 … m m 2 2 A 0 } A 1 A 2 A 0 h g 1 g void g(void) { 1 A 1 A 4 void (*fp)(void); // define a func. ptr. m 2 g 2 … A 3 fp=… // set the func. ptr. (*fp)(); A 3 // call by the func. ptr. A 2 end … g 2 g 2 } A 3 Push addresses on the dynamically � taken edges into stack void h(void) { h h Pop the addresses from stack … � during reverse execution and } A 4 branch to popped addresses 17
Recovering the Program Counter RCG Reverse of the algorithm Input Input Reverse Reverse input program Program Program Program Program Input Input RIG RIG instruction instruction address address address address Program being debugged Inversion Inversion 0x0 0x4000 Table Table 0x4 0x3FFC 0x8 0x3FE0 Designates the entry point into … … the reverse program for every instruction in the input program 18
Experimentation Platform Background Debug Mode (BDM) Interface MBX860 PC MPC860 processor Windows 2000 4MB DRAM, 2MB Flash RTC, four 16-bit timers, watchdog 19
Experimental Results 10 8 Memory 6 Overhead 4 (kB) 2 0 FNG SS MM RNG 1.6 1.9 1.9 8.8 ISS 1.2 1.5 1.1 5.6 ISSDI 0.004 0.6 0.2 0.8 Our algorithm ISS: Incremental State Saving, ISSDI: Incremental State Saving for Destructive Instructions FNG: Fibonacci Number Generator, SS: Selection Sort, MM: Matrix Multiply, RNG: Random Number Generator 20
Experimental Results (Cont.) 200 150 Time 100 Overhead (%) 50 0 FNG SS MM RNG ISS 109 107.3 132.4 146.4 85.4 90.7 84.3 100.8 ISSDI 13.4 38.9 28.6 20.6 Our algorithm ISS: Incremental State Saving, ISSDI: Incremental State Saving for Destructive Instructions FNG: Fibonacci Number Generator, SS: Selection Sort, MM: Matrix Multiply, RNG: Random Number Generator 21
Reverse Debugger Execute forward Step forward Execute backward Step backward Source window Memory window Register window Breakpoint window 22
Conclusion � Reduced debugging time with localized re-executions � Very low time and memory overheads in forward execution by using reverse code � Reverse execution up to an assembly instruction level granularity T. Akgul and V. J. Mooney. Instruction-level reverse execution for debugging. Technical Report GIT-CC-02-49, Georgia Institute of Technology, September 2002. http://www.cc.gatech.edu/tech_reports/index.02.html 23
More recommend