* command.c (shell_escape, make_command, _initialze_command):
[deliverable/binutils-gdb.git] / gdb / dwarfread.c
index 6d4cc1913c55e7ddd50ee734c31211db706c05a6..3da9e7673b60031e810eaf5da58e7d8bc082ea90 100644 (file)
@@ -41,10 +41,6 @@ other things to work on, if you get bored. :-)
 */
 
 #include "defs.h"
-#include <varargs.h>
-#include <fcntl.h>
-#include <string.h>
-
 #include "bfd.h"
 #include "symtab.h"
 #include "gdbtypes.h"
@@ -54,13 +50,135 @@ other things to work on, if you get bored. :-)
 #include "elf/dwarf.h"
 #include "buildsym.h"
 #include "demangle.h"
+#include "expression.h"        /* Needed for enum exp_opcode in language.h, sigh... */
+#include "language.h"
+#include "complaints.h"
 
-#ifdef MAINTENANCE     /* Define to 1 to compile in some maintenance stuff */
-#define SQUAWK(stuff) dwarfwarn stuff
-#else
-#define SQUAWK(stuff)
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+
+#ifndef        NO_SYS_FILE
+#include <sys/file.h>
+#endif
+
+/* FIXME -- convert this to SEEK_SET a la POSIX, move to config files.  */
+#ifndef L_SET
+#define L_SET 0
 #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 */
 #endif
@@ -76,15 +194,18 @@ typedef unsigned int DIE_REF;      /* Reference to a DIE */
 #endif
 
 #ifndef LCC_PRODUCER
-#define LCC_PRODUCER "LUCID C++ "
+#define LCC_PRODUCER "NCR C/C++"
 #endif
 
 #ifndef CFRONT_PRODUCER
 #define CFRONT_PRODUCER "CFRONT "      /* A wild a** guess... */
 #endif
 
-#define STREQ(a,b)             (strcmp(a,b)==0)
-#define STREQN(a,b,n)          (strncmp(a,b,n)==0)
+/* start-sanitize-chill */
+#ifndef CHILL_PRODUCER
+#define CHILL_PRODUCER "GNU Chill "
+#endif
+/* end-sanitize-chill */
 
 /* 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
@@ -195,18 +316,16 @@ struct dieinfo {
   unsigned long                at_member;
   unsigned long                at_discr;
   BLOCK *              at_discr_value;
-  unsigned short       at_visibility;
-  unsigned long                at_import;
   BLOCK *              at_string_length;
   char *               at_comp_dir;
   char *               at_producer;
-  unsigned long                at_frame_base;
   unsigned long                at_start_scope;
   unsigned long                at_stride_size;
   unsigned long                at_src_info;
   char *               at_prototyped;
   unsigned int         has_at_low_pc:1;
   unsigned int         has_at_stmt_list:1;
+  unsigned int         has_at_byte_size:1;
   unsigned int         short_element_list:1;
 };
 
@@ -214,6 +333,7 @@ static int diecount;        /* Approximate count of dies for compilation unit */
 static struct dieinfo *curdie; /* For warnings and such */
 
 static char *dbbase;   /* Base pointer to dwarf info */
+static int dbsize;     /* Size of dwarf info in bytes */
 static int dbroff;     /* Relative offset from start of .debug section */
 static char *lnbase;   /* Base pointer to line section */
 static int isreg;      /* Kludge to identify register variables */
@@ -254,10 +374,10 @@ static struct section_offsets *base_section_offsets;
  */
 
 struct dwfinfo {
-  int dbfoff;          /* Absolute file offset to start of .debug section */
+  file_ptr dbfoff;     /* Absolute file offset to start of .debug section */
   int dbroff;          /* Relative offset from start of .debug section */
   int dblength;                /* Size of the chunk of DIE's being examined */
-  int lnfoff;          /* Absolute file offset to line table fragment */
+  file_ptr lnfoff;     /* Absolute file offset to line table fragment */
 };
 
 #define DBFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbfoff)
@@ -297,11 +417,39 @@ struct pending **list_in_scope = &file_symbols;
    we can divide any DIE offset by 4 to obtain a unique index into this fixed
    size array.  Since each element is a 4 byte pointer, it takes exactly as
    much memory to hold this array as to hold the DWARF info for a given
-   compilation unit.  But it gets freed as soon as we are done with it. */
+   compilation unit.  But it gets freed as soon as we are done with it.
+   This has worked well in practice, as a reasonable tradeoff between memory
+   consumption and speed, without having to resort to much more complicated
+   algorithms. */
 
 static struct type **utypes;   /* Pointer to array of user type pointers */
 static int numutypes;          /* Max number of user type pointers */
 
+/* Maintain an array of referenced fundamental types for the current
+   compilation unit being read.  For DWARF version 1, we have to construct
+   the fundamental types on the fly, since no information about the
+   fundamental types is supplied.  Each such fundamental type is created by
+   calling a language dependent routine to create the type, and then a
+   pointer to that type is then placed in the array at the index specified
+   by it's FT_<TYPENAME> value.  The array has a fixed size set by the
+   FT_NUM_MEMBERS compile time constant, which is the number of predefined
+   fundamental types gdb knows how to construct. */
+
+static struct type *ftypes[FT_NUM_MEMBERS];  /* Fundamental types */
+
+/* Record the language for the compilation unit which is currently being
+   processed.  We know it once we have seen the TAG_compile_unit DIE,
+   and we need it while processing the DIE's for that compilation unit.
+   It is eventually saved in the symtab structure, but we don't finalize
+   the symtab struct until we have processed all the DIE's for the
+   compilation unit.  We also need to get and save a pointer to the 
+   language struct for this language, so we can call the language
+   dependent routines for doing things such as creating fundamental
+   types. */
+
+static enum language cu_language;
+static const struct language_defn *cu_language_defn;
+
 /* Forward declarations of static functions so we don't have to worry
    about ordering within this file.  */
 
@@ -327,15 +475,12 @@ 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 *));
 
 static void
-scan_compilation_units PARAMS ((char *, char *, char *, unsigned int,
-                               unsigned int, struct objfile *));
+scan_compilation_units PARAMS ((char *, char *, file_ptr,
+                               file_ptr, struct objfile *));
 
 static void
 add_partial_symbol PARAMS ((struct dieinfo *, struct objfile *));
@@ -369,7 +514,7 @@ static struct type *
 decode_array_element_type PARAMS ((char *));
 
 static struct type *
-decode_subscr_data PARAMS ((char *, char *));
+decode_subscript_data_item PARAMS ((char *, char *));
 
 static void
 dwarf_read_array_type PARAMS ((struct dieinfo *));
@@ -419,6 +564,10 @@ alloc_utype PARAMS ((DIE_REF, struct type *));
 static struct symbol *
 new_symbol PARAMS ((struct dieinfo *, struct objfile *));
 
+static void
+synthesize_typedef PARAMS ((struct dieinfo *, struct objfile *,
+                           struct type *));
+
 static int
 locval PARAMS ((char *));
 
@@ -426,6 +575,130 @@ static void
 record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type,
                               struct objfile *));
 
+static void
+set_cu_language PARAMS ((struct dieinfo *));
+
+static struct type *
+dwarf_fundamental_type PARAMS ((struct objfile *, int));
+
+
+/*
+
+LOCAL FUNCTION
+
+       dwarf_fundamental_type -- lookup or create a fundamental type
+
+SYNOPSIS
+
+       struct type *
+       dwarf_fundamental_type (struct objfile *objfile, int typeid)
+
+DESCRIPTION
+
+       DWARF version 1 doesn't supply any fundamental type information,
+       so gdb has to construct such types.  It has a fixed number of
+       fundamental types that it knows how to construct, which is the
+       union of all types that it knows how to construct for all languages
+       that it knows about.  These are enumerated in gdbtypes.h.
+
+       As an example, assume we find a DIE that references a DWARF
+       fundamental type of FT_integer.  We first look in the ftypes
+       array to see if we already have such a type, indexed by the
+       gdb internal value of FT_INTEGER.  If so, we simply return a
+       pointer to that type.  If not, then we ask an appropriate
+       language dependent routine to create a type FT_INTEGER, using
+       defaults reasonable for the current target machine, and install
+       that type in ftypes for future reference.
+
+RETURNS
+
+       Pointer to a fundamental type.
+
+*/
+
+static struct type *
+dwarf_fundamental_type (objfile, typeid)
+     struct objfile *objfile;
+     int typeid;
+{
+  if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
+    {
+      error ("internal error - invalid fundamental type id %d", typeid);
+    }
+
+  /* Look for this particular type in the fundamental type vector.  If one is
+     not found, create and install one appropriate for the current language
+     and the current target machine. */
+
+  if (ftypes[typeid] == NULL)
+    {
+      ftypes[typeid] = cu_language_defn -> la_fund_type(objfile, typeid);
+    }
+
+  return (ftypes[typeid]);
+}
+
+/*
+
+LOCAL FUNCTION
+
+       set_cu_language -- set local copy of language for compilation unit
+
+SYNOPSIS
+
+       void
+       set_cu_language (struct dieinfo *dip)
+
+DESCRIPTION
+
+       Decode the language attribute for a compilation unit DIE and
+       remember what the language was.  We use this at various times
+       when processing DIE's for a given compilation unit.
+
+RETURNS
+
+       No return value.
+
+ */
+
+static void
+set_cu_language (dip)
+     struct dieinfo *dip;
+{
+  switch (dip -> at_language)
+    {
+      case LANG_C89:
+      case LANG_C:
+        cu_language = language_c;
+       break;
+      case LANG_C_PLUS_PLUS:
+       cu_language = language_cplus;
+       break;
+      /* start-sanitize-chill */
+      case LANG_CHILL:
+       cu_language = language_chill;
+       break;
+      /* end-sanitize-chill */
+      case LANG_MODULA2:
+       cu_language = language_m2;
+       break;
+      case LANG_ADA83:
+      case LANG_COBOL74:
+      case LANG_COBOL85:
+      case LANG_FORTRAN77:
+      case LANG_FORTRAN90:
+      case LANG_PASCAL83:
+       /* 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);
+}
+
 /*
 
 GLOBAL FUNCTION
@@ -434,18 +707,17 @@ GLOBAL FUNCTION
 
 SYNOPSIS
 
-       void dwarf_build_psymtabs (int desc, char *filename, 
+       void dwarf_build_psymtabs (struct objfile *objfile,
             struct section_offsets *section_offsets,
-            int mainline, unsigned int dbfoff, unsigned int dbsize,
-            unsigned int lnoffset, unsigned int lnsize,
-            struct objfile *objfile)
+            int mainline, file_ptr dbfoff, unsigned int dbfsize,
+            file_ptr lnoffset, unsigned int lnsize)
 
 DESCRIPTION
 
        This function is called upon to build partial symtabs from files
        containing DIE's (Dwarf Information Entries) and DWARF line numbers.
 
-       It is passed a file descriptor for an open file containing the DIES
+       It is passed a bfd* containing the DIES
        and line number information, the corresponding filename for that
        file, a base address for relocating the symbols, a flag indicating
        whether or not this debugging information is from a "main symbol
@@ -460,28 +732,28 @@ RETURNS
  */
 
 void
-dwarf_build_psymtabs (desc, filename, section_offsets, mainline, dbfoff, dbsize,
-                     lnoffset, lnsize, objfile)
-     int desc;
-     char *filename;
+dwarf_build_psymtabs (objfile, section_offsets, mainline, dbfoff, dbfsize,
+                     lnoffset, lnsize)
+     struct objfile *objfile;
      struct section_offsets *section_offsets;
      int mainline;
-     unsigned int dbfoff;
-     unsigned int dbsize;
-     unsigned int lnoffset;
+     file_ptr dbfoff;
+     unsigned int dbfsize;
+     file_ptr lnoffset;
      unsigned int lnsize;
-     struct objfile *objfile;
 {
+  bfd *abfd = objfile->obfd;
   struct cleanup *back_to;
   
   current_objfile = objfile;
+  dbsize = dbfsize;
   dbbase = xmalloc (dbsize);
   dbroff = 0;
-  if ((lseek (desc, dbfoff, 0) != dbfoff) ||
-      (read (desc, dbbase, dbsize) != dbsize))
+  if ((bfd_seek (abfd, dbfoff, L_SET) != 0) ||
+      (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
     {
       free (dbbase);
-      error ("can't read DWARF data from '%s'", filename);
+      error ("can't read DWARF data from '%s'", bfd_get_filename (abfd));
     }
   back_to = make_cleanup (free, dbbase);
   
@@ -504,8 +776,7 @@ dwarf_build_psymtabs (desc, filename, section_offsets, mainline, dbfoff, dbsize,
      table entry for each one.  Save enough information about each compilation
      unit to locate the full DWARF information later. */
   
-  scan_compilation_units (filename, dbbase, dbbase + dbsize,
-                         dbfoff, lnoffset, objfile);
+  scan_compilation_units (dbbase, dbbase + dbsize, dbfoff, lnoffset, objfile);
   
   do_cleanups (back_to);
   current_objfile = NULL;
@@ -546,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
@@ -660,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
     {
@@ -703,13 +925,13 @@ alloc_utype (die_ref, utypep)
   typep = utypes + utypeidx;
   if ((utypeidx < 0) || (utypeidx >= numutypes))
     {
-      utypep = lookup_fundamental_type (current_objfile, FT_INTEGER);
-      dwarfwarn ("reference to DIE (0x%x) outside compilation unit", die_ref);
+      utypep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+      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
     {
@@ -766,7 +988,7 @@ decode_die_type (dip)
     }
   else
     {
-      type = lookup_fundamental_type (current_objfile, FT_INTEGER);
+      type = dwarf_fundamental_type (current_objfile, FT_INTEGER);
     }
   return (type);
 }
@@ -810,6 +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)
     {
@@ -819,6 +1044,10 @@ struct_type (dip, thisdie, enddie, objfile)
   INIT_CPLUS_SPECIFIC(type);
   switch (dip -> die_tag)
     {
+      case TAG_class_type:
+        TYPE_CODE (type) = TYPE_CODE_CLASS;
+       tpart1 = "class";
+       break;
       case TAG_structure_type:
         TYPE_CODE (type) = TYPE_CODE_STRUCT;
        tpart1 = "struct";
@@ -831,7 +1060,7 @@ struct_type (dip, thisdie, enddie, objfile)
        /* Should never happen */
        TYPE_CODE (type) = TYPE_CODE_UNDEF;
        tpart1 = "???";
-       SQUAWK (("missing structure or union tag"));
+       complain (&missing_tag, DIE_ID, DIE_NAME);
        break;
     }
   /* Some compilers try to be helpful by inventing "fake" names for
@@ -844,10 +1073,12 @@ struct_type (dip, thisdie, enddie, objfile)
       TYPE_NAME (type) = obconcat (&objfile -> type_obstack,
                                   tpart1, " ", dip -> at_name);
     }
-  if (dip -> at_byte_size != 0)
-    {
-      TYPE_LENGTH (type) = dip -> at_byte_size;
-    }
+  /* Use whatever size is known.  Zero is a valid size.  We might however
+     wish to check has_at_byte_size to make sure that some byte size was
+     given explicitly, but DWARF doesn't specify that explicit sizes of
+     zero have to present, so complaining about missing sizes should 
+     probably not be the default. */
+  TYPE_LENGTH (type) = dip -> at_byte_size;
   thisdie += dip -> die_length;
   while (thisdie < enddie)
     {
@@ -895,8 +1126,22 @@ struct_type (dip, thisdie, enddie, objfile)
             itself.  The result is the bit offset of the LSB of the field. */
          if (mbr.at_bit_size > 0)
            {
+             if (mbr.has_at_byte_size)
+               {
+                 /* The size of the anonymous object containing the bit field
+                    is explicit, so use the indicated size (in bytes). */
+                 anonymous_size = mbr.at_byte_size;
+               }
+             else
+               {
+                 /* The size of the anonymous object containing the bit field
+                    matches the size of an object of the bit field's type.
+                    DWARF allows at_byte_size to be left out in such cases,
+                    as a debug information size optimization. */
+                 anonymous_size = TYPE_LENGTH (list -> field.type);
+               }
              list -> field.bitpos +=
-               mbr.at_byte_size * 8 - mbr.at_bit_offset - mbr.at_bit_size;
+               anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size;
            }
 #endif
          nfields++;
@@ -920,8 +1165,7 @@ struct_type (dip, thisdie, enddie, objfile)
     {
       TYPE_NFIELDS (type) = nfields;
       TYPE_FIELDS (type) = (struct field *)
-       obstack_alloc (&objfile -> type_obstack,
-                      sizeof (struct field) * nfields);
+       TYPE_ALLOC (type, sizeof (struct field) * nfields);
       /* Copy the saved-up fields into the field vector.  */
       for (n = nfields; list; list = list -> next)
        {
@@ -978,9 +1222,14 @@ read_structure_scope (dip, thisdie, enddie, objfile)
   type = struct_type (dip, thisdie, enddie, objfile);
   if (!(TYPE_FLAGS (type) & TYPE_FLAG_STUB))
     {
-      if ((sym = new_symbol (dip, objfile)) != NULL)
+      sym = new_symbol (dip, objfile);
+      if (sym != NULL)
        {
          SYMBOL_TYPE (sym) = type;
+         if (cu_language == language_cplus)
+           {
+             synthesize_typedef (dip, objfile, type);
+           }
        }
     }
 }
@@ -1019,8 +1268,8 @@ decode_array_element_type (scan)
   scan += SIZEOF_ATTRIBUTE;
   if ((nbytes = attribute_size (attribute)) == -1)
     {
-      SQUAWK (("bad array element type attribute 0x%x", attribute));
-      typep = lookup_fundamental_type (current_objfile, FT_INTEGER);
+      complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
+      typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
     }
   else
     {
@@ -1046,8 +1295,8 @@ decode_array_element_type (scan)
            typep = decode_mod_u_d_type (scan);
            break;
          default:
-           SQUAWK (("bad array element type attribute 0x%x", attribute));
-           typep = lookup_fundamental_type (current_objfile, FT_INTEGER);
+           complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
+           typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
            break;
          }
     }
@@ -1058,11 +1307,12 @@ decode_array_element_type (scan)
 
 LOCAL FUNCTION
 
-       decode_subscr_data -- decode array subscript and element type data
+       decode_subscript_data_item -- decode array subscript item
 
 SYNOPSIS
 
-       static struct type *decode_subscr_data (char *scan, char *end)
+       static struct type *
+       decode_subscript_data_item (char *scan, char *end)
 
 DESCRIPTION
 
@@ -1074,9 +1324,21 @@ DESCRIPTION
        source (I.E. leftmost dimension first, next to leftmost second,
        etc).
 
+       The data items describing each array dimension consist of four
+       parts: (1) a format specifier, (2) type type of the subscript
+       index, (3) a description of the low bound of the array dimension,
+       and (4) a description of the high bound of the array dimension.
+
+       The last data item is the description of the type of each of
+       the array elements.
+
        We are passed a pointer to the start of the block of bytes
-       containing the data items, and a pointer to the first byte past
-       the data.  This function decodes the data and returns a type.
+       containing the remaining data items, and a pointer to the first
+       byte past the data.  This function recursively decodes the
+       remaining data items and returns a type.
+
+       If we somehow fail to decode some data, we complain about it
+       and return a type "array of int".
 
 BUGS
        FIXME:  This code only implements the forms currently used
@@ -1087,12 +1349,14 @@ BUGS
  */
 
 static struct type *
-decode_subscr_data (scan, end)
+decode_subscript_data_item (scan, end)
      char *scan;
      char *end;
 {
-  struct type *typep = NULL;
-  struct type *nexttype;
+  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;
@@ -1110,32 +1374,23 @@ decode_subscr_data (scan, end)
     case FMT_FT_C_C:
       fundtype = target_to_host (scan, SIZEOF_FMT_FT, GET_UNSIGNED,
                                 current_objfile);
+      indextype = decode_fund_type (fundtype);
       scan += SIZEOF_FMT_FT;
-      if (fundtype != FT_integer && fundtype != FT_signed_integer
-         && fundtype != FT_unsigned_integer)
-       {
-         SQUAWK (("array subscripts must be integral types, not type 0x%x",
-                  fundtype));
-       }
-      else
+      nbytes = TARGET_FT_LONG_SIZE (current_objfile);
+      lowbound = target_to_host (scan, nbytes, GET_UNSIGNED, current_objfile);
+      scan += nbytes;
+      highbound = target_to_host (scan, nbytes, GET_UNSIGNED, current_objfile);
+      scan += nbytes;
+      nexttype = decode_subscript_data_item (scan, end);
+      if (nexttype == NULL)
        {
-         nbytes = TARGET_FT_LONG_SIZE (current_objfile);
-         lowbound = target_to_host (scan, nbytes, GET_UNSIGNED,
-                                    current_objfile);
-         scan += nbytes;
-         highbound = target_to_host (scan, nbytes, GET_UNSIGNED,
-                                     current_objfile);
-         scan += nbytes;
-         nexttype = decode_subscr_data (scan, end);
-         if (nexttype != NULL)
-           {
-             typep = alloc_type (current_objfile);
-             TYPE_CODE (typep) = TYPE_CODE_ARRAY;
-             TYPE_LENGTH (typep) = TYPE_LENGTH (nexttype);
-             TYPE_LENGTH (typep) *= (highbound - lowbound) + 1;
-             TYPE_TARGET_TYPE (typep) = nexttype;
-           }               
+         /* Munged subscript data or other problem, fake it. */
+         complain (&subscript_data_items, DIE_ID, DIE_NAME);
+         nexttype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
        }
+      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:
@@ -1144,10 +1399,16 @@ decode_subscr_data (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));
+      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));
+      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);
@@ -1183,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)
     {
@@ -1191,30 +1452,29 @@ dwarf_read_array_type (dip)
       blocksz = target_to_host (sub, nbytes, GET_UNSIGNED, current_objfile);
       subend = sub + nbytes + blocksz;
       sub += nbytes;
-      type = decode_subscr_data (sub, subend);
-      if (type == NULL)
+      type = decode_subscript_data_item (sub, subend);
+      if ((utype = lookup_utype (dip -> die_ref)) == NULL)
        {
-         if ((utype = lookup_utype (dip -> die_ref)) == NULL)
-           {
-             utype = alloc_utype (dip -> die_ref, NULL);
-           }
-         TYPE_CODE (utype) = TYPE_CODE_ARRAY;
-         TYPE_TARGET_TYPE (utype) = 
-           lookup_fundamental_type (current_objfile, FT_INTEGER);
-         TYPE_LENGTH (utype) = 1 * TYPE_LENGTH (TYPE_TARGET_TYPE (utype));
+         /* Install user defined type that has not been referenced yet. */
+         alloc_utype (dip -> die_ref, type);
+       }
+      else if (TYPE_CODE (utype) == TYPE_CODE_UNDEF)
+       {
+         /* Ick!  A forward ref has already generated a blank type in our
+            slot, and this type probably already has things pointing to it
+            (which is what caused it to be created in the first place).
+            If it's just a place holder we can plop our fully defined type
+            on top of it.  We can't recover the space allocated for our
+            new type since it might be on an obstack, but we could reuse
+            it if we kept a list of them, but it might not be worth it
+            (FIXME). */
+         *utype = *type;
        }
       else
        {
-         if ((utype = lookup_utype (dip -> die_ref)) == NULL)
-           {
-             alloc_utype (dip -> die_ref, type);
-           }
-         else
-           {
-             TYPE_CODE (utype) = TYPE_CODE_ARRAY;
-             TYPE_LENGTH (utype) = TYPE_LENGTH (type);
-             TYPE_TARGET_TYPE (utype) = TYPE_TARGET_TYPE (type);
-           }
+         /* Double ick!  Not only is a type already in our slot, but
+            someone has decorated it.  Complain and leave it alone. */
+         complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
        }
     }
 }
@@ -1312,7 +1572,7 @@ read_subroutine_type (dip, thisdie, enddie)
       ftype = lookup_function_type (type);
       alloc_utype (dip -> die_ref, ftype);
     }
-  else
+  else if (TYPE_CODE (ftype) == TYPE_CODE_UNDEF)
     {
       /* We have an existing partially constructed type, so bash it
         into the correct type. */
@@ -1321,6 +1581,10 @@ read_subroutine_type (dip, thisdie, enddie)
       TYPE_LENGTH (ftype) = 1;
       TYPE_CODE (ftype) = TYPE_CODE_FUNC;
     }
+  else
+    {
+      complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+    }
 }
 
 /*
@@ -1357,9 +1621,14 @@ read_enumeration (dip, thisdie, enddie, objfile)
   struct symbol *sym;
   
   type = enum_type (dip, objfile);
-  if ((sym = new_symbol (dip, objfile)) != NULL)
+  sym = new_symbol (dip, objfile);
+  if (sym != NULL)
     {
       SYMBOL_TYPE (sym) = type;
+      if (cu_language == language_cplus)
+       {
+         synthesize_typedef (dip, objfile, type);
+       }
     }
 }
 
@@ -1468,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;
@@ -1570,6 +1840,9 @@ handle_producer (producer)
 
   processing_gcc_compilation =
     STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))
+      /* start-sanitize-chill */
+      || STREQN (producer, CHILL_PRODUCER, strlen (CHILL_PRODUCER))
+      /* end-sanitize-chill */
       || STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
 
   /* Select a demangling style if we can identify the producer and if
@@ -1578,7 +1851,7 @@ handle_producer (producer)
      gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */
 
 #if 1 /* Works, but is experimental.  -fnf */
-  if (current_demangling_style == auto_demangling)
+  if (AUTO_DEMANGLING)
     {
       if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)))
        {
@@ -1635,6 +1908,7 @@ read_file_scope (dip, thisdie, enddie, objfile)
       objfile -> ei.entry_file_lowpc = dip -> at_low_pc;
       objfile -> ei.entry_file_highpc = dip -> at_high_pc;
     }
+  set_cu_language (dip);
   if (dip -> at_producer != NULL)
     {
       handle_producer (dip -> at_producer);
@@ -1643,23 +1917,15 @@ read_file_scope (dip, thisdie, enddie, objfile)
   utypes = (struct type **) xmalloc (numutypes * sizeof (struct type *));
   back_to = make_cleanup (free, utypes);
   memset (utypes, 0, numutypes * sizeof (struct type *));
-  start_symtab (dip -> at_name, NULL, dip -> at_low_pc);
+  memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
+  start_symtab (dip -> at_name, dip -> at_comp_dir, dip -> at_low_pc);
   decode_line_numbers (lnbase);
   process_dies (thisdie + dip -> die_length, enddie, objfile);
   symtab = end_symtab (dip -> at_high_pc, 0, 0, objfile);
-  /* FIXME:  The following may need to be expanded for other languages */
-  switch (dip -> at_language)
+  if (symtab != NULL)
     {
-      case LANG_C89:
-      case LANG_C:
-       symtab -> language = language_c;
-       break;
-      case LANG_C_PLUS_PLUS:
-       symtab -> language = language_cplus;
-       break;
-      default:
-       ;
-    }
+      symtab -> language = cu_language;
+    }      
   do_cleanups (back_to);
   utypes = NULL;
   numutypes = 0;
@@ -1728,6 +1994,7 @@ process_dies (thisdie, enddie, objfile)
            case TAG_lexical_block:
              read_lexical_block_scope (&di, thisdie, nextdie, objfile);
              break;
+           case TAG_class_type:
            case TAG_structure_type:
            case TAG_union_type:
              read_structure_scope (&di, thisdie, nextdie, objfile);
@@ -1938,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:
@@ -1955,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];
@@ -1995,7 +2263,7 @@ read_ofile_symtab (pst)
 {
   struct cleanup *back_to;
   unsigned long lnsize;
-  int foffset;
+  file_ptr foffset;
   bfd *abfd;
   char lnsizedata[SIZEOF_LINETBL_LENGTH];
 
@@ -2006,13 +2274,14 @@ read_ofile_symtab (pst)
      unit, seek to the location in the file, and read in all the DIE's. */
 
   diecount = 0;
-  dbbase = xmalloc (DBLENGTH(pst));
+  dbsize = DBLENGTH (pst);
+  dbbase = xmalloc (dbsize);
   dbroff = DBROFF(pst);
   foffset = DBFOFF(pst) + dbroff;
   base_section_offsets = pst->section_offsets;
   baseaddr = ANOFFSET (pst->section_offsets, 0);
-  if (bfd_seek (abfd, foffset, 0) ||
-      (bfd_read (dbbase, DBLENGTH(pst), 1, abfd) != DBLENGTH(pst)))
+  if (bfd_seek (abfd, foffset, L_SET) ||
+      (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
     {
       free (dbbase);
       error ("can't read DWARF data");
@@ -2027,7 +2296,7 @@ read_ofile_symtab (pst)
   lnbase = NULL;
   if (LNFOFF (pst))
     {
-      if (bfd_seek (abfd, LNFOFF (pst), 0) ||
+      if (bfd_seek (abfd, LNFOFF (pst), L_SET) ||
          (bfd_read ((PTR) lnsizedata, sizeof (lnsizedata), 1, abfd) !=
           sizeof (lnsizedata)))
        {
@@ -2036,7 +2305,7 @@ read_ofile_symtab (pst)
       lnsize = target_to_host (lnsizedata, SIZEOF_LINETBL_LENGTH,
                               GET_UNSIGNED, pst -> objfile);
       lnbase = xmalloc (lnsize);
-      if (bfd_seek (abfd, LNFOFF (pst), 0) ||
+      if (bfd_seek (abfd, LNFOFF (pst), L_SET) ||
          (bfd_read (lnbase, lnsize, 1, abfd) != lnsize))
        {
          free (lnbase);
@@ -2045,7 +2314,7 @@ read_ofile_symtab (pst)
       make_cleanup (free, lnbase);
     }
 
-  process_dies (dbbase, dbbase + DBLENGTH(pst), pst -> objfile);
+  process_dies (dbbase, dbbase + dbsize, pst -> objfile);
   do_cleanups (back_to);
   current_objfile = NULL;
   return (pst -> objfile -> symtabs);
@@ -2073,6 +2342,7 @@ psymtab_to_symtab_1 (pst)
      struct partial_symtab *pst;
 {
   int i;
+  struct cleanup *old_chain;
   
   if (pst != NULL)
     {
@@ -2105,6 +2375,8 @@ psymtab_to_symtab_1 (pst)
            }     
          if (DBLENGTH (pst))           /* Otherwise it's a dummy */
            {
+             buildsym_init ();
+             old_chain = make_cleanup (really_free_pendings, 0);
              pst -> symtab = read_ofile_symtab (pst);
              if (info_verbose)
                {
@@ -2113,6 +2385,7 @@ psymtab_to_symtab_1 (pst)
                  fflush (stdout);
                }
              sort_symtab_syms (pst -> symtab);
+             do_cleanups (old_chain);
            }
          pst -> readin = 1;
        }
@@ -2272,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;
        }
     }
@@ -2290,6 +2564,9 @@ DESCRIPTION
        add to a partial symbol table, finish filling in the die info
        and then add a partial symbol table entry for it.
 
+NOTES
+
+       The caller must ensure that the DIE has a valid name attribute.
 */
 
 static void
@@ -2305,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),
@@ -2313,42 +2590,42 @@ 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:
     case TAG_union_type:
+    case TAG_enumeration_type:
       ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
                           STRUCT_NAMESPACE, LOC_TYPEDEF,
                           objfile -> static_psymbols,
-                          0);
-      break;
-    case TAG_enumeration_type:
-      if (dip -> at_name)
+                          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),
-                              STRUCT_NAMESPACE, LOC_TYPEDEF,
+                              VAR_NAMESPACE, LOC_TYPEDEF,
                               objfile -> static_psymbols,
-                              0);
+                              0, cu_language, objfile);
        }
-      add_enum_psymbol (dip, objfile);
       break;
     }
 }
@@ -2363,15 +2640,50 @@ DESCRIPTION
 
        Process the DIE's within a single compilation unit, looking for
        interesting DIE's that contribute to the partial symbol table entry
-       for this compilation unit.  Since we cannot follow any sibling
-       chains without reading the complete DIE info for every DIE,
-       it is probably faster to just sequentially check each one to
-       see if it is one of the types we are interested in, and if so,
-       then extract all the attributes info and generate a partial
-       symbol table entry.
+       for this compilation unit.
 
 NOTES
 
+       There are some DIE's that may appear both at file scope and within
+       the scope of a function.  We are only interested in the ones at file
+       scope, and the only way to tell them apart is to keep track of the
+       scope.  For example, consider the test case:
+
+               static int i;
+               main () { int j; }
+
+       for which the relevant DWARF segment has the structure:
+       
+               0x51:
+               0x23   global subrtn   sibling     0x9b
+                                      name        main
+                                      fund_type   FT_integer
+                                      low_pc      0x800004cc
+                                      high_pc     0x800004d4
+                                           
+               0x74:
+               0x23   local var       sibling     0x97
+                                      name        j
+                                      fund_type   FT_integer
+                                      location    OP_BASEREG 0xe
+                                                  OP_CONST 0xfffffffc
+                                                  OP_ADD
+               0x97:
+               0x4         
+               
+               0x9b:
+               0x1d   local var       sibling     0xb8
+                                      name        i
+                                      fund_type   FT_integer
+                                      location    OP_ADDR 0x800025dc
+                                           
+               0xb8:
+               0x4         
+
+       We want to include the symbol 'i' in the partial symbol table, but
+       not the symbol 'j'.  In essence, we want to skip all the dies within
+       the scope of a TAG_global_subroutine DIE.
+
        Don't attempt to add anonymous structures or unions since they have
        no name.  Anonymous enumerations however are processed, because we
        want to extract their member names (the check for a tag name is
@@ -2389,6 +2701,7 @@ scan_partial_symbols (thisdie, enddie, objfile)
      struct objfile *objfile;
 {
   char *nextdie;
+  char *temp;
   struct dieinfo di;
   
   while (thisdie < enddie)
@@ -2407,6 +2720,29 @@ scan_partial_symbols (thisdie, enddie, objfile)
            {
            case TAG_global_subroutine:
            case TAG_subroutine:
+             completedieinfo (&di, objfile);
+             if (di.at_name && (di.has_at_low_pc || di.at_location))
+               {
+                 add_partial_symbol (&di, objfile);
+                 /* If there is a sibling attribute, adjust the nextdie
+                    pointer to skip the entire scope of the subroutine.
+                    Apply some sanity checking to make sure we don't 
+                    overrun or underrun the range of remaining DIE's */
+                 if (di.at_sibling != 0)
+                   {
+                     temp = dbbase + di.at_sibling - dbroff;
+                     if ((temp < thisdie) || (temp >= enddie))
+                       {
+                         complain (&bad_die_ref, DIE_ID, DIE_NAME,
+                                   di.at_sibling);
+                       }
+                     else
+                       {
+                         nextdie = temp;
+                       }
+                   }
+               }
+             break;
            case TAG_global_variable:
            case TAG_local_variable:
              completedieinfo (&di, objfile);
@@ -2416,6 +2752,7 @@ scan_partial_symbols (thisdie, enddie, objfile)
                }
              break;
            case TAG_typedef:
+           case TAG_class_type:
            case TAG_structure_type:
            case TAG_union_type:
              completedieinfo (&di, objfile);
@@ -2426,7 +2763,11 @@ scan_partial_symbols (thisdie, enddie, objfile)
              break;
            case TAG_enumeration_type:
              completedieinfo (&di, objfile);
-             add_partial_symbol (&di, objfile);
+             if (di.at_name)
+               {
+                 add_partial_symbol (&di, objfile);
+               }
+             add_enum_psymbol (&di, objfile);
              break;
            }
        }
@@ -2478,12 +2819,11 @@ RETURNS
  */
 
 static void
-scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
-     char *filename;
+scan_compilation_units (thisdie, enddie, dbfoff, lnoffset, objfile)
      char *thisdie;
      char *enddie;
-     unsigned int dbfoff;
-     unsigned int lnoffset;
+     file_ptr dbfoff;
+     file_ptr lnoffset;
      struct objfile *objfile;
 {
   char *nextdie;
@@ -2491,7 +2831,7 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
   struct partial_symtab *pst;
   int culength;
   int curoff;
-  int curlnoffset;
+  file_ptr curlnoffset;
 
   while (thisdie < enddie)
     {
@@ -2507,6 +2847,7 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
       else
        {
          completedieinfo (&di, objfile);
+         set_cu_language (&di);
          if (di.at_sibling != 0)
            {
              nextdie = dbbase + di.at_sibling - dbroff;
@@ -2521,8 +2862,8 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
 
          /* First allocate a new partial symbol table structure */
 
-         pst = start_psymtab_common (objfile, base_section_offsets, di.at_name,
-                                     di.at_low_pc,
+         pst = start_psymtab_common (objfile, base_section_offsets,
+                                     di.at_name, di.at_low_pc,
                                      objfile -> global_psymbols.next,
                                      objfile -> static_psymbols.next);
 
@@ -2584,11 +2925,20 @@ new_symbol (dip, objfile)
       sym = (struct symbol *) obstack_alloc (&objfile -> symbol_obstack,
                                             sizeof (struct symbol));
       memset (sym, 0, sizeof (struct symbol));
-      SYMBOL_NAME (sym) = create_name (dip -> at_name, &objfile->symbol_obstack);
+      SYMBOL_NAME (sym) = create_name (dip -> at_name,
+                                      &objfile->symbol_obstack);
       /* default assumptions */
       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:
@@ -2657,6 +3007,7 @@ new_symbol (dip, objfile)
          /* From varargs functions; gdb doesn't seem to have any interest in
             this information, so just ignore it for now. (FIXME?) */
          break;
+       case TAG_class_type:
        case TAG_structure_type:
        case TAG_union_type:
        case TAG_enumeration_type:
@@ -2681,6 +3032,51 @@ new_symbol (dip, objfile)
 
 /*
 
+LOCAL FUNCTION
+
+       synthesize_typedef -- make a symbol table entry for a "fake" typedef
+
+SYNOPSIS
+
+       static void synthesize_typedef (struct dieinfo *dip,
+                                       struct objfile *objfile,
+                                       struct type *type);
+
+DESCRIPTION
+
+       Given a pointer to a DWARF information entry, synthesize a typedef
+       for the name in the DIE, using the specified type.
+
+       This is used for C++ class, structs, unions, and enumerations to
+       set up the tag name as a type.
+
+ */
+
+static void
+synthesize_typedef (dip, objfile, type)
+     struct dieinfo *dip;
+     struct objfile *objfile;
+     struct type *type;
+{
+  struct symbol *sym = NULL;
+  
+  if (dip -> at_name != NULL)
+    {
+      sym = (struct symbol *)
+       obstack_alloc (&objfile -> symbol_obstack, sizeof (struct symbol));
+      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;
+      add_symbol_to_list (sym, list_in_scope);
+    }
+}
+
+/*
+
 LOCAL FUNCTION
 
        decode_mod_fund_type -- decode a modified fundamental type
@@ -2845,8 +3241,8 @@ decode_modified_type (modifiers, modcount, mtype)
            }
          break;
        default:
-         SQUAWK (("botched modified type decoding (mtype 0x%x)", mtype));
-         typep = lookup_fundamental_type (current_objfile, FT_INTEGER);
+         complain (&botched_modified_type, DIE_ID, DIE_NAME, mtype);
+         typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
          break;
        }
     }
@@ -2863,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;
        }
@@ -2895,10 +3290,12 @@ DESCRIPTION
 
 NOTES
 
-       If we encounter a fundamental type that we are unprepared to
-       deal with, and it is not in the range of those types defined
-       as application specific types, then we issue a warning and
-       treat the type as an "int".
+       For robustness, if we are asked to translate a fundamental
+       type that we are unprepared to deal with, we return int so
+       callers can always depend upon a valid type being returned,
+       and so gdb may at least do something reasonable by default.
+       If the type is not in the range of those types defined as
+       application specific types, we also issue a warning.
 */
 
 static struct type *
@@ -2911,108 +3308,111 @@ decode_fund_type (fundtype)
     {
 
     case FT_void:
-      typep = lookup_fundamental_type (current_objfile, FT_VOID);
+      typep = dwarf_fundamental_type (current_objfile, FT_VOID);
       break;
     
     case FT_boolean:           /* Was FT_set in AT&T version */
-      typep = lookup_fundamental_type (current_objfile, FT_BOOLEAN);
+      typep = dwarf_fundamental_type (current_objfile, FT_BOOLEAN);
       break;
 
     case FT_pointer:           /* (void *) */
-      typep = lookup_fundamental_type (current_objfile, FT_VOID);
+      typep = dwarf_fundamental_type (current_objfile, FT_VOID);
       typep = lookup_pointer_type (typep);
       break;
     
     case FT_char:
-      typep = lookup_fundamental_type (current_objfile, FT_CHAR);
+      typep = dwarf_fundamental_type (current_objfile, FT_CHAR);
       break;
     
     case FT_signed_char:
-      typep = lookup_fundamental_type (current_objfile, FT_SIGNED_CHAR);
+      typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_CHAR);
       break;
 
     case FT_unsigned_char:
-      typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
+      typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
       break;
     
     case FT_short:
-      typep = lookup_fundamental_type (current_objfile, FT_SHORT);
+      typep = dwarf_fundamental_type (current_objfile, FT_SHORT);
       break;
 
     case FT_signed_short:
-      typep = lookup_fundamental_type (current_objfile, FT_SIGNED_SHORT);
+      typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_SHORT);
       break;
     
     case FT_unsigned_short:
-      typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_SHORT);
+      typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_SHORT);
       break;
     
     case FT_integer:
-      typep = lookup_fundamental_type (current_objfile, FT_INTEGER);
+      typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
       break;
 
     case FT_signed_integer:
-      typep = lookup_fundamental_type (current_objfile, FT_SIGNED_INTEGER);
+      typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_INTEGER);
       break;
     
     case FT_unsigned_integer:
-      typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
+      typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
       break;
     
     case FT_long:
-      typep = lookup_fundamental_type (current_objfile, FT_LONG);
+      typep = dwarf_fundamental_type (current_objfile, FT_LONG);
       break;
 
     case FT_signed_long:
-      typep = lookup_fundamental_type (current_objfile, FT_SIGNED_LONG);
+      typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_LONG);
       break;
     
     case FT_unsigned_long:
-      typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG);
+      typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_LONG);
       break;
     
     case FT_long_long:
-      typep = lookup_fundamental_type (current_objfile, FT_LONG_LONG);
+      typep = dwarf_fundamental_type (current_objfile, FT_LONG_LONG);
       break;
 
     case FT_signed_long_long:
-      typep = lookup_fundamental_type (current_objfile, FT_SIGNED_LONG_LONG);
+      typep = dwarf_fundamental_type (current_objfile, FT_SIGNED_LONG_LONG);
       break;
 
     case FT_unsigned_long_long:
-      typep = lookup_fundamental_type (current_objfile, FT_UNSIGNED_LONG_LONG);
+      typep = dwarf_fundamental_type (current_objfile, FT_UNSIGNED_LONG_LONG);
       break;
 
     case FT_float:
-      typep = lookup_fundamental_type (current_objfile, FT_FLOAT);
+      typep = dwarf_fundamental_type (current_objfile, FT_FLOAT);
       break;
     
     case FT_dbl_prec_float:
-      typep = lookup_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT);
+      typep = dwarf_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT);
       break;
     
     case FT_ext_prec_float:
-      typep = lookup_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT);
+      typep = dwarf_fundamental_type (current_objfile, FT_EXT_PREC_FLOAT);
       break;
     
     case FT_complex:
-      typep = lookup_fundamental_type (current_objfile, FT_COMPLEX);
+      typep = dwarf_fundamental_type (current_objfile, FT_COMPLEX);
       break;
     
     case FT_dbl_prec_complex:
-      typep = lookup_fundamental_type (current_objfile, FT_DBL_PREC_COMPLEX);
+      typep = dwarf_fundamental_type (current_objfile, FT_DBL_PREC_COMPLEX);
       break;
     
     case FT_ext_prec_complex:
-      typep = lookup_fundamental_type (current_objfile, FT_EXT_PREC_COMPLEX);
+      typep = dwarf_fundamental_type (current_objfile, FT_EXT_PREC_COMPLEX);
       break;
     
     }
 
-  if ((typep == NULL) && !(FT_lo_user <= fundtype && fundtype <= FT_hi_user))
+  if (typep == NULL)
     {
-      SQUAWK (("unexpected fundamental type 0x%x", fundtype));
-      typep = lookup_fundamental_type (current_objfile, FT_VOID);
+      typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+      if (!(FT_lo_user <= fundtype && fundtype <= FT_hi_user))
+       {
+         complain (&unexpected_fund_type, DIE_ID, DIE_NAME, fundtype);
+       }
     }
     
   return (typep);
@@ -3091,6 +3491,12 @@ NOTES
        that if a padding DIE is used for alignment and the amount needed is
        less than SIZEOF_DIE_LENGTH, then the padding DIE has to be big
        enough to align to the next alignment boundry.
+
+       We do some basic sanity checking here, such as verifying that the
+       length of the die would not cause it to overrun the recorded end of
+       the buffer holding the DIE info.  If we find a DIE that is either
+       too small or too large, we force it's length to zero which should
+       cause the caller to take appropriate action.
  */
 
 static void
@@ -3105,9 +3511,11 @@ basicdieinfo (dip, diep, objfile)
   dip -> die_ref = dbroff + (diep - dbbase);
   dip -> die_length = target_to_host (diep, SIZEOF_DIE_LENGTH, GET_UNSIGNED,
                                      objfile);
-  if (dip -> die_length < SIZEOF_DIE_LENGTH)
+  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))
     {
@@ -3174,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;
        }
@@ -3192,10 +3600,6 @@ completedieinfo (dip, objfile)
          dip -> at_bit_offset = target_to_host (diep, nbytes, GET_UNSIGNED,
                                                 objfile);
          break;
-       case AT_visibility:
-         dip -> at_visibility = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                                objfile);
-         break;
        case AT_sibling:
          dip -> at_sibling = target_to_host (diep, nbytes, GET_UNSIGNED,
                                              objfile);
@@ -3227,6 +3631,7 @@ completedieinfo (dip, objfile)
        case AT_byte_size:
          dip -> at_byte_size = target_to_host (diep, nbytes, GET_UNSIGNED,
                                                objfile);
+         dip -> has_at_byte_size = 1;
          break;
        case AT_bit_size:
          dip -> at_bit_size = target_to_host (diep, nbytes, GET_UNSIGNED,
@@ -3240,10 +3645,6 @@ completedieinfo (dip, objfile)
          dip -> at_discr = target_to_host (diep, nbytes, GET_UNSIGNED,
                                            objfile);
          break;
-       case AT_import:
-         dip -> at_import = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                            objfile);
-         break;
        case AT_location:
          dip -> at_location = diep;
          break;
@@ -3274,15 +3675,21 @@ completedieinfo (dip, objfile)
          dip -> at_name = diep;
          break;
        case AT_comp_dir:
-         dip -> at_comp_dir = diep;
+         /* For now, ignore any "hostname:" portion, since gdb doesn't
+            know how to deal with it.  (FIXME). */
+         dip -> at_comp_dir = strrchr (diep, ':');
+         if (dip -> at_comp_dir != NULL)
+           {
+             dip -> at_comp_dir++;
+           }
+         else
+           {
+             dip -> at_comp_dir = diep;
+           }
          break;
        case AT_producer:
          dip -> at_producer = diep;
          break;
-       case AT_frame_base:
-         dip -> at_frame_base = target_to_host (diep, nbytes, GET_UNSIGNED,
-                                                objfile);
-         break;
        case AT_start_scope:
          dip -> at_start_scope = target_to_host (diep, nbytes, GET_UNSIGNED,
                                                  objfile);
@@ -3332,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;
        }
@@ -3391,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;
     }
@@ -3447,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.045477 seconds and 4 git commands to generate.