struct refl * refl_begin (void) { struct refl *result = malloc (sizeof (*result)); if (result == NULL) { __refl_seterr (REFL_E_SYSTEM); return NULL; } Dwfl *dwfl = dwfl_begin (&callbacks); if (dwfl == NULL) { __refl_seterr (REFL_E_DWFL); goto err_out; } dwfl_report_begin (dwfl); int status = dwfl_linux_proc_report (dwfl, getpid ()); dwfl_report_end (dwfl, NULL, NULL); if (status < 0) { __refl_seterr (REFL_E_DWFL); goto err_out; } result->dwfl = dwfl; return result; err_out: free (result); return NULL; }
// Create a libdw session with DWARF information for all loaded modules LibdwSession *libdwInit() { LibdwSession *session = stgCallocBytes(1, sizeof(LibdwSession), "libdwInit"); // Initialize ELF library if (elf_version(EV_CURRENT) == EV_NONE) { sysErrorBelch("libelf version too old!"); return NULL; } // Initialize a libdwfl session static char *debuginfo_path; static const Dwfl_Callbacks proc_callbacks = { .find_debuginfo = dwfl_standard_find_debuginfo, .debuginfo_path = &debuginfo_path, .find_elf = dwfl_linux_proc_find_elf, }; session->dwfl = dwfl_begin (&proc_callbacks); if (session->dwfl == NULL) { sysErrorBelch("dwfl_begin failed: %s", dwfl_errmsg(dwfl_errno())); free(session); return NULL; } // Report the loaded modules int ret = dwfl_linux_proc_report(session->dwfl, getpid()); if (ret < 0) { sysErrorBelch("dwfl_linux_proc_report failed: %s", dwfl_errmsg(dwfl_errno())); goto fail; } if (dwfl_report_end (session->dwfl, NULL, NULL) != 0) { sysErrorBelch("dwfl_report_end failed: %s", dwfl_errmsg(dwfl_errno())); goto fail; } pid_t pid = getpid(); if (! dwfl_attach_state(session->dwfl, NULL, pid, &thread_cbs, NULL)) { sysErrorBelch("dwfl_attach_state failed: %s", dwfl_errmsg(dwfl_errno())); goto fail; } return session; fail: dwfl_end(session->dwfl); free(session); return NULL; }
int main (void) { Dwfl *dwfl = dwfl_begin (&callbacks); for (int i = 0; i < 5; ++i) { dwfl_report_begin (dwfl); dwfl_report_module (dwfl, "module1", 0, 10); dwfl_report_end (dwfl, NULL, NULL); } dwfl_end (dwfl); return 0; }
static void report_pid (Dwfl *dwfl, pid_t pid) { int result = dwfl_linux_proc_report (dwfl, pid); if (result < 0) error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1)); else if (result > 0) error (2, result, "dwfl_linux_proc_report"); if (dwfl_report_end (dwfl, NULL, NULL) != 0) error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1)); result = dwfl_linux_proc_attach (dwfl, pid, true); if (result < 0) error (2, 0, "dwfl_linux_proc_attach: %s", dwfl_errmsg (-1)); else if (result > 0) error (2, result, "dwfl_linux_proc_attach"); }
struct core_handle * open_coredump(const char *elf_file, const char *exe_file, char **error_msg) { struct core_handle *ch = sr_mallocz(sizeof(*ch)); struct exe_mapping_data *head = NULL, **tail = &head; /* Initialize libelf, open the file and get its Elf handle. */ if (elf_version(EV_CURRENT) == EV_NONE) { set_error_elf("elf_version"); goto fail_free; } /* Open input file, and parse it. */ ch->fd = open(elf_file, O_RDONLY); if (ch->fd < 0) { set_error("Unable to open '%s': %s", elf_file, strerror(errno)); goto fail_free; } ch->eh = elf_begin(ch->fd, ELF_C_READ_MMAP, NULL); if (ch->eh == NULL) { set_error_elf("elf_begin"); goto fail_close; } /* Check that we are working with a coredump. */ GElf_Ehdr ehdr; if (gelf_getehdr(ch->eh, &ehdr) == NULL || ehdr.e_type != ET_CORE) { set_error("File '%s' is not a coredump", elf_file); goto fail_elf; } executable_file = exe_file; ch->cb.find_elf = find_elf_core; ch->cb.find_debuginfo = find_debuginfo_none; ch->cb.section_address = dwfl_offline_section_address; ch->dwfl = dwfl_begin(&ch->cb); #if _ELFUTILS_PREREQ(0, 158) if (dwfl_core_file_report(ch->dwfl, ch->eh, exe_file) == -1) #else if (dwfl_core_file_report(ch->dwfl, ch->eh) == -1) #endif { set_error_dwfl("dwfl_core_file_report"); goto fail_dwfl; } if (dwfl_report_end(ch->dwfl, NULL, NULL) != 0) { set_error_dwfl("dwfl_report_end"); goto fail_dwfl; } /* needed so that module filenames are available during unwinding */ ptrdiff_t ret = dwfl_getmodules(ch->dwfl, touch_module, &tail, 0); if (ret == -1) { set_error_dwfl("dwfl_getmodules"); goto fail_dwfl; } ch->segments = head; if (!head) { if (error_msg && !*error_msg) set_error("No segments found in coredump '%s'", elf_file); goto fail_dwfl; } return ch; fail_dwfl: dwfl_end(ch->dwfl); fail_elf: elf_end(ch->eh); fail_close: close(ch->fd); fail_free: free(ch); return NULL; }
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; }