static void backtrace_and_maps (int do_abort, bool written, int fd) { if (do_abort > 1 && written) { void *addrs[64]; #define naddrs (sizeof (addrs) / sizeof (addrs[0])) int n = __backtrace (addrs, naddrs); if (n > 2) { #define strnsize(str) str, strlen (str) #define writestr(str) write_not_cancel (fd, str) writestr (strnsize ("======= Backtrace: =========\n")); __backtrace_symbols_fd (addrs + 1, n - 1, fd); writestr (strnsize ("======= Memory map: ========\n")); int fd2 = open_not_cancel_2 ("/proc/self/maps", O_RDONLY); char buf[1024]; ssize_t n2; while ((n2 = read_not_cancel (fd2, buf, sizeof (buf))) > 0) if (write_not_cancel (fd, buf, n2) != n2) break; close_not_cancel_no_status (fd2); } } }
/* This function is called when a segmentation fault is caught. The system is in an unstable state now. This means especially that malloc() might not work anymore. */ static void catch_segfault (int signal, SIGCONTEXT ctx) { int fd, cnt, i; void **arr; struct sigaction sa; uintptr_t pc; /* This is the name of the file we are writing to. If none is given or we cannot write to this file write to stderr. */ fd = 2; if (fname != NULL) { fd = open (fname, O_TRUNC | O_WRONLY | O_CREAT, 0666); if (fd == -1) fd = 2; } WRITE_STRING ("*** "); write_strsignal (fd, signal); WRITE_STRING ("\n"); #ifdef REGISTER_DUMP REGISTER_DUMP; #endif #if __OPTION_EGLIBC_BACKTRACE WRITE_STRING ("\nBacktrace:\n"); /* Get the backtrace. */ arr = alloca (256 * sizeof (void *)); cnt = backtrace (arr, 256); /* Now try to locate the PC from signal context in the backtrace. Normally it will be found at arr[2], but it might appear later if there were some signal handler wrappers. Allow a few bytes difference to cope with as many arches as possible. */ pc = (uintptr_t) GET_PC (ctx); for (i = 0; i < cnt; ++i) if ((uintptr_t) arr[i] >= pc - 16 && (uintptr_t) arr[i] <= pc + 16) break; /* If we haven't found it, better dump full backtrace even including the signal handler frames instead of not dumping anything. */ if (i == cnt) i = 0; /* Now generate nicely formatted output. */ __backtrace_symbols_fd (arr + i, cnt - i, fd); #endif #ifdef HAVE_PROC_SELF /* Now the link map. */ int mapfd = open ("/proc/self/maps", O_RDONLY); if (mapfd != -1) { write (fd, "\nMemory map:\n\n", 14); char buf[256]; ssize_t n; while ((n = TEMP_FAILURE_RETRY (read (mapfd, buf, sizeof (buf)))) > 0) TEMP_FAILURE_RETRY (write (fd, buf, n)); close (mapfd); } #endif /* Pass on the signal (so that a core file is produced). */ sa.sa_handler = SIG_DFL; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (signal, &sa, NULL); raise (signal); }
/* This function is called when a segmentation fault is caught. The system is in an instable state now. This means especially that malloc() might not work anymore. */ static void catch_segfault (int signal, SIGCONTEXT ctx) { struct layout *current; void *__unbounded top_frame; void *__unbounded top_stack; int fd; void **arr; size_t cnt; struct sigaction sa; /* This is the name of the file we are writing to. If none is given or we cannot write to this file write to stderr. */ fd = 2; if (fname != NULL) { fd = open (fname, O_TRUNC | O_WRONLY | O_CREAT, 0666); if (fd == -1) fd = 2; } WRITE_STRING ("*** "); write_strsignal (fd, signal); WRITE_STRING ("\n"); #ifdef REGISTER_DUMP REGISTER_DUMP; #endif WRITE_STRING ("\nBacktrace:\n"); top_frame = GET_FRAME (ctx); top_stack = GET_STACK (ctx); /* First count how many entries we'll have. */ cnt = 1; current = BOUNDED_1 ((struct layout *) top_frame); while (!((void *) current INNER_THAN top_stack || !((void *) current INNER_THAN __libc_stack_end))) { ++cnt; current = ADVANCE_STACK_FRAME (current->next); } arr = alloca (cnt * sizeof (void *)); /* First handle the program counter from the structure. */ arr[0] = GET_PC (ctx); current = BOUNDED_1 ((struct layout *) top_frame); cnt = 1; while (!((void *) current INNER_THAN top_stack || !((void *) current INNER_THAN __libc_stack_end))) { arr[cnt++] = current->return_address; current = ADVANCE_STACK_FRAME (current->next); } /* If the last return address was NULL, assume that it doesn't count. */ if (arr[cnt-1] == NULL) cnt--; /* Now generate nicely formatted output. */ __backtrace_symbols_fd (arr, cnt, fd); /* Pass on the signal (so that a core file is produced). */ sa.sa_handler = SIG_DFL; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (signal, &sa, NULL); raise (signal); }