Update comment for struct type's length field, introduce type_length_units
[deliverable/binutils-gdb.git] / gdb / cp-support.c
index 91533e8e4ece62353232e610686e27c8dcf26f26..3db9751924e11e7d626b688b84b6bb35081255a9 100644 (file)
@@ -1,5 +1,5 @@
 /* Helper routines for C++ support in GDB.
-   Copyright (C) 2002-2014 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 <string.h>
 #include "demangle.h"
-#include "gdb_assert.h"
 #include "gdbcmd.h"
 #include "dictionary.h"
 #include "objfiles.h"
 #include "block.h"
 #include "complaints.h"
 #include "gdbtypes.h"
-#include "exceptions.h"
 #include "expression.h"
 #include "value.h"
 #include "cp-abi.h"
-#include "language.h"
+#include <signal.h>
 
 #include "safe-ctype.h"
 
@@ -59,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);
 
@@ -160,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.  */
@@ -176,34 +172,18 @@ inspect_type (struct demangle_parse_info *info,
     }
 
   sym = NULL;
-  TRY_CATCH (except, RETURN_MASK_ALL)
-  {
-    /* It is not legal to have a typedef and tag name of the same
-       name in C++.  However, anonymous composite types that are defined
-       with a typedef ["typedef struct {...} anonymous_struct;"] WILL
-       have symbols for a TYPE_CODE_TYPEDEF (in VAR_DOMAIN) and a
-       TYPE_CODE_STRUCT (in STRUCT_DOMAIN).
-
-       If VAR_DOMAIN is searched first, it will return the TYPEDEF symbol,
-       and this function will never output the definition of the typedef,
-       since type_print is called below with SHOW = -1. [The typedef hash
-       is never initialized/used when SHOW <= 0 -- and the finder
-       (find_typedef_for_canonicalize) will always return NULL as a result.]
-
-       Consequently, type_print will eventually keep calling this function
-       to replace the typedef (via
-       print_name_maybe_canonical/cp_canonicalize_full).  This leads to
-       infinite recursion.
-
-       This can all be safely avoid by explicitly searching STRUCT_DOMAIN
-       first to find the structure definition.  */
-    if (current_language->la_language == language_cplus)
-      sym = lookup_symbol (name, 0, STRUCT_DOMAIN, 0);
-    if (sym == NULL)
-      sym = lookup_symbol (name, 0, VAR_DOMAIN, NULL);
-  }
 
-  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);
 
@@ -266,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);
@@ -351,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;
@@ -369,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.  */
@@ -471,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);
@@ -1199,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;
@@ -1212,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;
@@ -1243,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);
 }
 
@@ -1253,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;
@@ -1290,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;
 
@@ -1314,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))
@@ -1367,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;
@@ -1392,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.  */
@@ -1410,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.
@@ -1420,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;
 
@@ -1444,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;
@@ -1470,7 +1453,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);
 
   if (rtti_sym == NULL)
     {
@@ -1484,11 +1469,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
@@ -1505,12 +1490,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".  */
@@ -1522,7 +1629,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.
@@ -1585,4 +1692,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
 }
This page took 0.030909 seconds and 4 git commands to generate.