* command.c (shell_escape, make_command, _initialze_command):
[deliverable/binutils-gdb.git] / gdb / dwarfread.c
index 6d635439fff11889592fbc5ae5ea32cde5e33703..3da9e7673b60031e810eaf5da58e7d8bc082ea90 100644 (file)
@@ -52,11 +52,12 @@ other things to work on, if you get bored. :-)
 #include "demangle.h"
 #include "expression.h"        /* Needed for enum exp_opcode in language.h, sigh... */
 #include "language.h"
+#include "complaints.h"
 
-#include <varargs.h>
 #include <fcntl.h>
 #include <string.h>
 #include <sys/types.h>
+
 #ifndef        NO_SYS_FILE
 #include <sys/file.h>
 #endif
@@ -66,11 +67,117 @@ other things to work on, if you get bored. :-)
 #define L_SET 0
 #endif
 
-#ifdef MAINTENANCE     /* Define to 1 to compile in some maintenance stuff */
-#define SQUAWK(stuff) dwarfwarn stuff
-#else
-#define SQUAWK(stuff)
-#endif
+/* Some macros to provide DIE info for complaints. */
+
+#define DIE_ID (curdie!=NULL ? curdie->die_ref : 0)
+#define DIE_NAME (curdie!=NULL && curdie->at_name!=NULL) ? curdie->at_name : ""
+
+/* Complaints that can be issued during DWARF debug info reading. */
+
+struct complaint no_bfd_get_N =
+{
+  "DIE @ 0x%x \"%s\", no bfd support for %d byte data object", 0, 0
+};
+
+struct complaint malformed_die =
+{
+  "DIE @ 0x%x \"%s\", malformed DIE, bad length (%d bytes)", 0, 0
+};
+
+struct complaint bad_die_ref =
+{
+  "DIE @ 0x%x \"%s\", reference to DIE (0x%x) outside compilation unit", 0, 0
+};
+
+struct complaint unknown_attribute_form =
+{
+  "DIE @ 0x%x \"%s\", unknown attribute form (0x%x)", 0, 0
+};
+
+struct complaint unknown_attribute_length =
+{
+  "DIE @ 0x%x \"%s\", unknown attribute length, skipped remaining attributes", 0, 0
+};
+
+struct complaint unexpected_fund_type =
+{
+  "DIE @ 0x%x \"%s\", unexpected fundamental type 0x%x", 0, 0
+};
+
+struct complaint unknown_type_modifier =
+{
+  "DIE @ 0x%x \"%s\", unknown type modifier %u", 0, 0
+};
+
+struct complaint volatile_ignored =
+{
+  "DIE @ 0x%x \"%s\", type modifier 'volatile' ignored", 0, 0
+};
+
+struct complaint const_ignored =
+{
+  "DIE @ 0x%x \"%s\", type modifier 'const' ignored", 0, 0
+};
+
+struct complaint botched_modified_type =
+{
+  "DIE @ 0x%x \"%s\", botched modified type decoding (mtype 0x%x)", 0, 0
+};
+
+struct complaint op_deref2 =
+{
+  "DIE @ 0x%x \"%s\", OP_DEREF2 address 0x%x not handled", 0, 0
+};
+
+struct complaint op_deref4 =
+{
+  "DIE @ 0x%x \"%s\", OP_DEREF4 address 0x%x not handled", 0, 0
+};
+
+struct complaint basereg_not_handled =
+{
+  "DIE @ 0x%x \"%s\", BASEREG %d not handled", 0, 0
+};
+
+struct complaint dup_user_type_allocation =
+{
+  "DIE @ 0x%x \"%s\", internal error: duplicate user type allocation", 0, 0
+};
+
+struct complaint dup_user_type_definition =
+{
+  "DIE @ 0x%x \"%s\", internal error: duplicate user type definition", 0, 0
+};
+
+struct complaint missing_tag =
+{
+  "DIE @ 0x%x \"%s\", missing class, structure, or union tag", 0, 0
+};
+
+struct complaint bad_array_element_type =
+{
+  "DIE @ 0x%x \"%s\", bad array element type attribute 0x%x", 0, 0
+};
+
+struct complaint subscript_data_items =
+{
+  "DIE @ 0x%x \"%s\", can't decode subscript data items", 0, 0
+};
+
+struct complaint unhandled_array_subscript_format =
+{
+  "DIE @ 0x%x \"%s\", array subscript format 0x%x not handled yet", 0, 0
+};
+
+struct complaint unknown_array_subscript_format =
+{
+  "DIE @ 0x%x \"%s\", unknown array subscript format %x", 0, 0
+};
+
+struct complaint not_row_major =
+{
+  "DIE @ 0x%x \"%s\", array not row major; not handled correctly", 0, 0
+};
 
 #ifndef R_FP           /* FIXME */
 #define R_FP 14                /* Kludge to get frame pointer register number */
@@ -100,9 +207,6 @@ typedef unsigned int DIE_REF;       /* Reference to a DIE */
 #endif
 /* end-sanitize-chill */
 
-#define STREQ(a,b)             (strcmp(a,b)==0)
-#define STREQN(a,b,n)          (strncmp(a,b,n)==0)
-
 /* Flags to target_to_host() that tell whether or not the data object is
    expected to be signed.  Used, for example, when fetching a signed
    integer in the target environment which is used as a signed integer
@@ -371,9 +475,6 @@ static void
 read_lexical_block_scope PARAMS ((struct dieinfo *, char *, char *,
                                  struct objfile *));
 
-static void
-dwarfwarn ();
-
 static void
 scan_partial_symbols PARAMS ((char *, char *, struct objfile *));
 
@@ -587,9 +688,13 @@ set_cu_language (dip)
       case LANG_FORTRAN77:
       case LANG_FORTRAN90:
       case LANG_PASCAL83:
-      default:
+       /* We don't know anything special about these yet. */
        cu_language = language_unknown;
        break;
+      default:
+       /* If no at_language, try to deduce one from the filename */
+       cu_language = deduce_language_from_filename (dip -> at_name);
+       break;
     }
   cu_language_defn = language_def (cu_language);
 }
@@ -712,55 +817,6 @@ record_minimal_symbol (name, address, ms_type, objfile)
 
 /*
 
-LOCAL FUNCTION
-
-       dwarfwarn -- issue a DWARF related warning
-
-DESCRIPTION
-
-       Issue warnings about DWARF related things that aren't serious enough
-       to warrant aborting with an error, but should not be ignored either.
-       This includes things like detectable corruption in DIE's, missing
-       DIE's, unimplemented features, etc.
-
-       In general, running across tags or attributes that we don't recognize
-       is not considered to be a problem and we should not issue warnings
-       about such.
-
-NOTES
-
-       We mostly follow the example of the error() routine, but without
-       returning to command level.  It is arguable about whether warnings
-       should be issued at all, and if so, where they should go (stdout or
-       stderr).
-
-       We assume that curdie is valid and contains at least the basic
-       information for the DIE where the problem was noticed.
-*/
-
-static void
-dwarfwarn (va_alist)
-     va_dcl
-{
-  va_list ap;
-  char *fmt;
-  
-  va_start (ap);
-  fmt = va_arg (ap, char *);
-  warning_setup ();
-  fprintf (stderr, "warning: DWARF ref 0x%x: ", curdie -> die_ref);
-  if (curdie -> at_name)
-    {
-      fprintf (stderr, "'%s': ", curdie -> at_name);
-    }
-  vfprintf (stderr, fmt, ap);
-  fprintf (stderr, "\n");
-  fflush (stderr);
-  va_end (ap);
-}
-
-/*
-
 LOCAL FUNCTION
 
        read_lexical_block_scope -- process all dies in a lexical block
@@ -826,7 +882,7 @@ lookup_utype (die_ref)
   utypeidx = (die_ref - dbroff) / 4;
   if ((utypeidx < 0) || (utypeidx >= numutypes))
     {
-      dwarfwarn ("reference to DIE (0x%x) outside compilation unit", die_ref);
+      complain (&bad_die_ref, DIE_ID, DIE_NAME);
     }
   else
     {
@@ -870,12 +926,12 @@ alloc_utype (die_ref, utypep)
   if ((utypeidx < 0) || (utypeidx >= numutypes))
     {
       utypep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
-      dwarfwarn ("reference to DIE (0x%x) outside compilation unit", die_ref);
+      complain (&bad_die_ref, DIE_ID, DIE_NAME);
     }
   else if (*typep != NULL)
     {
       utypep = *typep;
-      SQUAWK (("internal error: dup user type allocation"));
+      complain (&dup_user_type_allocation, DIE_ID, DIE_NAME);
     }
   else
     {
@@ -976,7 +1032,9 @@ struct_type (dip, thisdie, enddie, objfile)
   char *tpart1;
   struct dieinfo mbr;
   char *nextdie;
+#if !BITS_BIG_ENDIAN
   int anonymous_size;
+#endif
   
   if ((type = lookup_utype (dip -> die_ref)) == NULL)
     {
@@ -1002,7 +1060,7 @@ struct_type (dip, thisdie, enddie, objfile)
        /* Should never happen */
        TYPE_CODE (type) = TYPE_CODE_UNDEF;
        tpart1 = "???";
-       SQUAWK (("missing class, structure, or union tag"));
+       complain (&missing_tag, DIE_ID, DIE_NAME);
        break;
     }
   /* Some compilers try to be helpful by inventing "fake" names for
@@ -1210,7 +1268,7 @@ decode_array_element_type (scan)
   scan += SIZEOF_ATTRIBUTE;
   if ((nbytes = attribute_size (attribute)) == -1)
     {
-      SQUAWK (("bad array element type attribute 0x%x", attribute));
+      complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
       typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
     }
   else
@@ -1237,7 +1295,7 @@ decode_array_element_type (scan)
            typep = decode_mod_u_d_type (scan);
            break;
          default:
-           SQUAWK (("bad array element type attribute 0x%x", attribute));
+           complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
            typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
            break;
          }
@@ -1298,6 +1356,7 @@ decode_subscript_data_item (scan, end)
   struct type *typep = NULL;   /* Array type we are building */
   struct type *nexttype;       /* Type of each element (may be array) */
   struct type *indextype;      /* Type of this index */
+  struct type *rangetype;
   unsigned int format;
   unsigned short fundtype;
   unsigned long lowbound;
@@ -1326,11 +1385,12 @@ decode_subscript_data_item (scan, end)
       if (nexttype == NULL)
        {
          /* Munged subscript data or other problem, fake it. */
-         SQUAWK (("can't decode subscript data items"));
+         complain (&subscript_data_items, DIE_ID, DIE_NAME);
          nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
        }
-      typep = create_array_type ((struct type *) NULL, nexttype, indextype,
-                                lowbound, highbound);
+      rangetype = create_range_type ((struct type *) NULL, indextype,
+                                     lowbound, highbound);
+      typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
       break;
     case FMT_FT_C_X:
     case FMT_FT_X_C:
@@ -1339,14 +1399,16 @@ decode_subscript_data_item (scan, end)
     case FMT_UT_C_X:
     case FMT_UT_X_C:
     case FMT_UT_X_X:
-      SQUAWK (("array subscript format 0x%x not handled yet", format));
-      typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
-      typep = create_array_type ((struct type *) NULL, typep, typep, 0, 1);
+      complain (&unhandled_array_subscript_format, DIE_ID, DIE_NAME, format);
+      nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+      rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0);
+      typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
       break;
     default:
-      SQUAWK (("unknown array subscript format %x", format));
-      typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
-      typep = create_array_type ((struct type *) NULL, typep, typep, 0, 1);
+      complain (&unknown_array_subscript_format, DIE_ID, DIE_NAME, format);
+      nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+      rangetype = create_range_type ((struct type *) NULL, nexttype, 0, 0);
+      typep = create_array_type ((struct type *) NULL, nexttype, rangetype);
       break;
     }
   return (typep);
@@ -1382,7 +1444,7 @@ dwarf_read_array_type (dip)
   if (dip -> at_ordering != ORD_row_major)
     {
       /* FIXME:  Can gdb even handle column major arrays? */
-      SQUAWK (("array not row major; not handled correctly"));
+      complain (&not_row_major, DIE_ID, DIE_NAME);
     }
   if ((sub = dip -> at_subscr_data) != NULL)
     {
@@ -1412,7 +1474,7 @@ dwarf_read_array_type (dip)
        {
          /* Double ick!  Not only is a type already in our slot, but
             someone has decorated it.  Complain and leave it alone. */
-         SQUAWK (("duplicate user defined array type definition"));
+         complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
        }
     }
 }
@@ -1521,7 +1583,7 @@ read_subroutine_type (dip, thisdie, enddie)
     }
   else
     {
-      SQUAWK (("duplicate user defined function type definition"));
+      complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
     }
 }
 
@@ -1675,6 +1737,7 @@ enum_type (dip, objfile)
          memset (sym, 0, sizeof (struct symbol));
          SYMBOL_NAME (sym) = create_name (list -> field.name,
                                           &objfile->symbol_obstack);
+         SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language);
          SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
          SYMBOL_CLASS (sym) = LOC_CONST;
          SYMBOL_TYPE (sym) = type;
@@ -2142,7 +2205,8 @@ locval (loc)
            else
              {
                stack[++stacki] = 0;
-               SQUAWK (("BASEREG %d not handled!", regno));
+
+               complain (&basereg_not_handled, DIE_ID, DIE_NAME, regno);
              }
            break;
          case OP_ADDR:
@@ -2159,10 +2223,10 @@ locval (loc)
            break;
          case OP_DEREF2:
            /* pop, deref and push 2 bytes (as a long) */
-           SQUAWK (("OP_DEREF2 address 0x%x not handled", stack[stacki]));
+           complain (&op_deref2, DIE_ID, DIE_NAME, stack[stacki]);
            break;
          case OP_DEREF4:       /* pop, deref and push 4 bytes (as a long) */
-           SQUAWK (("OP_DEREF4 address 0x%x not handled", stack[stacki]));
+           complain (&op_deref4, DIE_ID, DIE_NAME, stack[stacki]);
            break;
          case OP_ADD:  /* pop top 2 items, add, push result */
            stack[stacki - 1] += stack[stacki];
@@ -2481,7 +2545,8 @@ add_enum_psymbol (dip, objfile)
        {
          scan += TARGET_FT_LONG_SIZE (objfile);
          ADD_PSYMBOL_TO_LIST (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST,
-                              objfile -> static_psymbols, 0);
+                              objfile -> static_psymbols, 0, cu_language,
+                              objfile);
          scan += strlen (scan) + 1;
        }
     }
@@ -2517,7 +2582,7 @@ add_partial_symbol (dip, objfile)
       ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
                           VAR_NAMESPACE, LOC_BLOCK,
                           objfile -> global_psymbols,
-                          dip -> at_low_pc);
+                          dip -> at_low_pc, cu_language, objfile);
       break;
     case TAG_global_variable:
       record_minimal_symbol (dip -> at_name, locval (dip -> at_location),
@@ -2525,25 +2590,25 @@ add_partial_symbol (dip, objfile)
       ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
                           VAR_NAMESPACE, LOC_STATIC,
                           objfile -> global_psymbols,
-                          0);
+                          0, cu_language, objfile);
       break;
     case TAG_subroutine:
       ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
                           VAR_NAMESPACE, LOC_BLOCK,
                           objfile -> static_psymbols,
-                          dip -> at_low_pc);
+                          dip -> at_low_pc, cu_language, objfile);
       break;
     case TAG_local_variable:
       ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
                           VAR_NAMESPACE, LOC_STATIC,
                           objfile -> static_psymbols,
-                          0);
+                          0, cu_language, objfile);
       break;
     case TAG_typedef:
       ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
                           VAR_NAMESPACE, LOC_TYPEDEF,
                           objfile -> static_psymbols,
-                          0);
+                          0, cu_language, objfile);
       break;
     case TAG_class_type:
     case TAG_structure_type:
@@ -2552,14 +2617,14 @@ add_partial_symbol (dip, objfile)
       ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
                           STRUCT_NAMESPACE, LOC_TYPEDEF,
                           objfile -> static_psymbols,
-                          0);
+                          0, cu_language, objfile);
       if (cu_language == language_cplus)
        {
          /* For C++, these implicitly act as typedefs as well. */
          ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
                               VAR_NAMESPACE, LOC_TYPEDEF,
                               objfile -> static_psymbols,
-                              0);
+                              0, cu_language, objfile);
        }
       break;
     }
@@ -2668,7 +2733,8 @@ scan_partial_symbols (thisdie, enddie, objfile)
                      temp = dbbase + di.at_sibling - dbroff;
                      if ((temp < thisdie) || (temp >= enddie))
                        {
-                         dwarfwarn ("reference to DIE (0x%x) outside compilation unit", di.at_sibling);
+                         complain (&bad_die_ref, DIE_ID, DIE_NAME,
+                                   di.at_sibling);
                        }
                      else
                        {
@@ -2865,6 +2931,14 @@ new_symbol (dip, objfile)
       SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
       SYMBOL_CLASS (sym) = LOC_STATIC;
       SYMBOL_TYPE (sym) = decode_die_type (dip);
+
+      /* If this symbol is from a C++ compilation, then attempt to cache the
+        demangled form for future reference.  This is a typical time versus
+        space tradeoff, that was decided in favor of time because it sped up
+        C++ symbol lookups by a factor of about 20. */
+
+      SYMBOL_LANGUAGE (sym) = cu_language;
+      SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile -> symbol_obstack);
       switch (dip -> die_tag)
        {
        case TAG_label:
@@ -2993,6 +3067,7 @@ synthesize_typedef (dip, objfile, type)
       memset (sym, 0, sizeof (struct symbol));
       SYMBOL_NAME (sym) = create_name (dip -> at_name,
                                       &objfile->symbol_obstack);
+      SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language);
       SYMBOL_TYPE (sym) = type;
       SYMBOL_CLASS (sym) = LOC_TYPEDEF;
       SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
@@ -3166,7 +3241,7 @@ decode_modified_type (modifiers, modcount, mtype)
            }
          break;
        default:
-         SQUAWK (("botched modified type decoding (mtype 0x%x)", mtype));
+         complain (&botched_modified_type, DIE_ID, DIE_NAME, mtype);
          typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
          break;
        }
@@ -3184,17 +3259,16 @@ decode_modified_type (modifiers, modcount, mtype)
            typep = lookup_reference_type (typep);
            break;
          case MOD_const:
-           SQUAWK (("type modifier 'const' ignored"));         /* FIXME */
+           complain (&const_ignored, DIE_ID, DIE_NAME);  /* FIXME */
            break;
          case MOD_volatile:
-           SQUAWK (("type modifier 'volatile' ignored"));      /* FIXME */
+           complain (&volatile_ignored, DIE_ID, DIE_NAME); /* FIXME */
            break;
          default:
            if (!(MOD_lo_user <= (unsigned char) modifier
                  && (unsigned char) modifier <= MOD_hi_user))
              {
-               SQUAWK (("unknown type modifier %u",
-                        (unsigned char) modifier));
+               complain (&unknown_type_modifier, DIE_ID, DIE_NAME, modifier);
              }
            break;
        }
@@ -3337,7 +3411,7 @@ decode_fund_type (fundtype)
       typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
       if (!(FT_lo_user <= fundtype && fundtype <= FT_hi_user))
        {
-         SQUAWK (("unexpected fundamental type 0x%x", fundtype));
+         complain (&unexpected_fund_type, DIE_ID, DIE_NAME, fundtype);
        }
     }
     
@@ -3440,7 +3514,7 @@ basicdieinfo (dip, diep, objfile)
   if ((dip -> die_length < SIZEOF_DIE_LENGTH) ||
       ((diep + dip -> die_length) > (dbbase + dbsize)))
     {
-      dwarfwarn ("malformed DIE, bad length (%d bytes)", dip -> die_length);
+      complain (&malformed_die, DIE_ID, DIE_NAME, dip -> die_length);
       dip -> die_length = 0;
     }
   else if (dip -> die_length < (SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG))
@@ -3508,7 +3582,7 @@ completedieinfo (dip, objfile)
       diep += SIZEOF_ATTRIBUTE;
       if ((nbytes = attribute_size (attr)) == -1)
        {
-         SQUAWK (("unknown attribute length, skipped remaining attributes"));;
+         complain (&unknown_attribute_length, DIE_ID, DIE_NAME);
          diep = end;
          continue;
        }
@@ -3665,8 +3739,7 @@ completedieinfo (dip, objfile)
          diep += strlen (diep) + 1;
          break;
        default:
-         SQUAWK (("unknown attribute form (0x%x)", form));
-         SQUAWK (("unknown attribute length, skipped remaining attributes"));;
+         complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form);
          diep = end;
          break;
        }
@@ -3724,7 +3797,7 @@ target_to_host (from, nbytes, signextend, objfile)
        rtnval = bfd_get_8 (objfile -> obfd, (bfd_byte *) from);
        break;
       default:
-       dwarfwarn ("no bfd support for %d byte data object", nbytes);
+       complain (&no_bfd_get_N, DIE_ID, DIE_NAME, nbytes);
        rtnval = 0;
        break;
     }
@@ -3780,7 +3853,7 @@ attribute_size (attr)
        nbytes = TARGET_FT_POINTER_SIZE (objfile);
        break;
       default:
-       SQUAWK (("unknown attribute form (0x%x)", form));
+       complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form);
        nbytes = -1;
        break;
       }
This page took 0.031188 seconds and 4 git commands to generate.