Home | History | Annotate | Download | only in arm
      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 0
     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 */
     51 extern 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  */
     62 static 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  */
    130 static 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 
    193 void 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 
    317 void 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 
    335 void 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