From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31770 invoked by alias); 4 Jun 2014 10:10:06 -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 31756 invoked by uid 89); 4 Jun 2014 10:10:05 -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; Wed, 04 Jun 2014 10:10:04 +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 s54A9xLi013722 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 4 Jun 2014 06:09:59 -0400 Received: from blade.nx (ovpn-116-110.ams2.redhat.com [10.36.116.110]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s54A9wZF022422; Wed, 4 Jun 2014 06:09:58 -0400 Received: by blade.nx (Postfix, from userid 1000) id EFF3526243C; Wed, 4 Jun 2014 11:09:57 +0100 (BST) Date: Wed, 04 Jun 2014 10:10: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 v3] Demangler crash handler Message-ID: <20140604100957.GC7570@blade.nx> References: <20140604100755.GA7570@blade.nx> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20140604100755.GA7570@blade.nx> X-IsSubscribed: yes X-SW-Source: 2014-06/txt/msg00143.txt.bz2 This patch wraps calls to the demangler with a segmentation fault handler. The first time a segmentation fault is caught a core file is generated and the user is prompted to file a bug and offered the choice to exit or to continue their GDB session. A maintainence option is provided to allow the user to disable the crash handler if required. Eli pointed out that SIGSEGV is an ANSI-standard signal but I found various other SIGSEGV checks in GDB so I have left the preprocessor conditionals intact for consistency. I hope this is ok. gdb/ 2014-06-04 Gary Benson * utils.h (dump_core): New declaration. * utils.c (dump_core): Make non-static. * 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 static global. (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 demangler_warning the first time a segmentation fault is caught. (_initialize_cp_support): New maint set/show command. gdb/doc/ 2014-06-04 Gary Benson * gdb.texinfo (Maintenance Commands): Document new "maint set/show catch-demangler-crashes" option. diff --git a/gdb/utils.h b/gdb/utils.h index 31f9c19..8ada98e 100644 --- a/gdb/utils.h +++ b/gdb/utils.h @@ -374,4 +374,8 @@ extern ULONGEST align_down (ULONGEST v, int n); extern LONGEST gdb_sign_extend (LONGEST value, int bit); +/* Dump core trying to increase the core soft limit to hard limit first. */ + +extern void dump_core (void); + #endif /* UTILS_H */ diff --git a/gdb/utils.c b/gdb/utils.c index 686b153..733c697 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -600,7 +600,7 @@ error_stream (struct ui_file *stream) /* Dump core trying to increase the core soft limit to hard limit first. */ -static void +void dump_core (void) { #ifdef HAVE_SETRLIMIT diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 91533e8..96f7d89 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,111 @@ cp_lookup_rtti_type (const char *name, struct block *block) return rtti_type; } +#if defined (SIGSEGV) && defined (HAVE_WORKING_FORK) + +/* If nonzero, attempt to catch crashes in the demangler and print + useful debugging information. */ + +static int catch_demangler_crashes = 1; + +/* 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) +{ + static int core_dumped = 0; + + if (!core_dumped) + { + if (fork () == 0) + dump_core (); + + core_dumped = 1; + } + + 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; + +#if defined (SIGSEGV) && defined (HAVE_WORKING_FORK) +#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); + +#if defined (SIGSEGV) && defined (HAVE_WORKING_FORK) + 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) + { + demangler_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 +1685,17 @@ _initialize_cp_support (void) Usage: info vtbl EXPRESSION\n\ Evaluate EXPRESSION and display the virtual function table for the\n\ resulting object.")); + +#if defined (SIGSEGV) && defined (HAVE_WORKING_FORK) + add_setshow_boolean_cmd ("catch-demangler-crashes", class_maintenance, + &catch_demangler_crashes, _("\ +Set whether to attempt to catch demangler crashes."), _("\ +Show whether to 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 } diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6104f55..6b39452 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -33235,6 +33235,17 @@ Expand symbol tables. If @var{regexp} is specified, only expand symbol tables for file names matching @var{regexp}. +@kindex maint set catch-demangler-crashes +@kindex maint show catch-demangler-crashes +@cindex demangler crashes +@item maint set catch-demangler-crashes [on|off] +@itemx maint show catch-demangler-crashes +Control whether @value{GDBN} should attempt to catch crashes in the +symbol name demangler. The default is to attempt to catch crashes. +If enabled, the first time a crash is caught, a core file is created, +the offending symbol is displayed and the user is presented with the +option to terminate the current session. + @kindex maint cplus first_component @item maint cplus first_component @var{name} Print the first C@t{++} class/namespace component of @var{name}.