Esempio n. 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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}