blob: 58a7839bcc4caab95a1bab2c2f13f94d0223fdf2 [file] [log] [blame]
Bruce Beare84924902010-10-13 14:21:30 -07001/* system/debuggerd/debuggerd.c
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include <stdio.h>
19#include <errno.h>
20#include <signal.h>
21#include <pthread.h>
22#include <fcntl.h>
23#include <sys/types.h>
24#include <dirent.h>
25
26#include <sys/ptrace.h>
27#include <sys/wait.h>
28#include <sys/exec_elf.h>
29#include <sys/stat.h>
30
31#include <cutils/sockets.h>
32#include <cutils/properties.h>
33
34#include <linux/input.h>
David 'Digit' Turner2c259912011-01-26 15:11:04 +010035#include <linux/user.h>
Bruce Beare84924902010-10-13 14:21:30 -070036
37#include "utility.h"
38
39#ifdef WITH_VFP
40#ifdef WITH_VFP_D32
41#define NUM_VFP_REGS 32
42#else
43#define NUM_VFP_REGS 16
44#endif
45#endif
46
47/* Main entry point to get the backtrace from the crashing process */
48extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map,
49 unsigned int sp_list[],
50 int *frame0_pc_sane,
51 bool at_fault);
52
Andy McFadden136dcc52011-09-22 16:37:06 -070053/*
54 * If this isn't clearly a null pointer dereference, dump the
55 * /proc/maps entries near the fault address.
56 */
57static void show_nearby_maps(int tfd, int pid, mapinfo *map)
58{
59 siginfo_t si;
60
61 memset(&si, 0, sizeof(si));
62 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si)) {
63 _LOG(tfd, false, "cannot get siginfo: %s\n", strerror(errno));
64 return;
65 }
66 if (!signal_has_address(si.si_signo))
67 return;
68
69 uintptr_t addr = (uintptr_t) si.si_addr;
70 addr &= ~0xfff; /* round to 4K page boundary */
71 if (addr == 0) /* null-pointer deref */
72 return;
73
74 _LOG(tfd, false, "\nmemory map around addr %08x:\n", si.si_addr);
75
76 /*
77 * Search for a match, or for a hole where the match would be. The list
78 * is backward from the file content, so it starts at high addresses.
79 */
80 bool found = false;
81 mapinfo *next = NULL;
82 mapinfo *prev = NULL;
83 while (map != NULL) {
84 if (addr >= map->start && addr < map->end) {
85 found = true;
86 next = map->next;
87 break;
88 } else if (addr >= map->end) {
89 /* map would be between "prev" and this entry */
90 next = map;
91 map = NULL;
92 break;
93 }
94
95 prev = map;
96 map = map->next;
97 }
98
99 /*
100 * Show "next" then "match" then "prev" so that the addresses appear in
101 * ascending order (like /proc/pid/maps).
102 */
103 if (next != NULL) {
104 _LOG(tfd, false, "%08x-%08x %s\n", next->start, next->end, next->name);
105 } else {
106 _LOG(tfd, false, "(no map below)\n");
107 }
108 if (map != NULL) {
109 _LOG(tfd, false, "%08x-%08x %s\n", map->start, map->end, map->name);
110 } else {
111 _LOG(tfd, false, "(no map for address)\n");
112 }
113 if (prev != NULL) {
114 _LOG(tfd, false, "%08x-%08x %s\n", prev->start, prev->end, prev->name);
115 } else {
116 _LOG(tfd, false, "(no map above)\n");
117 }
118}
119
120
Bruce Beare84924902010-10-13 14:21:30 -0700121void dump_stack_and_code(int tfd, int pid, mapinfo *map,
122 int unwind_depth, unsigned int sp_list[],
123 bool at_fault)
124{
Ben Chengdce4d062011-02-24 16:37:52 -0800125 unsigned int sp, pc, lr, p, end, data;
Bruce Beare84924902010-10-13 14:21:30 -0700126 struct pt_regs r;
127 int sp_depth;
128 bool only_in_tombstone = !at_fault;
129 char code_buffer[80];
130
131 if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return;
132 sp = r.ARM_sp;
133 pc = r.ARM_pc;
Ben Chengdce4d062011-02-24 16:37:52 -0800134 lr = r.ARM_lr;
Bruce Beare84924902010-10-13 14:21:30 -0700135
136 _LOG(tfd, only_in_tombstone, "\ncode around pc:\n");
137
Ben Chengdce4d062011-02-24 16:37:52 -0800138 p = pc & ~3;
Bruce Beare84924902010-10-13 14:21:30 -0700139 p -= 32;
Ben Chengdce4d062011-02-24 16:37:52 -0800140 if (p > pc)
Paul Eastham3227b5c2010-12-14 16:07:58 -0800141 p = 0;
Ben Chengdce4d062011-02-24 16:37:52 -0800142 end = p + 80;
143 /* 'end - p' has to be multiples of 16 */
144 while (end < p)
145 end -= 16;
Bruce Beare84924902010-10-13 14:21:30 -0700146
147 /* Dump the code around PC as:
148 * addr contents
149 * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c
150 * 00008d44 f7ff18a0 490ced94 68035860 d0012b00
151 */
Ben Chengdce4d062011-02-24 16:37:52 -0800152 while (p < end) {
Bruce Beare84924902010-10-13 14:21:30 -0700153 int i;
154
155 sprintf(code_buffer, "%08x ", p);
156 for (i = 0; i < 4; i++) {
157 data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
158 sprintf(code_buffer + strlen(code_buffer), "%08x ", data);
159 p += 4;
160 }
161 _LOG(tfd, only_in_tombstone, "%s\n", code_buffer);
162 }
163
Ben Chengdce4d062011-02-24 16:37:52 -0800164 if (lr != pc) {
Bruce Beare84924902010-10-13 14:21:30 -0700165 _LOG(tfd, only_in_tombstone, "\ncode around lr:\n");
166
Ben Chengdce4d062011-02-24 16:37:52 -0800167 p = lr & ~3;
Bruce Beare84924902010-10-13 14:21:30 -0700168 p -= 32;
Ben Chengdce4d062011-02-24 16:37:52 -0800169 if (p > lr)
Paul Eastham3227b5c2010-12-14 16:07:58 -0800170 p = 0;
Ben Chengdce4d062011-02-24 16:37:52 -0800171 end = p + 80;
172 /* 'end - p' has to be multiples of 16 */
173 while (end < p)
174 end -= 16;
Bruce Beare84924902010-10-13 14:21:30 -0700175
176 /* Dump the code around LR as:
177 * addr contents
178 * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c
179 * 00008d44 f7ff18a0 490ced94 68035860 d0012b00
180 */
Ben Chengdce4d062011-02-24 16:37:52 -0800181 while (p < end) {
Bruce Beare84924902010-10-13 14:21:30 -0700182 int i;
183
184 sprintf(code_buffer, "%08x ", p);
185 for (i = 0; i < 4; i++) {
186 data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
187 sprintf(code_buffer + strlen(code_buffer), "%08x ", data);
188 p += 4;
189 }
190 _LOG(tfd, only_in_tombstone, "%s\n", code_buffer);
191 }
192 }
193
Andy McFadden136dcc52011-09-22 16:37:06 -0700194 show_nearby_maps(tfd, pid, map);
195
Bruce Beare84924902010-10-13 14:21:30 -0700196 p = sp - 64;
Paul Eastham3227b5c2010-12-14 16:07:58 -0800197 if (p > sp)
198 p = 0;
Bruce Beare84924902010-10-13 14:21:30 -0700199 p &= ~3;
200 if (unwind_depth != 0) {
201 if (unwind_depth < STACK_CONTENT_DEPTH) {
202 end = sp_list[unwind_depth-1];
203 }
204 else {
205 end = sp_list[STACK_CONTENT_DEPTH-1];
206 }
207 }
208 else {
Ben Chengdce4d062011-02-24 16:37:52 -0800209 end = p + 256;
210 /* 'end - p' has to be multiples of 4 */
211 if (end < p)
212 end = ~7;
Bruce Beare84924902010-10-13 14:21:30 -0700213 }
214
215 _LOG(tfd, only_in_tombstone, "\nstack:\n");
216
217 /* If the crash is due to PC == 0, there will be two frames that
218 * have identical SP value.
219 */
220 if (sp_list[0] == sp_list[1]) {
221 sp_depth = 1;
222 }
223 else {
224 sp_depth = 0;
225 }
226
227 while (p <= end) {
228 char *prompt;
229 char level[16];
230 data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
231 if (p == sp_list[sp_depth]) {
232 sprintf(level, "#%02d", sp_depth++);
233 prompt = level;
234 }
235 else {
236 prompt = " ";
237 }
238
239 /* Print the stack content in the log for the first 3 frames. For the
240 * rest only print them in the tombstone file.
241 */
242 _LOG(tfd, (sp_depth > 2) || only_in_tombstone,
243 "%s %08x %08x %s\n", prompt, p, data,
244 map_to_name(map, data, ""));
245 p += 4;
246 }
247 /* print another 64-byte of stack data after the last frame */
248
249 end = p+64;
Ben Chengdce4d062011-02-24 16:37:52 -0800250 /* 'end - p' has to be multiples of 4 */
Paul Eastham3227b5c2010-12-14 16:07:58 -0800251 if (end < p)
Ben Chengdce4d062011-02-24 16:37:52 -0800252 end = ~7;
Paul Eastham3227b5c2010-12-14 16:07:58 -0800253
Bruce Beare84924902010-10-13 14:21:30 -0700254 while (p <= end) {
255 data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
256 _LOG(tfd, (sp_depth > 2) || only_in_tombstone,
257 " %08x %08x %s\n", p, data,
258 map_to_name(map, data, ""));
259 p += 4;
260 }
261}
262
263void dump_pc_and_lr(int tfd, int pid, mapinfo *map, int unwound_level,
264 bool at_fault)
265{
266 struct pt_regs r;
267
268 if(ptrace(PTRACE_GETREGS, pid, 0, &r)) {
269 _LOG(tfd, !at_fault, "tid %d not responding!\n", pid);
270 return;
271 }
272
273 if (unwound_level == 0) {
274 _LOG(tfd, !at_fault, " #%02d pc %08x %s\n", 0, r.ARM_pc,
275 map_to_name(map, r.ARM_pc, "<unknown>"));
276 }
277 _LOG(tfd, !at_fault, " #%02d lr %08x %s\n", 1, r.ARM_lr,
278 map_to_name(map, r.ARM_lr, "<unknown>"));
279}
280
281void dump_registers(int tfd, int pid, bool at_fault)
282{
283 struct pt_regs r;
284 bool only_in_tombstone = !at_fault;
285
286 if(ptrace(PTRACE_GETREGS, pid, 0, &r)) {
287 _LOG(tfd, only_in_tombstone,
288 "cannot get registers: %s\n", strerror(errno));
289 return;
290 }
291
292 _LOG(tfd, only_in_tombstone, " r0 %08x r1 %08x r2 %08x r3 %08x\n",
293 r.ARM_r0, r.ARM_r1, r.ARM_r2, r.ARM_r3);
294 _LOG(tfd, only_in_tombstone, " r4 %08x r5 %08x r6 %08x r7 %08x\n",
295 r.ARM_r4, r.ARM_r5, r.ARM_r6, r.ARM_r7);
296 _LOG(tfd, only_in_tombstone, " r8 %08x r9 %08x 10 %08x fp %08x\n",
297 r.ARM_r8, r.ARM_r9, r.ARM_r10, r.ARM_fp);
298 _LOG(tfd, only_in_tombstone,
299 " ip %08x sp %08x lr %08x pc %08x cpsr %08x\n",
300 r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr);
301
302#ifdef WITH_VFP
303 struct user_vfp vfp_regs;
304 int i;
305
306 if(ptrace(PTRACE_GETVFPREGS, pid, 0, &vfp_regs)) {
307 _LOG(tfd, only_in_tombstone,
308 "cannot get registers: %s\n", strerror(errno));
309 return;
310 }
311
312 for (i = 0; i < NUM_VFP_REGS; i += 2) {
313 _LOG(tfd, only_in_tombstone,
314 " d%-2d %016llx d%-2d %016llx\n",
315 i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]);
316 }
317 _LOG(tfd, only_in_tombstone, " scr %08lx\n\n", vfp_regs.fpscr);
318#endif
319}