summaryrefslogtreecommitdiff
path: root/gas/messages.c
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2017-01-18 08:23:10 -0500
committerNathan Sidwell <nathan@acm.org>2017-01-18 08:23:10 -0500
commit1ec4b9f28bab4400c882a0f3e966eb12b73cee1a (patch)
treed5c4263ec5061e83bc72f5096247ec0ebec1b892 /gas/messages.c
parent319b82e47dd12d6554e17a2ceedd3139b88ba55f (diff)
downloadbinutils-gdb-1ec4b9f28bab4400c882a0f3e966eb12b73cee1a.tar.gz
Catch gas exit-via-signal
gas/ * as.h (gas_assert): Use abort. (as_assert): Remove. (signal_init): Declare. * as.c (main): Call signal_init. * messages.c: #include <signal.h> (as_assert): Delete. (as_abort): Allow NULL FILE. (signal_crash): New. (signal_init): Register fatal signal handlers. * configure.ac: Check for strsignal. * config.in: Rebuilt. * configure: Rebuilt.
Diffstat (limited to 'gas/messages.c')
-rw-r--r--gas/messages.c76
1 files changed, 55 insertions, 21 deletions
diff --git a/gas/messages.c b/gas/messages.c
index f452f227efb..57d4ed7c5e8 100644
--- a/gas/messages.c
+++ b/gas/messages.c
@@ -18,11 +18,19 @@
02110-1301, USA. */
#include "as.h"
+#include <signal.h>
+
+/* If the system doesn't provide strsignal, we get it defined in
+ libiberty but no declaration is supplied. Because, reasons. */
+#if !defined (HAVE_STRSIGNAL) && !defined (strsignal)
+extern const char *strsignal (int);
+#endif
static void identify (const char *);
static void as_show_where (void);
static void as_warn_internal (const char *, unsigned int, char *);
static void as_bad_internal (const char *, unsigned int, char *);
+static void signal_crash (int) ATTRIBUTE_NORETURN;
/* Despite the rest of the comments in this file, (FIXME-SOON),
here is the current scheme for error messages etc:
@@ -58,7 +66,10 @@ static void as_bad_internal (const char *, unsigned int, char *);
as_tsktsk() is used when we see a minor error for which
our error recovery action is almost certainly correct.
In this case, we print a message and then assembly
- continues as though no error occurred. */
+ continues as though no error occurred.
+
+ as_abort () is used for logic failure (assert or abort, signal).
+*/
static void
identify (const char *file)
@@ -286,38 +297,61 @@ as_fatal (const char *format, ...)
xexit (EXIT_FAILURE);
}
-/* Indicate assertion failure.
- Arguments: Filename, line number, optional function name. */
+/* Indicate internal constency error.
+ Arguments: Filename, line number, optional function name.
+ FILENAME may be NULL, which we use for crash-via-signal. */
void
-as_assert (const char *file, int line, const char *fn)
+as_abort (const char *file, int line, const char *fn)
{
as_show_where ();
- fprintf (stderr, _("Internal error!\n"));
- if (fn)
- fprintf (stderr, _("Assertion failure in %s at %s:%d.\n"),
- fn, file, line);
+
+ if (!file)
+ fprintf (stderr, _("Internal error (%s).\n"), fn ? fn : "unknown");
+ else if (fn)
+ fprintf (stderr, _("Internal error in %s at %s:%d.\n"), fn, file, line);
else
- fprintf (stderr, _("Assertion failure at %s:%d.\n"), file, line);
+ fprintf (stderr, _("Internal error at %s:%d.\n"), file, line);
+
fprintf (stderr, _("Please report this bug.\n"));
+
xexit (EXIT_FAILURE);
}
-/* as_abort: Print a friendly message saying how totally hosed we are,
- and exit without producing a core file. */
+/* Handler for fatal signals, such as SIGSEGV. */
+
+static void
+signal_crash (int signo)
+{
+ /* Reset, to prevent unbounded recursion. */
+ signal (signo, SIG_DFL);
+
+ as_abort (NULL, 0, strsignal (signo));
+}
+
+/* Register signal handlers, for less abrubt crashes. */
void
-as_abort (const char *file, int line, const char *fn)
+signal_init (void)
{
- as_show_where ();
- if (fn)
- fprintf (stderr, _("Internal error, aborting at %s:%d in %s\n"),
- file, line, fn);
- else
- fprintf (stderr, _("Internal error, aborting at %s:%d\n"),
- file, line);
- fprintf (stderr, _("Please report this bug.\n"));
- xexit (EXIT_FAILURE);
+#ifdef SIGSEGV
+ signal (SIGSEGV, signal_crash);
+#endif
+#ifdef SIGILL
+ signal (SIGILL, signal_crash);
+#endif
+#ifdef SIGBUS
+ signal (SIGBUS, signal_crash);
+#endif
+#ifdef SIGABRT
+ signal (SIGABRT, signal_crash);
+#endif
+#if defined SIGIOT && (!defined SIGABRT || SIGABRT != SIGIOT)
+ signal (SIGIOT, signal_crash);
+#endif
+#ifdef SIGFPE
+ signal (SIGFPE, signal_crash);
+#endif
}
/* Support routines. */