Loading debuggerd/arm/machine.c +70 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,74 @@ extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, int *frame0_pc_sane, bool at_fault); /* * If this isn't clearly a null pointer dereference, dump the * /proc/maps entries near the fault address. */ static void show_nearby_maps(int tfd, int pid, mapinfo *map) { siginfo_t si; memset(&si, 0, sizeof(si)); if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si)) { _LOG(tfd, false, "cannot get siginfo: %s\n", strerror(errno)); return; } if (!signal_has_address(si.si_signo)) return; uintptr_t addr = (uintptr_t) si.si_addr; addr &= ~0xfff; /* round to 4K page boundary */ if (addr == 0) /* null-pointer deref */ return; _LOG(tfd, false, "\nmemory map around addr %08x:\n", si.si_addr); /* * Search for a match, or for a hole where the match would be. The list * is backward from the file content, so it starts at high addresses. */ bool found = false; mapinfo *next = NULL; mapinfo *prev = NULL; while (map != NULL) { if (addr >= map->start && addr < map->end) { found = true; next = map->next; break; } else if (addr >= map->end) { /* map would be between "prev" and this entry */ next = map; map = NULL; break; } prev = map; map = map->next; } /* * Show "next" then "match" then "prev" so that the addresses appear in * ascending order (like /proc/pid/maps). */ if (next != NULL) { _LOG(tfd, false, "%08x-%08x %s\n", next->start, next->end, next->name); } else { _LOG(tfd, false, "(no map below)\n"); } if (map != NULL) { _LOG(tfd, false, "%08x-%08x %s\n", map->start, map->end, map->name); } else { _LOG(tfd, false, "(no map for address)\n"); } if (prev != NULL) { _LOG(tfd, false, "%08x-%08x %s\n", prev->start, prev->end, prev->name); } else { _LOG(tfd, false, "(no map above)\n"); } } void dump_stack_and_code(int tfd, int pid, mapinfo *map, int unwind_depth, unsigned int sp_list[], bool at_fault) Loading Loading @@ -123,6 +191,8 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, } } show_nearby_maps(tfd, pid, map); p = sp - 64; if (p > sp) p = 0; Loading debuggerd/debuggerd.c +20 −7 Original line number Diff line number Diff line Loading @@ -70,15 +70,18 @@ mapinfo *parse_maps_line(char *line) mapinfo *mi; int len = strlen(line); if(len < 1) return 0; if (len < 1) return 0; /* not expected */ line[--len] = 0; if(len < 50) return 0; if(line[20] != 'x') return 0; if (len < 50) { mi = malloc(sizeof(mapinfo) + 1); } else { mi = malloc(sizeof(mapinfo) + (len - 47)); } if (mi == 0) return 0; mi->isExecutable = (line[20] == 'x'); mi->start = strtoul(line, 0, 16); mi->end = strtoul(line + 9, 0, 16); /* To be filled in parse_elf_info if the mapped section starts with Loading @@ -87,7 +90,11 @@ mapinfo *parse_maps_line(char *line) mi->exidx_start = mi->exidx_end = 0; mi->symbols = 0; mi->next = 0; if (len < 50) { mi->name[0] = '\0'; } else { strcpy(mi->name, line + 49); } return mi; } Loading Loading @@ -165,11 +172,14 @@ void dump_fault_addr(int tfd, int pid, int sig) memset(&si, 0, sizeof(si)); if(ptrace(PTRACE_GETSIGINFO, pid, 0, &si)){ _LOG(tfd, false, "cannot get siginfo: %s\n", strerror(errno)); } else { } else if (signal_has_address(sig)) { _LOG(tfd, false, "signal %d (%s), code %d (%s), fault addr %08x\n", sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code), si.si_addr); } else { _LOG(tfd, false, "signal %d (%s), code %d (%s), fault addr --------\n", sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code)); } } Loading Loading @@ -199,6 +209,9 @@ static void parse_elf_info(mapinfo *milist, pid_t pid) { mapinfo *mi; for (mi = milist; mi != NULL; mi = mi->next) { if (!mi->isExecutable) continue; Elf32_Ehdr ehdr; memset(&ehdr, 0, sizeof(Elf32_Ehdr)); Loading debuggerd/utility.c +18 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <sys/ptrace.h> #include <sys/exec_elf.h> #include <signal.h> #include <assert.h> #include <string.h> #include <errno.h> Loading Loading @@ -82,3 +83,20 @@ const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc) } return NULL; } /* * Returns true if the specified signal has an associated address (i.e. it * sets siginfo_t.si_addr). */ bool signal_has_address(int sig) { switch (sig) { case SIGILL: case SIGFPE: case SIGSEGV: case SIGBUS: return true; default: return false; } } debuggerd/utility.h +4 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ typedef struct mapinfo { unsigned exidx_start; unsigned exidx_end; struct symbol_table *symbols; bool isExecutable; char name[]; } mapinfo; Loading @@ -56,6 +57,9 @@ const char *map_to_name(mapinfo *mi, unsigned pc, const char* def); /* Log information onto the tombstone */ extern void _LOG(int tfd, bool in_tombstone_only, const char *fmt, ...); /* Determine whether si_addr is valid for this signal */ bool signal_has_address(int sig); #define LOG(fmt...) _LOG(-1, 0, fmt) /* Set to 1 for normal debug traces */ Loading Loading
debuggerd/arm/machine.c +70 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,74 @@ extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map, int *frame0_pc_sane, bool at_fault); /* * If this isn't clearly a null pointer dereference, dump the * /proc/maps entries near the fault address. */ static void show_nearby_maps(int tfd, int pid, mapinfo *map) { siginfo_t si; memset(&si, 0, sizeof(si)); if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si)) { _LOG(tfd, false, "cannot get siginfo: %s\n", strerror(errno)); return; } if (!signal_has_address(si.si_signo)) return; uintptr_t addr = (uintptr_t) si.si_addr; addr &= ~0xfff; /* round to 4K page boundary */ if (addr == 0) /* null-pointer deref */ return; _LOG(tfd, false, "\nmemory map around addr %08x:\n", si.si_addr); /* * Search for a match, or for a hole where the match would be. The list * is backward from the file content, so it starts at high addresses. */ bool found = false; mapinfo *next = NULL; mapinfo *prev = NULL; while (map != NULL) { if (addr >= map->start && addr < map->end) { found = true; next = map->next; break; } else if (addr >= map->end) { /* map would be between "prev" and this entry */ next = map; map = NULL; break; } prev = map; map = map->next; } /* * Show "next" then "match" then "prev" so that the addresses appear in * ascending order (like /proc/pid/maps). */ if (next != NULL) { _LOG(tfd, false, "%08x-%08x %s\n", next->start, next->end, next->name); } else { _LOG(tfd, false, "(no map below)\n"); } if (map != NULL) { _LOG(tfd, false, "%08x-%08x %s\n", map->start, map->end, map->name); } else { _LOG(tfd, false, "(no map for address)\n"); } if (prev != NULL) { _LOG(tfd, false, "%08x-%08x %s\n", prev->start, prev->end, prev->name); } else { _LOG(tfd, false, "(no map above)\n"); } } void dump_stack_and_code(int tfd, int pid, mapinfo *map, int unwind_depth, unsigned int sp_list[], bool at_fault) Loading Loading @@ -123,6 +191,8 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, } } show_nearby_maps(tfd, pid, map); p = sp - 64; if (p > sp) p = 0; Loading
debuggerd/debuggerd.c +20 −7 Original line number Diff line number Diff line Loading @@ -70,15 +70,18 @@ mapinfo *parse_maps_line(char *line) mapinfo *mi; int len = strlen(line); if(len < 1) return 0; if (len < 1) return 0; /* not expected */ line[--len] = 0; if(len < 50) return 0; if(line[20] != 'x') return 0; if (len < 50) { mi = malloc(sizeof(mapinfo) + 1); } else { mi = malloc(sizeof(mapinfo) + (len - 47)); } if (mi == 0) return 0; mi->isExecutable = (line[20] == 'x'); mi->start = strtoul(line, 0, 16); mi->end = strtoul(line + 9, 0, 16); /* To be filled in parse_elf_info if the mapped section starts with Loading @@ -87,7 +90,11 @@ mapinfo *parse_maps_line(char *line) mi->exidx_start = mi->exidx_end = 0; mi->symbols = 0; mi->next = 0; if (len < 50) { mi->name[0] = '\0'; } else { strcpy(mi->name, line + 49); } return mi; } Loading Loading @@ -165,11 +172,14 @@ void dump_fault_addr(int tfd, int pid, int sig) memset(&si, 0, sizeof(si)); if(ptrace(PTRACE_GETSIGINFO, pid, 0, &si)){ _LOG(tfd, false, "cannot get siginfo: %s\n", strerror(errno)); } else { } else if (signal_has_address(sig)) { _LOG(tfd, false, "signal %d (%s), code %d (%s), fault addr %08x\n", sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code), si.si_addr); } else { _LOG(tfd, false, "signal %d (%s), code %d (%s), fault addr --------\n", sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code)); } } Loading Loading @@ -199,6 +209,9 @@ static void parse_elf_info(mapinfo *milist, pid_t pid) { mapinfo *mi; for (mi = milist; mi != NULL; mi = mi->next) { if (!mi->isExecutable) continue; Elf32_Ehdr ehdr; memset(&ehdr, 0, sizeof(Elf32_Ehdr)); Loading
debuggerd/utility.c +18 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <sys/ptrace.h> #include <sys/exec_elf.h> #include <signal.h> #include <assert.h> #include <string.h> #include <errno.h> Loading Loading @@ -82,3 +83,20 @@ const mapinfo *pc_to_mapinfo(mapinfo *mi, unsigned pc, unsigned *rel_pc) } return NULL; } /* * Returns true if the specified signal has an associated address (i.e. it * sets siginfo_t.si_addr). */ bool signal_has_address(int sig) { switch (sig) { case SIGILL: case SIGFPE: case SIGSEGV: case SIGBUS: return true; default: return false; } }
debuggerd/utility.h +4 −0 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ typedef struct mapinfo { unsigned exidx_start; unsigned exidx_end; struct symbol_table *symbols; bool isExecutable; char name[]; } mapinfo; Loading @@ -56,6 +57,9 @@ const char *map_to_name(mapinfo *mi, unsigned pc, const char* def); /* Log information onto the tombstone */ extern void _LOG(int tfd, bool in_tombstone_only, const char *fmt, ...); /* Determine whether si_addr is valid for this signal */ bool signal_has_address(int sig); #define LOG(fmt...) _LOG(-1, 0, fmt) /* Set to 1 for normal debug traces */ Loading