static void dump_fault_addr(log_t* log, pid_t tid, int sig) { siginfo_t si; memset(&si, 0, sizeof(si)); if (ptrace(PTRACE_GETSIGINFO, tid, 0, &si)){ _LOG(log, false, "cannot get siginfo: %s\n", strerror(errno)); } else if (signal_has_address(sig)) { _LOG(log, false, "signal %d (%s), code %d (%s), fault addr %08x\n", sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code), (uintptr_t) si.si_addr); } else { _LOG(log, false, "signal %d (%s), code %d (%s), fault addr --------\n", sig, get_signame(sig), si.si_code, get_sigcode(sig, si.si_code)); } }
/* * If this isn't clearly a null pointer dereference, dump the * /proc/maps entries near the fault address. * * This only makes sense to do on the thread that crashed. */ 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 for %d: %s\n", pid, 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"); } }