int main (int argc __attribute__ ((unused)), char **argv) { /* We use no threads here which can interfere with handling a stream. */ __fsetlocking (stdin, FSETLOCKING_BYCALLER); __fsetlocking (stdout, FSETLOCKING_BYCALLER); __fsetlocking (stderr, FSETLOCKING_BYCALLER); /* Set locale. */ (void) setlocale (LC_ALL, ""); elf_version (EV_CURRENT); pid_t pid = fork (); switch (pid) { case -1: abort (); case 0:; long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL); assert (errno == 0); assert (l == 0); cleanup_13_main (); abort (); default: break; } errno = 0; int status; pid_t got = waitpid (pid, &status, 0); assert (errno == 0); assert (got == pid); assert (WIFSTOPPED (status)); assert (WSTOPSIG (status) == SIGABRT); Dwfl *dwfl = pid_to_dwfl (pid); dwfl_getthreads (dwfl, thread_callback, NULL); /* There is an exit (0) call if we find the "main" frame, */ error (1, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1)); }
int coredump_make_stack_trace(int fd, const char *executable, char **ret) { static const Dwfl_Callbacks callbacks = { .find_elf = dwfl_build_id_find_elf, .find_debuginfo = dwfl_standard_find_debuginfo, }; struct stack_context c = {}; char *buf = NULL; size_t sz = 0; int r; assert(fd >= 0); assert(ret); if (lseek(fd, 0, SEEK_SET) == (off_t) -1) return -errno; c.f = open_memstream(&buf, &sz); if (!c.f) return -ENOMEM; elf_version(EV_CURRENT); c.elf = elf_begin(fd, ELF_C_READ_MMAP, NULL); if (!c.elf) { r = -EINVAL; goto finish; } c.dwfl = dwfl_begin(&callbacks); if (!c.dwfl) { r = -EINVAL; goto finish; } if (dwfl_core_file_report(c.dwfl, c.elf, executable) < 0) { r = -EINVAL; goto finish; } if (dwfl_report_end(c.dwfl, NULL, NULL) != 0) { r = -EINVAL; goto finish; } if (dwfl_core_file_attach(c.dwfl, c.elf) < 0) { r = -EINVAL; goto finish; } if (dwfl_getthreads(c.dwfl, thread_callback, &c) < 0) { r = -EINVAL; goto finish; } c.f = safe_fclose(c.f); *ret = buf; buf = NULL; r = 0; finish: if (c.dwfl) dwfl_end(c.dwfl); if (c.elf) elf_end(c.elf); safe_fclose(c.f); free(buf); return r; }
struct sr_core_stacktrace * sr_parse_coredump_maps(const char *core_file, const char *exe_file, const char *maps_file, char **error_msg) { struct sr_core_stacktrace *stacktrace = NULL; /* Initialize error_msg to 'no error'. */ if (error_msg) *error_msg = NULL; struct core_handle *ch = open_coredump(core_file, exe_file, maps_file, error_msg); if (!ch) goto fail; if (dwfl_core_file_attach(ch->dwfl, ch->eh) < 0) { set_error_dwfl("dwfl_core_file_attach"); goto fail; } stacktrace = sr_core_stacktrace_new(); if (!stacktrace) { set_error("Failed to initialize stacktrace memory"); goto fail; } struct thread_callback_arg thread_arg = { .stacktrace = stacktrace, .error_msg = NULL }; int ret = dwfl_getthreads(ch->dwfl, unwind_thread, &thread_arg); if (ret != 0) { if (ret == -1) set_error_dwfl("dwfl_getthreads"); else if (ret == DWARF_CB_ABORT) { set_error("%s", thread_arg.error_msg); free(thread_arg.error_msg); } else set_error("Unknown error in dwfl_getthreads"); sr_core_stacktrace_free(stacktrace); stacktrace = NULL; goto fail; } stacktrace->executable = sr_strdup(exe_file); stacktrace->signal = get_signal_number(ch->eh, core_file); /* FIXME: is this the best we can do? */ stacktrace->crash_thread = stacktrace->threads; fail: core_handle_free(ch); return stacktrace; }