From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26579 invoked by alias); 19 May 2014 11:48:14 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 26556 invoked by uid 89); 19 May 2014 11:48:13 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD,SPF_HELO_PASS,SPF_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 19 May 2014 11:48:11 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s4JBm46t021741 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 19 May 2014 07:48:04 -0400 Received: from blade.nx (ovpn-116-75.ams2.redhat.com [10.36.116.75]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s4JBm2Jn019432; Mon, 19 May 2014 07:48:03 -0400 Received: by blade.nx (Postfix, from userid 1000) id 245B926240E; Mon, 19 May 2014 12:48:02 +0100 (BST) Date: Mon, 19 May 2014 11:48:00 -0000 From: Gary Benson To: gdb-patches@sourceware.org Cc: Andrew Burgess , Doug Evans , Eli Zaretskii , Florian Weimer , Mark Kettenis , Pedro Alves , Tom Tromey Subject: [PATCH 2/2 v2] Demangler crash handler Message-ID: <20140519114801.GA31140@blade.nx> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-IsSubscribed: yes X-SW-Source: 2014-05/txt/msg00337.txt.bz2 Hi all, This patch is an updated version of patch 2 of the demangler crash handler I posted last week. Patch 1 of this series [1] remains the same. The main change I have made is to cause the crash handler to be disabled by default. The user must explicitly enable the handler with "maint set catch-demangler-crashes on". This will simplify triage of bugs such as PR 16957 [2], a new demangler crash that was reported on Friday. The user did not supply enough information to see the offending symbol, and I don't have the necessary compiler or libraries to reproduce the bug locally. With this patch we can instruct the user to enter "maint set catch-demangler-crashes on" and repeat whatever they did to cause the crash in the first place. We can then easily obtain the first offending symbol GDB encountered. The other main change I have made from the original patch is to remove as much code as possible from the signal handler itself such that only a (sig)longjmp remains. While this is still not strictly safe, it should be clear if any future problems have been caused by this because the problem will only occur if the user has enabled the crash handler. One final change from my original patch is that this patch uses internal_warning to offer the same "quit this session/create a core file" choices as offered for other internal problems. Is this ok to commit? Thanks, Gary -- [1] https://sourceware.org/ml/gdb-patches/2014-05/msg00109.html [2] https://sourceware.org/bugzilla/show_bug.cgi?id=16957 -- This patch adds a new maintainence boolean, catch_demangler_crashes. If set, calls to the demangler are wrapped with a segmentation fault handler. The first time a segmentation fault is caught the offending symbol is displayed and internal_warning is called. The NEWS file entry for this patch is as follows: * New options maint set catch-demangler-crashes (on|off) maint show catch-demangler-crashes Control whether the debugger should attempt to catch crashes in the symbol name demangler. The default is not to attempt to catch crashes. The first time a crash is caught the offending symbol is displayed and the user is presented with options to terminate the current session and/or to create a core file. gdb/ 2014-05-19 Gary Benson * cp-support.c (signal.h): New include. (catch_demangler_crashes): New flag. (SIGJMP_BUF): New define. (SIGSETJMP): Likewise. (SIGLONGJMP): Likewise. (gdb_demangle_jmp_buf): New variable. (gdb_demangle_signal_handler): New function. (gdb_demangle): If catch_demangler_crashes is set, install the above signal handler before calling bfd_demangle, and restore the original signal handler afterwards. Display the offending symbol and call internal_warning the first time a segmentation fault is caught. (_initialize_cp_support): New maint set/show command. gdb/doc/ 2014-05-19 Gary Benson * gdb.texinfo (Maintenance Commands): Document new "maint set/show catch-demangler-crashes" option. diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 91533e8..d065d1f 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -36,6 +36,7 @@ #include "value.h" #include "cp-abi.h" #include "language.h" +#include #include "safe-ctype.h" @@ -1505,12 +1506,101 @@ cp_lookup_rtti_type (const char *name, struct block *block) return rtti_type; } +#ifdef SIGSEGV + +/* If nonzero, attempt to catch crashes in the demangler and print + useful debugging information. */ + +static int catch_demangler_crashes = 0; + +/* Wrap set/long jmp so that it's more portable. */ + +#if defined(HAVE_SIGSETJMP) +#define SIGJMP_BUF sigjmp_buf +#define SIGSETJMP(buf) sigsetjmp((buf), 1) +#define SIGLONGJMP(buf,val) siglongjmp((buf), (val)) +#else +#define SIGJMP_BUF jmp_buf +#define SIGSETJMP(buf) setjmp(buf) +#define SIGLONGJMP(buf,val) longjmp((buf), (val)) +#endif + +/* Stack context and environment for demangler crash recovery. */ + +static SIGJMP_BUF gdb_demangle_jmp_buf; + +/* Signal handler for gdb_demangle. */ + +static void +gdb_demangle_signal_handler (int signo) +{ + SIGLONGJMP (gdb_demangle_jmp_buf, signo); +} + +#endif + /* A wrapper for bfd_demangle. */ char * gdb_demangle (const char *name, int options) { - return bfd_demangle (NULL, name, options); + char *result = NULL; + int crash_signal = 0; + +#ifdef SIGSEGV +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + struct sigaction sa, old_sa; + + if (catch_demangler_crashes) + { + sa.sa_handler = gdb_demangle_signal_handler; + sigemptyset (&sa.sa_mask); + sa.sa_flags = 0; + sigaction (SIGSEGV, &sa, &old_sa); + } +#else + void (*ofunc) (); + + if (catch_demangler_crashes) + ofunc = (void (*)()) signal (SIGSEGV, gdb_demangle_signal_handler); +#endif + + if (catch_demangler_crashes) + crash_signal = SIGSETJMP (gdb_demangle_jmp_buf); +#endif + + if (crash_signal == 0) + result = bfd_demangle (NULL, name, options); + +#ifdef SIGSEGV + if (catch_demangler_crashes) + { +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + sigaction (SIGSEGV, &old_sa, NULL); +#else + signal (SIGSEGV, ofunc); +#endif + + if (crash_signal != 0) + { + static int error_reported = 0; + + if (!error_reported) + { + internal_warning (__FILE__, __LINE__, + _("unable to demangle '%s' " + "(demangler failed with signal %d)"), + name, crash_signal); + + error_reported = 1; + } + + result = NULL; + } + } +#endif + + return result; } /* Don't allow just "maintenance cplus". */ @@ -1585,4 +1675,17 @@ _initialize_cp_support (void) Usage: info vtbl EXPRESSION\n\ Evaluate EXPRESSION and display the virtual function table for the\n\ resulting object.")); + +#ifdef SIGSEGV + add_setshow_boolean_cmd ("catch-demangler-crashes", class_maintenance, + &catch_demangler_crashes, _("\ +Set whether to attempt to catch demangler crashes."), _("\ +Show whether GDB will attempt to catch demangler crashes."), _("\ +If enabled GDB will attempt to catch demangler crashes and\n\ +display the offending symbol."), + NULL, + NULL, + &maintenance_set_cmdlist, + &maintenance_show_cmdlist); +#endif }