From patchwork Thu Jan 12 16:41:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 91188 Delivered-To: patch@linaro.org Received: by 10.182.3.34 with SMTP id 2csp1991928obz; Thu, 12 Jan 2017 08:42:34 -0800 (PST) X-Received: by 10.99.38.198 with SMTP id m189mr18548705pgm.140.1484239354172; Thu, 12 Jan 2017 08:42:34 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id 33si9768606plt.66.2017.01.12.08.42.33 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 Jan 2017 08:42:34 -0800 (PST) Received-SPF: pass (google.com: domain of binutils-return-95378-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org; spf=pass (google.com: domain of binutils-return-95378-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=binutils-return-95378-patch=linaro.org@sourceware.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:to:from:subject:message-id:date:mime-version :content-type; q=dns; s=default; b=CJOn7L/HChwNc+uo1dksWt8KZRMG0 /rfOP3+KIIdscy4nKqmmqmkD6NRXgLBr+Z3egueCravBXuMUiVCLGaCFWMWMACv0 PNQfV075PRODTXFyZm6I6D202NSBhvOpJbGcR6ZeufK7tgfEXcsMSY1adNPs06Ax 4CY1/YuOInR9eE= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:to:from:subject:message-id:date:mime-version :content-type; s=default; bh=yPtiqMqn832xvlAE+KKLnnTpNWU=; b=GA6 Z4RkjjEKI60bqrkalCabguKMYhs3Xd7N4WDWv0PypnW6tWABHhU/M1W92Yk6Mqu5 mRnzcziaGlqpx1kG91Zf/Ajay0NWcLZdfgcuWxWHNItz0CqWZTLKXdbBNVsxyCyG GnY2ZyCZLyS5aTIJDZXoEQ/DLFBjUk2A5BiLtOMs= Received: (qmail 39042 invoked by alias); 12 Jan 2017 16:42:13 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Delivered-To: mailing list binutils@sourceware.org Received: (qmail 38909 invoked by uid 89); 12 Jan 2017 16:42:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.4 required=5.0 tests=BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=no version=3.3.2 spammy=bus, iot, IOT, SIGABRT X-HELO: mail-yw0-f193.google.com Received: from mail-yw0-f193.google.com (HELO mail-yw0-f193.google.com) (209.85.161.193) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 12 Jan 2017 16:42:02 +0000 Received: by mail-yw0-f193.google.com with SMTP id l75so1803439ywb.3 for ; Thu, 12 Jan 2017 08:42:02 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version; bh=WJvLPyc3MqQB3yfaXrAUqn/hktLmu2YGthDnuBNV3rQ=; b=qbqBm8iXorWPp3rzvoOdgPtCaxA7NlCfV9hpnCnonbiRmUuu/KYhd2BhiIDvnJ9ogW ix4jzqUvb7H90umlVGYCvD88BcDdvMkuSUQUeVUrhnKWz7nPsZ3P1vU3hDq8tZUBNbU/ YTxWrSxLkz9ACNlOdrxQAjVwky7mHzCQEMLoqKtYzzc2DK5bDFoNUxhggZL9qOuYe9Qr 5Sz0nclGZmrkDMOhZtk/EmClCGZ88hgZKWQ0zESm8x1JiSLmlrt11Edt8GgZPYAe6I34 2MzUAd0JSMFxD1qr24SLFPA4IXhJqtOKQm9xV+FsjgCcPrBZk0c/lbrBawYhr41gyI6s 7Tog== X-Gm-Message-State: AIkVDXK4iiiwbCACujWyVTakkGhaj2QETSfeo90QDCIV3TLkkqMnLgTnuPrkL3YEHARYGg== X-Received: by 10.13.201.65 with SMTP id l62mr12975441ywd.96.1484239321021; Thu, 12 Jan 2017 08:42:01 -0800 (PST) Received: from ?IPv6:2620:10d:c0a3:20fb:f6d0:5ac5:64cd:f102? ([2620:10d:c091:200::d:41ba]) by smtp.googlemail.com with ESMTPSA id z65sm3874758ywf.0.2017.01.12.08.42.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 12 Jan 2017 08:42:00 -0800 (PST) To: nickc@redhat.com, binutils@sourceware.org From: Nathan Sidwell Subject: [GAS PATCH] intercept signal crashes Message-ID: Date: Thu, 12 Jan 2017 11:41:58 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.6.0 MIME-Version: 1.0 gas's fatal signal handling is not as nice as gcc's has become. This patch is a move towards fixing that. 1) rather than have as_assert and as_abort fatal error functions with almost the same behaviour -- they differ only in their initial message. This patch kills 'as_assert' and rewords 'as_abort' to meet assert fail behaviour. So now on a failed assert, instead of: Internal error! Assertion failure in FOO at BAZ:17. Please report this bug. we get Internal error in FOO at BAZ:17. Please report this bug. That's now the same message for any explicit call to 'abort'. 2) Added a signal handler to catch SEGV, ILL, BUS, ABRT, IOT and FPE (when they exist), and forward it to as_abort using a NULL FILE, so we get a message such as: Internal error (Segmentation fault). Please report this bug. or in the worst case: Internal error (unknown). Please report this bug. I tested that on an x86_64-linux system by using gdb to inject a signal into gas. Most of that handling code is stolen from gcc (toplev.c, diagnostic.c and system.h) ok? nathan -- Nathan Sidwell 2017-01-12 Nathan Sidwell * as.h (gas_assert): Use abort. (as_assert): Remove. (signal_init): Declare. * as.c (main): Call signal_init. * messages.c: #include (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. diff --git a/gas/as.c b/gas/as.c index 6c55e76..83a572b 100644 --- a/gas/as.c +++ b/gas/as.c @@ -1186,6 +1186,7 @@ main (int argc, char ** argv) int macro_strip_at; start_time = get_run_time (); + signal_init (); #ifdef HAVE_SBRK start_sbrk = (char *) sbrk (0); #endif diff --git a/gas/as.h b/gas/as.h index 76aa9ac..fee7c75 100644 --- a/gas/as.h +++ b/gas/as.h @@ -85,8 +85,7 @@ #if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 6) #define __PRETTY_FUNCTION__ ((char *) NULL) #endif -#define gas_assert(P) \ - ((void) ((P) ? 0 : (as_assert (__FILE__, __LINE__, __PRETTY_FUNCTION__), 0))) +#define gas_assert(P) ((void) ((P) ? 0 : (abort (), 0))) #undef abort #define abort() as_abort (__FILE__, __LINE__, __PRETTY_FUNCTION__) @@ -459,8 +458,8 @@ PRINTF_LIKE (as_warn); PRINTF_WHERE_LIKE (as_bad_where); PRINTF_WHERE_LIKE (as_warn_where); -void as_assert (const char *, int, const char *) ATTRIBUTE_NORETURN; void as_abort (const char *, int, const char *) ATTRIBUTE_NORETURN; +void signal_init (void); void sprint_value (char *, addressT); int had_errors (void); int had_warnings (void); diff --git a/gas/config.in b/gas/config.in index 5129c28..0855179 100644 --- a/gas/config.in +++ b/gas/config.in @@ -144,6 +144,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H +/* Define to 1 if you have the `strsignal' function. */ +#undef HAVE_STRSIGNAL + /* Define if has struct stat.st_mtim.tv_nsec */ #undef HAVE_ST_MTIM_TV_NSEC diff --git a/gas/configure b/gas/configure index 2b54054..d3ae96e 100755 --- a/gas/configure +++ b/gas/configure @@ -13899,6 +13899,17 @@ _ACEOF fi done +for ac_func in strsignal +do : + ac_fn_c_check_func "$LINENO" "strsignal" "ac_cv_func_strsignal" +if test "x$ac_cv_func_strsignal" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_STRSIGNAL 1 +_ACEOF + +fi +done + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LC_MESSAGES" >&5 diff --git a/gas/configure.ac b/gas/configure.ac index c4c3036..cc70aa7 100644 --- a/gas/configure.ac +++ b/gas/configure.ac @@ -826,6 +826,7 @@ AC_C_INLINE # VMS doesn't have unlink. AC_CHECK_FUNCS(unlink remove, break) AC_CHECK_FUNCS(sbrk setlocale) +AC_CHECK_FUNCS(strsignal) AM_LC_MESSAGES diff --git a/gas/messages.c b/gas/messages.c index f452f22..57d4ed7 100644 --- a/gas/messages.c +++ b/gas/messages.c @@ -18,11 +18,19 @@ 02110-1301, USA. */ #include "as.h" +#include + +/* 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. */