Exemple #1
0
static char *build_ids_from_core_backtrace(const char *dump_dir_name)
{
    char *error = NULL;
    char *core_backtrace_path = xasprintf("%s/"FILENAME_CORE_BACKTRACE, dump_dir_name);
    char *json = xmalloc_open_read_close(core_backtrace_path, /*maxsize:*/ NULL);
    free(core_backtrace_path);

    if (!json)
        return NULL;

    struct sr_core_stacktrace *stacktrace = sr_core_stacktrace_from_json_text(json, &error);
    free(json);
    if (!stacktrace)
    {
        if (error)
        {
            log_info("Failed to parse core backtrace: %s", error);
            free(error);
        }
        return NULL;
    }

    struct sr_core_thread *thread = sr_core_stacktrace_find_crash_thread(stacktrace);
    if (!thread)
    {
        log_info("Failed to find crash thread");
        sr_core_stacktrace_free(stacktrace);
        return NULL;
    }

    void *build_id_list = NULL;

    struct strbuf *strbuf = strbuf_new();
    for (struct sr_core_frame *frame = thread->frames;
         frame;
         frame = frame->next)
    {
        if (frame->build_id)
            build_id_list = g_list_prepend(build_id_list, frame->build_id);
    }

    build_id_list = g_list_sort(build_id_list, (GCompareFunc)strcmp);
    for (GList *iter = build_id_list; iter; iter = g_list_next(iter))
    {
        GList *next = g_list_next(iter);
        if (next == NULL || 0 != strcmp(iter->data, next->data))
        {
            strbuf = strbuf_append_strf(strbuf, "%s\n", (char *)iter->data);
        }
    }
    g_list_free(build_id_list);
    sr_core_stacktrace_free(stacktrace);

    return strbuf_free_nobuf(strbuf);
}
Exemple #2
0
char *
sr_abrt_get_core_stacktrace_from_core_hook(pid_t thread_id,
                                           const char *executable,
                                           int signum,
                                           char **error_message)
{

    struct sr_core_stacktrace *core_stacktrace;
    core_stacktrace = sr_core_stacktrace_from_core_hook(thread_id, executable,
                                                        signum, error_message);

    if (!core_stacktrace)
        return false;

    fulfill_missing_values(core_stacktrace);

    char *json = sr_core_stacktrace_to_json(core_stacktrace);
    sr_core_stacktrace_free(core_stacktrace);

    // Add newline to the end of core stacktrace file to make text
    // editors happy.
    json = sr_realloc(json, strlen(json) + 2);
    strcat(json, "\n");

    return json;
;
}
Exemple #3
0
struct sr_core_stacktrace *
sr_core_stacktrace_from_json(struct sr_json_value *root,
                             char **error_message)
{
    if (!JSON_CHECK_TYPE(root, SR_JSON_OBJECT, "stacktrace"))
        return NULL;

    struct sr_core_stacktrace *result = sr_core_stacktrace_new();

    bool success =
        JSON_READ_UINT16(root, "signal", &result->signal) &&
        JSON_READ_STRING(root, "executable", &result->executable) &&
        JSON_READ_BOOL(root, "only_crash_thread", &result->only_crash_thread);

    if (!success)
        goto fail;

    /* Read threads. */
    struct sr_json_value *stacktrace = json_element(root, "stacktrace");
    if (stacktrace)
    {
        if (!JSON_CHECK_TYPE(stacktrace, SR_JSON_ARRAY, "stacktrace"))
            goto fail;

        struct sr_json_value *json_thread;
        FOR_JSON_ARRAY(stacktrace, json_thread)
        {
            struct sr_core_thread *thread = sr_core_thread_from_json(json_thread,
                    error_message);

            if (!thread)
                goto fail;

            struct sr_json_value *crash_thread = json_element(json_thread, "crash_thread");
            if (crash_thread)
            {
                if (!JSON_CHECK_TYPE(crash_thread, SR_JSON_BOOLEAN, "crash_thread"))
                {
                    sr_core_thread_free(thread);
                    goto fail;
                }

                if (crash_thread->u.boolean)
                    result->crash_thread = thread;
            }

            result->threads = sr_core_thread_append(result->threads, thread);
        }
    }

    return result;

fail:
    sr_core_stacktrace_free(result);
    return NULL;
}
Exemple #4
0
static bool
create_core_stacktrace(const char *directory, const char *gdb_output,
                       bool hash_fingerprints, char **error_message)
{
    char *executable_contents = file_contents(directory, "executable",
                                              error_message);
    if (!executable_contents)
        return NULL;

    char *coredump_filename = sr_build_path(directory, "coredump", NULL);

    struct sr_core_stacktrace *core_stacktrace;

    if (gdb_output)
        core_stacktrace = sr_core_stacktrace_from_gdb(gdb_output,
                coredump_filename, executable_contents, error_message);
    else
        core_stacktrace = sr_parse_coredump(coredump_filename,
                executable_contents, error_message);

    free(executable_contents);
    free(coredump_filename);
    if (!core_stacktrace)
        return false;

    fulfill_missing_values(core_stacktrace);

#if 0
    sr_core_fingerprint_generate(core_stacktrace,
                                 error_message);

    if (hash_fingerprints)
        sr_core_fingerprint_hash(core_stacktrace);
#endif

    char *json = sr_core_stacktrace_to_json(core_stacktrace);

    // Add newline to the end of core stacktrace file to make text
    // editors happy.
    json = sr_realloc(json, strlen(json) + 2);
    strcat(json, "\n");

    char *core_backtrace_filename = sr_build_path(directory, "core_backtrace", NULL);
    bool success = sr_string_to_file(core_backtrace_filename,
                                    json,
                                    error_message);

    free(core_backtrace_filename);
    free(json);
    sr_core_stacktrace_free(core_stacktrace);
    return success;
}
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;
}
Exemple #6
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;
}