>From 9cb9c5d961bcb02727f2c2992b3bceef72abc361 Mon Sep 17 00:00:00 2001
From: Karel Klic <kklic@redhat.com>
Date: Thu, 23 Sep 2010 17:50:38 +0200
Subject: [PATCH 2/2] Integrate the btparser library into ABRT.

---
 Makefile.am                                 |    2 +-
 configure.ac                                |    3 +-
 lib/plugins/CCpp.cpp                        |  136 ++------------------------
 lib/plugins/Makefile.am                     |    1 -
 src/daemon/Makefile.am                      |    3 +-
 src/daemon/abrt-action-generate-backtrace.c |  143 ++++++++++++---------------
 6 files changed, 76 insertions(+), 212 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 6303e73..09d0054 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
 ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = lib src inc po icons
+SUBDIRS = btparser lib src inc po icons
 
 DISTCHECK_CONFIGURE_FLAGS = \
         --with-systemdsystemunitdir=$$dc_install_base/$(systemdsystemunitdir)
diff --git a/configure.ac b/configure.ac
index db86865..64995df 100644
--- a/configure.ac
+++ b/configure.ac
@@ -47,7 +47,7 @@ PKG_CHECK_MODULES([LIBNOTIFY], [libnotify])
 #PKG_CHECK_MODULES([NSS], [nss])
 PKG_CHECK_MODULES([XMLRPC], [xmlrpc])
 PKG_CHECK_MODULES([XMLRPC_CLIENT], [xmlrpc_client])
-PKG_CHECK_MODULES([POLKIT],[polkit-gobject-1])
+PKG_CHECK_MODULES([POLKIT], [polkit-gobject-1])
 
 PKG_PROG_PKG_CONFIG
 AC_ARG_WITH([systemdsystemunitdir],
@@ -123,4 +123,5 @@ AC_CONFIG_FILES([
 	icons/Makefile
 ])
 
+AC_CONFIG_SUBDIRS([btparser])
 AC_OUTPUT
diff --git a/lib/plugins/CCpp.cpp b/lib/plugins/CCpp.cpp
index 041c85b..b5f7ecb 100644
--- a/lib/plugins/CCpp.cpp
+++ b/lib/plugins/CCpp.cpp
@@ -25,7 +25,6 @@
 #include "abrt_exception.h"
 #include "comm_layer_inner.h"
 #include "Polkit.h"
-#include "backtrace.h"
 
 using namespace std;
 
@@ -457,137 +456,20 @@ string CAnalyzerCCpp::GetGlobalUUID(const char *pDebugDumpDir)
 {
     struct dump_dir *dd = dd_init();
     if (!dd_opendir(dd, pDebugDumpDir, DD_CLOSE_ON_OPEN_ERR))
-        return string("");
+        return "";
 
-    if (dd_exist(dd, FILENAME_GLOBAL_UUID))
+    if (!dd_exist(dd, FILENAME_GLOBAL_UUID))
     {
-        char *uuid = dd_load_text(dd, FILENAME_GLOBAL_UUID);
+        VERB1 log(_("Unable to find %s in %s"), FILENAME_GLOBAL_UUID, pDebugDumpDir);
         dd_close(dd);
-        string ret = uuid;
-        free(uuid);
-        return ret;
+        return "";
     }
-    else
-    {
-        // Compatibility code.
-        // This whole block should be deleted for Fedora 14.
-        log(_("Getting global universal unique identification..."));
-
-        string backtrace_path = concat_path_file(pDebugDumpDir, FILENAME_BACKTRACE);
-        char *executable = dd_load_text(dd, FILENAME_EXECUTABLE);
-        char *package = dd_load_text(dd, FILENAME_PACKAGE);
-        char *uid_str = m_bBacktrace ? dd_load_text(dd, CD_UID) : xstrdup("");
-
-        string independent_backtrace;
-        if (m_bBacktrace)
-        {
-            /* Run abrt-backtrace to get independent backtrace suitable
-               to UUID calculation. */
-            char *backtrace_path = concat_path_file(pDebugDumpDir, FILENAME_BACKTRACE);
-            char *args[7];
-            args[0] = (char*)"abrt-backtrace";
-            args[1] = (char*)"--single-thread";
-            args[2] = (char*)"--remove-exit-handlers";
-            args[3] = (char*)"--frame-depth=5";
-            args[4] = (char*)"--remove-noncrash-frames";
-            args[5] = backtrace_path;
-            args[6] = NULL;
-
-            int pipeout[2];
-            xpipe(pipeout); /* stdout of abrt-backtrace */
-
-            fflush(NULL);
-            pid_t child = fork();
-            if (child == -1)
-                perror_msg_and_die("fork");
-            if (child == 0)
-            {
-                VERB1 log("Executing %s", args[0]);
-
-                xmove_fd(pipeout[1], STDOUT_FILENO);
-                close(pipeout[0]); /* read side of the pipe */
-
-                /* abrt-backtrace is executed under the user's uid and gid. */
-                uid_t uid = xatoi_u(uid_str);
-                struct passwd* pw = getpwuid(uid);
-                gid_t gid = pw ? pw->pw_gid : uid;
-                setgroups(1, &gid);
-                xsetregid(gid, gid);
-                xsetreuid(uid, uid);
-
-                execvp(args[0], args);
-                VERB1 perror_msg("Can't execute '%s'", args[0]);
-                exit(1);
-            }
-
-            free(backtrace_path);
-            close(pipeout[1]); /* write side of the pipe */
 
-            /* Read the result from abrt-backtrace. */
-            int r;
-            char buff[1024];
-            while ((r = safe_read(pipeout[0], buff, sizeof(buff) - 1)) > 0)
-            {
-                buff[r] = '\0';
-                independent_backtrace += buff;
-            }
-            close(pipeout[0]);
-
-            /* Wait until it exits, and check the exit status. */
-            errno = 0;
-            int status;
-            waitpid(child, &status, 0);
-            if (!WIFEXITED(status))
-            {
-                perror_msg("abrt-backtrace not executed properly, "
-                           "status: %x signal: %d", status, WIFSIGNALED(status));
-            }
-            else
-            {
-                int exit_status = WEXITSTATUS(status);
-                if (exit_status == 79) /* EX_PARSINGFAILED */
-                {
-                    /* abrt-backtrace returns alternative backtrace
-                       representation in this case, so everything will work
-                       as expected except worse duplication detection */
-                    log_msg("abrt-backtrace failed to parse the backtrace");
-                }
-                else if (exit_status == 80) /* EX_THREADDETECTIONFAILED */
-                {
-                    /* abrt-backtrace returns backtrace with all threads
-                       in this case, so everything will work as expected
-                       except worse duplication detection */
-                    log_msg("abrt-backtrace failed to determine crash frame");
-                }
-                else if (exit_status != 0)
-                {
-                    /* this is unexpected problem and it should be investigated */
-                    error_msg("abrt-backtrace run failed, exit value: %d",
-                              exit_status);
-                }
-            }
-
-            /*VERB1 log("abrt-backtrace result: %s", independent_backtrace.c_str());*/
-        }
-        /* else: no backtrace, independent_backtrace == ""
-           no backtrace => rating = 0
-        */
-        else
-        {
-            dd_save_text(dd, FILENAME_RATING, "0");
-        }
-        dd_close(dd);
-
-        char *hash_str = xasprintf("%s%s%s", package, executable, independent_backtrace.c_str());
-        free(package);
-        free(executable);
-
-        char hash_str2[SHA1_RESULT_LEN*2 + 1];
-        create_hash(hash_str2, hash_str);
-        free(hash_str);
-
-        return hash_str2;
-    }
+    char *uuid = dd_load_text(dd, FILENAME_GLOBAL_UUID);
+    dd_close(dd);
+    string ret = uuid;
+    free(uuid);
+    return ret;
 }
 
 static bool DebuginfoCheckPolkit(uid_t uid)
diff --git a/lib/plugins/Makefile.am b/lib/plugins/Makefile.am
index ffdfa33..d27e177 100644
--- a/lib/plugins/Makefile.am
+++ b/lib/plugins/Makefile.am
@@ -66,7 +66,6 @@ UTILS_PATH=$(srcdir)/../utils
 # CCpp
 libCCpp_la_SOURCES = CCpp.cpp CCpp.h
 libCCpp_la_LDFLAGS = -avoid-version
-#libCCpp_la_LIBADD =
 libCCpp_la_CPPFLAGS = -Wall -Werror \
     -I$(INC_PATH) -I$(UTILS_PATH) \
     -DCCPP_HOOK_PATH=\"${libexecdir}/abrt-hook-ccpp\" \
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index c03463b..b480647 100644
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
@@ -69,7 +69,8 @@ abrt_action_generate_backtrace_CPPFLAGS = \
     -D_GNU_SOURCE \
     -Wall -Werror
 abrt_action_generate_backtrace_LDADD = \
-    ../../lib/utils/libABRTUtils.la
+    ../../lib/utils/libABRTUtils.la \
+    ../../btparser/lib/libbtparser.la
 
 abrt_action_save_package_data_SOURCES = \
     rpm.h rpm.c \
diff --git a/src/daemon/abrt-action-generate-backtrace.c b/src/daemon/abrt-action-generate-backtrace.c
index 46f002a..64ed7eb 100644
--- a/src/daemon/abrt-action-generate-backtrace.c
+++ b/src/daemon/abrt-action-generate-backtrace.c
@@ -17,7 +17,9 @@
     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 #include "abrtlib.h"
-#include "backtrace.h"
+#include "btparser/lib/backtrace.h"
+#include "btparser/lib/frame.h"
+#include "btparser/lib/location.h"
 
 
 #define DEBUGINFO_CACHE_DIR     LOCALSTATEDIR"/cache/abrt-di"
@@ -325,97 +327,76 @@ int main(int argc, char **argv)
     dd_save_text(dd, FILENAME_BACKTRACE, backtrace_str);
 
     /* Compute and store backtrace hash. */
-    char *backtrace_cpy = xstrdup(backtrace_str);
-    struct backtrace *backtrace = backtrace_parse(backtrace_cpy, false, false);
-    free(backtrace_cpy);
-    if (backtrace)
+    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);
+    if (!backtrace)
     {
-        /* Get the quality of the full backtrace. */
-        float q1 = backtrace_quality(backtrace);
-
-        /* Remove all the other threads except the crash thread. */
-        struct thread *crash_thread = backtrace_find_crash_thread(backtrace);
-        if (crash_thread)
-            backtrace_remove_threads_except_one(backtrace, crash_thread);
-        else
-            log_msg("Detection of crash thread failed");
-
-        /* Get the quality of the crash thread. */
-        float q2 = backtrace_quality(backtrace);
-
-        backtrace_remove_noncrash_frames(backtrace);
-
-        /* Do the frame removal now. */
-        backtrace_limit_frame_depth(backtrace, 5);
-        /* Frame removal can be done before removing exit handlers. */
-        backtrace_remove_exit_handlers(backtrace);
-
-        /* Get the quality of frames around the crash. */
-        float q3 = backtrace_quality(backtrace);
-
-        /* Compute UUID. */
-        struct strbuf *bt = backtrace_tree_as_str(backtrace, false);
-        strbuf_prepend_str(bt, executable);
-        strbuf_prepend_str(bt, package);
+        VERB1 log(_("Backtrace parsing failed for %s"), dump_dir_name);
+        VERB1 log("%d:%d: %s", location.line, location.column, location.message);
+        /* If the parser failed compute the UUID from the executable
+           and package only.  This is not supposed to happen often.
+           Do not store the rating, as we do not know how good the
+           backtrace is. */
+        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, bt->buf);
+        create_hash(hash_str, emptybt->buf);
         dd_save_text(dd, FILENAME_GLOBAL_UUID, hash_str);
-        strbuf_free(bt);
-
-        /* Compute and store backtrace rating. The crash frame
-           is more important that the others. The frames around
-           the crash are more important than the rest.  */
-        float qtot = 0.25f * q1 + 0.35f * q2 + 0.4f * q3;
-
-        /* Turn the quality to rating. */
-        const char *rating;
-        if (qtot < 0.6f)      rating = "0";
-        else if (qtot < 0.7f) rating = "1";
-        else if (qtot < 0.8f) rating = "2";
-        else if (qtot < 0.9f) rating = "3";
-        else                  rating = "4";
-        dd_save_text(dd, FILENAME_RATING, rating);
-
-        /* Get the function name from the crash frame. */
-        if (crash_thread)
-        {
-            struct frame *crash_frame = crash_thread->frames;
-            struct frame *abort_frame = thread_find_abort_frame(crash_thread);
-            if (abort_frame)
-                crash_frame = abort_frame->next;
-            if (crash_frame && crash_frame->function && 0 != strcmp(crash_frame->function, "??"))
-                dd_save_text(dd, FILENAME_CRASH_FUNCTION, crash_frame->function);
-        }
-
-        backtrace_free(backtrace);
+        strbuf_free(emptybt);
+        free(backtrace_str);
+        free(package);
+        free(executable);
+        dd_close(dd);
+        return 2;
     }
+    free(backtrace_str);
+
+    /* Compute UUID. */
+    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_GLOBAL_UUID, 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 the parser failed fall back to the independent backtrace. */
-        /* If we write and use a hand-written parser instead of the bison one,
-           the parser never fails, and it will be possible to get rid of
-           the independent_backtrace and backtrace_rate_old. */
-        struct strbuf *ibt = independent_backtrace(backtrace_str);
-        strbuf_prepend_str(ibt, executable);
-        strbuf_prepend_str(ibt, package);
-        char hash_str[SHA1_RESULT_LEN*2 + 1];
-        create_hash(hash_str, ibt->buf);
-        dd_save_text(dd, FILENAME_GLOBAL_UUID, hash_str);
-        strbuf_free(ibt);
-
-        /* Compute and store backtrace rating. */
-        /* Crash frame is not known so store nothing. */
-        int rate = backtrace_rate_old(backtrace_str);
-        char rate_buf[sizeof(rate)*3 + 2];
-        sprintf(rate_buf, "%d", rate);
-        dd_save_text(dd, FILENAME_RATING, rate_buf);
+        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);
-    free(backtrace_str);
 
     return 0;
 }
-- 
1.7.2.3

