summaryrefslogtreecommitdiff
path: root/gcc/diagnostic.c
diff options
context:
space:
mode:
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-09-26 12:38:08 +0000
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>2012-09-26 12:38:08 +0000
commit3f4257112ebaa98abb97d3170ad95eafd8998261 (patch)
tree4cd99601f0770b6683b8099f845efc0cb209f0f1 /gcc/diagnostic.c
parent8fdb69579a887bd55f8ecd98e999cc6b857721f2 (diff)
downloadgcc-3f4257112ebaa98abb97d3170ad95eafd8998261.tar.gz
./:
* Makefile.def: Make all-gcc depend on all-libbacktrace. * Makefile.in: Rebuild. gcc/: * 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). git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@191757 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/diagnostic.c')
-rw-r--r--gcc/diagnostic.c121
1 files changed, 115 insertions, 6 deletions
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index b3ae86c74a8..afe958d7623 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)