diff --git a/abrt.spec b/abrt.spec
index ab6610c..8758ab8 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 8dd618e..5344cdb 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 0000000..e65b178
--- /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 0c2d9a0..5afe6e4 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 0698e65..8a5f377 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
