machine.c revision 08dedcfd5cfeab526bb02382e4292f3150ed986f
1/* 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>
35#include <linux/user.h>
36
37#include "utility.h"
38
39/* enable to dump memory pointed to by every register */
40#define DUMP_MEM_FOR_ALL_REGS 1
41
42#ifdef WITH_VFP
43#ifdef WITH_VFP_D32
44#define NUM_VFP_REGS 32
45#else
46#define NUM_VFP_REGS 16
47#endif
48#endif
49
50/* Main entry point to get the backtrace from the crashing process */
51extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map,
52                                        unsigned int sp_list[],
53                                        int *frame0_pc_sane,
54                                        bool at_fault);
55
56/*
57 * If this isn't clearly a null pointer dereference, dump the
58 * /proc/maps entries near the fault address.
59 *
60 * This only makes sense to do on the thread that crashed.
61 */
62static void show_nearby_maps(int tfd, int pid, mapinfo *map)
63{
64    siginfo_t si;
65
66    memset(&si, 0, sizeof(si));
67    if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si)) {
68        _LOG(tfd, false, "cannot get siginfo for %d: %s\n",
69            pid, strerror(errno));
70        return;
71    }
72    if (!signal_has_address(si.si_signo))
73        return;
74
75    uintptr_t addr = (uintptr_t) si.si_addr;
76    addr &= ~0xfff;     /* round to 4K page boundary */
77    if (addr == 0)      /* null-pointer deref */
78        return;
79
80    _LOG(tfd, false, "\nmemory map around addr %08x:\n", si.si_addr);
81
82    /*
83     * Search for a match, or for a hole where the match would be.  The list
84     * is backward from the file content, so it starts at high addresses.
85     */
86    bool found = false;
87    mapinfo *next = NULL;
88    mapinfo *prev = NULL;
89    while (map != NULL) {
90        if (addr >= map->start && addr < map->end) {
91            found = true;
92            next = map->next;
93            break;
94        } else if (addr >= map->end) {
95            /* map would be between "prev" and this entry */
96            next = map;
97            map = NULL;
98            break;
99        }
100
101        prev = map;
102        map = map->next;
103    }
104
105    /*
106     * Show "next" then "match" then "prev" so that the addresses appear in
107     * ascending order (like /proc/pid/maps).
108     */
109    if (next != NULL) {
110        _LOG(tfd, false, "%08x-%08x %s\n", next->start, next->end, next->name);
111    } else {
112        _LOG(tfd, false, "(no map below)\n");
113    }
114    if (map != NULL) {
115        _LOG(tfd, false, "%08x-%08x %s\n", map->start, map->end, map->name);
116    } else {
117        _LOG(tfd, false, "(no map for address)\n");
118    }
119    if (prev != NULL) {
120        _LOG(tfd, false, "%08x-%08x %s\n", prev->start, prev->end, prev->name);
121    } else {
122        _LOG(tfd, false, "(no map above)\n");
123    }
124}
125
126/*
127 * Dumps a few bytes of memory, starting a bit before and ending a bit
128 * after the specified address.
129 */
130static void dump_memory(int tfd, int pid, uintptr_t addr,
131    bool only_in_tombstone)
132{
133    char code_buffer[64];       /* actual 8+1+((8+1)*4) + 1 == 45 */
134    char ascii_buffer[32];      /* actual 16 + 1 == 17 */
135    uintptr_t p, end;
136
137    p = addr & ~3;
138    p -= 32;
139    if (p > addr) {
140        /* catch underflow */
141        p = 0;
142    }
143    end = p + 80;
144    /* catch overflow; 'end - p' has to be multiples of 16 */
145    while (end < p)
146        end -= 16;
147
148    /* Dump the code around PC as:
149     *  addr     contents                             ascii
150     *  00008d34 ef000000 e8bd0090 e1b00000 512fff1e  ............../Q
151     *  00008d44 ea00b1f9 e92d0090 e3a070fc ef000000  ......-..p......
152     */
153    while (p < end) {
154        char* asc_out = ascii_buffer;
155
156        sprintf(code_buffer, "%08x ", p);
157
158        int i;
159        for (i = 0; i < 4; i++) {
160            /*
161             * If we see (data == -1 && errno != 0), we know that the ptrace
162             * call failed, probably because we're dumping memory in an
163             * unmapped or inaccessible page.  I don't know if there's
164             * value in making that explicit in the output -- it likely
165             * just complicates parsing and clarifies nothing for the
166             * enlightened reader.
167             */
168            long data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
169            sprintf(code_buffer + strlen(code_buffer), "%08lx ", data);
170
171            int j;
172            for (j = 0; j < 4; j++) {
173                /*
174                 * Our isprint() allows high-ASCII characters that display
175                 * differently (often badly) in different viewers, so we
176                 * just use a simpler test.
177                 */
178                char val = (data >> (j*8)) & 0xff;
179                if (val >= 0x20 && val < 0x7f) {
180                    *asc_out++ = val;
181                } else {
182                    *asc_out++ = '.';
183                }
184            }
185            p += 4;
186        }
187        *asc_out = '\0';
188        _LOG(tfd, only_in_tombstone, "%s %s\n", code_buffer, ascii_buffer);
189    }
190
191}
192
193void dump_stack_and_code(int tfd, int pid, mapinfo *map,
194                         int unwind_depth, unsigned int sp_list[],
195                         bool at_fault)
196{
197    struct pt_regs r;
198    int sp_depth;
199    bool only_in_tombstone = !at_fault;
200
201    if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return;
202
203    if (DUMP_MEM_FOR_ALL_REGS && at_fault) {
204        /*
205         * If configured to do so, dump memory around *all* registers
206         * for the crashing thread.
207         *
208         * TODO: remove duplicates.
209         */
210        static const char REG_NAMES[] = "R0R1R2R3R4R5R6R7R8R9SLFPIPSPLRPC";
211
212        int reg;
213        for (reg = 0; reg < 16; reg++) {
214            /* this may not be a valid way to access, but it'll do for now */
215            uintptr_t addr = r.uregs[reg];
216
217            /*
218             * Don't bother if it looks like a small int or ~= null, or if
219             * it's in the kernel area.
220             */
221            if (addr < 4096 || addr >= 0xc0000000) {
222                continue;
223            }
224
225            _LOG(tfd, only_in_tombstone, "\nmem near %.2s:\n",
226                &REG_NAMES[reg*2]);
227            dump_memory(tfd, pid, addr, false);
228        }
229    } else {
230        unsigned int pc, lr;
231        pc = r.ARM_pc;
232        lr = r.ARM_lr;
233
234        _LOG(tfd, only_in_tombstone, "\ncode around pc:\n");
235        dump_memory(tfd, pid, (uintptr_t) pc, only_in_tombstone);
236
237        if (lr != pc) {
238            _LOG(tfd, only_in_tombstone, "\ncode around lr:\n");
239            dump_memory(tfd, pid, (uintptr_t) lr, only_in_tombstone);
240        }
241    }
242
243    if (at_fault) {
244        show_nearby_maps(tfd, pid, map);
245    }
246
247    unsigned int p, end;
248    unsigned int sp = r.ARM_sp;
249
250    p = sp - 64;
251    if (p > sp)
252        p = 0;
253    p &= ~3;
254    if (unwind_depth != 0) {
255        if (unwind_depth < STACK_CONTENT_DEPTH) {
256            end = sp_list[unwind_depth-1];
257        }
258        else {
259            end = sp_list[STACK_CONTENT_DEPTH-1];
260        }
261    }
262    else {
263        end = p + 256;
264        /* 'end - p' has to be multiples of 4 */
265        if (end < p)
266            end = ~7;
267    }
268
269    _LOG(tfd, only_in_tombstone, "\nstack:\n");
270
271    /* If the crash is due to PC == 0, there will be two frames that
272     * have identical SP value.
273     */
274    if (sp_list[0] == sp_list[1]) {
275        sp_depth = 1;
276    }
277    else {
278        sp_depth = 0;
279    }
280
281    while (p <= end) {
282         char *prompt;
283         char level[16];
284         long data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
285         if (p == sp_list[sp_depth]) {
286             sprintf(level, "#%02d", sp_depth++);
287             prompt = level;
288         }
289         else {
290             prompt = "   ";
291         }
292
293         /* Print the stack content in the log for the first 3 frames. For the
294          * rest only print them in the tombstone file.
295          */
296         _LOG(tfd, (sp_depth > 2) || only_in_tombstone,
297              "%s %08x  %08x  %s\n", prompt, p, data,
298              map_to_name(map, data, ""));
299         p += 4;
300    }
301    /* print another 64-byte of stack data after the last frame */
302
303    end = p+64;
304    /* 'end - p' has to be multiples of 4 */
305    if (end < p)
306        end = ~7;
307
308    while (p <= end) {
309         long data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
310         _LOG(tfd, (sp_depth > 2) || only_in_tombstone,
311              "    %08x  %08x  %s\n", p, data,
312              map_to_name(map, data, ""));
313         p += 4;
314    }
315}
316
317void dump_pc_and_lr(int tfd, int pid, mapinfo *map, int unwound_level,
318                    bool at_fault)
319{
320    struct pt_regs r;
321
322    if(ptrace(PTRACE_GETREGS, pid, 0, &r)) {
323        _LOG(tfd, !at_fault, "tid %d not responding!\n", pid);
324        return;
325    }
326
327    if (unwound_level == 0) {
328        _LOG(tfd, !at_fault, "         #%02d  pc %08x  %s\n", 0, r.ARM_pc,
329             map_to_name(map, r.ARM_pc, "<unknown>"));
330    }
331    _LOG(tfd, !at_fault, "         #%02d  lr %08x  %s\n", 1, r.ARM_lr,
332            map_to_name(map, r.ARM_lr, "<unknown>"));
333}
334
335void dump_registers(int tfd, int pid, bool at_fault)
336{
337    struct pt_regs r;
338    bool only_in_tombstone = !at_fault;
339
340    if(ptrace(PTRACE_GETREGS, pid, 0, &r)) {
341        _LOG(tfd, only_in_tombstone,
342             "cannot get registers: %s\n", strerror(errno));
343        return;
344    }
345
346    _LOG(tfd, only_in_tombstone, " r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",
347         r.ARM_r0, r.ARM_r1, r.ARM_r2, r.ARM_r3);
348    _LOG(tfd, only_in_tombstone, " r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",
349         r.ARM_r4, r.ARM_r5, r.ARM_r6, r.ARM_r7);
350    _LOG(tfd, only_in_tombstone, " r8 %08x  r9 %08x  10 %08x  fp %08x\n",
351         r.ARM_r8, r.ARM_r9, r.ARM_r10, r.ARM_fp);
352    _LOG(tfd, only_in_tombstone,
353         " ip %08x  sp %08x  lr %08x  pc %08x  cpsr %08x\n",
354         r.ARM_ip, r.ARM_sp, r.ARM_lr, r.ARM_pc, r.ARM_cpsr);
355
356#ifdef WITH_VFP
357    struct user_vfp vfp_regs;
358    int i;
359
360    if(ptrace(PTRACE_GETVFPREGS, pid, 0, &vfp_regs)) {
361        _LOG(tfd, only_in_tombstone,
362             "cannot get registers: %s\n", strerror(errno));
363        return;
364    }
365
366    for (i = 0; i < NUM_VFP_REGS; i += 2) {
367        _LOG(tfd, only_in_tombstone,
368             " d%-2d %016llx  d%-2d %016llx\n",
369              i, vfp_regs.fpregs[i], i+1, vfp_regs.fpregs[i+1]);
370    }
371    _LOG(tfd, only_in_tombstone, " scr %08lx\n\n", vfp_regs.fpscr);
372#endif
373}
374