static int core_backtrace_is_duplicate(struct sr_stacktrace *bt1, const char *bt2_text) { struct sr_thread *thread1 = sr_stacktrace_find_crash_thread(bt1); if (thread1 == NULL) { log_notice("New stacktrace has no crash thread, disabling core stacktrace deduplicate"); dup_corebt_fini(); return 0; } int result; char *error_message; struct sr_stacktrace *bt2 = sr_stacktrace_parse(sr_abrt_type_from_type(type), bt2_text, &error_message); if (bt2 == NULL) { log_notice("Failed to parse backtrace, considering it not duplicate: %s", error_message); free(error_message); return 0; } struct sr_thread *thread2 = sr_stacktrace_find_crash_thread(bt2); if (thread2 == NULL) { log_notice("Failed to get crash thread, considering it not duplicate"); result = 0; goto end; } int length2 = sr_thread_frame_count(thread2); if (length2 <= 0) { log_notice("Core backtrace has zero frames, considering it not duplicate"); result = 0; goto end; } float distance = sr_distance(SR_DISTANCE_DAMERAU_LEVENSHTEIN, thread1, thread2); log_info("Distance between backtraces: %f", distance); result = (distance <= BACKTRACE_DUP_THRESHOLD); end: sr_stacktrace_free(bt2); return result; }
int koops_hash_str_ext(char result[SHA1_RESULT_LEN*2 + 1], const char *oops_buf, int frame_count, int duphash_flags) { char *hash_str = NULL, *error = NULL; int bad = 0; struct sr_stacktrace *stacktrace = sr_stacktrace_parse(SR_REPORT_KERNELOOPS, oops_buf, &error); if (!stacktrace) { log_debug("Failed to parse koops: %s", error); free(error); bad = 1; goto end; } struct sr_thread *thread = sr_stacktrace_find_crash_thread(stacktrace); if (!thread) { log_debug("Failed to find crash thread"); bad = 1; goto end; } if (g_verbose >= 3) { hash_str = sr_thread_get_duphash(thread, frame_count, NULL, duphash_flags|SR_DUPHASH_NOHASH); if (hash_str) log("Generating duphash: '%s'", hash_str); else log("Nothing useful for duphash"); free(hash_str); } hash_str = sr_thread_get_duphash(thread, frame_count, NULL, duphash_flags); if (hash_str) { strncpy(result, hash_str, SHA1_RESULT_LEN*2); result[SHA1_RESULT_LEN*2] = '\0'; free(hash_str); } else bad = 1; end: sr_stacktrace_free(stacktrace); return bad; }
static void dup_corebt_fini(void) { sr_stacktrace_free(corebt); corebt = NULL; }
void abrt_oops_save_data_in_dump_dir(struct dump_dir *dd, char *oops, const char *proc_modules) { char *first_line = oops; char *second_line = (char*)strchr(first_line, '\n'); /* never NULL */ *second_line++ = '\0'; if (first_line[0]) dd_save_text(dd, FILENAME_KERNEL, first_line); dd_save_text(dd, FILENAME_BACKTRACE, second_line); /* check if trace doesn't have line: 'Your BIOS is broken' */ if (strstr(second_line, "Your BIOS is broken")) dd_save_text(dd, FILENAME_NOT_REPORTABLE, _("A kernel problem occurred because of broken BIOS. " "Unfortunately, such problems are not fixable by kernel maintainers.")); /* check if trace doesn't have line: 'Your hardware is unsupported' */ else if (strstr(second_line, "Your hardware is unsupported")) dd_save_text(dd, FILENAME_NOT_REPORTABLE, _("A kernel problem occurred, but your hardware is unsupported, " "therefore kernel maintainers are unable to fix this problem.")); else { char *tainted_short = kernel_tainted_short(second_line); if (tainted_short) { log_notice("Kernel is tainted '%s'", tainted_short); dd_save_text(dd, FILENAME_TAINTED_SHORT, tainted_short); char *tnt_long = kernel_tainted_long(tainted_short); dd_save_text(dd, FILENAME_TAINTED_LONG, tnt_long); free(tnt_long); struct strbuf *reason = strbuf_new(); const char *fmt = _("A kernel problem occurred, but your kernel has been " "tainted (flags:%s). Kernel maintainers are unable to " "diagnose tainted reports."); strbuf_append_strf(reason, fmt, tainted_short); char *modlist = !proc_modules ? NULL : abrt_oops_list_of_tainted_modules(proc_modules); if (modlist) { strbuf_append_strf(reason, _(" Tainted modules: %s."), modlist); free(modlist); } dd_save_text(dd, FILENAME_NOT_REPORTABLE, reason->buf); strbuf_free(reason); free(tainted_short); } } // TODO: add "Kernel oops: " prefix, so that all oopses have recognizable FILENAME_REASON? // kernel oops 1st line may look quite puzzling otherwise... char *reason_pretty = NULL; char *error = NULL; struct sr_stacktrace *trace = sr_stacktrace_parse(SR_REPORT_KERNELOOPS, second_line, &error); if (trace) { reason_pretty = sr_stacktrace_get_reason(trace); sr_stacktrace_free(trace); } else free(error); if (reason_pretty) { dd_save_text(dd, FILENAME_REASON, reason_pretty); free(reason_pretty); } else dd_save_text(dd, FILENAME_REASON, second_line); }
static int core_backtrace_is_duplicate(struct sr_stacktrace *bt1, const char *bt2_text) { struct sr_thread *thread1 = sr_stacktrace_find_crash_thread(bt1); if (thread1 == NULL) { log_notice("New stacktrace has no crash thread, disabling core stacktrace deduplicate"); dup_corebt_fini(); return 0; } int result; char *error_message; struct sr_stacktrace *bt2 = sr_stacktrace_parse(sr_abrt_type_from_analyzer(analyzer), bt2_text, &error_message); if (bt2 == NULL) { log_notice("Failed to parse backtrace, considering it not duplicate: %s", error_message); free(error_message); return 0; } struct sr_thread *thread2 = sr_stacktrace_find_crash_thread(bt2); if (thread2 == NULL) { log_notice("Failed to get crash thread, considering it not duplicate"); result = 0; goto end; } int length2 = sr_thread_frame_count(thread2); if (length2 <= 0) { log_notice("Core backtrace has zero frames, considering it not duplicate"); result = 0; goto end; } /* This is an ugly workaround for https://github.com/abrt/btparser/issues/6 */ /* int length1 = sr_core_thread_get_frame_count(thread1); if (length1 <= 2 || length2 <= 2) { log_notice("Backtraces too short, falling back on full comparison"); result = (sr_core_thread_cmp(thread1, thread2) == 0); goto end; } */ float distance = sr_distance(SR_DISTANCE_DAMERAU_LEVENSHTEIN, thread1, thread2); log_info("Distance between backtraces: %f", distance); result = (distance <= BACKTRACE_DUP_THRESHOLD); end: sr_stacktrace_free(bt2); return result; }
static int append_short_backtrace(struct strbuf *result, problem_data_t *problem_data, bool print_item_name, problem_report_settings_t *settings) { const problem_item *backtrace_item = problem_data_get_item_or_NULL(problem_data, FILENAME_BACKTRACE); const problem_item *core_stacktrace_item = NULL; if (!backtrace_item || !(backtrace_item->flags & CD_FLAG_TXT)) { backtrace_item = NULL; core_stacktrace_item = problem_data_get_item_or_NULL(problem_data, FILENAME_CORE_BACKTRACE); if (!core_stacktrace_item || !(core_stacktrace_item->flags & CD_FLAG_TXT)) return 0; } char *truncated = NULL; if (core_stacktrace_item || strlen(backtrace_item->content) >= settings->prs_shortbt_max_text_size) { log_debug("'backtrace' exceeds the text file size, going to append its short version"); char *error_msg = NULL; const char *type = problem_data_get_content_or_NULL(problem_data, FILENAME_TYPE); if (!type) { log_debug("Problem data does not contain '"FILENAME_TYPE"' file"); return 0; } /* For CCpp crashes, use the GDB-produced backtrace which should be * available by now. sr_abrt_type_from_type returns SR_REPORT_CORE * by default for CCpp crashes. */ enum sr_report_type report_type = sr_abrt_type_from_type(type); if (backtrace_item && strcmp(type, "CCpp") == 0) { log_debug("Successfully identified 'CCpp' abrt type"); report_type = SR_REPORT_GDB; } const char *content = backtrace_item ? backtrace_item->content : core_stacktrace_item->content; struct sr_stacktrace *backtrace = sr_stacktrace_parse(report_type, content, &error_msg); if (!backtrace) { log(_("Can't parse backtrace: %s"), error_msg); free(error_msg); return 0; } /* normalize */ struct sr_thread *thread = sr_stacktrace_find_crash_thread(backtrace); sr_thread_normalize(thread); /* Get optimized thread stack trace for max_frames top most frames */ truncated = sr_stacktrace_to_short_text(backtrace, settings->prs_shortbt_max_frames); sr_stacktrace_free(backtrace); if (!truncated) { log(_("Can't generate stacktrace description (no crash thread?)")); return 0; } } else { log_debug("'backtrace' is small enough to be included as is"); } /* full item content */ append_text(result, /*item_name:*/ truncated ? "truncated_backtrace" : FILENAME_BACKTRACE, /*content:*/ truncated ? truncated : backtrace_item->content, print_item_name ); free(truncated); return 1; }