diff mbox

PATCH RFA: Print backtrace on ICE

Message ID mcrfw6gpo0s.fsf@google.com
State New
Headers show

Commit Message

Ian Lance Taylor Sept. 17, 2012, 5:17 p.m. UTC
This patch to the diagnostic code uses the new backtrace library to
print a backtrace on an ICE.  For example, here is the output of a test
case I took from a C++ PR:

/home/iant/foo2.cc:6:6: internal compiler error: in cp_lexer_new_from_tokens, at cp/parser.c:638
0xec549f internal_error(char const*, ...)
	../../trunk/gcc/diagnostic.c:1057
0xec3f53 fancy_abort(char const*, int, char const*)
	../../trunk/gcc/diagnostic.c:1111
0x5ff78e cp_lexer_new_from_tokens
	../../trunk/gcc/cp/parser.c:638
0x5ff78e cp_parser_push_lexer_for_tokens
	../../trunk/gcc/cp/parser.c:3290
0x60ff40 cp_parser_late_parsing_for_member
	../../trunk/gcc/cp/parser.c:21713
0x60ff40 cp_parser_class_specifier_1
	../../trunk/gcc/cp/parser.c:18207
0x60ff40 cp_parser_class_specifier
	../../trunk/gcc/cp/parser.c:18231
0x60ff40 cp_parser_type_specifier
	../../trunk/gcc/cp/parser.c:13390
0x61c83d cp_parser_decl_specifier_seq
	../../trunk/gcc/cp/parser.c:10731
0x628317 cp_parser_single_declaration
	../../trunk/gcc/cp/parser.c:21313
0x6289c0 cp_parser_template_declaration_after_export
	../../trunk/gcc/cp/parser.c:21198
0x62de39 cp_parser_declaration
	../../trunk/gcc/cp/parser.c:10183
0x62c487 cp_parser_declaration_seq_opt
	../../trunk/gcc/cp/parser.c:10105
0x62c762 cp_parser_translation_unit
	../../trunk/gcc/cp/parser.c:3757
0x62c762 c_parse_file()
	../../trunk/gcc/cp/parser.c:27557
0x72e4e4 c_common_parse_file()
	../../trunk/gcc/c-family/c-opts.c:1138
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.


Bootstrapped on x86_64-unknown-linux-gnu.  I didn't bother to run the
testsuite, since the code only changes when an ICE occurs anyhow.

OK for mainline?

Ian

gcc/:

2012-09-17  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-17  Ian Lance Taylor  <iant@google.com>

	* Makefile.def: Make all-gcc depend on all-libbacktrace.
	* Makefile.in: Rebuild.

Comments

Richard Biener Sept. 18, 2012, 8:49 a.m. UTC | #1
On Mon, Sep 17, 2012 at 7:17 PM, Ian Lance Taylor <iant@google.com> wrote:
> This patch to the diagnostic code uses the new backtrace library to
> print a backtrace on an ICE.  For example, here is the output of a test
> case I took from a C++ PR:
>
> /home/iant/foo2.cc:6:6: internal compiler error: in cp_lexer_new_from_tokens, at cp/parser.c:638
> 0xec549f internal_error(char const*, ...)
>         ../../trunk/gcc/diagnostic.c:1057
> 0xec3f53 fancy_abort(char const*, int, char const*)
>         ../../trunk/gcc/diagnostic.c:1111
> 0x5ff78e cp_lexer_new_from_tokens
>         ../../trunk/gcc/cp/parser.c:638
> 0x5ff78e cp_parser_push_lexer_for_tokens
>         ../../trunk/gcc/cp/parser.c:3290
> 0x60ff40 cp_parser_late_parsing_for_member
>         ../../trunk/gcc/cp/parser.c:21713
> 0x60ff40 cp_parser_class_specifier_1
>         ../../trunk/gcc/cp/parser.c:18207
> 0x60ff40 cp_parser_class_specifier
>         ../../trunk/gcc/cp/parser.c:18231
> 0x60ff40 cp_parser_type_specifier
>         ../../trunk/gcc/cp/parser.c:13390
> 0x61c83d cp_parser_decl_specifier_seq
>         ../../trunk/gcc/cp/parser.c:10731
> 0x628317 cp_parser_single_declaration
>         ../../trunk/gcc/cp/parser.c:21313
> 0x6289c0 cp_parser_template_declaration_after_export
>         ../../trunk/gcc/cp/parser.c:21198
> 0x62de39 cp_parser_declaration
>         ../../trunk/gcc/cp/parser.c:10183
> 0x62c487 cp_parser_declaration_seq_opt
>         ../../trunk/gcc/cp/parser.c:10105
> 0x62c762 cp_parser_translation_unit
>         ../../trunk/gcc/cp/parser.c:3757
> 0x62c762 c_parse_file()
>         ../../trunk/gcc/cp/parser.c:27557
> 0x72e4e4 c_common_parse_file()
>         ../../trunk/gcc/c-family/c-opts.c:1138
> Please submit a full bug report,
> with preprocessed source if appropriate.
> See <http://gcc.gnu.org/bugs.html> for instructions.
>
>
> Bootstrapped on x86_64-unknown-linux-gnu.  I didn't bother to run the
> testsuite, since the code only changes when an ICE occurs anyhow.
>
> OK for mainline?

Hm.  Can you please be that verbose only for ENABLE_CHECKING compilers?
I'd say that we should do sth fancy with the backtrace first, like in your
example note that it came from an assert (and skip the first two frames),
or more simple - skip frames until the function name we printed anyways
is listed.  Then for !ENABLE_CHECKING I'd derive bugzilla components
(backtrace from the frontend? from which tree/RTL pass?).

I mean the above is so verbose that bugreporters likely will only paste the
last non-interesting lines like

0x62c762 cp_parser_translation_unit
        ../../trunk/gcc/cp/parser.c:3757
0x62c762 c_parse_file()
        ../../trunk/gcc/cp/parser.c:27557
0x72e4e4 c_common_parse_file()
        ../../trunk/gcc/c-family/c-opts.c:1138
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.

also consider ICEs from infinite recursion - you'd get a way too large backtrace
(so please consider pruning recursions).

Or at least provide a way to disable the backtrace printing with a configure
switch.

Thanks,
Richard.

> Ian
>
> gcc/:
>
> 2012-09-17  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-17  Ian Lance Taylor  <iant@google.com>
>
>         * Makefile.def: Make all-gcc depend on all-libbacktrace.
>         * Makefile.in: Rebuild.
>
>
Richard Biener Sept. 18, 2012, 8:51 a.m. UTC | #2
On Tue, Sep 18, 2012 at 10:49 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Mon, Sep 17, 2012 at 7:17 PM, Ian Lance Taylor <iant@google.com> wrote:
>> This patch to the diagnostic code uses the new backtrace library to
>> print a backtrace on an ICE.  For example, here is the output of a test
>> case I took from a C++ PR:
>>
>> /home/iant/foo2.cc:6:6: internal compiler error: in cp_lexer_new_from_tokens, at cp/parser.c:638
>> 0xec549f internal_error(char const*, ...)
>>         ../../trunk/gcc/diagnostic.c:1057
>> 0xec3f53 fancy_abort(char const*, int, char const*)
>>         ../../trunk/gcc/diagnostic.c:1111
>> 0x5ff78e cp_lexer_new_from_tokens
>>         ../../trunk/gcc/cp/parser.c:638
>> 0x5ff78e cp_parser_push_lexer_for_tokens
>>         ../../trunk/gcc/cp/parser.c:3290
>> 0x60ff40 cp_parser_late_parsing_for_member
>>         ../../trunk/gcc/cp/parser.c:21713
>> 0x60ff40 cp_parser_class_specifier_1
>>         ../../trunk/gcc/cp/parser.c:18207
>> 0x60ff40 cp_parser_class_specifier
>>         ../../trunk/gcc/cp/parser.c:18231
>> 0x60ff40 cp_parser_type_specifier
>>         ../../trunk/gcc/cp/parser.c:13390
>> 0x61c83d cp_parser_decl_specifier_seq
>>         ../../trunk/gcc/cp/parser.c:10731
>> 0x628317 cp_parser_single_declaration
>>         ../../trunk/gcc/cp/parser.c:21313
>> 0x6289c0 cp_parser_template_declaration_after_export
>>         ../../trunk/gcc/cp/parser.c:21198
>> 0x62de39 cp_parser_declaration
>>         ../../trunk/gcc/cp/parser.c:10183
>> 0x62c487 cp_parser_declaration_seq_opt
>>         ../../trunk/gcc/cp/parser.c:10105
>> 0x62c762 cp_parser_translation_unit
>>         ../../trunk/gcc/cp/parser.c:3757
>> 0x62c762 c_parse_file()
>>         ../../trunk/gcc/cp/parser.c:27557
>> 0x72e4e4 c_common_parse_file()
>>         ../../trunk/gcc/c-family/c-opts.c:1138
>> Please submit a full bug report,
>> with preprocessed source if appropriate.
>> See <http://gcc.gnu.org/bugs.html> for instructions.
>>
>>
>> Bootstrapped on x86_64-unknown-linux-gnu.  I didn't bother to run the
>> testsuite, since the code only changes when an ICE occurs anyhow.
>>
>> OK for mainline?
>
> Hm.  Can you please be that verbose only for ENABLE_CHECKING compilers?
> I'd say that we should do sth fancy with the backtrace first, like in your
> example note that it came from an assert (and skip the first two frames),
> or more simple - skip frames until the function name we printed anyways
> is listed.  Then for !ENABLE_CHECKING I'd derive bugzilla components
> (backtrace from the frontend? from which tree/RTL pass?).
>
> I mean the above is so verbose that bugreporters likely will only paste the
> last non-interesting lines like
>
> 0x62c762 cp_parser_translation_unit
>         ../../trunk/gcc/cp/parser.c:3757
> 0x62c762 c_parse_file()
>         ../../trunk/gcc/cp/parser.c:27557
> 0x72e4e4 c_common_parse_file()
>         ../../trunk/gcc/c-family/c-opts.c:1138
> Please submit a full bug report,
> with preprocessed source if appropriate.
> See <http://gcc.gnu.org/bugs.html> for instructions.
>
> also consider ICEs from infinite recursion - you'd get a way too large backtrace
> (so please consider pruning recursions).

Which also means to use an alternate stack for all this (we probably should
use sigaltstack for the ICEs anyway).

Richard.
Ian Lance Taylor Sept. 18, 2012, 1:58 p.m. UTC | #3
On Tue, Sep 18, 2012 at 1:49 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Mon, Sep 17, 2012 at 7:17 PM, Ian Lance Taylor <iant@google.com> wrote:
>> This patch to the diagnostic code uses the new backtrace library to
>> print a backtrace on an ICE.  For example, here is the output of a test
>> case I took from a C++ PR:
>>
>> /home/iant/foo2.cc:6:6: internal compiler error: in cp_lexer_new_from_tokens, at cp/parser.c:638
>> 0xec549f internal_error(char const*, ...)
>>         ../../trunk/gcc/diagnostic.c:1057
>> 0xec3f53 fancy_abort(char const*, int, char const*)
>>         ../../trunk/gcc/diagnostic.c:1111
>> 0x5ff78e cp_lexer_new_from_tokens
>>         ../../trunk/gcc/cp/parser.c:638
>> 0x5ff78e cp_parser_push_lexer_for_tokens
>>         ../../trunk/gcc/cp/parser.c:3290
>> 0x60ff40 cp_parser_late_parsing_for_member
>>         ../../trunk/gcc/cp/parser.c:21713
>> 0x60ff40 cp_parser_class_specifier_1
>>         ../../trunk/gcc/cp/parser.c:18207
>> 0x60ff40 cp_parser_class_specifier
>>         ../../trunk/gcc/cp/parser.c:18231
>> 0x60ff40 cp_parser_type_specifier
>>         ../../trunk/gcc/cp/parser.c:13390
>> 0x61c83d cp_parser_decl_specifier_seq
>>         ../../trunk/gcc/cp/parser.c:10731
>> 0x628317 cp_parser_single_declaration
>>         ../../trunk/gcc/cp/parser.c:21313
>> 0x6289c0 cp_parser_template_declaration_after_export
>>         ../../trunk/gcc/cp/parser.c:21198
>> 0x62de39 cp_parser_declaration
>>         ../../trunk/gcc/cp/parser.c:10183
>> 0x62c487 cp_parser_declaration_seq_opt
>>         ../../trunk/gcc/cp/parser.c:10105
>> 0x62c762 cp_parser_translation_unit
>>         ../../trunk/gcc/cp/parser.c:3757
>> 0x62c762 c_parse_file()
>>         ../../trunk/gcc/cp/parser.c:27557
>> 0x72e4e4 c_common_parse_file()
>>         ../../trunk/gcc/c-family/c-opts.c:1138
>> Please submit a full bug report,
>> with preprocessed source if appropriate.
>> See <http://gcc.gnu.org/bugs.html> for instructions.
>>
>>
>> Bootstrapped on x86_64-unknown-linux-gnu.  I didn't bother to run the
>> testsuite, since the code only changes when an ICE occurs anyhow.
>>
>> OK for mainline?
>
> Hm.  Can you please be that verbose only for ENABLE_CHECKING compilers?

That would be easy enough but I don't think it's a good idea.  The
time when this can help the most is when we get a bug report from
somebody who doesn't know how to or doesn't want to share the input
file.  The backtrace can show us whether this is a known ICE.  But
that will only work if we actually dump the backtrace for a release
compiler.

It's not like this is something that happens in an ordinary
compilation.  I think verbosity is just fine here.

> I'd say that we should do sth fancy with the backtrace first, like in your
> example note that it came from an assert (and skip the first two frames),
> or more simple - skip frames until the function name we printed anyways
> is listed.

That function name is not convenient to access.  I changed the
backtrace to simply skip any leading stack frames in diagnostic.c,
which achieves the same effect.

> Then for !ENABLE_CHECKING I'd derive bugzilla components
> (backtrace from the frontend? from which tree/RTL pass?).

That's a good idea but I'd rather leave it for later.

> I mean the above is so verbose that bugreporters likely will only paste the
> last non-interesting lines like

I added an explicit note directing them to include the complete backtrace.

> also consider ICEs from infinite recursion - you'd get a way too large backtrace
> (so please consider pruning recursions).

In my original patch the backtrace is already cut off after 20 functions.

> Or at least provide a way to disable the backtrace printing with a configure
> switch.

Again, I don't think this is necessary or appropriate.  I could add a
command line option to disable the backtrace if you think that is
important, but I think it's important that the default be to print it.

I've attached the updated patch.  Here is what it prints now.

/home/iant/foo2.cc:6:6: internal compiler error: in
cp_lexer_new_from_tokens, at cp/parser.c:638
0x5ff78e cp_lexer_new_from_tokens
	../../trunk/gcc/cp/parser.c:638
0x5ff78e cp_parser_push_lexer_for_tokens
	../../trunk/gcc/cp/parser.c:3290
0x60ff40 cp_parser_late_parsing_for_member
	../../trunk/gcc/cp/parser.c:21713
0x60ff40 cp_parser_class_specifier_1
	../../trunk/gcc/cp/parser.c:18207
0x60ff40 cp_parser_class_specifier
	../../trunk/gcc/cp/parser.c:18231
0x60ff40 cp_parser_type_specifier
	../../trunk/gcc/cp/parser.c:13390
0x61c83d cp_parser_decl_specifier_seq
	../../trunk/gcc/cp/parser.c:10731
0x628317 cp_parser_single_declaration
	../../trunk/gcc/cp/parser.c:21313
0x6289c0 cp_parser_template_declaration_after_export
	../../trunk/gcc/cp/parser.c:21198
0x62de39 cp_parser_declaration
	../../trunk/gcc/cp/parser.c:10183
0x62c487 cp_parser_declaration_seq_opt
	../../trunk/gcc/cp/parser.c:10105
0x62c762 cp_parser_translation_unit
	../../trunk/gcc/cp/parser.c:3757
0x62c762 c_parse_file()
	../../trunk/gcc/cp/parser.c:27557
0x72e4e4 c_common_parse_file()
	../../trunk/gcc/c-family/c-opts.c:1138
Please submit a full bug report,
with preprocessed source if appropriate.
Please include the complete backtrace with any bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.

Ian
Markus Trippelsdorf Sept. 18, 2012, 2:40 p.m. UTC | #4
On 2012.09.18 at 06:58 -0700, Ian Lance Taylor wrote:
> On Tue, Sep 18, 2012 at 1:49 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
> > On Mon, Sep 17, 2012 at 7:17 PM, Ian Lance Taylor <iant@google.com> wrote:
> >> OK for mainline?
> >
> > Hm.  Can you please be that verbose only for ENABLE_CHECKING compilers?
> 
> That would be easy enough but I don't think it's a good idea.  The
> time when this can help the most is when we get a bug report from
> somebody who doesn't know how to or doesn't want to share the input
> file.  The backtrace can show us whether this is a known ICE.  But
> that will only work if we actually dump the backtrace for a release
> compiler.
> 
> It's not like this is something that happens in an ordinary
> compilation.  I think verbosity is just fine here.
> 
> > Or at least provide a way to disable the backtrace printing with a configure
> > switch.
> 
> Again, I don't think this is necessary or appropriate.  I could add a
> command line option to disable the backtrace if you think that is
> important, but I think it's important that the default be to print it.

If you use "make install-strip" to install, then libbacktrace will have
been build in vain. At least for this case a way to disable libbacktrace
should be available.
Richard Biener Sept. 18, 2012, 2:55 p.m. UTC | #5
On Tue, Sep 18, 2012 at 4:40 PM, Markus Trippelsdorf
<markus@trippelsdorf.de> wrote:
> On 2012.09.18 at 06:58 -0700, Ian Lance Taylor wrote:
>> On Tue, Sep 18, 2012 at 1:49 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>> > On Mon, Sep 17, 2012 at 7:17 PM, Ian Lance Taylor <iant@google.com> wrote:
>> >> OK for mainline?
>> >
>> > Hm.  Can you please be that verbose only for ENABLE_CHECKING compilers?
>>
>> That would be easy enough but I don't think it's a good idea.  The
>> time when this can help the most is when we get a bug report from
>> somebody who doesn't know how to or doesn't want to share the input
>> file.  The backtrace can show us whether this is a known ICE.  But
>> that will only work if we actually dump the backtrace for a release
>> compiler.
>>
>> It's not like this is something that happens in an ordinary
>> compilation.  I think verbosity is just fine here.
>>
>> > Or at least provide a way to disable the backtrace printing with a configure
>> > switch.
>>
>> Again, I don't think this is necessary or appropriate.  I could add a
>> command line option to disable the backtrace if you think that is
>> important, but I think it's important that the default be to print it.
>
> If you use "make install-strip" to install, then libbacktrace will have
> been build in vain. At least for this case a way to disable libbacktrace
> should be available.

Indeed - we ship binaries with stripped debug info, usually not installed.
libbacktrace will only produce useless garbage then.  So I want a way
to disable it (at least by default) at configure time.

Richard.

> --
> Markus
Markus Trippelsdorf Sept. 18, 2012, 3:09 p.m. UTC | #6
On 2012.09.18 at 16:55 +0200, Richard Guenther wrote:
> On Tue, Sep 18, 2012 at 4:40 PM, Markus Trippelsdorf
> <markus@trippelsdorf.de> wrote:
> > On 2012.09.18 at 06:58 -0700, Ian Lance Taylor wrote:
> >> On Tue, Sep 18, 2012 at 1:49 AM, Richard Guenther
> >> <richard.guenther@gmail.com> wrote:
> >> > On Mon, Sep 17, 2012 at 7:17 PM, Ian Lance Taylor <iant@google.com> wrote:
> >> >> OK for mainline?
> >> >
> >> > Hm.  Can you please be that verbose only for ENABLE_CHECKING compilers?
> >>
> >> That would be easy enough but I don't think it's a good idea.  The
> >> time when this can help the most is when we get a bug report from
> >> somebody who doesn't know how to or doesn't want to share the input
> >> file.  The backtrace can show us whether this is a known ICE.  But
> >> that will only work if we actually dump the backtrace for a release
> >> compiler.
> >>
> >> It's not like this is something that happens in an ordinary
> >> compilation.  I think verbosity is just fine here.
> >>
> >> > Or at least provide a way to disable the backtrace printing with a configure
> >> > switch.
> >>
> >> Again, I don't think this is necessary or appropriate.  I could add a
> >> command line option to disable the backtrace if you think that is
> >> important, but I think it's important that the default be to print it.
> >
> > If you use "make install-strip" to install, then libbacktrace will have
> > been build in vain. At least for this case a way to disable libbacktrace
> > should be available.
> 
> Indeed - we ship binaries with stripped debug info, usually not installed.
> libbacktrace will only produce useless garbage then.  So I want a way
> to disable it (at least by default) at configure time.

To be fair, libbacktrace doesn't print garbage in this case. It's clever
enough to just get out of the way...
Ian Lance Taylor Sept. 18, 2012, 4:24 p.m. UTC | #7
On Tue, Sep 18, 2012 at 7:40 AM, Markus Trippelsdorf
<markus@trippelsdorf.de> wrote:
>
> If you use "make install-strip" to install, then libbacktrace will have
> been build in vain. At least for this case a way to disable libbacktrace
> should be available.

Why bother?  The library will fail to find anything useful to print,
and nothing will be printed.

Ian
Ian Lance Taylor Sept. 18, 2012, 4:25 p.m. UTC | #8
On Tue, Sep 18, 2012 at 7:55 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
>
> Indeed - we ship binaries with stripped debug info, usually not installed.
> libbacktrace will only produce useless garbage then.  So I want a way
> to disable it (at least by default) at configure time.

The library won't print useless garbage.  That would be pointless.  It
simply won't print anything at all.

I can add a configure option to not dump backtraces if you really want
it.  I only care that the default is to print them.

Ian
diff mbox

Patch

Index: gcc/diagnostic.c
===================================================================
--- gcc/diagnostic.c	(revision 191393)
+++ gcc/diagnostic.c	(working copy)
@@ -27,8 +27,10 @@  along with GCC; see the file COPYING3.  
 #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,93 @@  diagnostic_show_locus (diagnostic_contex
   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;
+
+  /* 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,6 +423,17 @@  diagnostic_action_after_output (diagnost
       break;
 
     case DK_ICE:
+      {
+	struct backtrace_state *state =
+	  backtrace_create_state (NULL, 0, bt_err_callback, NULL);
+	if (state != NULL)
+	  {
+	    int count = 0;
+	    backtrace_full (state, 2, bt_callback, bt_err_callback,
+			    (void *) &count);
+	  }
+      }
+
       if (context->abort_on_error)
 	real_abort ();
 
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 191393)
+++ gcc/Makefile.in	(working copy)
@@ -346,6 +346,11 @@  DECNUMFMT = $(srcdir)/../libdecnumber/$(
 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@
@@ -905,6 +910,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
@@ -987,7 +993,7 @@  BUILD_LIBIBERTY = $(build_libobjdir)/lib
 
 # 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.
@@ -995,8 +1001,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.
@@ -1028,7 +1034,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:
@@ -2613,7 +2619,8 @@  fold-const.o : fold-const.c $(CONFIG_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) \
Index: Makefile.def
===================================================================
--- Makefile.def	(revision 191397)
+++ Makefile.def	(working copy)
@@ -305,6 +305,7 @@  dependencies = { module=all-gcc; on=all-
 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; };