Example #1
0
static int
frame_callback(Dwfl_Frame *frame, void *data)
{
    struct frame_callback_arg *frame_arg = data;
    char **error_msg = &frame_arg->error_msg;

    Dwarf_Addr pc;
    bool minus_one;
    if (!dwfl_frame_pc(frame, &pc, &minus_one))
    {
        set_error_dwfl("dwfl_frame_pc");
        return DWARF_CB_ABORT;
    }

    Dwfl *dwfl = dwfl_thread_dwfl(dwfl_frame_thread(frame));
    struct sr_core_frame *result = resolve_frame(dwfl, pc, minus_one);

    /* Do not unwind below __libc_start_main. */
    if (0 == sr_strcmp0(result->function_name, "__libc_start_main"))
    {
        sr_core_frame_free(result);
        return CB_STOP_UNWIND;
    }

    frame_arg->thread->frames =
        sr_core_frame_append(frame_arg->thread->frames, result);

    return DWARF_CB_OK;
}
Example #2
0
struct sr_core_stacktrace *
sr_core_stacktrace_from_gdb(const char *gdb_output, const char *core_file,
                            const char *exe_file, char **error_msg)
{
    /* I'm not going to rewrite it now since the function is not being used. */
    assert(error_msg);
    /* Initialize error_msg to 'no error'. */
    *error_msg = NULL;

    struct core_handle *ch = open_coredump(core_file, exe_file, error_msg);
    if (*error_msg)
        return NULL;

    struct sr_gdb_stacktrace *gdb_stacktrace;
    struct sr_location location;
    sr_location_init(&location);

    gdb_stacktrace = sr_gdb_stacktrace_parse(&gdb_output, &location);
    if (!gdb_stacktrace)
    {
        *error_msg = sr_location_to_string(&location);
        core_handle_free(ch);
        return NULL;
    }

    struct sr_core_stacktrace *core_stacktrace = sr_core_stacktrace_new();

    for (struct sr_gdb_thread *gdb_thread = gdb_stacktrace->threads;
         gdb_thread;
         gdb_thread = gdb_thread->next)
    {
        struct sr_core_thread *core_thread = sr_core_thread_new();

        for (struct sr_gdb_frame *gdb_frame = gdb_thread->frames;
             gdb_frame;
             gdb_frame = gdb_frame->next)
        {
            if (gdb_frame->signal_handler_called)
                continue;

            struct sr_core_frame *core_frame = resolve_frame(ch->dwfl,
                    gdb_frame->address, false);

            core_thread->frames = sr_core_frame_append(core_thread->frames,
                    core_frame);
        }

        if (sr_gdb_stacktrace_find_crash_thread(gdb_stacktrace) == gdb_thread)
        {
            core_stacktrace->crash_thread = core_thread;
        }

        core_stacktrace->threads = sr_core_thread_append(
                core_stacktrace->threads, core_thread);
    }

    core_stacktrace->signal = get_signal_number(ch->eh, core_file);
    core_stacktrace->executable = realpath(exe_file, NULL);

    core_handle_free(ch);
    sr_gdb_stacktrace_free(gdb_stacktrace);
    return core_stacktrace;
}
Example #3
0
static struct sr_core_thread *
unwind_thread(struct UCD_info *ui,
              unw_addr_space_t as,
              Dwfl *dwfl,
              int thread_no,
              char **error_msg)
{
    int ret;
    unw_cursor_t c;
    struct sr_core_frame *trace = NULL;

    _UCD_select_thread(ui, thread_no);

    ret = unw_init_remote(&c, as, ui);
    if (ret < 0)
    {
        set_error("unw_init_remote failed: %s", unw_strerror(ret));
        return NULL;
    }

    int count = 1000;
    while (--count > 0)
    {
        unw_word_t ip;
        ret = unw_get_reg(&c, UNW_REG_IP, &ip);
        if (ret < 0)
            warn("unw_get_reg(UNW_REG_IP) failed: %s", unw_strerror(ret));

        /* Seen this happen when unwinding thread that did not start
         * in main(). */
        if (ip == 0)
            break;

        struct sr_core_frame *entry = resolve_frame(dwfl, ip, false);

        if (!entry->function_name)
        {
            size_t funcname_len = 512;
            char *funcname = sr_malloc(funcname_len);

            if (unw_get_proc_name(&c, funcname, funcname_len, NULL) == 0)
                entry->function_name = funcname;
            else
                free(funcname);
        }

        trace = sr_core_frame_append(trace, entry);
        /*
        printf("%s 0x%llx %s %s -\n",
                (ip_seg && ip_seg->build_id) ? ip_seg->build_id : "-",
                (unsigned long long)(ip_seg ? ip - ip_seg->vaddr : ip),
                (entry->symbol ? entry->symbol : "-"),
                (ip_seg && ip_seg->filename) ? ip_seg->filename : "-");
        */

        /* Do not unwind below __libc_start_main. */
        if (0 == sr_strcmp0(entry->function_name, "__libc_start_main"))
            break;

        ret = unw_step(&c);
        if (ret == 0)
            break;

        if (ret < 0)
        {
            warn("unw_step failed: %s", unw_strerror(ret));
            break;
        }
    }

    if (error_msg && !*error_msg && !trace)
    {
        set_error("No frames found for thread %d", thread_no);
    }

    struct sr_core_thread *thread = sr_core_thread_new();
    thread->frames = trace;
    return thread;
}