/** * Prints a list containing "crashes" to stdout. * @param only_unreported * Do not skip entries marked as already reported. */ static bool print_crash_list(vector_of_problem_data_t *crash_list, int detailed, int only_not_reported, long since, long until, int text_size) { bool output = false; unsigned i; for (i = 0; i < crash_list->len; ++i) { problem_data_t *crash = get_problem_data(crash_list, i); if (only_not_reported) { if (problem_data_get_content_or_NULL(crash, FILENAME_REPORTED_TO)) continue; } if (since || until) { char *s = problem_data_get_content_or_NULL(crash, FILENAME_LAST_OCCURRENCE); long val = s ? atol(s) : 0; if (since && val < since) continue; if (until && val > until) continue; } char hash_str[SHA1_RESULT_LEN*2 + 1]; struct problem_item *item = g_hash_table_lookup(crash, CD_DUMPDIR); if (item) printf("id %s\n", str_to_sha1str(hash_str, item->content)); print_crash(crash, detailed, text_size); if (i != crash_list->len - 1) printf("\n"); output = true; } return output; }
static int find_dir_by_hash(struct dump_dir *dd, void *arg) { struct name_resolution_param *param = arg; char hash_str[SHA1_RESULT_LEN*2 + 1]; str_to_sha1str(hash_str, dd->dd_dirname); if (strncasecmp(param->shortcut, hash_str, param->strlen_shortcut) == 0) { if (param->found_name) error_msg_and_die(_("'%s' identifies more than one problem directory"), param->shortcut); param->found_name = xstrdup(dd->dd_dirname); } return 0; }
char *find_problem_by_hash(const char *hash, GList *problems) { unsigned hash_len = strlen(hash); if (!isxdigit_str(hash) || hash_len < 5) return NULL; char *found_name = NULL; for (GList *iter = problems; iter; iter = g_list_next(iter)) { char hash_str[SHA1_RESULT_LEN*2 + 1]; str_to_sha1str(hash_str, (const char *)(iter->data)); if (strncasecmp(hash, hash_str, hash_len) == 0) { if (found_name) error_msg_and_die(_("'%s' identifies more than one problem directory"), hash); found_name = xstrdup((const char *)(iter->data)); } } return found_name; }
int main(int argc, char **argv) { /* I18n */ setlocale(LC_ALL, ""); #if ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif abrt_init(argv); /* Can't keep these strings/structs static: _() doesn't support that */ const char *program_usage_string = _( "& [options] -d DIR\n" "\n" "Analyzes C/C++ backtrace, generates duplication hash, backtrace rating,\n" "and identifies crash function in problem directory DIR" ); enum { OPT_v = 1 << 0, OPT_d = 1 << 1 }; /* Keep enum above and order of options below in sync! */ struct options program_options[] = { OPT__VERBOSE(&g_verbose), OPT_STRING('d', NULL, &dump_dir_name, "DIR", _("Problem directory")), OPT_END() }; /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string); export_abrt_envvars(0); struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); if (!dd) return 1; char *component = dd_load_text(dd, FILENAME_COMPONENT); /* Read backtrace */ char *backtrace_str = dd_load_text_ext(dd, FILENAME_BACKTRACE, DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE); if (!backtrace_str) { dd_close(dd); return 1; } /* Compute backtrace hash */ struct sr_location location; sr_location_init(&location); const char *backtrace_str_ptr = backtrace_str; struct sr_gdb_stacktrace *backtrace = sr_gdb_stacktrace_parse(&backtrace_str_ptr, &location); free(backtrace_str); /* Store backtrace hash */ if (!backtrace) { /* * The parser failed. Compute the duphash from the executable * instead of a backtrace. * and component only. This is not supposed to happen often. */ log(_("Backtrace parsing failed for %s"), dump_dir_name); log("%d:%d: %s", location.line, location.column, location.message); struct strbuf *emptybt = strbuf_new(); char *executable = dd_load_text(dd, FILENAME_EXECUTABLE); strbuf_prepend_str(emptybt, executable); free(executable); strbuf_prepend_str(emptybt, component); log_debug("Generating duphash: %s", emptybt->buf); char hash_str[SHA1_RESULT_LEN*2 + 1]; str_to_sha1str(hash_str, emptybt->buf); dd_save_text(dd, FILENAME_DUPHASH, hash_str); /* * Other parts of ABRT assume that if no rating is available, * it is ok to allow reporting of the bug. To be sure no bad * backtrace is reported, rate the backtrace with the lowest * rating. */ dd_save_text(dd, FILENAME_RATING, "0"); strbuf_free(emptybt); free(component); dd_close(dd); /* Report success even if the parser failed, as the backtrace * has been created and rated. The failure is caused by a flaw * in the parser, not in the backtrace. */ return 0; } /* Compute duplication hash. */ struct sr_thread *crash_thread = (struct sr_thread *)sr_gdb_stacktrace_find_crash_thread(backtrace); if (crash_thread) { char *hash_str; if (g_verbose >= 3) { hash_str = sr_thread_get_duphash(crash_thread, 3, component, SR_DUPHASH_NOHASH); log("Generating duphash: %s", hash_str); free(hash_str); } hash_str = sr_thread_get_duphash(crash_thread, 3, component, SR_DUPHASH_NORMAL); dd_save_text(dd, FILENAME_DUPHASH, hash_str); free(hash_str); } else log(_("Crash thread not found")); /* Compute the backtrace rating. */ float quality = sr_gdb_stacktrace_quality_complex(backtrace); const char *rating; if (quality < 0.6f) rating = "0"; else if (quality < 0.7f) rating = "1"; else if (quality < 0.8f) rating = "2"; else if (quality < 0.9f) rating = "3"; else rating = "4"; dd_save_text(dd, FILENAME_RATING, rating); /* Get the function name from the crash frame. */ struct sr_gdb_frame *crash_frame = sr_gdb_stacktrace_get_crash_frame(backtrace); if (crash_frame) { if (crash_frame->function_name && 0 != strcmp(crash_frame->function_name, "??")) { dd_save_text(dd, FILENAME_CRASH_FUNCTION, crash_frame->function_name); } sr_gdb_frame_free(crash_frame); } sr_gdb_stacktrace_free(backtrace); dd_close(dd); free(component); return 0; }
int main(int argc, char **argv) { /* I18n */ setlocale(LC_ALL, ""); #if ENABLE_NLS bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #endif abrt_init(argv); const char *dump_dir_name = "."; /* Can't keep these strings/structs static: _() doesn't support that */ const char *program_usage_string = _( "& [-v] -d DIR\n" "\n" "Calculates and saves UUID of coredump in problem directory DIR" ); enum { OPT_v = 1 << 0, OPT_d = 1 << 1, }; /* Keep enum above and order of options below in sync! */ struct options program_options[] = { OPT__VERBOSE(&g_verbose), OPT_STRING('d', NULL, &dump_dir_name, "DIR", _("Problem directory")), OPT_END() }; /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string); export_abrt_envvars(0); char *unstrip_n_output = NULL; char *coredump_path = xasprintf("%s/"FILENAME_COREDUMP, dump_dir_name); if (access(coredump_path, R_OK) == 0) unstrip_n_output = run_unstrip_n(dump_dir_name, /*timeout_sec:*/ 30); free(coredump_path); if (unstrip_n_output) { /* Run unstrip -n and trim its output, leaving only sizes and build ids */ /* modifies unstrip_n_output in-place: */ trim_unstrip_output(unstrip_n_output, unstrip_n_output); } else { /* bad dump_dir_name, can't run unstrip, etc... * or maybe missing coredump - try generating it from core_backtrace */ unstrip_n_output = build_ids_from_core_backtrace(dump_dir_name); } /* Hash package + executable + unstrip_n_output and save it as UUID */ struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); if (!dd) return 1; char *executable = dd_load_text(dd, FILENAME_EXECUTABLE); /* FILENAME_PACKAGE may be missing if ProcessUnpackaged = yes... */ char *package = dd_load_text_ext(dd, FILENAME_PACKAGE, DD_FAIL_QUIETLY_ENOENT); /* Package variable has "firefox-3.5.6-1.fc11[.1]" format */ /* Remove distro suffix and maybe least significant version number */ char *p = package; while (*p) { if (*p == '.' && (p[1] < '0' || p[1] > '9')) { /* We found "XXXX.nondigitXXXX", trim this part */ *p = '\0'; break; } p++; } char *first_dot = strchr(package, '.'); if (first_dot) { char *last_dot = strrchr(first_dot, '.'); if (last_dot != first_dot) { /* There are more than one dot: "1.2.3" * Strip last part, we don't want to distinquish crashes * in packages which differ only by minor release number. */ *last_dot = '\0'; } } char *string_to_hash = xasprintf("%s%s%s", package, executable, unstrip_n_output); /*free(package);*/ /*free(executable);*/ /*free(unstrip_n_output);*/ log_debug("String to hash: %s", string_to_hash); char hash_str[SHA1_RESULT_LEN*2 + 1]; str_to_sha1str(hash_str, string_to_hash); dd_save_text(dd, FILENAME_UUID, hash_str); dd_close(dd); return 0; }