struct thread* unwind_stacks(Dwfl *dwfl, const char *core_file, struct exec_map *em, struct expr_context *ctx) { unw_addr_space_t as; struct UCD_info *ui; struct thread *head = NULL, *tail = NULL; as = unw_create_addr_space(&_UCD_accessors, 0); fail_if(!as, "unw_create_addr_space"); ui = _UCD_create(core_file); fail_if(!ui, "_UCD_create"); for (; em != NULL; em = em->next) { if (_UCD_add_backing_file_at_vaddr(ui, em->vaddr, em->file) < 0) { fail("_UCD_add_backing_file_at_vaddr"); } } int tnum; int nthreads = _UCD_get_num_threads(ui); for (tnum = 0; tnum < nthreads; tnum++) { struct thread *thread = xalloc(sizeof(struct thread)); thread->frames = unwind_thread(dwfl, as, ui, tnum, ctx); list_append(head, tail, thread); } return head; }
int main(int argc UNUSED, char **argv) { unw_addr_space_t as; struct UCD_info *ui; unw_cursor_t c; int ret; #define TEST_FRAMES 4 #define TEST_NAME_LEN 32 int testcase = 0; int test_cur = 0; long test_start_ips[TEST_FRAMES]; char test_names[TEST_FRAMES][TEST_NAME_LEN]; install_sigsegv_handler(); const char *progname = strrchr(argv[0], '/'); if (progname) progname++; else progname = argv[0]; if (!argv[1]) error_msg_and_die("Usage: %s COREDUMP [VADDR:BINARY_FILE]...", progname); msg_prefix = progname; as = unw_create_addr_space(&_UCD_accessors, 0); if (!as) error_msg_and_die("unw_create_addr_space() failed"); ui = _UCD_create(argv[1]); if (!ui) error_msg_and_die("_UCD_create('%s') failed", argv[1]); ret = unw_init_remote(&c, as, ui); if (ret < 0) error_msg_and_die("unw_init_remote() failed: ret=%d\n", ret); argv += 2; /* Enable checks for the crasher test program? */ if (*argv && !strcmp(*argv, "-testcase")) { testcase = 1; logmode = LOGMODE_NONE; argv++; } while (*argv) { char *colon; unsigned long vaddr = strtoul(*argv, &colon, 16); if (*colon != ':') error_msg_and_die("Bad format: '%s'", *argv); if (_UCD_add_backing_file_at_vaddr(ui, vaddr, colon + 1) < 0) error_msg_and_die("Can't add backing file '%s'", colon + 1); argv++; } for (;;) { unw_word_t ip; ret = unw_get_reg(&c, UNW_REG_IP, &ip); if (ret < 0) error_msg_and_die("unw_get_reg(UNW_REG_IP) failed: ret=%d\n", ret); unw_proc_info_t pi; ret = unw_get_proc_info(&c, &pi); if (ret < 0) error_msg_and_die("unw_get_proc_info(ip=0x%lx) failed: ret=%d\n", (long) ip, ret); if (!testcase) printf("\tip=0x%08lx proc=%08lx-%08lx handler=0x%08lx lsda=0x%08lx\n", (long) ip, (long) pi.start_ip, (long) pi.end_ip, (long) pi.handler, (long) pi.lsda); if (testcase && test_cur < TEST_FRAMES) { unw_word_t off; test_start_ips[test_cur] = (long) pi.start_ip; if (unw_get_proc_name(&c, test_names[test_cur], sizeof(test_names[0]), &off) != 0) { test_names[test_cur][0] = '\0'; } test_cur++; } log("step"); ret = unw_step(&c); log("step done:%d", ret); if (ret < 0) error_msg_and_die("FAILURE: unw_step() returned %d", ret); if (ret == 0) break; } log("stepping ended"); /* Check that the second and third frames are equal, but distinct of the * others */ if (testcase && (test_cur != 4 || test_start_ips[1] != test_start_ips[2] || test_start_ips[0] == test_start_ips[1] || test_start_ips[2] == test_start_ips[3] ) ) { fprintf(stderr, "FAILURE: start IPs incorrect\n"); return -1; } if (testcase && ( strcmp(test_names[0], "a") || strcmp(test_names[1], "b") || strcmp(test_names[2], "b") || strcmp(test_names[3], "main") ) ) { fprintf(stderr, "FAILURE: procedure names are missing/incorrect\n"); return -1; } _UCD_destroy(ui); unw_destroy_addr_space(as); return 0; }
int main(int argc , char **argv) { unw_addr_space_t as; unw_cursor_t cursor; struct UCD_info *ui; unw_word_t ip, sp, off; char buf[512], name[256]; int line; int depth = 0; int ret; bool pybt_done = false; #define TEST_NAME_LEN 256 install_signal_handler(); if (argc != 3) { fprintf(stderr, "Usage: %s <binary> <corefile>", argv[0]); exit(1); } as = unw_create_addr_space(&_UCD_accessors, 0); if (!as) { fprintf(stderr, "unw_create_addr_space() failed"); exit(1); } ui = _UCD_create(argv[2]); if (!ui) { fprintf(stderr,"_UCD_create('%s') failed", argv[1]); exit(1); } ret = unw_init_remote(&cursor, as, ui); if (ret < 0) { fprintf(stderr,"unw_init_remote() failed: ret=%d\n", ret); exit(1); } read_elfnotes(argv[2], ui); while (unw_step(&cursor) > 0) { // Avoid going too deep if (depth++ > MAX_STACK_DEPTH) { exit(1); } unw_get_reg(&cursor, UNW_REG_IP, &ip); unw_get_reg(&cursor, UNW_REG_SP, &sp); if (unw_get_proc_name(&cursor, name, sizeof (name), &off) == 0) { if (off) { snprintf(buf, sizeof (buf), "<%s+0x%lx>", name, (long) off); } else { snprintf(buf, sizeof (buf), "<%s>", name); } } /* Check for Python backtrace */ if (!strncmp(name,"PyEval_EvalFrameEx", 18) && !pybt_done) { pybacktrace(cursor); pybt_done = true; } rw_get_file_and_line((long)ip, name, argv[1], 256, &line); printf("%016lx %s <%s:%d> (sp=%016lx)\n", (long) ip, buf, basename(name), line, (long) sp); } _UCD_destroy(ui); unw_destroy_addr_space(as); return 0; }
struct sr_core_stacktrace * sr_parse_coredump(const char *core_file, const char *exe_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, error_msg); if (*error_msg) return NULL; unw_addr_space_t as; struct UCD_info *ui; as = unw_create_addr_space(&_UCD_accessors, 0); if (!as) { set_error("Failed to create address space"); goto fail_destroy_handle; } ui = _UCD_create(core_file); if (!ui) { set_error("Failed to set up core dump accessors for '%s'", core_file); goto fail_destroy_as; } struct exe_mapping_data *s; for (s = ch->segments; s != NULL; s = s->next) { if (_UCD_add_backing_file_at_vaddr(ui, s->start, s->filename) < 0) { /* Sometimes produces: * >_UCD_add_backing_file_at_segment: * Error reading from '/usr/lib/modules/3.6.9-2.fc17.x86_64/vdso/vdso.so' * Ignore errors for now & fail later. */ warn("Can't add backing file '%s' at addr 0x%jx", s->filename, (uintmax_t)s->start); /* goto fail_destroy_ui; */ } } stacktrace = sr_core_stacktrace_new(); int tnum, nthreads = _UCD_get_num_threads(ui); for (tnum = 0; tnum < nthreads; ++tnum) { struct sr_core_thread *trace = unwind_thread(ui, as, ch->dwfl, tnum, error_msg); if (trace) { stacktrace->threads = sr_core_thread_append(stacktrace->threads, trace); } else { sr_core_stacktrace_free(stacktrace); stacktrace = NULL; break; } } stacktrace->executable = realpath(exe_file, NULL); stacktrace->signal = get_signal_number_libunwind(ui); /* FIXME: is this the best we can do? */ stacktrace->crash_thread = stacktrace->threads; _UCD_destroy(ui); fail_destroy_as: unw_destroy_addr_space(as); fail_destroy_handle: core_handle_free(ch); return stacktrace; }