1 This is a tutorial/unittest for gdb's reverse debugging feature. It is a new 2 feature that allows users to take a snapshot of the machine state, continue 3 until a later stage of the program, then return to the previously recorded 4 state and execute again. An ideal usage case is to help track down the reason 5 why a memory location is clobbered. 6 7 In the sample below, the "clobber" function trashes a neighboring variable "p" 8 on the stack next to the "values" variable, and the program will crash at 9 line 42 when "p" is being dereferenced. 10 11 18 #include <stdio.h> 12 19 #include <stdlib.h> 13 20 14 21 #define ARRAY_LENGTH 10 15 22 16 23 int flag; 17 24 18 25 void clobber(int *array, int size) { 19 26 /* Make sure it clobbers something. */ 20 27 array[-1] = 0x123; 21 28 array[size] = 0x123; 22 29 } 23 30 24 31 int main(void) { 25 32 int values[ARRAY_LENGTH]; 26 33 int *p = (int *) malloc(sizeof(int)); 27 34 *p = 10; 28 35 29 36 while (!flag) { 30 37 sleep(1); 31 38 } 32 39 33 40 /* Set a breakpint here: "b main.c:41" */ 34 41 clobber(values, ARRAY_LENGTH); 35 42 printf("*p = %d\n", *p); 36 43 free(p); 37 44 38 45 return 0; 39 46 } 40 41 The test program can be built/installed on the device by doing: 42 43 > mmm development/tutorials/ReverseDebug 44 > adb sync 45 > adb shell reverse_debug 46 47 In another window the following command can be used to attach to the running 48 program: 49 50 > gdbclient reverse_debug :5039 reverse_debug 51 [1] 12802 52 Attached; pid = 1842 53 Listening on port 5039 54 GNU gdb (GDB) 7.6 55 Copyright (C) 2013 Free Software Foundation, Inc. 56 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> 57 This is free software: you are free to change and redistribute it. 58 There is NO WARRANTY, to the extent permitted by law. Type "show copying" 59 and "show warranty" for details. 60 This GDB was configured as "--host=x86_64-linux-gnu --target=arm-linux-android". 61 For bug reporting instructions, please see: 62 <http://source.android.com/source/report-bugs.html>... 63 Reading symbols from /usr/local/google/work/master/out/target/product/manta/symbols/system/bin/reverse_debug...done. 64 Remote debugging from host 127.0.0.1 65 nanosleep () at bionic/libc/arch-arm/syscalls/nanosleep.S:10 66 10 mov r7, ip 67 68 ==== 69 70 Now set a breakpoint on line 41 and set flag to 1 so that the program can 71 continue. 72 73 (gdb) b main.c:41 74 Breakpoint 1 at 0xb6f174a8: file development/tutorials/ReverseDebug/main.c, line 41. 75 (gdb) p flag=1 76 $1 = 1 77 (gdb) c 78 Continuing. 79 80 ==== 81 82 Now try the new "record" command to take a snapshot of the machine state. 83 84 Breakpoint 1, main () at development/tutorials/ReverseDebug/main.c:41 85 41 clobber(values, ARRAY_LENGTH); 86 (gdb) record 87 (gdb) c 88 Continuing. 89 90 ==== 91 92 Now the program crashes as expected as "p" has been clobbered. The 93 "reverse-continue" command will bring the program back to line 41 and let you 94 replay each instruction from there. 95 96 Program received signal SIGSEGV, Segmentation fault. 97 0xb6f174bc in main () at development/tutorials/ReverseDebug/main.c:42 98 42 printf("*p = %d\n", *p); 99 (gdb) reverse-continue 100 Continuing. 101 102 No more reverse-execution history. 103 main () at development/tutorials/ReverseDebug/main.c:41 104 41 clobber(values, ARRAY_LENGTH); 105 106 107 ==== 108 109 Now let's add a watch point at "&p" to hopefully catch the clobber on the spot: 110 111 (gdb) watch *(&p) 112 Hardware watchpoint 2: *(&p) 113 (gdb) c 114 Continuing. 115 Hardware watchpoint 2: *(&p) 116 117 ==== 118 119 And here it is: 120 121 Old value = (int *) 0xb728c020 122 New value = (int *) 0x123 123 0xb6f17440 in clobber (array=0xbebcaab0, size=10) 124 at development/tutorials/ReverseDebug/main.c:28 125 28 array[size] = 0x123; 126 127 128 =============================== 129 130 That said, reverse debugging on ARM is still in the infant stage. Currently 131 (as of gdb 7.6) it only recognizes ARM instructions and will punt on all 132 Thumb(2) instructions. To give it a try you will need to recompile your 133 program in ARM mode. To do that you have to add the ".arm" suffix to the 134 desired file in Android.mk: 135 136 LOCAL_SRC_FILES:= main.c.arm 137 138