Пример #1
0
int
sr_java_frame_cmp(struct sr_java_frame *frame1,
                  struct sr_java_frame *frame2)
{
    if (frame1->is_exception != frame2->is_exception)
        return frame1->is_exception ? 1 : -1;

    int res = sr_strcmp0(frame1->name, frame2->name);
    if (res != 0)
        return res;

    /* Don't compare exception messages because of localization! */
    if (frame1->is_exception)
        return 0;

    /* Method call comparsion */
    res = sr_strcmp0(frame1->class_path, frame2->class_path);
    if (res != 0)
        return res;

    res = sr_strcmp0(frame1->file_name, frame2->file_name);
    if (res != 0)
        return res;

    if (frame1->is_native != frame2->is_native)
        return frame1->is_native ? 1 : -1;

    return frame1->file_line - frame2->file_line;
}
Пример #2
0
int
sr_python_frame_cmp_distance(struct sr_python_frame *frame1,
                             struct sr_python_frame *frame2)
{
    /* function_name */
    int function_name = sr_strcmp0(frame1->function_name,
                                   frame2->function_name);
    if (function_name != 0)
        return function_name;

    /* file_name */
    int file_name = sr_strcmp0(frame1->file_name,
                               frame2->file_name);
    if (file_name != 0)
        return file_name;

    /* special_function */
    int special_function = frame1->special_function - frame2->special_function;

    if (special_function != 0)
        return special_function;

    /* special_file */
    int special_file = frame1->special_file - frame2->special_file;

    if (special_file != 0)
        return special_file;

    return 0;
}
Пример #3
0
static bool
next_functions_similar(struct sr_gdb_frame *frame1,
                       struct sr_gdb_frame *frame2)
{
    if ((!frame1->next && frame2->next) ||
        (frame1->next && !frame2->next) ||
        (frame1->next && frame2->next &&
         (0 != sr_strcmp0(frame1->next->function_name,
                          frame2->next->function_name) ||
          0 == sr_strcmp0(frame1->next->function_name, "??") ||
         (frame1->next->library_name && frame2->next->library_name &&
          0 != strcmp(frame1->next->library_name, frame2->next->library_name)))))
        return false;
    return true;
}
Пример #4
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;
}
Пример #5
0
int
sr_java_frame_cmp_distance(struct sr_java_frame *frame1,
                           struct sr_java_frame *frame2)
{
    int res = sr_strcmp0(frame1->name, frame2->name);
    if (res != 0)
        return res;

    return 0;
}
Пример #6
0
int
sr_python_frame_cmp(struct sr_python_frame *frame1,
                    struct sr_python_frame *frame2)
{
    /* function_name */
    int function_name = sr_strcmp0(frame1->function_name,
                                   frame2->function_name);
    if (function_name != 0)
        return function_name;

    /* file_name */
    int file_name = sr_strcmp0(frame1->file_name,
                               frame2->file_name);
    if (file_name != 0)
        return file_name;

    /* file_line */
    int file_line = frame1->file_line - frame2->file_line;
    if (file_line != 0)
        return file_line;

    /* special_function */
    int special_function = frame1->special_function - frame2->special_function;

    if (special_function != 0)
        return special_function;

    /* special_file */
    int special_file = frame1->special_file - frame2->special_file;

    if (special_file != 0)
        return special_file;

    /* line_contents */
    int line_contents = sr_strcmp0(frame1->line_contents,
                                   frame2->line_contents);
    if (line_contents != 0)
        return line_contents;

    return 0;
}
Пример #7
0
int
sr_ruby_frame_cmp(struct sr_ruby_frame *frame1,
                  struct sr_ruby_frame *frame2)
{
    /* function_name */
    int function_name = sr_strcmp0(frame1->function_name,
                                   frame2->function_name);
    if (function_name != 0)
        return function_name;

    /* file_name */
    int file_name = sr_strcmp0(frame1->file_name,
                               frame2->file_name);
    if (file_name != 0)
        return file_name;

    /* file_line */
    int file_line = frame1->file_line - frame2->file_line;
    if (file_line != 0)
        return file_line;

    /* special_function */
    int special_function = frame1->special_function - frame2->special_function;
    if (special_function != 0)
        return special_function;

    /* block_level */
    int block_level = frame1->block_level - frame2->block_level;
    if (block_level != 0)
            return block_level;

    /* rescue_level */
    int rescue_level = frame1->rescue_level - frame2->rescue_level;
    if (rescue_level != 0)
            return rescue_level;

    return 0;
}
Пример #8
0
void
sr_normalize_gdb_paired_unknown_function_names(struct sr_gdb_thread *thread1,
                                               struct sr_gdb_thread *thread2)

{
    if (!thread1->frames || !thread2->frames)
    {
        return;
    }

    int i = 0;
    struct sr_gdb_frame *curr_frame1 = thread1->frames;
    struct sr_gdb_frame *curr_frame2 = thread2->frames;

    if (0 == sr_strcmp0(curr_frame1->function_name, "??") &&
        0 == sr_strcmp0(curr_frame2->function_name, "??") &&
        !(curr_frame1->library_name && curr_frame2->library_name &&
          strcmp(curr_frame1->library_name, curr_frame2->library_name)) &&
        next_functions_similar(curr_frame1, curr_frame2))
    {
        free(curr_frame1->function_name);
        curr_frame1->function_name = sr_asprintf("__unknown_function_%d", i);
        free(curr_frame2->function_name);
        curr_frame2->function_name = sr_asprintf("__unknown_function_%d", i);
        i++;
    }

    struct sr_gdb_frame *prev_frame1 = curr_frame1;
    struct sr_gdb_frame *prev_frame2 = curr_frame2;
    curr_frame1 = curr_frame1->next;
    curr_frame2 = curr_frame2->next;

    while (curr_frame1)
    {
        if (0 == sr_strcmp0(curr_frame1->function_name, "??"))
        {
            while (curr_frame2)
            {
                if (0 == sr_strcmp0(curr_frame2->function_name, "??") &&
                    !(curr_frame1->library_name && curr_frame2->library_name &&
                      strcmp(curr_frame1->library_name, curr_frame2->library_name)) &&
                    0 != sr_strcmp0(prev_frame2->function_name, "??") &&
                    next_functions_similar(curr_frame1, curr_frame2) &&
                    0 == sr_strcmp0(prev_frame1->function_name,
                                     prev_frame2->function_name) &&
                    !(prev_frame1->library_name && prev_frame2->library_name &&
                      strcmp(prev_frame1->library_name, prev_frame2->library_name)))
                {
                    free(curr_frame1->function_name);
                    curr_frame1->function_name = sr_asprintf("__unknown_function_%d", i);
                    free(curr_frame2->function_name);
                    curr_frame2->function_name = sr_asprintf("__unknown_function_%d", i);
                    i++;
                    break;
                }
                prev_frame2 = curr_frame2;
                curr_frame2 = curr_frame2->next;
            }
        }
        prev_frame1 = curr_frame1;
        curr_frame1 = curr_frame1->next;
        prev_frame2 = thread2->frames;
        curr_frame2 = prev_frame2->next;
    }
}
Пример #9
0
void
sr_normalize_core_thread(struct sr_core_thread *thread)
{
    /* Find the exit frame and remove everything above it. */
    struct sr_core_frame *exit_frame = sr_core_thread_find_exit_frame(thread);
    if (exit_frame)
    {
        bool success = sr_thread_remove_frames_above((struct sr_thread *)thread,
                                                     (struct sr_frame *)exit_frame);
        assert(success); /* if this fails, some code become broken */
        success = sr_thread_remove_frame((struct sr_thread *)thread,
                                         (struct sr_frame *)exit_frame);
        assert(success); /* if this fails, some code become broken */
    }

    /* Normalize function names by removing various prefixes that
     * occur only in some cases.
     */
    struct sr_core_frame *frame = thread->frames;
    while (frame)
    {
        /* Remove IA__ prefix used in GLib, GTK and GDK. */
        remove_func_prefix(frame->function_name, "IA__gdk", strlen("IA__"));
        remove_func_prefix(frame->function_name, "IA__g_", strlen("IA__"));
        remove_func_prefix(frame->function_name, "IA__gtk", strlen("IA__"));

        /* Remove __GI_ (glibc internal) prefix. */
        remove_func_prefix(frame->function_name, "__GI_", strlen("__GI_"));

        frame = frame->next;
    }

    /* Unify some functions by renaming them.
     */
    frame = thread->frames;
    while (frame)
    {
        char *new_function_name =
            find_new_function_name_glibc(frame->function_name, frame->file_name);

        if (new_function_name)
        {
            free(frame->function_name);
            frame->function_name = new_function_name;
        }

        frame = frame->next;
    }

    /* Remove redundant frames from the thread.
     */
    frame = thread->frames;
    while (frame)
    {
        struct sr_core_frame *next_frame = frame->next;

        /* Remove frames which are not a cause of the crash. */
        bool removable =
            is_removable_dbus(frame->function_name, frame->file_name) ||
            is_removable_gdk(frame->function_name, frame->file_name) ||
            is_removable_glib(frame->function_name, frame->file_name) ||
            is_removable_glibc(frame->function_name, frame->file_name) ||
            is_removable_libstdcpp(frame->function_name, frame->file_name) ||
            is_removable_linux(frame->function_name, frame->file_name) ||
            is_removable_xorg(frame->function_name, frame->file_name) ||
            is_removable_jvm(frame->function_name, frame->file_name) ||
            is_removable_vim(frame->function_name, frame->file_name);

        bool removable_with_above =
            is_removable_glibc_with_above(frame->function_name, frame->file_name)  ||
            sr_core_thread_is_exit_frame(frame);

        if (removable_with_above)
        {
            bool success = sr_thread_remove_frames_above((struct sr_thread *)thread,
                                                         (struct sr_frame *)frame);
            assert(success);
        }

        if (removable || removable_with_above)
            sr_thread_remove_frame((struct sr_thread *)thread, (struct sr_frame *)frame);

        frame = next_frame;
    }

    /* If the first frame has address 0x0000 and its name is '??', it
     * is a dereferenced null, and we remove it. This frame is not
     * really invalid, but it affects stacktrace quality rating. See
     * Red Hat Bugzilla bug #639038.
     * @code
     * #0  0x0000000000000000 in ?? ()
     * No symbol table info available.
     * #1  0x0000000000422648 in main (argc=1, argv=0x7fffa57cf0d8) at totem.c:242
     *       error = 0x0
     *       totem = 0xdee070 [TotemObject]
     * @endcode
     */
    if (thread->frames &&
        thread->frames->address == 0x0000 &&
        !thread->frames->function_name)
    {
        sr_thread_remove_frame((struct sr_thread *)thread,
                               (struct sr_frame *)thread->frames);
    }

    /* If the last frame has address 0x0000 and its name is '??',
     * remove it. This frame is not really invalid, but it affects
     * stacktrace quality rating. See Red Hat Bugzilla bug #592523.
     * @code
     * #2  0x00007f4dcebbd62d in clone ()
     * at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112
     * No locals.
     * #3  0x0000000000000000 in ?? ()
     * @endcode
     */
    struct sr_core_frame *last = thread->frames;
    while (last && last->next)
        last = last->next;
    if (last &&
        last->address == 0x0000 &&
        !last->function_name)
    {
        sr_thread_remove_frame((struct sr_thread *)thread, (struct sr_frame *)last);
    }

    /* Merge recursively called functions into single frame */
    struct sr_core_frame *curr_frame = thread->frames;
    struct sr_core_frame *prev_frame = NULL;
    while (curr_frame)
    {
        if (prev_frame &&
            prev_frame->function_name &&
            0 == sr_strcmp0(prev_frame->function_name, curr_frame->function_name))
        {
            prev_frame->next = curr_frame->next;
            sr_core_frame_free(curr_frame);
            curr_frame = prev_frame->next;
            continue;
        }

        prev_frame = curr_frame;
        curr_frame = curr_frame->next;
    }

}
Пример #10
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;
}