X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fcp-support.c;h=5662f86249763aff3bbae1b7ba1fe83acdddb5c0;hb=f166f943f30a91792e8754cbca9d7652fc400aae;hp=3c1442d15e6be30722124591b46a6f956e41b061;hpb=8de20a37d6eb551a69a04b1b8e67874b9f14123d;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/cp-support.c b/gdb/cp-support.c index 3c1442d15e..5662f86249 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-2016 Free Software Foundation, Inc. Contributed by MontaVista Software. @@ -20,9 +20,7 @@ #include "defs.h" #include "cp-support.h" -#include "gdb_string.h" #include "demangle.h" -#include "gdb_assert.h" #include "gdbcmd.h" #include "dictionary.h" #include "objfiles.h" @@ -31,15 +29,14 @@ #include "block.h" #include "complaints.h" #include "gdbtypes.h" -#include "exceptions.h" #include "expression.h" #include "value.h" #include "cp-abi.h" - +#include "namespace.h" +#include +#include "gdb_setjmp.h" #include "safe-ctype.h" -#include "psymtab.h" - #define d_left(dc) (dc)->u.s_binary.left #define d_right(dc) (dc)->u.s_binary.right @@ -60,7 +57,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); @@ -95,7 +92,7 @@ copy_string_to_obstack (struct obstack *obstack, const char *string, long *len) { *len = strlen (string); - return obstack_copy (obstack, string, *len); + return (char *) obstack_copy (obstack, string, *len); } /* A cleanup wrapper for cp_demangled_name_parse_free. */ @@ -161,7 +158,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. */ @@ -177,12 +173,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).symbol; + } + CATCH (except, RETURN_MASK_ALL) + { + return 0; + } + END_CATCH + + if (sym != NULL) { struct type *otype = SYMBOL_TYPE (sym); @@ -200,8 +202,9 @@ inspect_type (struct demangle_parse_info *info, return 0; } - /* If the type is a typedef, replace it. */ - if (TYPE_CODE (otype) == TYPE_CODE_TYPEDEF) + /* If the type is a typedef or namespace alias, replace it. */ + if (TYPE_CODE (otype) == TYPE_CODE_TYPEDEF + || TYPE_CODE (otype) == TYPE_CODE_NAMESPACE) { long len; int is_anon; @@ -212,6 +215,13 @@ inspect_type (struct demangle_parse_info *info, /* Get the real type of the typedef. */ type = check_typedef (otype); + /* If the symbol is a namespace and its type name is no different + than the name we looked up, this symbol is not a namespace + alias and does not need to be substituted. */ + if (TYPE_CODE (otype) == TYPE_CODE_NAMESPACE + && strcmp (TYPE_NAME (type), name) == 0) + return 0; + is_anon = (TYPE_TAG_NAME (type) == NULL && (TYPE_CODE (type) == TYPE_CODE_ENUM || TYPE_CODE (type) == TYPE_CODE_STRUCT @@ -237,18 +247,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); @@ -322,15 +333,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; @@ -340,7 +351,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. */ @@ -442,17 +453,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).symbol; + } + CATCH (except, RETURN_MASK_ALL) { - sym = lookup_symbol (local_name, 0, VAR_DOMAIN, 0); } + 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); @@ -1022,8 +1037,13 @@ cp_find_first_component_aux (const char *name, int permissive) return strlen (name); } case '\0': - case ':': return index; + case ':': + /* ':' marks a component iff the next character is also a ':'. + Otherwise it is probably malformed input. */ + if (name[index + 1] == ':') + return index; + break; case 'o': /* Operator names can screw up the recursion. */ if (operator_possible @@ -1170,28 +1190,27 @@ 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; sym_return_val_size = 100; sym_return_val_index = 0; - sym_return_val = xmalloc ((sym_return_val_size + 1) * - sizeof (struct symbol *)); + sym_return_val = XNEWVEC (struct symbol *, sym_return_val_size + 1); sym_return_val[0] = NULL; 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); + = (char *) 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; @@ -1214,9 +1233,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); } @@ -1224,19 +1241,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); + = (char *) 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; @@ -1261,7 +1278,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; @@ -1285,15 +1302,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 = (char *) 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)) @@ -1327,7 +1344,7 @@ make_symbol_overload_list_adl (struct type **arg_types, int nargs, static void reset_directive_searched (void *data) { - struct using_direct *direct = data; + struct using_direct *direct = (struct using_direct *) data; direct->searched = 0; } @@ -1338,7 +1355,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; @@ -1363,7 +1380,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. */ @@ -1381,7 +1398,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. @@ -1391,7 +1408,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; @@ -1415,17 +1432,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; @@ -1441,7 +1458,9 @@ cp_lookup_rtti_type (const char *name, struct block *block) struct symbol * rtti_sym; struct type * rtti_type; - rtti_sym = lookup_symbol (name, block, STRUCT_DOMAIN, NULL); + /* Use VAR_DOMAIN here as NAME may be a typedef. PR 18141, 18417. + Classes "live" in both STRUCT_DOMAIN and VAR_DOMAIN. */ + rtti_sym = lookup_symbol (name, block, VAR_DOMAIN, NULL).symbol; if (rtti_sym == NULL) { @@ -1455,11 +1474,11 @@ cp_lookup_rtti_type (const char *name, struct block *block) return NULL; } - rtti_type = SYMBOL_TYPE (rtti_sym); + rtti_type = check_typedef (SYMBOL_TYPE (rtti_sym)); 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 @@ -1476,12 +1495,136 @@ 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 + sighandler_t 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 = 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); + + make_cleanup_restore_target_terminal (); + target_terminal_ours_for_output (); + + 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". */ @@ -1493,7 +1636,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. @@ -1510,7 +1653,7 @@ first_component_command (char *arg, int from_tty) return; len = cp_find_first_component (arg); - prefix = alloca (len + 1); + prefix = (char *) alloca (len + 1); memcpy (prefix, arg, len); prefix[len] = '\0'; @@ -1556,4 +1699,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 }