summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarel Klic <kklic@redhat.com>2011-03-26 15:01:47 +0100
committerJiri Moskovcak <jmoskovc@redhat.com>2011-03-26 15:21:15 +0100
commitdd11716e5c6c3e2589dfc6440e131a06d7eecd3a (patch)
treefc67c49e94f6c8afe71d22b93abee94af61e031c
parent508e1d6585a37483cc5166824840fd6be776869d (diff)
downloadabrt-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
-rw-r--r--abrt.spec1
-rw-r--r--src/plugins/Makefile.am20
-rw-r--r--src/plugins/abrt-action-analyze-backtrace.c190
-rw-r--r--src/plugins/abrt-action-generate-backtrace.c131
-rw-r--r--src/plugins/ccpp_events.conf6
5 files changed, 223 insertions, 125 deletions
diff --git a/abrt.spec b/abrt.spec
index ab6610cb..8758ab82 100644
--- a/abrt.spec
+++ b/abrt.spec
@@ -487,6 +487,7 @@ fi
%attr(2755, abrt, abrt) %{_bindir}/abrt-action-install-debuginfo
%{_bindir}/abrt-action-install-debuginfo.py*
%{_bindir}/abrt-action-generate-backtrace
+%{_bindir}/abrt-action-analyze-backtrace
%{_bindir}/abrt-action-list-dsos.py*
%{_sysconfdir}/%{name}/events.d/ccpp_events.conf
%{_sysconfdir}/%{name}/events/analyze_LocalGDB.xml
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