X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fcp-support.c;h=4bbee943b24665c47447536f2e19abfee648bc8f;hb=00923338dec84505addaf9cdeca2e9c844757824;hp=6b85ecb2f87a585f55cbdc301cf9d1594c1af576;hpb=0e9f083f4cb94a9dc861f38ba151aac06efce2b8;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 6b85ecb2f8..4bbee943b2 100644 --- a/gdb/cp-support.c +++ b/gdb/cp-support.c @@ -1,5 +1,5 @@ /* Helper routines for C++ support in GDB. - Copyright (C) 2002-2013 Free Software Foundation, Inc. + Copyright (C) 2002-2015 Free Software Foundation, Inc. Contributed by MontaVista Software. @@ -20,9 +20,7 @@ #include "defs.h" #include "cp-support.h" -#include #include "demangle.h" -#include "gdb_assert.h" #include "gdbcmd.h" #include "dictionary.h" #include "objfiles.h" @@ -31,10 +29,10 @@ #include "block.h" #include "complaints.h" #include "gdbtypes.h" -#include "exceptions.h" #include "expression.h" #include "value.h" #include "cp-abi.h" +#include #include "safe-ctype.h" @@ -58,7 +56,7 @@ static void overload_list_add_symbol (struct symbol *sym, const char *oload_name); static void make_symbol_overload_list_using (const char *func_name, - const char *namespace); + const char *the_namespace); static void make_symbol_overload_list_qualified (const char *func_name); @@ -159,7 +157,6 @@ inspect_type (struct demangle_parse_info *info, int i; char *name; struct symbol *sym; - volatile struct gdb_exception except; /* Copy the symbol's name from RET_COMP and look it up in the symbol table. */ @@ -175,12 +172,18 @@ inspect_type (struct demangle_parse_info *info, } sym = NULL; - TRY_CATCH (except, RETURN_MASK_ALL) - { - sym = lookup_symbol (name, 0, VAR_DOMAIN, 0); - } - if (except.reason >= 0 && sym != NULL) + TRY + { + sym = lookup_symbol (name, 0, VAR_DOMAIN, 0); + } + CATCH (except, RETURN_MASK_ALL) + { + return 0; + } + END_CATCH + + if (sym != NULL) { struct type *otype = SYMBOL_TYPE (sym); @@ -243,18 +246,19 @@ inspect_type (struct demangle_parse_info *info, } buf = mem_fileopen (); - TRY_CATCH (except, RETURN_MASK_ERROR) + TRY { type_print (type, "", buf, -1); } /* If type_print threw an exception, there is little point in continuing, so just bow out gracefully. */ - if (except.reason < 0) + CATCH (except, RETURN_MASK_ERROR) { ui_file_delete (buf); return 0; } + END_CATCH name = ui_file_obsavestring (buf, &info->obstack, &len); ui_file_delete (buf); @@ -328,15 +332,15 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info, { if (d_left (comp)->type == DEMANGLE_COMPONENT_NAME) { - struct demangle_component new; + struct demangle_component newobj; ui_file_write (buf, d_left (comp)->u.s_name.s, d_left (comp)->u.s_name.len); name = ui_file_obsavestring (buf, &info->obstack, &len); - new.type = DEMANGLE_COMPONENT_NAME; - new.u.s_name.s = name; - new.u.s_name.len = len; - if (inspect_type (info, &new, finder, data)) + newobj.type = DEMANGLE_COMPONENT_NAME; + newobj.u.s_name.s = name; + newobj.u.s_name.len = len; + if (inspect_type (info, &newobj, finder, data)) { char *n, *s; long slen; @@ -346,7 +350,7 @@ replace_typedefs_qualified_name (struct demangle_parse_info *info, node. */ ui_file_rewind (buf); - n = cp_comp_to_string (&new, 100); + n = cp_comp_to_string (&newobj, 100); if (n == NULL) { /* If something went astray, abort typedef substitutions. */ @@ -448,17 +452,21 @@ replace_typedefs (struct demangle_parse_info *info, if (local_name != NULL) { - struct symbol *sym; - volatile struct gdb_exception except; + struct symbol *sym = NULL; sym = NULL; - TRY_CATCH (except, RETURN_MASK_ALL) + TRY { sym = lookup_symbol (local_name, 0, VAR_DOMAIN, 0); } + CATCH (except, RETURN_MASK_ALL) + { + } + END_CATCH + xfree (local_name); - if (except.reason >= 0 && sym != NULL) + if (sym != NULL) { struct type *otype = SYMBOL_TYPE (sym); const char *new_name = (*finder) (otype, data); @@ -1176,7 +1184,7 @@ overload_list_add_symbol (struct symbol *sym, struct symbol ** make_symbol_overload_list (const char *func_name, - const char *namespace) + const char *the_namespace) { struct cleanup *old_cleanups; const char *name; @@ -1189,15 +1197,15 @@ make_symbol_overload_list (const char *func_name, old_cleanups = make_cleanup (xfree, sym_return_val); - make_symbol_overload_list_using (func_name, namespace); + make_symbol_overload_list_using (func_name, the_namespace); - if (namespace[0] == '\0') + if (the_namespace[0] == '\0') name = func_name; else { char *concatenated_name - = alloca (strlen (namespace) + 2 + strlen (func_name) + 1); - strcpy (concatenated_name, namespace); + = alloca (strlen (the_namespace) + 2 + strlen (func_name) + 1); + strcpy (concatenated_name, the_namespace); strcat (concatenated_name, "::"); strcat (concatenated_name, func_name); name = concatenated_name; @@ -1220,9 +1228,7 @@ make_symbol_overload_list_block (const char *name, struct block_iterator iter; struct symbol *sym; - for (sym = block_iter_name_first (block, name, &iter); - sym != NULL; - sym = block_iter_name_next (name, &iter)) + ALL_BLOCK_SYMBOLS_WITH_NAME (block, name, iter, sym) overload_list_add_symbol (sym, name); } @@ -1230,19 +1236,19 @@ make_symbol_overload_list_block (const char *name, static void make_symbol_overload_list_namespace (const char *func_name, - const char *namespace) + const char *the_namespace) { const char *name; const struct block *block = NULL; - if (namespace[0] == '\0') + if (the_namespace[0] == '\0') name = func_name; else { char *concatenated_name - = alloca (strlen (namespace) + 2 + strlen (func_name) + 1); + = alloca (strlen (the_namespace) + 2 + strlen (func_name) + 1); - strcpy (concatenated_name, namespace); + strcpy (concatenated_name, the_namespace); strcat (concatenated_name, "::"); strcat (concatenated_name, func_name); name = concatenated_name; @@ -1267,7 +1273,7 @@ static void make_symbol_overload_list_adl_namespace (struct type *type, const char *func_name) { - char *namespace; + char *the_namespace; const char *type_name; int i, prefix_len; @@ -1291,15 +1297,15 @@ make_symbol_overload_list_adl_namespace (struct type *type, if (prefix_len != 0) { - namespace = alloca (prefix_len + 1); - strncpy (namespace, type_name, prefix_len); - namespace[prefix_len] = '\0'; + the_namespace = alloca (prefix_len + 1); + strncpy (the_namespace, type_name, prefix_len); + the_namespace[prefix_len] = '\0'; - make_symbol_overload_list_namespace (func_name, namespace); + make_symbol_overload_list_namespace (func_name, the_namespace); } /* Check public base type */ - if (TYPE_CODE (type) == TYPE_CODE_CLASS) + if (TYPE_CODE (type) == TYPE_CODE_STRUCT) for (i = 0; i < TYPE_N_BASECLASSES (type); i++) { if (BASETYPE_VIA_PUBLIC (type, i)) @@ -1344,7 +1350,7 @@ reset_directive_searched (void *data) static void make_symbol_overload_list_using (const char *func_name, - const char *namespace) + const char *the_namespace) { struct using_direct *current; const struct block *block; @@ -1369,7 +1375,7 @@ make_symbol_overload_list_using (const char *func_name, if (current->alias != NULL || current->declaration != NULL) continue; - if (strcmp (namespace, current->import_dest) == 0) + if (strcmp (the_namespace, current->import_dest) == 0) { /* Mark this import as searched so that the recursive call does not search it again. */ @@ -1387,7 +1393,7 @@ make_symbol_overload_list_using (const char *func_name, } /* Now, add names for this namespace. */ - make_symbol_overload_list_namespace (func_name, namespace); + make_symbol_overload_list_namespace (func_name, the_namespace); } /* This does the bulk of the work of finding overloaded symbols. @@ -1397,7 +1403,7 @@ make_symbol_overload_list_using (const char *func_name, static void make_symbol_overload_list_qualified (const char *func_name) { - struct symtab *s; + struct compunit_symtab *cust; struct objfile *objfile; const struct block *b, *surrounding_static_block = 0; @@ -1421,17 +1427,17 @@ make_symbol_overload_list_qualified (const char *func_name) /* Go through the symtabs and check the externs and statics for symbols which match. */ - ALL_PRIMARY_SYMTABS (objfile, s) + ALL_COMPUNITS (objfile, cust) { QUIT; - b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); + b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), GLOBAL_BLOCK); make_symbol_overload_list_block (func_name, b); } - ALL_PRIMARY_SYMTABS (objfile, s) + ALL_COMPUNITS (objfile, cust) { QUIT; - b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); + b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), STATIC_BLOCK); /* Don't do this block twice. */ if (b == surrounding_static_block) continue; @@ -1465,7 +1471,7 @@ cp_lookup_rtti_type (const char *name, struct block *block) switch (TYPE_CODE (rtti_type)) { - case TYPE_CODE_CLASS: + case TYPE_CODE_STRUCT: break; case TYPE_CODE_NAMESPACE: /* chastain/2003-11-26: the symbol tables often contain fake @@ -1482,12 +1488,134 @@ cp_lookup_rtti_type (const char *name, struct block *block) return rtti_type; } +#ifdef HAVE_WORKING_FORK + +/* If nonzero, attempt to catch crashes in the demangler and print + useful debugging information. */ + +static int catch_demangler_crashes = 1; + +/* Stack context and environment for demangler crash recovery. */ + +static SIGJMP_BUF gdb_demangle_jmp_buf; + +/* If nonzero, attempt to dump core from the signal handler. */ + +static int gdb_demangle_attempt_core_dump = 1; + +/* Signal handler for gdb_demangle. */ + +static void +gdb_demangle_signal_handler (int signo) +{ + if (gdb_demangle_attempt_core_dump) + { + if (fork () == 0) + dump_core (); + + gdb_demangle_attempt_core_dump = 0; + } + + 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 HAVE_WORKING_FORK +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + struct sigaction sa, old_sa; +#else + void (*ofunc) (); +#endif + static int core_dump_allowed = -1; + + if (core_dump_allowed == -1) + { + core_dump_allowed = can_dump_core (LIMIT_CUR); + + if (!core_dump_allowed) + gdb_demangle_attempt_core_dump = 0; + } + + if (catch_demangler_crashes) + { +#if defined (HAVE_SIGACTION) && defined (SA_RESTART) + sa.sa_handler = gdb_demangle_signal_handler; + sigemptyset (&sa.sa_mask); +#ifdef HAVE_SIGALTSTACK + sa.sa_flags = SA_ONSTACK; +#else + sa.sa_flags = 0; +#endif + sigaction (SIGSEGV, &sa, &old_sa); +#else + ofunc = (void (*)()) signal (SIGSEGV, gdb_demangle_signal_handler); +#endif + + crash_signal = SIGSETJMP (gdb_demangle_jmp_buf); + } +#endif + + if (crash_signal == 0) + result = bfd_demangle (NULL, name, options); + +#ifdef 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) + { + char *short_msg, *long_msg; + struct cleanup *back_to; + + short_msg = xstrprintf (_("unable to demangle '%s' " + "(demangler failed with signal %d)"), + name, crash_signal); + back_to = make_cleanup (xfree, short_msg); + + long_msg = xstrprintf ("%s:%d: %s: %s", __FILE__, __LINE__, + "demangler-warning", short_msg); + make_cleanup (xfree, long_msg); + + target_terminal_ours (); + begin_line (); + if (core_dump_allowed) + fprintf_unfiltered (gdb_stderr, + _("%s\nAttempting to dump core.\n"), + long_msg); + else + warn_cant_dump_core (long_msg); + + demangler_warning (__FILE__, __LINE__, "%s", short_msg); + + do_cleanups (back_to); + + error_reported = 1; + } + + result = NULL; + } + } +#endif + + return result; } /* Don't allow just "maintenance cplus". */ @@ -1499,7 +1627,7 @@ maint_cplus_command (char *arg, int from_tty) "by the name of a command.\n")); help_list (maint_cplus_cmd_list, "maintenance cplus ", - -1, gdb_stdout); + all_commands, gdb_stdout); } /* This is a front end for cp_find_first_component, for unit testing. @@ -1562,4 +1690,17 @@ _initialize_cp_support (void) Usage: info vtbl EXPRESSION\n\ Evaluate EXPRESSION and display the virtual function table for the\n\ resulting object.")); + +#ifdef 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 }