static int append_short_backtrace(struct strbuf *result, problem_data_t *problem_data, size_t max_text_size, bool print_item_name) { const problem_item *item = problem_data_get_item_or_NULL(problem_data, FILENAME_BACKTRACE); if (!item) return 0; /* "I did not print anything" */ if (!(item->flags & CD_FLAG_TXT)) return 0; /* "I did not print anything" */ char *truncated = NULL; if (strlen(item->content) >= max_text_size) { struct sr_location location; sr_location_init(&location); /* sr_gdb_stacktrace_parse modifies the input parameter */ char *content = item->content; struct sr_gdb_stacktrace *backtrace = sr_gdb_stacktrace_parse((const char **)&content, &location); if (!backtrace) { log(_("Can't parse backtrace")); return 0; } /* Get optimized thread stack trace for 10 top most frames */ struct sr_gdb_thread *thread = sr_gdb_stacktrace_get_optimized_thread(backtrace, 10); sr_gdb_stacktrace_free(backtrace); if (!thread) { log(_("Can't find crash thread")); return 0; } /* Cannot be NULL, it dies on memory error */ struct sr_strbuf *bt = sr_strbuf_new(); sr_gdb_thread_append_to_str(thread, bt, true); sr_gdb_thread_free(thread); truncated = sr_strbuf_free_nobuf(bt); } append_text(result, /*item_name:*/ truncated ? "truncated_backtrace" : FILENAME_BACKTRACE, /*content:*/ truncated ? truncated : item->content, print_item_name ); free(truncated); return 1; }
struct sr_distances * sr_threads_compare(struct sr_thread **threads, int m, int n, enum sr_distance_type dist_type) { struct sr_distances *distances; int i, j; float dist; distances = sr_distances_new(m, n); if (n <= 0) return distances; /* Check that all threads are of the same type */ enum sr_report_type type, prev_type = threads[0]->type; for (i = 0; i < n; i++) { type = threads[i]->type; assert(prev_type == type); prev_type = type; } for (i = 0; i < m; i++) { for (j = i + 1; j < n; j++) { /* XXX: GDB crashes have a special normalization step for * clustering. If there's something similar for other types, we can * generalize it -- meanwhile there's a separate case for GDB here */ if (type == SR_REPORT_GDB) { struct sr_gdb_thread *thread1 = (struct sr_gdb_thread*)threads[i], *thread2 = (struct sr_gdb_thread*)threads[j]; int ok = 0, all = 0; sr_gdb_thread_quality_counts(thread1, &ok, &all); sr_gdb_thread_quality_counts(thread2, &ok, &all); if (ok != all) { /* There are some unknown function names, try to pair them, but * the threads need to be copied first. */ thread1 = sr_gdb_thread_dup(thread1, false); thread2 = sr_gdb_thread_dup(thread2, false); sr_normalize_gdb_paired_unknown_function_names(thread1, thread2); } dist = sr_distance(dist_type, (struct sr_thread*)thread1, (struct sr_thread*)thread2); if (ok != all) { sr_gdb_thread_free(thread1); sr_gdb_thread_free(thread2); } } else dist = sr_distance(dist_type, threads[i], threads[j]); distances->distances[get_distance_position(distances, i, j)] = dist; } } return distances; }