1This is a tutorial/unittest for gdb's reverse debugging feature. It is a new
2feature that allows users to take a snapshot of the machine state, continue
3until a later stage of the program, then return to the previously recorded
4state and execute again. An ideal usage case is to help track down the reason
5why a memory location is clobbered.
6
7In the sample below, the "clobber" function trashes a neighboring variable "p"
8on the stack next to the "values" variable, and the program will crash at
9line 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
41The 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
47In another window the following command can be used to attach to the running
48program:
49
50> gdbclient reverse_debug :5039 reverse_debug
51[1] 12802
52Attached; pid = 1842
53Listening on port 5039
54GNU gdb (GDB) 7.6
55Copyright (C) 2013 Free Software Foundation, Inc.
56License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
57This is free software: you are free to change and redistribute it.
58There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
59and "show warranty" for details.
60This GDB was configured as "--host=x86_64-linux-gnu --target=arm-linux-android".
61For bug reporting instructions, please see:
62<http://source.android.com/source/report-bugs.html>...
63Reading symbols from /usr/local/google/work/master/out/target/product/manta/symbols/system/bin/reverse_debug...done.
64Remote debugging from host 127.0.0.1
65nanosleep () at bionic/libc/arch-arm/syscalls/nanosleep.S:10
6610      mov     r7, ip
67
68====
69
70Now 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
74Breakpoint 1 at 0xb6f174a8: file development/tutorials/ReverseDebug/main.c, line 41.
75(gdb) p flag=1
76$1 = 1
77(gdb) c
78Continuing.
79
80====
81
82Now try the new "record" command to take a snapshot of the machine state.
83
84Breakpoint 1, main () at development/tutorials/ReverseDebug/main.c:41
8541      clobber(values, ARRAY_LENGTH);
86(gdb) record
87(gdb) c
88Continuing.
89
90====
91
92Now 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
94replay each instruction from there.
95
96Program received signal SIGSEGV, Segmentation fault.
970xb6f174bc in main () at development/tutorials/ReverseDebug/main.c:42
9842      printf("*p = %d\n", *p);
99(gdb) reverse-continue
100Continuing.
101
102No more reverse-execution history.
103main () at development/tutorials/ReverseDebug/main.c:41
10441      clobber(values, ARRAY_LENGTH);
105
106
107====
108
109Now let's add a watch point at "&p" to hopefully catch the clobber on the spot:
110
111(gdb) watch *(&p)
112Hardware watchpoint 2: *(&p)
113(gdb) c
114Continuing.
115Hardware watchpoint 2: *(&p)
116
117====
118
119And here it is:
120
121Old value = (int *) 0xb728c020
122New value = (int *) 0x123
1230xb6f17440 in clobber (array=0xbebcaab0, size=10)
124    at development/tutorials/ReverseDebug/main.c:28
12528      array[size] = 0x123;
126
127
128===============================
129
130That 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
132Thumb(2) instructions. To give it a try you will need to recompile your
133program in ARM mode. To do that you have to add the ".arm" suffix to the
134desired file in Android.mk:
135
136LOCAL_SRC_FILES:= main.c.arm
137
138