diff --git a/ChangeLog b/ChangeLog
index c1c024d7ed8ba75cfd624279fc5156539a4b60dc..6da506e39aca7dbccac9d6432c2ffd2803b986bd 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2012-09-26  Ian Lance Taylor  <iant@google.com>
+
+	* Makefile.def: Make all-gcc depend on all-libbacktrace.
+	* Makefile.in: Rebuild.
+
 2012-09-21  Anthony Green  <green@moxielogic.com>
 
 	* config/moxie/moxie.opt: Add -mno-crt0 option.
diff --git a/Makefile.def b/Makefile.def
index f32ffb0f5cae16c4d182dd77e4eaeddef52f3397..b3430a4e82ec0ab72eae6ac53d85679c9697471b 100644
--- a/Makefile.def
+++ b/Makefile.def
@@ -305,6 +305,7 @@ dependencies = { module=all-gcc; on=all-build-flex; };
 dependencies = { module=all-gcc; on=all-build-libiberty; };
 dependencies = { module=all-gcc; on=all-build-fixincludes; };
 dependencies = { module=all-gcc; on=all-zlib; };
+dependencies = { module=all-gcc; on=all-libbacktrace; hard=true; };
 dependencies = { module=all-gcc; on=all-libcpp; hard=true; };
 dependencies = { module=all-gcc; on=all-libdecnumber; hard=true; };
 dependencies = { module=all-gcc; on=all-libiberty; };
diff --git a/Makefile.in b/Makefile.in
index 4200d5d5307a3cf7b25271f8bdc0adb03dc550dd..2cdd08cf491eb12ecea93faf9a1ab5979d58469a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -44825,6 +44825,14 @@ all-stage3-gcc: maybe-all-stage3-zlib
 all-stage4-gcc: maybe-all-stage4-zlib
 all-stageprofile-gcc: maybe-all-stageprofile-zlib
 all-stagefeedback-gcc: maybe-all-stagefeedback-zlib
+all-gcc: all-libbacktrace
+
+all-stage1-gcc: all-stage1-libbacktrace
+all-stage2-gcc: all-stage2-libbacktrace
+all-stage3-gcc: all-stage3-libbacktrace
+all-stage4-gcc: all-stage4-libbacktrace
+all-stageprofile-gcc: all-stageprofile-libbacktrace
+all-stagefeedback-gcc: all-stagefeedback-libbacktrace
 all-gcc: all-libcpp
 
 all-stage1-gcc: all-stage1-libcpp
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9941f62612d5c225222e30c61ee23463bb434539..6b723e498d015df8dcb527a3bdda569d5fde633f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,16 @@
+2012-09-26  Ian Lance Taylor  <iant@google.com>
+
+	* diagnostic.c: Include "demangle.h" and "backtrace.h".
+	(bt_stop): New static array.
+	(bt_callback, bt_err_callback): New static functions.
+	(diagnostic_action_after_output): Call backtrace_full for DK_ICE.
+	* Makefile.in (BACKTRACE): New variable.
+	(BACKTRACEINC, LIBBACKTRACE): New variables.
+	(BACKTRACE_H): New variable.
+	(LIBDEPS, LIBS): Add $(LIBBACKTRACE).
+	(INCLUDES): Add $(BACKTRACEINC).
+	(diagnostic.o): Depend upon $(DEMANGLE_H) and $(BACKTRACE_H).
+
 2012-09-25  Segher Boessenkool  <segher@kernel.crashing.org>
 
 	PR target/51274
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 7a4a6e8206c6da736a33f3d6fb82bc071a4eb4e1..b036e884e57a107373428a825487f9c4e7de9e0d 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -346,6 +346,11 @@ DECNUMFMT = $(srcdir)/../libdecnumber/$(enable_decimal_float)
 DECNUMINC = -I$(DECNUM) -I$(DECNUMFMT) -I../libdecnumber
 LIBDECNUMBER = ../libdecnumber/libdecnumber.a
 
+# The backtrace library.
+BACKTRACE = $(srcdir)/../libbacktrace
+BACKTRACEINC = -I$(BACKTRACE)
+LIBBACKTRACE = ../libbacktrace/.libs/libbacktrace.a
+
 # Target to use when installing include directory.  Either
 # install-headers-tar, install-headers-cpio or install-headers-cp.
 INSTALL_HEADERS_DIR = @build_install_headers_dir@
@@ -906,6 +911,7 @@ OPTS_H = $(INPUT_H) $(VEC_H) opts.h
 DECNUM_H = $(DECNUM)/decContext.h $(DECNUM)/decDPD.h $(DECNUM)/decNumber.h \
 	$(DECNUMFMT)/decimal32.h $(DECNUMFMT)/decimal64.h \
 	$(DECNUMFMT)/decimal128.h $(DECNUMFMT)/decimal128Local.h
+BACKTRACE_H = $(BACKTRACE)/backtrace.h
 MKDEPS_H = $(srcdir)/../libcpp/include/mkdeps.h
 SYMTAB_H = $(srcdir)/../libcpp/include/symtab.h $(OBSTACK_H)
 CPP_ID_DATA_H = $(CPPLIB_H) $(srcdir)/../libcpp/include/cpp-id-data.h
@@ -988,7 +994,7 @@ BUILD_LIBIBERTY = $(build_libobjdir)/libiberty/libiberty.a
 
 # Dependencies on the intl and portability libraries.
 LIBDEPS= libcommon.a $(CPPLIB) $(LIBIBERTY) $(LIBINTL_DEP) $(LIBICONV_DEP) \
-	$(LIBDECNUMBER)
+	$(LIBDECNUMBER) $(LIBBACKTRACE)
 
 # Likewise, for use in the tools that must run on this machine
 # even if we are cross-building GCC.
@@ -996,8 +1002,8 @@ BUILD_LIBDEPS= $(BUILD_LIBIBERTY)
 
 # How to link with both our special library facilities
 # and the system's installed libraries.
-LIBS = @LIBS@ libcommon.a $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBIBERTY) \
-	$(LIBDECNUMBER) $(HOST_LIBS)
+LIBS = @LIBS@ libcommon.a $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBBACKTRACE) \
+	$(LIBIBERTY) $(LIBDECNUMBER) $(HOST_LIBS)
 BACKENDLIBS = $(CLOOGLIBS) $(GMPLIBS) $(PLUGINLIBS) $(HOST_LIBS) \
 	$(ZLIB)
 # Any system libraries needed just for GNAT.
@@ -1029,7 +1035,7 @@ BUILD_ERRORS = build/errors.o
 # libintl.h will be found in ../intl if we are using the included libintl.
 INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
 	   -I$(srcdir)/../include @INCINTL@ \
-	   $(CPPINC) $(GMPINC) $(DECNUMINC) \
+	   $(CPPINC) $(GMPINC) $(DECNUMINC) $(BACKTRACEINC) \
 	   $(CLOOGINC) $(ISLINC)
 
 .c.o:
@@ -2614,7 +2620,8 @@ fold-const.o : fold-const.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(GGC_H) $(TM_P_H) langhooks.h $(MD5_H) intl.h $(TARGET_H) \
    $(GIMPLE_H) realmpfr.h $(TREE_FLOW_H)
 diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
-   version.h $(INPUT_H) intl.h $(DIAGNOSTIC_H) diagnostic.def
+   version.h $(DEMANGLE_H) $(INPUT_H) intl.h $(BACKTRACE_H) $(DIAGNOSTIC_H) \
+   diagnostic.def
 opts.o : opts.c $(OPTS_H) $(OPTIONS_H) $(DIAGNOSTIC_CORE_H) $(CONFIG_H) $(SYSTEM_H) \
    coretypes.h $(TM_H) \
    $(DIAGNOSTIC_H) insn-attr-common.h intl.h $(COMMON_TARGET_H) \
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index b3ae86c74a8399be2785faa17b0c9c8e1230236e..afe958d7623e275b4b78f275a1e2aea2a1e7c0fb 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -27,8 +27,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "version.h"
+#include "demangle.h"
 #include "input.h"
 #include "intl.h"
+#include "backtrace.h"
 #include "diagnostic.h"
 
 #define pedantic_warning_kind(DC)			\
@@ -296,6 +298,99 @@ diagnostic_show_locus (diagnostic_context * context,
   pp_set_prefix (context->printer, saved_prefix);
 }
 
+/* Functions at which to stop the backtrace print.  It's not
+   particularly helpful to print the callers of these functions.  */
+
+static const char * const bt_stop[] =
+{
+  "main",
+  "toplev_main",
+  "execute_one_pass",
+  "compile_file",
+};
+
+/* A callback function passed to the backtrace_full function.  */
+
+static int
+bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
+	     const char *function)
+{
+  int *pcount = (int *) data;
+
+  /* If we don't have any useful information, don't print
+     anything.  */
+  if (filename == NULL && function == NULL)
+    return 0;
+
+  /* Skip functions in diagnostic.c.  */
+  if (*pcount == 0
+      && filename != NULL
+      && strcmp (lbasename(filename), "diagnostic.c") == 0)
+    return 0;
+
+  /* Print up to 20 functions.  We could make this a --param, but
+     since this is only for debugging just use a constant for now.  */
+  if (*pcount >= 20)
+    {
+      /* Returning a non-zero value stops the backtrace.  */
+      return 1;
+    }
+  ++*pcount;
+
+  char *alc = NULL;
+  if (function != NULL)
+    {
+      char *str = cplus_demangle_v3 (function,
+				     (DMGL_VERBOSE | DMGL_ANSI
+				      | DMGL_GNU_V3 | DMGL_PARAMS));
+      if (str != NULL)
+	{
+	  alc = str;
+	  function = str;
+	}
+
+      for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
+	{
+	  size_t len = strlen (bt_stop[i]);
+	  if (strncmp (function, bt_stop[i], len) == 0
+	      && (function[len] == '\0' || function[len] == '('))
+	    {
+	      if (alc != NULL)
+		free (alc);
+	      /* Returning a non-zero value stops the backtrace.  */
+	      return 1;
+	    }
+	}
+    }
+
+  fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
+	   pc,
+	   function == NULL ? "???" : function,
+	   filename == NULL ? "???" : filename,
+	   lineno);
+
+  if (alc != NULL)
+    free (alc);
+
+  return 0;
+}
+
+/* A callback function passed to the backtrace_full function.  This is
+   called if backtrace_full has an error.  */
+
+static void
+bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
+{
+  if (errnum < 0)
+    {
+      /* This means that no debug info was available.  Just quietly
+	 skip printing backtrace info.  */
+      return;
+    }
+  fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
+	   errnum == 0 ? "" : xstrerror (errnum));
+}
+
 /* Take any action which is expected to happen after the diagnostic
    is written out.  This function does not always return.  */
 static void
@@ -334,13 +429,27 @@ diagnostic_action_after_output (diagnostic_context *context,
       break;
 
     case DK_ICE:
-      if (context->abort_on_error)
-	real_abort ();
+      {
+	struct backtrace_state *state =
+	  backtrace_create_state (NULL, 0, bt_err_callback, NULL);
+	int count = 0;
+	if (state != NULL)
+	  backtrace_full (state, 2, bt_callback, bt_err_callback,
+			  (void *) &count);
+
+	if (context->abort_on_error)
+	  real_abort ();
+
+	fnotice (stderr, "Please submit a full bug report,\n"
+		 "with preprocessed source if appropriate.\n");
+	if (count > 0)
+	  fnotice (stderr,
+		   ("Please include the complete backtrace "
+		    "with any bug report.\n"));
+	fnotice (stderr, "See %s for instructions.\n", bug_report_url);
 
-      fnotice (stderr, "Please submit a full bug report,\n"
-	       "with preprocessed source if appropriate.\n"
-	       "See %s for instructions.\n", bug_report_url);
-      exit (ICE_EXIT_CODE);
+	exit (ICE_EXIT_CODE);
+      }
 
     case DK_FATAL:
       if (context->abort_on_error)