diff options
author | Karel Klic <kklic@redhat.com> | 2011-03-26 15:01:47 +0100 |
---|---|---|
committer | Jiri Moskovcak <jmoskovc@redhat.com> | 2011-03-26 15:21:15 +0100 |
commit | dd11716e5c6c3e2589dfc6440e131a06d7eecd3a (patch) | |
tree | fc67c49e94f6c8afe71d22b93abee94af61e031c /src | |
parent | 508e1d6585a37483cc5166824840fd6be776869d (diff) | |
download | abrt-dd11716e5c6c3e2589dfc6440e131a06d7eecd3a.tar.gz abrt-dd11716e5c6c3e2589dfc6440e131a06d7eecd3a.tar.xz abrt-dd11716e5c6c3e2589dfc6440e131a06d7eecd3a.zip |
Analyze backtraces from retrace server
Hi,
the attached patch splits a part of abrt-action-generate-backtrace to a
new tool abrt-action-analyze-backtrace, which is used by both LocalGDB
and RetraceServer analyzers.
Then new abrt-action-analyze-backtrace tool reads backtrace and
generates duplication hash, detects crash function, and provides
backtrace rating. These steps haven't been performed for remotely
analyzed crashes so far.
Karel
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/Makefile.am | 20 | ||||
-rw-r--r-- | src/plugins/abrt-action-analyze-backtrace.c | 190 | ||||
-rw-r--r-- | src/plugins/abrt-action-generate-backtrace.c | 131 | ||||
-rw-r--r-- | src/plugins/ccpp_events.conf | 6 |
4 files changed, 222 insertions, 125 deletions
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 8dd618e6..5344cdb4 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -11,6 +11,7 @@ bin_PROGRAMS = \ abrt-action-analyze-oops \ abrt-action-trim-files \ abrt-action-generate-backtrace \ + abrt-action-analyze-backtrace \ abrt-action-bugzilla \ abrt-action-rhtsupport \ abrt-action-kerneloops \ @@ -179,6 +180,25 @@ abrt_action_generate_backtrace_CPPFLAGS = \ -D_GNU_SOURCE \ -Wall -Wwrite-strings -Werror abrt_action_generate_backtrace_LDADD = \ + ../lib/libreport.la + +abrt_action_analyze_backtrace_SOURCES = \ + abrt-action-analyze-backtrace.c +abrt_action_analyze_backtrace_CPPFLAGS = \ + -I$(srcdir)/../include/report -I$(srcdir)/../include \ + -I$(srcdir)/../lib \ + -DBIN_DIR=\"$(bindir)\" \ + -DVAR_RUN=\"$(VAR_RUN)\" \ + -DCONF_DIR=\"$(CONF_DIR)\" \ + -DLOCALSTATEDIR='"$(localstatedir)"' \ + -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \ + -DDEBUG_INFO_DIR=\"$(DEBUG_INFO_DIR)\" \ + -DPLUGINS_LIB_DIR=\"$(PLUGINS_LIB_DIR)\" \ + -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \ + $(GLIB_CFLAGS) \ + -D_GNU_SOURCE \ + -Wall -Wwrite-strings -Werror +abrt_action_analyze_backtrace_LDADD = \ ../lib/libreport.la \ ../btparser/libbtparser.la diff --git a/src/plugins/abrt-action-analyze-backtrace.c b/src/plugins/abrt-action-analyze-backtrace.c new file mode 100644 index 00000000..e65b1781 --- /dev/null +++ b/src/plugins/abrt-action-analyze-backtrace.c @@ -0,0 +1,190 @@ +/* + Copyright (C) 2010, 2011 Red Hat, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "abrtlib.h" +#include "../btparser/backtrace.h" +#include "../btparser/frame.h" +#include "../btparser/location.h" +#include "parse_options.h" + +#define PROGNAME "abrt-action-generate-backtrace" + +static const char *dump_dir_name = "."; + + +static void create_hash(char hash_str[SHA1_RESULT_LEN*2 + 1], const char *pInput) +{ + unsigned len; + unsigned char hash2[SHA1_RESULT_LEN]; + sha1_ctx_t sha1ctx; + + sha1_begin(&sha1ctx); + sha1_hash(pInput, strlen(pInput), &sha1ctx); + sha1_end(hash2, &sha1ctx); + len = SHA1_RESULT_LEN; + + char *d = hash_str; + unsigned char *s = hash2; + while (len) + { + *d++ = "0123456789abcdef"[*s >> 4]; + *d++ = "0123456789abcdef"[*s & 0xf]; + s++; + len--; + } + *d = '\0'; + //log("hash2:%s str:'%s'", hash_str, pInput); +} + +int main(int argc, char **argv) +{ + char *env_verbose = getenv("ABRT_VERBOSE"); + if (env_verbose) + g_verbose = atoi(env_verbose); + + /* Can't keep these strings/structs static: _() doesn't support that */ + const char *program_usage_string = _( + PROGNAME" [options] -d DIR\n" + "\n" + "Analyzes C/C++ backtrace, generates duplication hash, backtrace rating, and identifies crash function in dump 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", _("Dump directory")), + OPT_END() + }; + /*unsigned opts =*/ parse_opts(argc, argv, program_options, program_usage_string); + + putenv(xasprintf("ABRT_VERBOSE=%u", g_verbose)); + + char *pfx = getenv("ABRT_PROG_PREFIX"); + if (pfx && string_to_bool(pfx)) + msg_prefix = PROGNAME; + + struct dump_dir *dd = dd_opendir(dump_dir_name, /*flags:*/ 0); + if (!dd) + return 1; + + char *package = dd_load_text(dd, FILENAME_PACKAGE); + char *executable = dd_load_text(dd, FILENAME_EXECUTABLE); + + /* Read backtrace */ + /* NB: get_backtrace() closes dd */ + char *backtrace_str = dd_load_text(dd, FILENAME_BACKTRACE); + if (!backtrace_str) + { + backtrace_str = xstrdup(""); + log("Backtrace file is missing"); + } + + /* Compute backtrace hash */ + struct btp_location location; + btp_location_init(&location); + char *backtrace_str_ptr = backtrace_str; + struct btp_backtrace *backtrace = btp_backtrace_parse(&backtrace_str_ptr, &location); + free(backtrace_str); + + /* Store backtrace hash */ + if (!backtrace) + { + /* + * The parser failed. Compute the UUID from the executable + * and package only. This is not supposed to happen often. + */ + VERB1 log(_("Backtrace parsing failed for %s"), dump_dir_name); + VERB1 log("%d:%d: %s", location.line, location.column, location.message); + struct strbuf *emptybt = strbuf_new(); + strbuf_prepend_str(emptybt, executable); + strbuf_prepend_str(emptybt, package); + + char hash_str[SHA1_RESULT_LEN*2 + 1]; + create_hash(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(package); + free(executable); + 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. */ + char *str_hash_core = btp_backtrace_get_duplication_hash(backtrace); + struct strbuf *str_hash = strbuf_new(); + strbuf_append_str(str_hash, package); + strbuf_append_str(str_hash, executable); + strbuf_append_str(str_hash, str_hash_core); + + char hash_str[SHA1_RESULT_LEN*2 + 1]; + create_hash(hash_str, str_hash->buf); + + dd_save_text(dd, FILENAME_DUPHASH, hash_str); + strbuf_free(str_hash); + free(str_hash_core); + + /* Compute the backtrace rating. */ + float quality = btp_backtrace_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 btp_frame *crash_frame = btp_backtrace_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); + } + btp_frame_free(crash_frame); + } + btp_backtrace_free(backtrace); + dd_close(dd); + + free(executable); + free(package); + + return 0; +} diff --git a/src/plugins/abrt-action-generate-backtrace.c b/src/plugins/abrt-action-generate-backtrace.c index 0c2d9a0a..5afe6e43 100644 --- a/src/plugins/abrt-action-generate-backtrace.c +++ b/src/plugins/abrt-action-generate-backtrace.c @@ -1,6 +1,6 @@ /* Copyright (C) 2009 Zdenek Prikryl (zprikryl@redhat.com) - Copyright (C) 2009 RedHat inc. + Copyright (C) 2009 Red Hat, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,30 +33,6 @@ static const char *debuginfo_dirs = DEBUGINFO_CACHE_DIR; static int exec_timeout_sec = 240; -static void create_hash(char hash_str[SHA1_RESULT_LEN*2 + 1], const char *pInput) -{ - unsigned len; - unsigned char hash2[SHA1_RESULT_LEN]; - sha1_ctx_t sha1ctx; - - sha1_begin(&sha1ctx); - sha1_hash(pInput, strlen(pInput), &sha1ctx); - sha1_end(hash2, &sha1ctx); - len = SHA1_RESULT_LEN; - - char *d = hash_str; - unsigned char *s = hash2; - while (len) - { - *d++ = "0123456789abcdef"[*s >> 4]; - *d++ = "0123456789abcdef"[*s & 0xf]; - s++; - len--; - } - *d = '\0'; - //log("hash2:%s str:'%s'", hash_str, pInput); -} - /** * * @param[out] status See `man 2 wait` for status information. @@ -299,119 +275,26 @@ int main(int argc, char **argv) if (!dd) return 1; - char *package = dd_load_text(dd, FILENAME_PACKAGE); - char *executable = dd_load_text(dd, FILENAME_EXECUTABLE); - /* Create gdb backtrace */ /* NB: get_backtrace() closes dd */ - char *backtrace_str = get_backtrace(dd); - if (!backtrace_str) + char *backtrace = get_backtrace(dd); + if (!backtrace) { - backtrace_str = xstrdup(""); + backtrace = xstrdup(""); log("get_backtrace() returns NULL, broken core/gdb?"); } - /* Compute backtrace hash */ - struct btp_location location; - btp_location_init(&location); - char *backtrace_str_ptr = backtrace_str; - struct btp_backtrace *backtrace = btp_backtrace_parse(&backtrace_str_ptr, &location); - /* Store gdb backtrace */ dd = dd_opendir(dump_dir_name, /*flags:*/ 0); if (!dd) return 1; - dd_save_text(dd, FILENAME_BACKTRACE, backtrace_str); + dd_save_text(dd, FILENAME_BACKTRACE, backtrace); /* Don't be completely silent. gdb run takes a few seconds, * it is useful to let user know it (maybe) worked. */ - log(_("Backtrace is generated and saved, %u bytes"), (int)strlen(backtrace_str)); - free(backtrace_str); - - /* Store backtrace hash */ - - if (!backtrace) - { - /* - * The parser failed. Compute the UUID from the executable - * and package only. This is not supposed to happen often. - */ - VERB1 log(_("Backtrace parsing failed for %s"), dump_dir_name); - VERB1 log("%d:%d: %s", location.line, location.column, location.message); - struct strbuf *emptybt = strbuf_new(); - strbuf_prepend_str(emptybt, executable); - strbuf_prepend_str(emptybt, package); - - char hash_str[SHA1_RESULT_LEN*2 + 1]; - create_hash(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(package); - free(executable); - 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. */ - char *str_hash_core = btp_backtrace_get_duplication_hash(backtrace); - struct strbuf *str_hash = strbuf_new(); - strbuf_append_str(str_hash, package); - strbuf_append_str(str_hash, executable); - strbuf_append_str(str_hash, str_hash_core); - - char hash_str[SHA1_RESULT_LEN*2 + 1]; - create_hash(hash_str, str_hash->buf); - - dd_save_text(dd, FILENAME_DUPHASH, hash_str); - strbuf_free(str_hash); - free(str_hash_core); - - /* Compute the backtrace rating. */ - float quality = btp_backtrace_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 btp_frame *crash_frame = btp_backtrace_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); - } - btp_frame_free(crash_frame); - } - btp_backtrace_free(backtrace); - dd_close(dd); - - free(executable); - free(package); + log(_("Backtrace is generated and saved, %u bytes"), (int)strlen(backtrace)); + free(backtrace); return 0; } diff --git a/src/plugins/ccpp_events.conf b/src/plugins/ccpp_events.conf index 0698e655..8a5f377e 100644 --- a/src/plugins/ccpp_events.conf +++ b/src/plugins/ccpp_events.conf @@ -7,13 +7,17 @@ EVENT=analyze_LocalGDB analyzer=CCpp backtrace= abrt-action-trim-files -f 4 # or was this ability lost with move to python installer? EVENT=analyze_LocalGDB analyzer=CCpp backtrace= abrt-action-install-debuginfo --core="$DUMP_DIR/coredump" EVENT=analyze_LocalGDB analyzer=CCpp backtrace= abrt-action-generate-backtrace -EVENT=analyze_RetraceServer analyzer=CCpp backtrace= abrt-retrace-client batch -k --dir "$DUMP_DIR" +EVENT=analyze_LocalGDB analyzer=CCpp backtrace= abrt-action-analyze-backtrace +EVENT=analyze_RetraceServer analyzer=CCpp backtrace= abrt-retrace-client batch -k --dir "$DUMP_DIR" +EVENT=analyze_RetraceServer analyzer=CCpp backtrace= abrt-action-analyze-backtrace # Same as "analyze", but executed when user requests "refresh" in GUI # It doesn't check that backtrace is empty: EVENT=reanalyze_LocalGDB analyzer=CCpp abrt-action-trim-files -f 4096m:/var/cache/abrt-di EVENT=reanalyze_LocalGDB analyzer=CCpp abrt-action-install-debuginfo --core="$DUMP_DIR/coredump" EVENT=reanalyze_LocalGDB analyzer=CCpp abrt-action-generate-backtrace +EVENT=reanalyze_LocalGDB analyzer=CCpp abrt-action-analyze-backtrace EVENT=reanalyze_RetraceServer analyzer=CCpp abrt-retrace-client batch -k --dir "$DUMP_DIR" +EVENT=reanalyze_RetraceServer analyzer=CCpp abrt-action-analyze-backtrace EVENT=report_Bugzilla analyzer=CCpp abrt-action-bugzilla -c /etc/abrt/plugins/Bugzilla.conf |