diff -x '*.po' -d -urpN abrt.2/abrt.spec.in abrt.3/abrt.spec.in
--- abrt.2/abrt.spec.in	2012-03-14 03:14:52.446107757 +0100
+++ abrt.3/abrt.spec.in	2012-03-15 02:16:27.085424033 +0100
@@ -507,6 +507,7 @@ gtk-update-icon-cache %{_datadir}/icons/
 %endif
 %{_bindir}/abrt-watch-log
 %{_bindir}/abrt-dump-oops
+%{_bindir}/abrt-dump-xorg
 %{_bindir}/abrt-action-analyze-oops
 %{_mandir}/man1/abrt-action-analyze-oops.1*
 
diff -x '*.po' -d -urpN abrt.2/.gitignore abrt.3/.gitignore
--- abrt.2/.gitignore	2012-03-14 03:15:04.891070662 +0100
+++ abrt.3/.gitignore	2012-03-15 02:16:43.150412417 +0100
@@ -25,6 +25,7 @@ src/plugins/abrt-action-install-debuginf
 src/plugins/abrt-action-trim-files
 src/plugins/abrt-watch-log
 src/plugins/abrt-dump-oops
+src/plugins/abrt-dump-xorg
 src/plugins/abrt-dedup-client
 src/plugins/abrt-retrace-client
 src/plugins/abrt-action-install-debuginfo
diff -x '*.po' -d -urpN abrt.2/po/POTFILES.in abrt.3/po/POTFILES.in
--- abrt.2/po/POTFILES.in	2012-03-14 03:24:28.105323391 +0100
+++ abrt.3/po/POTFILES.in	2012-03-15 02:38:13.059137117 +0100
@@ -23,6 +23,7 @@ src/plugins/abrt-action-trim-files.c
 src/plugins/abrt-dedup-client.c
 src/plugins/abrt-watch-log.c
 src/plugins/abrt-dump-oops.c
+src/plugins/abrt-dump-xorg.c
 src/plugins/abrt-retrace-client.c
 src/plugins/analyze_LocalGDB.xml.in
 src/plugins/analyze_RetraceServer.xml.in
diff -x '*.po' -d -urpN abrt.2/src/plugins/abrt-dump-oops.c abrt.3/src/plugins/abrt-dump-oops.c
--- abrt.2/src/plugins/abrt-dump-oops.c	2012-03-14 21:53:33.350848696 +0100
+++ abrt.3/src/plugins/abrt-dump-oops.c	2012-03-15 02:34:30.514389890 +0100
@@ -206,9 +206,6 @@ int main(int argc, char **argv)
     };
     unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
 
-    if ((opts & OPT_d) && (opts & OPT_D))
-        show_usage_and_die(program_usage_string, program_options);
-
     export_abrt_envvars(0);
 
     msg_prefix = g_progname;
@@ -218,6 +215,16 @@ int main(int argc, char **argv)
         logmode = LOGMODE_SYSLOG;
     }
 
+    if (opts & OPT_D)
+    {
+        if (opts & OPT_d)
+            show_usage_and_die(program_usage_string, program_options);
+        load_abrt_conf();
+        debug_dumps_dir = g_settings_dump_location;
+        g_settings_dump_location = NULL;
+        free_abrt_conf_data();
+    }
+
     argv += optind;
     if (argv[0])
         xmove_fd(xopen(argv[0], O_RDONLY), STDIN_FILENO);
@@ -267,9 +274,6 @@ int main(int argc, char **argv)
                     "Reported %u kernel oopses to Abrt",
                     oops_cnt
             );
-
-            //if (opts & OPT_D)
-            //    free_abrt_conf_data();
         }
     }
     //list_free_with_free(oops_list);
diff -x '*.po' -d -urpN abrt.2/src/plugins/abrt-dump-xorg.c abrt.3/src/plugins/abrt-dump-xorg.c
--- abrt.2/src/plugins/abrt-dump-xorg.c	1970-01-01 01:00:00.000000000 +0100
+++ abrt.3/src/plugins/abrt-dump-xorg.c	2012-03-15 02:34:30.514389890 +0100
@@ -0,0 +1,240 @@
+/*
+    Copyright (C) 2012  ABRT Team
+    Copyright (C) 2012  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 <syslog.h>
+#include "libabrt.h"
+
+/* I want to use -Werror, but gcc-4.4 throws a curveball:
+ * "warning: ignoring return value of 'ftruncate', declared with attribute warn_unused_result"
+ * and (void) cast is not enough to shut it up! Oh God...
+ */
+#define IGNORE_RESULT(func_call) do { if (func_call) /* nothing */; } while (0)
+
+enum {
+    OPT_v = 1 << 0,
+    OPT_s = 1 << 1,
+    OPT_o = 1 << 2,
+    OPT_d = 1 << 3,
+    OPT_D = 1 << 4,
+    OPT_x = 1 << 5,
+};
+
+static unsigned g_opts;
+static const char *debug_dumps_dir = ".";
+static unsigned dir_seq_no = 0;
+
+static char *skip_pfx(char *p)
+{
+    if (p[0] != '[')
+        return p;
+    char *q = strchr(p, ']');
+    if (!q)
+        return p;
+    if (q[1] == ' ')
+        return q + 2;
+    return p;
+}
+
+static char *list2lines(GList *list)
+{
+    struct strbuf *s = strbuf_new();
+    while (list)
+    {
+        strbuf_append_str(s, (char*)list->data);
+        strbuf_append_char(s, '\n');
+        free(list->data);
+        list = g_list_delete_link(list, list);
+    }
+    return strbuf_free_nobuf(s);
+}
+
+static void save_bt_to_dump_dir(const char *bt, const char *reason)
+{
+    time_t t = time(NULL);
+    const char *iso_date = iso_date_string(&t);
+    /* dump should be readable by all if we're run with -x */
+    uid_t my_euid = (uid_t)-1L;
+    mode_t mode = 0644;
+    /* and readable only for the owner otherwise */
+    if (!(g_opts & OPT_x))
+    {
+        mode = 0640;
+        my_euid = geteuid();
+    }
+
+    pid_t my_pid = getpid();
+
+    struct dump_dir *dd;
+    {
+        char base[sizeof("xorg-YYYY-MM-DD-hh:mm:ss-%lu-%lu") + 2 * sizeof(long)*3];
+        sprintf(base, "xorg-%s-%lu-%u", iso_date, (long)my_pid, ++dir_seq_no);
+        char *path = concat_path_file(debug_dumps_dir, base);
+        dd = dd_create(path, /*uid:*/ my_euid, mode);
+        free(path);
+    }
+
+    if (dd)
+    {
+        dd_create_basic_files(dd, /*uid:*/ my_euid);
+        dd_save_text(dd, "abrt_version", VERSION);
+        dd_save_text(dd, FILENAME_ANALYZER, "xorg");
+        dd_save_text(dd, FILENAME_REASON, reason);
+        dd_save_text(dd, FILENAME_BACKTRACE, bt);
+        dd_close(dd);
+    }
+}
+
+/* Called after "Backtrace:" line was read.
+ * Example (yes, stray newline before 'B' is real):
+[ 86985.879]<space>
+Backtrace:
+[ 86985.880] 0: /usr/bin/Xorg (xorg_backtrace+0x2f) [0x462d8f]
+[ 86985.880] 1: /usr/bin/Xorg (0x400000+0x67b56) [0x467b56]
+[ 86985.880] 2: /lib64/libpthread.so.0 (0x30a5800000+0xf4f0) [0x30a580f4f0]
+[ 86985.880] 3: /usr/lib64/xorg/modules/extensions/librecord.so (0x7ff6c225e000+0x26c3) [0x7ff6c22606c3]
+[ 86985.880] 4: /usr/bin/Xorg (_CallCallbacks+0x3c) [0x43820c]
+[ 86985.880] 5: /usr/bin/Xorg (WriteToClient+0x1f5) [0x466315]
+[ 86985.880] 6: /usr/lib64/xorg/modules/extensions/libdri2.so (ProcDRI2WaitMSCReply+0x4f) [0x7ff6c1e4feef]
+[ 86985.880] 7: /usr/lib64/xorg/modules/extensions/libdri2.so (DRI2WaitMSCComplete+0x52) [0x7ff6c1e4e6d2]
+[ 86985.880] 8: /usr/lib64/xorg/modules/drivers/intel_drv.so (0x7ff6c1bfb000+0x25ae4) [0x7ff6c1c20ae4]
+[ 86985.880] 9: /usr/lib64/libdrm.so.2 (drmHandleEvent+0xa3) [0x376b407513]
+[ 86985.880] 10: /usr/bin/Xorg (WakeupHandler+0x6b) [0x4379db]
+[ 86985.880] 11: /usr/bin/Xorg (WaitForSomething+0x1a9) [0x460289]
+[ 86985.880] 12: /usr/bin/Xorg (0x400000+0x3379a) [0x43379a]
+[ 86985.880] 13: /usr/bin/Xorg (0x400000+0x22dc5) [0x422dc5]
+[ 86985.880] 14: /lib64/libc.so.6 (__libc_start_main+0xed) [0x30a542169d]
+[ 86985.880] 15: /usr/bin/Xorg (0x400000+0x230b1) [0x4230b1]
+[ 86985.880] Segmentation fault at address 0x7ff6bf09e010
+ */
+static void process_xorg_bt(void)
+{
+    char *reason = NULL;
+    GList *list = NULL;
+    unsigned cnt = 0;
+    char *line;
+    while ((line = xmalloc_fgetline(stdin)) != NULL)
+    {
+        char *p = skip_pfx(line);
+
+        if (*p < '0' || *p > '9')
+        {
+            if (strncasecmp(p, "Segmentation fault", strlen("Segmentation fault")) == 0)
+            {
+                overlapping_strcpy(line, p);
+                reason = line;
+                line = NULL;
+            }
+            /* TODO: Other cases when we have useful reason string? */
+            break;
+        }
+
+        errno = 0;
+        char *end;
+        IGNORE_RESULT(strtoul(p, &end, 10));
+        if (errno || end == p || *end != ':')
+            break;
+
+        /* This looks like bt line. Save it to list */
+        overlapping_strcpy(line, p);
+        list = g_list_prepend(list, line);
+        line = NULL;
+        if (++cnt > 255) /* prevent ridiculously large bts */
+            break;
+    }
+    free(line);
+
+    if (list)
+    {
+        list = g_list_reverse(list);
+        char *bt = list2lines(list); /* frees list */
+        if (g_opts & OPT_o)
+            printf("%s%s%s", bt, reason ? reason : "", reason ? "\n" : "");
+        if (g_opts & (OPT_d|OPT_D))
+            save_bt_to_dump_dir(bt, reason ? reason : "Xorg server crashed");
+        free(bt);
+    }
+    free(reason);
+}
+
+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 = _(
+        "& [-vsox] [-d DIR]/[-D] [FILE]\n"
+        "\n"
+        "Extract Xorg crash from FILE (or standard input)"
+    );
+    /* Keep OPT_z enums and order of options below in sync! */
+    struct options program_options[] = {
+        OPT__VERBOSE(&g_verbose),
+        OPT_BOOL(  's', NULL, NULL, _("Log to syslog")),
+        OPT_BOOL(  'o', NULL, NULL, _("Print found crash data on standard output")),
+        OPT_STRING('d', NULL, &debug_dumps_dir, "DIR", _("Create ABRT dump in DIR for every crash found")),
+        OPT_BOOL(  'D', NULL, NULL, _("Same as -d DumpLocation, DumpLocation is specified in abrt.conf")),
+        OPT_BOOL(  'x', NULL, NULL, _("Make the problem directory world readable")),
+        OPT_END()
+    };
+    unsigned opts = g_opts = parse_opts(argc, argv, program_options, program_usage_string);
+
+    export_abrt_envvars(0);
+
+    msg_prefix = g_progname;
+    if ((opts & OPT_s) || getenv("ABRT_SYSLOG"))
+    {
+        openlog(msg_prefix, 0, LOG_DAEMON);
+        logmode = LOGMODE_SYSLOG;
+    }
+
+    if (opts & OPT_D)
+    {
+        if (opts & OPT_d)
+            show_usage_and_die(program_usage_string, program_options);
+        load_abrt_conf();
+        debug_dumps_dir = g_settings_dump_location;
+        g_settings_dump_location = NULL;
+        free_abrt_conf_data();
+    }
+
+    argv += optind;
+    if (argv[0])
+        xmove_fd(xopen(argv[0], O_RDONLY), STDIN_FILENO);
+
+    char *line;
+    while ((line = xmalloc_fgetline(stdin)) != NULL)
+    {
+        char *p = skip_pfx(line);
+        if (strcmp(p, "Backtrace:") == 0)
+        {
+            free(line);
+            process_xorg_bt();
+            continue;
+        }
+        free(line);
+    }
+
+    return 0;
+}
diff -x '*.po' -d -urpN abrt.2/src/plugins/Makefile.am abrt.3/src/plugins/Makefile.am
--- abrt.2/src/plugins/Makefile.am	2012-03-14 03:14:31.418176392 +0100
+++ abrt.3/src/plugins/Makefile.am	2012-03-15 02:18:02.839346242 +0100
@@ -9,6 +9,7 @@ bin_SCRIPTS = \
 bin_PROGRAMS = \
     abrt-watch-log \
     abrt-dump-oops \
+    abrt-dump-xorg \
     abrt-action-analyze-c \
     abrt-action-analyze-python \
     abrt-action-analyze-oops \
@@ -97,6 +98,20 @@ abrt_dump_oops_LDADD = \
     $(GLIB_LIBS) \
     $(LIBREPORT_LIBS) \
     ../lib/libabrt.la
+
+abrt_dump_xorg_SOURCES = \
+    abrt-dump-xorg.c
+abrt_dump_xorg_CPPFLAGS = \
+    -I$(srcdir)/../include \
+    -I$(srcdir)/../lib \
+    $(GLIB_CFLAGS) \
+    $(LIBREPORT_CFLAGS) \
+    -D_GNU_SOURCE \
+    -Wall -Wwrite-strings -Werror
+abrt_dump_xorg_LDADD = \
+    $(GLIB_LIBS) \
+    $(LIBREPORT_LIBS) \
+    ../lib/libabrt.la
 
 abrt_action_analyze_c_SOURCES = \
     abrt-action-analyze-c.c
