char * sr_koops_stacktrace_get_reason(struct sr_koops_stacktrace *stacktrace) { char *func = "<unknown>"; char *result; struct sr_koops_stacktrace *copy = sr_koops_stacktrace_dup(stacktrace); sr_normalize_koops_stacktrace(copy); if (copy->frames && copy->frames->function_name) func = copy->frames->function_name; if (copy->frames && copy->frames->module_name) { result = sr_asprintf("Kernel oops in %s [%s]", func, copy->frames->module_name); } else result = sr_asprintf("Kernel oops in %s", func); sr_koops_stacktrace_free(copy); return result; }
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); /* save crash_function into dumpdir */ char *error_message = NULL; struct sr_stacktrace *stacktrace = sr_stacktrace_parse(SR_REPORT_KERNELOOPS, (const char *)second_line, &error_message); if (stacktrace) { sr_normalize_koops_stacktrace((struct sr_koops_stacktrace *)stacktrace); /* stacktrace is the same as thread, there is no need to check return value */ struct sr_thread *thread = sr_stacktrace_find_crash_thread(stacktrace); struct sr_koops_frame *frame = (struct sr_koops_frame *)sr_thread_frames(thread); if (frame && frame->function_name) dd_save_text(dd, FILENAME_CRASH_FUNCTION, frame->function_name); sr_stacktrace_free(stacktrace); } else { error_msg("Can't parse stacktrace: %s", error_message); free(error_message); } /* 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); }