* tracepoint.c (trace_start_command): Set trace_running_p.
[deliverable/binutils-gdb.git] / gdb / dwarfread.c
index 77a2bc77faed56a334d9c159c32aa9dc2dd70ab6..323ceaf0023960d8bc63132092d28bb8bd22d611 100644 (file)
@@ -1,5 +1,6 @@
 /* DWARF debugging format support for GDB.
-   Copyright (C) 1991, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996
+   Free Software Foundation, Inc.
    Written by Fred Fish at Cygnus Support.  Portions based on dbxread.c,
    mipsread.c, coffread.c, and dwarfread.c from a Data General SVR4 gdb port.
 
@@ -17,18 +18,12 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /*
 
-FIXME: Figure out how to get the frame pointer register number in the
-execution environment of the target.  Remove R_FP kludge
-
-FIXME: Add generation of dependencies list to partial symtab code.
-
-FIXME: Currently we ignore host/target byte ordering and integer size
-differences.  Should remap data from external form to an internal form
-before trying to use it.
+FIXME: Do we need to generate dependencies in partial symtabs?
+(Perhaps we don't need to).
 
 FIXME: Resolve minor differences between what information we put in the
 partial symbol table and what dbxread puts in.  For example, we don't yet
@@ -39,55 +34,205 @@ contents.
 FIXME: Figure out a better way to tell gdb about the name of the function
 contain the user's entry point (I.E. main())
 
-FIXME: The current DWARF specification has a very strong bias towards
-machines with 32-bit integers, as it assumes that many attributes of the
-program (such as an address) will fit in such an integer.  There are many
-references in the spec to things that are 2, 4, or 8 bytes long.  Given that
-we will probably run into problems on machines where some of these assumptions
-are invalid (64-bit ints for example), we don't bother at this time to try to
-make this code more flexible and just use shorts, ints, and longs (and their
-sizes) where it seems appropriate.  I.E. we use a short int to hold DWARF
-tags, and assume that the tag size in the file is the same as sizeof(short).
-
 FIXME: See other FIXME's and "ifdef 0" scattered throughout the code for
 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"
 #include "symfile.h"
 #include "objfiles.h"
-#include "libbfd.h"            /* FIXME Secret Internal BFD stuff (bfd_read) */
 #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)
-#endif
+#include <fcntl.h>
+#include "gdb_string.h"
 
-#ifndef R_FP           /* FIXME */
-#define R_FP 14                /* Kludge to get frame pointer register number */
-#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. */
 
-typedef unsigned int DIEREF;   /* Reference to a DIE */
+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
+};
+
+struct complaint missing_at_name =
+{
+  "DIE @ 0x%x, AT_name tag missing", 0, 0
+};
+
+typedef unsigned int DIE_REF;  /* Reference to a DIE */
 
 #ifndef GCC_PRODUCER
 #define GCC_PRODUCER "GNU C "
 #endif
 
-#define STREQ(a,b)             (strcmp(a,b)==0)
-#define STREQN(a,b,n)          (strncmp(a,b,n)==0)
+#ifndef GPLUS_PRODUCER
+#define GPLUS_PRODUCER "GNU C++ "
+#endif
+
+#ifndef LCC_PRODUCER
+#define LCC_PRODUCER "NCR C/C++"
+#endif
+
+#ifndef CHILL_PRODUCER
+#define CHILL_PRODUCER "GNU Chill "
+#endif
+
+/* Provide a default mapping from a DWARF register number to a gdb REGNUM.  */
+#ifndef DWARF_REG_TO_REGNUM
+#define DWARF_REG_TO_REGNUM(num) (num)
+#endif
 
-#define SWAPIN(to,from,objfile)        swapin((char *)&(to),from,sizeof(to),objfile)
+/* 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
+   in the host environment, and the two environments have different sized
+   ints.  In this case, *somebody* has to sign extend the smaller sized
+   int. */
+
+#define GET_UNSIGNED   0       /* No sign extension required */
+#define GET_SIGNED     1       /* Sign extension required */
+
+/* Defines for things which are specified in the document "DWARF Debugging
+   Information Format" published by UNIX International, Programming Languages
+   SIG.  These defines are based on revision 1.0.0, Jan 20, 1992. */
+
+#define SIZEOF_DIE_LENGTH      4
+#define SIZEOF_DIE_TAG         2
+#define SIZEOF_ATTRIBUTE       2
+#define SIZEOF_FORMAT_SPECIFIER        1
+#define SIZEOF_FMT_FT          2
+#define SIZEOF_LINETBL_LENGTH  4
+#define SIZEOF_LINETBL_LINENO  4
+#define SIZEOF_LINETBL_STMT    2
+#define SIZEOF_LINETBL_DELTA   4
+#define SIZEOF_LOC_ATOM_CODE   1
+
+#define FORM_FROM_ATTR(attr)   ((attr) & 0xF)  /* Implicitly specified */
+
+/* Macros that return the sizes of various types of data in the target
+   environment.
+
+   FIXME:  Currently these are just compile time constants (as they are in
+   other parts of gdb as well).  They need to be able to get the right size
+   either from the bfd or possibly from the DWARF info.  It would be nice if
+   the DWARF producer inserted DIES that describe the fundamental types in
+   the target environment into the DWARF info, similar to the way dbx stabs
+   producers produce information about their fundamental types. */
+
+#define TARGET_FT_POINTER_SIZE(objfile)        (TARGET_PTR_BIT / TARGET_CHAR_BIT)
+#define TARGET_FT_LONG_SIZE(objfile)   (TARGET_LONG_BIT / TARGET_CHAR_BIT)
 
 /* The Amiga SVR4 header file <dwarf.h> defines AT_element_list as a
    FORM_BLOCK2, and this is the value emitted by the AT&T compiler.
@@ -109,7 +254,7 @@ extern char *warning_pre_print;             /* From utils.c */
    the information for a single DIE, the one currently being processed.
 
    In order to make it easier to randomly access the attribute fields
-   of the current DIE, which are specifically unordered within the DIE
+   of the current DIE, which are specifically unordered within the DIE,
    each DIE is scanned and an instance of the "struct dieinfo"
    structure is initialized.
 
@@ -133,88 +278,101 @@ extern char *warning_pre_print;          /* From utils.c */
 typedef char BLOCK;
 
 struct dieinfo {
-  char *       die;                    /* Pointer to the raw DIE data */
-  long         dielength;              /* Length of the raw DIE data */
-  DIEREF       dieref;                 /* Offset of this DIE */
-  short                dietag;                 /* Tag for this DIE */
-  long         at_padding;
-  long         at_sibling;
-  BLOCK *      at_location;
-  char *       at_name;
-  unsigned short at_fund_type;
-  BLOCK *      at_mod_fund_type;
-  long         at_user_def_type;
-  BLOCK *      at_mod_u_d_type;
-  short                at_ordering;
-  BLOCK *      at_subscr_data;
-  long         at_byte_size;
-  short                at_bit_offset;
-  long         at_bit_size;
-  BLOCK *      at_element_list;
-  long         at_stmt_list;
-  long         at_low_pc;
-  long         at_high_pc;
-  long         at_language;
-  long         at_member;
-  long         at_discr;
-  BLOCK *      at_discr_value;
-  short                at_visibility;
-  long         at_import;
-  BLOCK *      at_string_length;
-  char *       at_comp_dir;
-  char *       at_producer;
-  long         at_frame_base;
-  long         at_start_scope;
-  long         at_stride_size;
-  long         at_src_info;
-  short                at_prototyped;
-  unsigned int has_at_low_pc:1;
-  unsigned int has_at_stmt_list:1;
-  unsigned int short_element_list:1;
+  char *               die;            /* Pointer to the raw DIE data */
+  unsigned long        die_length;     /* Length of the raw DIE data */
+  DIE_REF              die_ref;        /* Offset of this DIE */
+  unsigned short       die_tag;        /* Tag for this DIE */
+  unsigned long                at_padding;
+  unsigned long                at_sibling;
+  BLOCK *              at_location;
+  char *               at_name;
+  unsigned short       at_fund_type;
+  BLOCK *              at_mod_fund_type;
+  unsigned long                at_user_def_type;
+  BLOCK *              at_mod_u_d_type;
+  unsigned short       at_ordering;
+  BLOCK *              at_subscr_data;
+  unsigned long                at_byte_size;
+  unsigned short       at_bit_offset;
+  unsigned long                at_bit_size;
+  BLOCK *              at_element_list;
+  unsigned long                at_stmt_list;
+  CORE_ADDR            at_low_pc;
+  CORE_ADDR            at_high_pc;
+  unsigned long                at_language;
+  unsigned long                at_member;
+  unsigned long                at_discr;
+  BLOCK *              at_discr_value;
+  BLOCK *              at_string_length;
+  char *               at_comp_dir;
+  char *               at_producer;
+  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;
+
+  /* Kludge to identify register variables */
+
+  unsigned int         isreg;
+
+  /* Kludge to identify optimized out variables */
+
+  unsigned int         optimized_out;
+
+  /* Kludge to identify basereg references.
+     Nonzero if we have an offset relative to a basereg.  */
+
+  unsigned int         offreg;
+
+  /* Kludge to identify which base register is it relative to.  */
+
+  unsigned int         basereg;
 };
 
 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 */
-static int offreg;     /* Kludge to identify basereg references */
 
+/* This value is added to each symbol value.  FIXME:  Generalize to 
+   the section_offsets structure used by dbxread (once this is done,
+   pass the appropriate section number to end_symtab).  */
 static CORE_ADDR baseaddr;     /* Add to each symbol value */
 
-/* Each partial symbol table entry contains a pointer to private data for the
-   read_symtab() function to use when expanding a partial symbol table entry
-   to a full symbol table entry.  For DWARF debugging info, this data is
-   contained in the following structure and macros are provided for easy
-   access to the members given a pointer to a partial symbol table entry.
-
-   dbfoff      Always the absolute file offset to the start of the ".debug"
-               section for the file containing the DIE's being accessed.
-
-   dbroff      Relative offset from the start of the ".debug" access to the
-               first DIE to be accessed.  When building the partial symbol
-               table, this value will be zero since we are accessing the
-               entire ".debug" section.  When expanding a partial symbol
-               table entry, this value will be the offset to the first
-               DIE for the compilation unit containing the symbol that
-               triggers the expansion.
-
-   dblength    The size of the chunk of DIE's being examined, in bytes.
-
-   lnfoff      The absolute file offset to the line table fragment.  Ignored
-               when building partial symbol tables, but used when expanding
-               them, and contains the absolute file offset to the fragment
-               of the ".line" section containing the line numbers for the
-               current compilation unit.
- */
+/* The section offsets used in the current psymtab or symtab.  FIXME,
+   only used to pass one value (baseaddr) at the moment.  */
+static struct section_offsets *base_section_offsets;
+
+/* We put a pointer to this structure in the read_symtab_private field
+   of the psymtab.  */
 
 struct dwfinfo {
-  int 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 */
+  /* Always the absolute file offset to the start of the ".debug"
+     section for the file containing the DIE's being accessed.  */
+  file_ptr dbfoff;
+  /* Relative offset from the start of the ".debug" section to the
+     first DIE to be accessed.  When building the partial symbol
+     table, this value will be zero since we are accessing the
+     entire ".debug" section.  When expanding a partial symbol
+     table entry, this value will be the offset to the first
+     DIE for the compilation unit containing the symbol that
+     triggers the expansion.  */
+  int dbroff;
+  /* The size of the chunk of DIE's being examined, in bytes.  */
+  int dblength;
+  /* The absolute file offset to the line table fragment.  Ignored
+     when building partial symbol tables, but used when expanding
+     them, and contains the absolute file offset to the fragment
+     of the ".line" section containing the line numbers for the
+     current compilation unit.  */
+  file_ptr lnfoff;
 };
 
 #define DBFOFF(p) (((struct dwfinfo *)((p)->read_symtab_private))->dbfoff)
@@ -254,20 +412,57 @@ 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.  */
 
 static void
-swapin PARAMS ((char *, char *, int, struct objfile *));
+free_utypes PARAMS ((PTR));
+
+static int
+attribute_size PARAMS ((unsigned int));
+
+static CORE_ADDR
+target_to_host PARAMS ((char *, int, int, struct objfile *));
 
 static void
 add_enum_psymbol PARAMS ((struct dieinfo *, struct objfile *));
 
+static void
+handle_producer PARAMS ((char *));
+
 static void
 read_file_scope PARAMS ((struct dieinfo *, char *, char *, struct objfile *));
 
@@ -278,22 +473,16 @@ 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 *));
 
-static void
-init_psymbol_list PARAMS ((struct objfile *, int));
-
 static void
 basicdieinfo PARAMS ((struct dieinfo *, char *, struct objfile *));
 
@@ -306,7 +495,7 @@ dwarf_psymtab_to_symtab PARAMS ((struct partial_symtab *));
 static void
 psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
 
-static struct symtab *
+static void
 read_ofile_symtab PARAMS ((struct partial_symtab *));
 
 static void
@@ -320,7 +509,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 *));
@@ -328,6 +517,9 @@ dwarf_read_array_type PARAMS ((struct dieinfo *));
 static void
 read_tag_pointer_type PARAMS ((struct dieinfo *dip));
 
+static void
+read_tag_string_type PARAMS ((struct dieinfo *dip));
+
 static void
 read_subroutine_type PARAMS ((struct dieinfo *, char *, char *));
 
@@ -353,7 +545,7 @@ static struct type *
 decode_mod_u_d_type PARAMS ((char *));
 
 static struct type *
-decode_modified_type PARAMS ((unsigned char *, unsigned int, int));
+decode_modified_type PARAMS ((char *, unsigned int, int));
 
 static struct type *
 decode_fund_type PARAMS ((unsigned int));
@@ -362,20 +554,144 @@ static char *
 create_name PARAMS ((char *, struct obstack *));
 
 static struct type *
-lookup_utype PARAMS ((DIEREF));
+lookup_utype PARAMS ((DIE_REF));
 
 static struct type *
-alloc_utype PARAMS ((DIEREF, struct type *));
+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 *));
+locval PARAMS ((struct dieinfo *));
 
 static void
-record_minimal_symbol PARAMS ((char *, CORE_ADDR, enum minimal_symbol_type,
-                              struct objfile *));
+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;
+      case LANG_CHILL:
+       cu_language = language_chill;
+       break;
+      case LANG_MODULA2:
+       cu_language = language_m2;
+       break;
+      case LANG_FORTRAN77:
+      case LANG_FORTRAN90:
+       cu_language = language_fortran;
+       break;
+      case LANG_ADA83:
+      case LANG_COBOL74:
+      case LANG_COBOL85:
+      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);
+}
 
 /*
 
@@ -385,17 +701,17 @@ GLOBAL FUNCTION
 
 SYNOPSIS
 
-       void dwarf_build_psymtabs (int desc, char *filename, CORE_ADDR addr,
-            int mainline, unsigned int dbfoff, unsigned int dbsize,
-            unsigned int lnoffset, unsigned int lnsize,
-            struct objfile *objfile)
+       void dwarf_build_psymtabs (struct objfile *objfile,
+            struct section_offsets *section_offsets,
+            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
@@ -410,28 +726,28 @@ RETURNS
  */
 
 void
-dwarf_build_psymtabs (desc, filename, addr, mainline, dbfoff, dbsize,
-                     lnoffset, lnsize, objfile)
-     int desc;
-     char *filename;
-     CORE_ADDR addr;
+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, SEEK_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);
   
@@ -439,108 +755,27 @@ dwarf_build_psymtabs (desc, filename, addr, mainline, dbfoff, dbsize,
      Since we have no idea how many DIES we are looking at, we just guess
      some arbitrary value. */
   
-  if (mainline || objfile->global_psymbols.size == 0 || objfile->static_psymbols.size == 0)
+  if (mainline || objfile -> global_psymbols.size == 0 ||
+      objfile -> static_psymbols.size == 0)
     {
       init_psymbol_list (objfile, 1024);
     }
   
   /* Save the relocation factor where everybody can see it.  */
 
-  baseaddr = addr;
+  base_section_offsets = section_offsets;
+  baseaddr = ANOFFSET (section_offsets, 0);
 
   /* Follow the compilation unit sibling chain, building a partial symbol
      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;
 }
 
-
-/*
-
-LOCAL FUNCTION
-
-       record_minimal_symbol -- add entry to gdb's minimal symbol table
-
-SYNOPSIS
-
-       static void record_minimal_symbol (char *name, CORE_ADDR address,
-                                         enum minimal_symbol_type ms_type,
-                                         struct objfile *objfile)
-
-DESCRIPTION
-
-       Given a pointer to the name of a symbol that should be added to the
-       minimal symbol table, and the address associated with that
-       symbol, records this information for later use in building the
-       minimal symbol table.
-
- */
-
-static void
-record_minimal_symbol (name, address, ms_type, objfile)
-     char *name;
-     CORE_ADDR address;
-     enum minimal_symbol_type ms_type;
-     struct objfile *objfile;
-{
-  name = obsavestring (name, strlen (name), &objfile -> symbol_obstack);
-  prim_record_minimal_symbol (name, address, ms_type);
-}
-
-/*
-
-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 -> dieref);
-  if (curdie -> at_name)
-    {
-      fprintf (stderr, "'%s': ", curdie -> at_name);
-    }
-  vfprintf (stderr, fmt, ap);
-  fprintf (stderr, "\n");
-  fflush (stderr);
-  va_end (ap);
-}
-
 /*
 
 LOCAL FUNCTION
@@ -568,8 +803,8 @@ read_lexical_block_scope (dip, thisdie, enddie, objfile)
 {
   register struct context_stack *new;
 
-  (void) push_context (0, dip -> at_low_pc);
-  process_dies (thisdie + dip -> dielength, enddie, objfile);
+  push_context (0, dip -> at_low_pc);
+  process_dies (thisdie + dip -> die_length, enddie, objfile);
   new = pop_context ();
   if (local_symbols != NULL)
     {
@@ -587,7 +822,7 @@ LOCAL FUNCTION
 
 SYNOPSIS
 
-       static type *lookup_utype (DIEREF dieref)
+       static type *lookup_utype (DIE_REF die_ref)
 
 DESCRIPTION
 
@@ -599,16 +834,16 @@ DESCRIPTION
  */
 
 static struct type *
-lookup_utype (dieref)
-     DIEREF dieref;
+lookup_utype (die_ref)
+     DIE_REF die_ref;
 {
   struct type *type = NULL;
   int utypeidx;
   
-  utypeidx = (dieref - dbroff) / 4;
+  utypeidx = (die_ref - dbroff) / 4;
   if ((utypeidx < 0) || (utypeidx >= numutypes))
     {
-      dwarfwarn ("reference to DIE (0x%x) outside compilation unit", dieref);
+      complain (&bad_die_ref, DIE_ID, DIE_NAME);
     }
   else
     {
@@ -626,54 +861,77 @@ LOCAL FUNCTION
 
 SYNOPSIS
 
-       static type *alloc_utype (DIEREF dieref, struct type *utypep)
+       static type *alloc_utype (DIE_REF die_ref, struct type *utypep)
 
 DESCRIPTION
 
-       Given a die reference DIEREF, and a possible pointer to a user
+       Given a die reference DIE_REF, and a possible pointer to a user
        defined type UTYPEP, register that this reference has a user
        defined type and either use the specified type in UTYPEP or
        make a new empty type that will be filled in later.
 
        We should only be called after calling lookup_utype() to verify that
-       there is not currently a type registered for DIEREF.
+       there is not currently a type registered for DIE_REF.
  */
 
 static struct type *
-alloc_utype (dieref, utypep)
-     DIEREF dieref;
+alloc_utype (die_ref, utypep)
+     DIE_REF die_ref;
      struct type *utypep;
 {
   struct type **typep;
   int utypeidx;
   
-  utypeidx = (dieref - dbroff) / 4;
+  utypeidx = (die_ref - dbroff) / 4;
   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", dieref);
+      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
     {
       if (utypep == NULL)
        {
-         utypep = (struct type *)
-           obstack_alloc (&current_objfile -> type_obstack,
-                          sizeof (struct type));
-         (void) memset (utypep, 0, sizeof (struct type));
-         TYPE_OBJFILE (utypep) = current_objfile;
+         utypep = alloc_type (current_objfile);
        }
       *typep = utypep;
     }
   return (utypep);
 }
 
+/*
+
+LOCAL FUNCTION
+
+       free_utypes -- free the utypes array and reset pointer & count
+
+SYNOPSIS
+
+       static void free_utypes (PTR dummy)
+
+DESCRIPTION
+
+       Called via do_cleanups to free the utypes array, reset the pointer to NULL,
+       and set numutypes back to zero.  This ensures that the utypes does not get
+       referenced after being freed.
+ */
+
+static void
+free_utypes (dummy)
+     PTR dummy;
+{
+  free (utypes);
+  utypes = NULL;
+  numutypes = 0;
+}
+
+
 /*
 
 LOCAL FUNCTION
@@ -718,7 +976,7 @@ decode_die_type (dip)
     }
   else
     {
-      type = lookup_fundamental_type (current_objfile, FT_INTEGER);
+      type = dwarf_fundamental_type (current_objfile, FT_VOID);
     }
   return (type);
 }
@@ -759,31 +1017,31 @@ struct_type (dip, thisdie, enddie, objfile)
   struct nextfield *new;
   int nfields = 0;
   int n;
-  char *tpart1;
   struct dieinfo mbr;
   char *nextdie;
+  int anonymous_size;
   
-  if ((type = lookup_utype (dip -> dieref)) == NULL)
+  if ((type = lookup_utype (dip -> die_ref)) == NULL)
     {
       /* No forward references created an empty type, so install one now */
-      type = alloc_utype (dip -> dieref, NULL);
+      type = alloc_utype (dip -> die_ref, NULL);
     }
   INIT_CPLUS_SPECIFIC(type);
-  switch (dip -> dietag)
+  switch (dip -> die_tag)
     {
+      case TAG_class_type:
+        TYPE_CODE (type) = TYPE_CODE_CLASS;
+       break;
       case TAG_structure_type:
         TYPE_CODE (type) = TYPE_CODE_STRUCT;
-       tpart1 = "struct";
        break;
       case TAG_union_type:
        TYPE_CODE (type) = TYPE_CODE_UNION;
-       tpart1 = "union";
        break;
       default:
        /* 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
@@ -793,19 +1051,21 @@ struct_type (dip, thisdie, enddie, objfile)
       && *dip -> at_name != '~'
       && *dip -> at_name != '.')
     {
-      TYPE_NAME (type) = obconcat (&objfile -> type_obstack,
-                                  tpart1, " ", dip -> at_name);
-    }
-  if (dip -> at_byte_size != 0)
-    {
-      TYPE_LENGTH (type) = dip -> at_byte_size;
+      TYPE_TAG_NAME (type) = obconcat (&objfile -> type_obstack,
+                                      "", "", dip -> at_name);
     }
-  thisdie += dip -> dielength;
+  /* 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)
     {
       basicdieinfo (&mbr, thisdie, objfile);
       completedieinfo (&mbr, objfile);
-      if (mbr.dielength <= sizeof (long))
+      if (mbr.die_length <= SIZEOF_DIE_LENGTH)
        {
          break;
        }
@@ -815,9 +1075,9 @@ struct_type (dip, thisdie, enddie, objfile)
        }
       else
        {
-         nextdie = thisdie + mbr.dielength;
+         nextdie = thisdie + mbr.die_length;
        }
-      switch (mbr.dietag)
+      switch (mbr.die_tag)
        {
        case TAG_member:
          /* Get space to record the next field's data.  */
@@ -825,10 +1085,54 @@ struct_type (dip, thisdie, enddie, objfile)
          new -> next = list;
          list = new;
          /* Save the data.  */
-         list -> field.name = savestring (mbr.at_name, strlen (mbr.at_name));
-         list -> field.type = decode_die_type (&mbr);
-         list -> field.bitpos = 8 * locval (mbr.at_location);
-         list -> field.bitsize = 0;
+         list -> field.name =
+             obsavestring (mbr.at_name, strlen (mbr.at_name),
+                           &objfile -> type_obstack);
+         FIELD_TYPE (list->field) = decode_die_type (&mbr);
+         FIELD_BITPOS (list->field) = 8 * locval (&mbr);
+         /* Handle bit fields. */
+         FIELD_BITSIZE (list->field) = mbr.at_bit_size;
+         if (BITS_BIG_ENDIAN)
+           {
+             /* For big endian bits, the at_bit_offset gives the
+                additional bit offset from the MSB of the containing
+                anonymous object to the MSB of the field.  We don't
+                have to do anything special since we don't need to
+                know the size of the anonymous object. */
+             FIELD_BITPOS (list->field) += mbr.at_bit_offset;
+           }
+         else
+           {
+             /* For little endian bits, we need to have a non-zero
+                at_bit_size, so that we know we are in fact dealing
+                with a bitfield.  Compute the bit offset to the MSB
+                of the anonymous object, subtract off the number of
+                bits from the MSB of the field to the MSB of the
+                object, and then subtract off the number of bits of
+                the field 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);
+                   }
+                 FIELD_BITPOS (list->field) +=
+                   anonymous_size * 8 - mbr.at_bit_offset - mbr.at_bit_size;
+               }
+           }
          nfields++;
          break;
        default:
@@ -850,8 +1154,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)
        {
@@ -908,9 +1211,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);
+           }
        }
     }
 }
@@ -939,36 +1247,47 @@ decode_array_element_type (scan)
      char *scan;
 {
   struct type *typep;
-  short attribute;
-  DIEREF dieref;
+  DIE_REF die_ref;
+  unsigned short attribute;
   unsigned short fundtype;
+  int nbytes;
   
-  /* FIXME, does this confuse the host and target sizeof's?  --gnu */
-  SWAPIN (attribute, scan, current_objfile);
-  scan += sizeof (short);
-  switch (attribute)
-    {
-    case AT_fund_type:
-      SWAPIN (fundtype, scan, current_objfile);
-      typep = decode_fund_type (fundtype);
-      break;
-    case AT_mod_fund_type:
-      typep = decode_mod_fund_type (scan);
-      break;
-    case AT_user_def_type:
-      SWAPIN (dieref, scan, current_objfile);
-      if ((typep = lookup_utype (dieref)) == NULL)
+  attribute = target_to_host (scan, SIZEOF_ATTRIBUTE, GET_UNSIGNED,
+                             current_objfile);
+  scan += SIZEOF_ATTRIBUTE;
+  if ((nbytes = attribute_size (attribute)) == -1)
+    {
+      complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
+      typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+    }
+  else
+    {
+      switch (attribute)
        {
-         typep = alloc_utype (dieref, NULL);
-       }
-      break;
-    case AT_mod_u_d_type:
-      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);
-      break;
+         case AT_fund_type:
+           fundtype = target_to_host (scan, nbytes, GET_UNSIGNED,
+                                      current_objfile);
+           typep = decode_fund_type (fundtype);
+           break;
+         case AT_mod_fund_type:
+           typep = decode_mod_fund_type (scan);
+           break;
+         case AT_user_def_type:
+           die_ref = target_to_host (scan, nbytes, GET_UNSIGNED,
+                                     current_objfile);
+           if ((typep = lookup_utype (die_ref)) == NULL)
+             {
+               typep = alloc_utype (die_ref, NULL);
+             }
+           break;
+         case AT_mod_u_d_type:
+           typep = decode_mod_u_d_type (scan);
+           break;
+         default:
+           complain (&bad_array_element_type, DIE_ID, DIE_NAME, attribute);
+           typep = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+           break;
+         }
     }
   return (typep);
 }
@@ -977,11 +1296,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
 
@@ -993,9 +1313,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
@@ -1006,52 +1338,48 @@ 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;
-  int format;
-  short fundtype;
-  long lowbound;
-  long highbound;
+  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;
+  unsigned long highbound;
+  int nbytes;
   
-  format = *scan++;
+  format = target_to_host (scan, SIZEOF_FORMAT_SPECIFIER, GET_UNSIGNED,
+                          current_objfile);
+  scan += SIZEOF_FORMAT_SPECIFIER;
   switch (format)
     {
     case FMT_ET:
       typep = decode_array_element_type (scan);
       break;
     case FMT_FT_C_C:
-      SWAPIN (fundtype, scan, current_objfile);
-      scan += sizeof (short);
-      if (fundtype != FT_integer && fundtype != FT_signed_integer
-         && fundtype != FT_unsigned_integer)
+      fundtype = target_to_host (scan, SIZEOF_FMT_FT, GET_UNSIGNED,
+                                current_objfile);
+      indextype = decode_fund_type (fundtype);
+      scan += SIZEOF_FMT_FT;
+      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)
        {
-         SQUAWK (("array subscripts must be integral types, not type 0x%x",
-                    fundtype));
-       }
-      else
-       {
-         SWAPIN (lowbound, scan, current_objfile);
-         scan += sizeof (long);
-         SWAPIN (highbound, scan, current_objfile);
-         scan += sizeof (long);
-         nexttype = decode_subscr_data (scan, end);
-         if (nexttype != NULL)
-           {
-             typep = (struct type *)
-               obstack_alloc (&current_objfile -> type_obstack,
-                              sizeof (struct type));
-             (void) memset (typep, 0, sizeof (struct type));
-             TYPE_OBJFILE (typep) = current_objfile;
-             TYPE_CODE (typep) = TYPE_CODE_ARRAY;
-             TYPE_LENGTH (typep) = TYPE_LENGTH (nexttype);
-             TYPE_LENGTH (typep) *= lowbound + highbound + 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:
@@ -1060,10 +1388,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);
@@ -1093,42 +1427,43 @@ dwarf_read_array_type (dip)
   struct type *utype;
   char *sub;
   char *subend;
-  short temp;
+  unsigned short blocksz;
+  int nbytes;
   
   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)
     {
-      SWAPIN (temp, sub, current_objfile);
-      subend = sub + sizeof (short) + temp;
-      sub += sizeof (short);
-      type = decode_subscr_data (sub, subend);
-      if (type == NULL)
+      nbytes = attribute_size (AT_subscr_data);
+      blocksz = target_to_host (sub, nbytes, GET_UNSIGNED, current_objfile);
+      subend = sub + nbytes + blocksz;
+      sub += nbytes;
+      type = decode_subscript_data_item (sub, subend);
+      if ((utype = lookup_utype (dip -> die_ref)) == NULL)
        {
-         if ((utype = lookup_utype (dip -> dieref)) == NULL)
-           {
-             utype = alloc_utype (dip -> dieref, 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 -> dieref)) == NULL)
-           {
-             (void) alloc_utype (dip -> dieref, 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);
        }
     }
 }
@@ -1153,27 +1488,88 @@ static void
 read_tag_pointer_type (dip)
      struct dieinfo *dip;
 {
-  struct type *type;
+  struct type *type;
+  struct type *utype;
+  
+  type = decode_die_type (dip);
+  if ((utype = lookup_utype (dip -> die_ref)) == NULL)
+    {
+      utype = lookup_pointer_type (type);
+      alloc_utype (dip -> die_ref, utype);
+    }
+  else
+    {
+      TYPE_TARGET_TYPE (utype) = type;
+      TYPE_POINTER_TYPE (type) = utype;
+
+      /* We assume the machine has only one representation for pointers!  */
+      /* FIXME:  Possably a poor assumption  */
+      TYPE_LENGTH (utype) = TARGET_PTR_BIT / TARGET_CHAR_BIT ;
+      TYPE_CODE (utype) = TYPE_CODE_PTR;
+    }
+}
+
+/*
+
+LOCAL FUNCTION
+
+       read_tag_string_type -- read TAG_string_type DIE
+
+SYNOPSIS
+
+       static void read_tag_string_type (struct dieinfo *dip)
+
+DESCRIPTION
+
+       Extract all information from a TAG_string_type DIE and add to
+       the user defined type vector.  It isn't really a user defined
+       type, but it behaves like one, with other DIE's using an
+       AT_user_def_type attribute to reference it.
+ */
+
+static void
+read_tag_string_type (dip)
+     struct dieinfo *dip;
+{
   struct type *utype;
-  
-  type = decode_die_type (dip);
-  if ((utype = lookup_utype (dip -> dieref)) == NULL)
+  struct type *indextype;
+  struct type *rangetype;
+  unsigned long lowbound = 0;
+  unsigned long highbound;
+
+  if (dip -> has_at_byte_size)
     {
-      utype = lookup_pointer_type (type);
-      (void) alloc_utype (dip -> dieref, utype);
+      /* A fixed bounds string */
+      highbound = dip -> at_byte_size - 1;
     }
   else
     {
-      TYPE_TARGET_TYPE (utype) = type;
-      TYPE_POINTER_TYPE (type) = utype;
-
-      /* We assume the machine has only one representation for pointers!  */
-      /* FIXME:  This confuses host<->target data representations, and is a
-        poor assumption besides. */
+      /* A varying length string.  Stub for now.  (FIXME) */
+      highbound = 1;
+    }
+  indextype = dwarf_fundamental_type (current_objfile, FT_INTEGER);
+  rangetype = create_range_type ((struct type *) NULL, indextype, lowbound,
+                                highbound);
       
-      TYPE_LENGTH (utype) = sizeof (char *);
-      TYPE_CODE (utype) = TYPE_CODE_PTR;
+  utype = lookup_utype (dip -> die_ref);
+  if (utype == NULL)
+    {
+      /* No type defined, go ahead and create a blank one to use. */
+      utype = alloc_utype (dip -> die_ref, (struct type *) NULL);
+    }
+  else
+    {
+      /* Already a type in our slot due to a forward reference. Make sure it
+        is a blank one.  If not, complain and leave it alone. */
+      if (TYPE_CODE (utype) != TYPE_CODE_UNDEF)
+       {
+         complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+         return;
+       }
     }
+
+  /* Create the string type using the blank type we either found or created. */
+  utype = create_string_type (utype, rangetype);
 }
 
 /*
@@ -1219,22 +1615,25 @@ read_subroutine_type (dip, thisdie, enddie)
   /* Check to see if we already have a partially constructed user
      defined type for this DIE, from a forward reference. */
 
-  if ((ftype = lookup_utype (dip -> dieref)) == NULL)
+  if ((ftype = lookup_utype (dip -> die_ref)) == NULL)
     {
       /* This is the first reference to one of these types.  Make
         a new one and place it in the user defined types. */
       ftype = lookup_function_type (type);
-      (void) alloc_utype (dip -> dieref, ftype);
+      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. */
       TYPE_TARGET_TYPE (ftype) = type;
-      TYPE_FUNCTION_TYPE (type) = ftype;
       TYPE_LENGTH (ftype) = 1;
       TYPE_CODE (ftype) = TYPE_CODE_FUNC;
     }
+  else
+    {
+      complain (&dup_user_type_definition, DIE_ID, DIE_NAME);
+    }
 }
 
 /*
@@ -1271,9 +1670,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);
+       }
     }
 }
 
@@ -1324,14 +1728,15 @@ enum_type (dip, objfile)
   int n;
   char *scan;
   char *listend;
-  long ltemp;
-  short stemp;
+  unsigned short blocksz;
   struct symbol *sym;
+  int nbytes;
+  int unsigned_enum = 1;
   
-  if ((type = lookup_utype (dip -> dieref)) == NULL)
+  if ((type = lookup_utype (dip -> die_ref)) == NULL)
     {
       /* No forward references created an empty type, so install one now */
-      type = alloc_utype (dip -> dieref, NULL);
+      type = alloc_utype (dip -> die_ref, NULL);
     }
   TYPE_CODE (type) = TYPE_CODE_ENUM;
   /* Some compilers try to be helpful by inventing "fake" names for
@@ -1341,8 +1746,8 @@ enum_type (dip, objfile)
       && *dip -> at_name != '~'
       && *dip -> at_name != '.')
     {
-      TYPE_NAME (type) = obconcat (&objfile -> type_obstack, "enum",
-                                  ", dip -> at_name);
+      TYPE_TAG_NAME (type) = obconcat (&objfile -> type_obstack,
+                                      "", "", dip -> at_name);
     }
   if (dip -> at_byte_size != 0)
     {
@@ -1352,46 +1757,54 @@ enum_type (dip, objfile)
     {
       if (dip -> short_element_list)
        {
-         SWAPIN (stemp, scan, objfile);
-         listend = scan + stemp + sizeof (stemp);
-         scan += sizeof (stemp);
+         nbytes = attribute_size (AT_short_element_list);
        }
       else
        {
-         SWAPIN (ltemp, scan, objfile);
-         listend = scan + ltemp + sizeof (ltemp);
-         scan += sizeof (ltemp);
+         nbytes = attribute_size (AT_element_list);
        }
+      blocksz = target_to_host (scan, nbytes, GET_UNSIGNED, objfile);
+      listend = scan + nbytes + blocksz;
+      scan += nbytes;
       while (scan < listend)
        {
          new = (struct nextfield *) alloca (sizeof (struct nextfield));
          new -> next = list;
          list = new;
-         list -> field.type = NULL;
-         list -> field.bitsize = 0;
-         SWAPIN (list -> field.bitpos, scan, objfile);
-         scan += sizeof (long);
-         list -> field.name = savestring (scan, strlen (scan));
+         FIELD_TYPE (list->field) = NULL;
+         FIELD_BITSIZE (list->field) = 0;
+         FIELD_BITPOS (list->field) =
+           target_to_host (scan, TARGET_FT_LONG_SIZE (objfile), GET_SIGNED,
+                           objfile);
+         scan += TARGET_FT_LONG_SIZE (objfile);
+         list -> field.name = obsavestring (scan, strlen (scan),
+                                            &objfile -> type_obstack);
          scan += strlen (scan) + 1;
          nfields++;
          /* Handcraft a new symbol for this enum member. */
          sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
                                                 sizeof (struct symbol));
-         (void) memset (sym, 0, sizeof (struct symbol));
-         SYMBOL_NAME (sym) = create_name (list -> field.name, &objfile->symbol_obstack);
+         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;
-         SYMBOL_VALUE (sym) = list -> field.bitpos;
+         SYMBOL_VALUE (sym) = FIELD_BITPOS (list->field);
+         if (SYMBOL_VALUE (sym) < 0)
+           unsigned_enum = 0;
          add_symbol_to_list (sym, list_in_scope);
        }
       /* Now create the vector of fields, and record how big it is. This is
-        where we reverse the order, by pulling the members of the list in
+        where we reverse the order, by pulling the members off the list in
         reverse order from how they were inserted.  If we have no fields
         (this is apparently possible in C++) then skip building a field
         vector. */
       if (nfields > 0)
        {
+         if (unsigned_enum)
+           TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
          TYPE_NFIELDS (type) = nfields;
          TYPE_FIELDS (type) = (struct field *)
            obstack_alloc (&objfile->symbol_obstack, sizeof (struct field) * nfields);
@@ -1435,6 +1848,16 @@ read_func_scope (dip, thisdie, enddie, objfile)
 {
   register struct context_stack *new;
   
+  /* AT_name is absent if the function is described with an
+     AT_abstract_origin tag.
+     Ignore the function description for now to avoid GDB core dumps.
+     FIXME: Add code to handle AT_abstract_origin tags properly.  */
+  if (dip -> at_name == NULL)
+    {
+      complain (&missing_at_name, DIE_ID);
+      return;
+    }
+
   if (objfile -> ei.entry_point >= dip -> at_low_pc &&
       objfile -> ei.entry_point <  dip -> at_high_pc)
     {
@@ -1449,7 +1872,7 @@ read_func_scope (dip, thisdie, enddie, objfile)
   new = push_context (0, dip -> at_low_pc);
   new -> name = new_symbol (dip, objfile);
   list_in_scope = &local_symbols;
-  process_dies (thisdie + dip -> dielength, enddie, objfile);
+  process_dies (thisdie + dip -> die_length, enddie, objfile);
   new = pop_context ();
   /* Make a block for the local symbols within.  */
   finish_block (new -> name, &local_symbols, new -> old_blocks,
@@ -1457,6 +1880,52 @@ read_func_scope (dip, thisdie, enddie, objfile)
   list_in_scope = &file_symbols;
 }
 
+
+/*
+
+LOCAL FUNCTION
+
+       handle_producer -- process the AT_producer attribute
+
+DESCRIPTION
+
+       Perform any operations that depend on finding a particular
+       AT_producer attribute.
+
+ */
+
+static void
+handle_producer (producer)
+     char *producer;
+{
+
+  /* If this compilation unit was compiled with g++ or gcc, then set the
+     processing_gcc_compilation flag. */
+
+  processing_gcc_compilation =
+    STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER))
+      || STREQN (producer, CHILL_PRODUCER, strlen (CHILL_PRODUCER))
+      || STREQN (producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
+
+  /* Select a demangling style if we can identify the producer and if
+     the current style is auto.  We leave the current style alone if it
+     is not auto.  We also leave the demangling style alone if we find a
+     gcc (cc1) producer, as opposed to a g++ (cc1plus) producer. */
+
+  if (AUTO_DEMANGLING)
+    {
+      if (STREQN (producer, GPLUS_PRODUCER, strlen (GPLUS_PRODUCER)))
+       {
+         set_demangling_style (GNU_DEMANGLING_STYLE_STRING);
+       }
+      else if (STREQN (producer, LCC_PRODUCER, strlen (LCC_PRODUCER)))
+       {
+         set_demangling_style (LUCID_DEMANGLING_STYLE_STRING);
+       }
+    }
+}
+
+
 /*
 
 LOCAL FUNCTION
@@ -1495,35 +1964,27 @@ 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)
     {
-      processing_gcc_compilation =
-       STREQN (dip -> at_producer, GCC_PRODUCER, strlen (GCC_PRODUCER));
+      handle_producer (dip -> at_producer);
     }
   numutypes = (enddie - thisdie) / 4;
   utypes = (struct type **) xmalloc (numutypes * sizeof (struct type *));
-  back_to = make_cleanup (free, utypes);
-  (void) memset (utypes, 0, numutypes * sizeof (struct type *));
-  start_symtab (dip -> at_name, NULL, dip -> at_low_pc);
+  back_to = make_cleanup (free_utypes, NULL);
+  memset (utypes, 0, numutypes * sizeof (struct type *));
+  memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
+  start_symtab (dip -> at_name, dip -> at_comp_dir, dip -> at_low_pc);
+  record_debugformat ("DWARF 1");
   decode_line_numbers (lnbase);
-  process_dies (thisdie + dip -> dielength, 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)
+  process_dies (thisdie + dip -> die_length, enddie, objfile);
+
+  symtab = end_symtab (dip -> at_high_pc, objfile, 0);
+  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;
 }
 
 /*
@@ -1555,13 +2016,13 @@ process_dies (thisdie, enddie, objfile)
   while (thisdie < enddie)
     {
       basicdieinfo (&di, thisdie, objfile);
-      if (di.dielength < sizeof (long))
+      if (di.die_length < SIZEOF_DIE_LENGTH)
        {
          break;
        }
-      else if (di.dietag == TAG_padding)
+      else if (di.die_tag == TAG_padding)
        {
-         nextdie = thisdie + di.dielength;
+         nextdie = thisdie + di.die_length;
        }
       else
        {
@@ -1572,12 +2033,23 @@ process_dies (thisdie, enddie, objfile)
            }
          else
            {
-             nextdie = thisdie + di.dielength;
+             nextdie = thisdie + di.die_length;
            }
-         switch (di.dietag)
+#ifdef SMASH_TEXT_ADDRESS
+         /* I think that these are always text, not data, addresses.  */
+         SMASH_TEXT_ADDRESS (di.at_low_pc);
+         SMASH_TEXT_ADDRESS (di.at_high_pc);
+#endif
+         switch (di.die_tag)
            {
            case TAG_compile_unit:
-             read_file_scope (&di, thisdie, nextdie, objfile);
+             /* Skip Tag_compile_unit if we are already inside a compilation
+                unit, we are unable to handle nested compilation units
+                properly (FIXME).  */
+             if (current_subfile == NULL)
+               read_file_scope (&di, thisdie, nextdie, objfile);
+             else
+               nextdie = thisdie + di.die_length;
              break;
            case TAG_global_subroutine:
            case TAG_subroutine:
@@ -1589,6 +2061,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);
@@ -1605,8 +2078,11 @@ process_dies (thisdie, enddie, objfile)
            case TAG_pointer_type:
              read_tag_pointer_type (&di);
              break;
+           case TAG_string_type:
+             read_tag_string_type (&di);
+             break;
            default:
-             (void) new_symbol (&di, objfile);
+             new_symbol (&di, objfile);
              break;
            }
        }
@@ -1680,28 +2156,32 @@ decode_line_numbers (linetable)
 {
   char *tblscan;
   char *tblend;
-  long length;
-  long base;
-  long line;
-  long pc;
+  unsigned long length;
+  unsigned long base;
+  unsigned long line;
+  unsigned long pc;
   
   if (linetable != NULL)
     {
       tblscan = tblend = linetable;
-      SWAPIN (length, tblscan, current_objfile);
-      tblscan += sizeof (long);
+      length = target_to_host (tblscan, SIZEOF_LINETBL_LENGTH, GET_UNSIGNED,
+                              current_objfile);
+      tblscan += SIZEOF_LINETBL_LENGTH;
       tblend += length;
-      SWAPIN (base, tblscan, current_objfile);
+      base = target_to_host (tblscan, TARGET_FT_POINTER_SIZE (objfile),
+                            GET_UNSIGNED, current_objfile);
+      tblscan += TARGET_FT_POINTER_SIZE (objfile);
       base += baseaddr;
-      tblscan += sizeof (long);
       while (tblscan < tblend)
        {
-         SWAPIN (line, tblscan, current_objfile);
-         tblscan += sizeof (long) + sizeof (short);
-         SWAPIN (pc, tblscan, current_objfile);
-         tblscan += sizeof (long);
+         line = target_to_host (tblscan, SIZEOF_LINETBL_LINENO, GET_UNSIGNED,
+                                current_objfile);
+         tblscan += SIZEOF_LINETBL_LINENO + SIZEOF_LINETBL_STMT;
+         pc = target_to_host (tblscan, SIZEOF_LINETBL_DELTA, GET_UNSIGNED,
+                              current_objfile);
+         tblscan += SIZEOF_LINETBL_DELTA;
          pc += base;
-         if (line > 0)
+         if (line != 0)
            {
              record_line (current_subfile, line, pc);
            }
@@ -1717,20 +2197,23 @@ LOCAL FUNCTION
 
 SYNOPSIS
 
-       static int locval (char *loc)
+       static int locval (struct dieinfo *dip)
 
 DESCRIPTION
 
        Given pointer to a string of bytes that define a location, compute
        the location and return the value.
+       A location description containing no atoms indicates that the
+       object is optimized out. The optimized_out flag is set for those,
+       the return value is meaningless.
 
        When computing values involving the current value of the frame pointer,
        the value zero is used, which results in a value relative to the frame
        pointer, rather than the absolute value.  This is what GDB wants
        anyway.
     
-       When the result is a register number, the global isreg flag is set,
-       otherwise it is cleared.  This is a kludge until we figure out a better
+       When the result is a register number, the isreg flag is set, otherwise
+       it is cleared.  This is a kludge until we figure out a better
        way to handle the problem.  Gdb's design does not mesh well with the
        DWARF notion of a location computing interpreter, which is a shame
        because the flexibility goes unused.
@@ -1742,71 +2225,84 @@ NOTES
  */
 
 static int
-locval (loc)
-     char *loc;
+locval (dip)
+     struct dieinfo *dip;
 {
   unsigned short nbytes;
-  auto int stack[64];
+  unsigned short locsize;
+  auto long stack[64];
   int stacki;
+  char *loc;
   char *end;
-  long regno;
+  int loc_atom_code;
+  int loc_value_size;
   
-  SWAPIN (nbytes, loc, current_objfile);
-  end = loc + sizeof (short) + nbytes;
+  loc = dip -> at_location;
+  nbytes = attribute_size (AT_location);
+  locsize = target_to_host (loc, nbytes, GET_UNSIGNED, current_objfile);
+  loc += nbytes;
+  end = loc + locsize;
   stacki = 0;
   stack[stacki] = 0;
-  isreg = 0;
-  offreg = 0;
-  for (loc += sizeof (short); loc < end; loc += sizeof (long))
-    {
-      switch (*loc++) {
-      case 0:
-       /* error */
-       loc = end;
-       break;
-      case OP_REG:
-       /* push register (number) */
-       stacki++;
-       SWAPIN (stack[stacki], loc, current_objfile);
-       isreg = 1;
-       break;
-      case OP_BASEREG:
-       /* push value of register (number) */
-       /* Actually, we compute the value as if register has 0 */
-       offreg = 1;
-       SWAPIN (regno, loc, current_objfile);
-       if (regno == R_FP)
-         {
-           stack[++stacki] = 0;
-         }
-       else
-         {
+  dip -> isreg = 0;
+  dip -> offreg = 0;
+  dip -> optimized_out = 1;
+  loc_value_size = TARGET_FT_LONG_SIZE (current_objfile);
+  while (loc < end)
+    {
+      dip -> optimized_out = 0;
+      loc_atom_code = target_to_host (loc, SIZEOF_LOC_ATOM_CODE, GET_UNSIGNED,
+                                     current_objfile);
+      loc += SIZEOF_LOC_ATOM_CODE;
+      switch (loc_atom_code)
+       {
+         case 0:
+           /* error */
+           loc = end;
+           break;
+         case OP_REG:
+           /* push register (number) */
+           stack[++stacki]
+             = DWARF_REG_TO_REGNUM (target_to_host (loc, loc_value_size,
+                                                    GET_UNSIGNED,
+                                                    current_objfile));
+           loc += loc_value_size;
+           dip -> isreg = 1;
+           break;
+         case OP_BASEREG:
+           /* push value of register (number) */
+           /* Actually, we compute the value as if register has 0, so the
+              value ends up being the offset from that register.  */
+           dip -> offreg = 1;
+           dip -> basereg = target_to_host (loc, loc_value_size, GET_UNSIGNED,
+                                            current_objfile);
+           loc += loc_value_size;
            stack[++stacki] = 0;
-           SQUAWK (("BASEREG %d not handled!", regno));
-         }
-       break;
-      case OP_ADDR:
-       /* push address (relocated address) */
-       stacki++;
-       SWAPIN (stack[stacki], loc, current_objfile);
-       break;
-      case OP_CONST:
-       /* push constant (number) */
-       stacki++;
-       SWAPIN (stack[stacki], loc, current_objfile);
-       break;
-      case OP_DEREF2:
-       /* pop, deref and push 2 bytes (as a long) */
-       SQUAWK (("OP_DEREF2 address %#x not handled", stack[stacki]));
-       break;
-      case OP_DEREF4:  /* pop, deref and push 4 bytes (as a long) */
-       SQUAWK (("OP_DEREF4 address %#x not handled", stack[stacki]));
-       break;
-      case OP_ADD:     /* pop top 2 items, add, push result */
-       stack[stacki - 1] += stack[stacki];
-       stacki--;
-       break;
-      }
+           break;
+         case OP_ADDR:
+           /* push address (relocated address) */
+           stack[++stacki] = target_to_host (loc, loc_value_size,
+                                             GET_UNSIGNED, current_objfile);
+           loc += loc_value_size;
+           break;
+         case OP_CONST:
+           /* push constant (number)   FIXME: signed or unsigned! */
+           stack[++stacki] = target_to_host (loc, loc_value_size,
+                                             GET_SIGNED, current_objfile);
+           loc += loc_value_size;
+           break;
+         case OP_DEREF2:
+           /* pop, deref and push 2 bytes (as a long) */
+           complain (&op_deref2, DIE_ID, DIE_NAME, stack[stacki]);
+           break;
+         case OP_DEREF4:       /* pop, deref and push 4 bytes (as a long) */
+           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];
+           stacki--;
+           break;
+       }
     }
   return (stack[stacki]);
 }
@@ -1819,26 +2315,26 @@ LOCAL FUNCTION
 
 SYNOPSIS
 
-       static struct symtab *read_ofile_symtab (struct partial_symtab *pst)
+       static void read_ofile_symtab (struct partial_symtab *pst)
 
 DESCRIPTION
 
        When expanding a partial symbol table entry to a full symbol table
        entry, this is the function that gets called to read in the symbols
-       for the compilation unit.
-
-       Returns a pointer to the newly constructed symtab (which is now
-       the new first one on the objfile's symtab list).
+       for the compilation unit.  A pointer to the newly constructed symtab,
+       which is now the new first one on the objfile's symtab list, is
+       stashed in the partial symbol table entry.
  */
 
-static struct symtab *
+static void
 read_ofile_symtab (pst)
      struct partial_symtab *pst;
 {
   struct cleanup *back_to;
-  long lnsize;
-  int foffset;
+  unsigned long lnsize;
+  file_ptr foffset;
   bfd *abfd;
+  char lnsizedata[SIZEOF_LINETBL_LENGTH];
 
   abfd = pst -> objfile -> obfd;
   current_objfile = pst -> objfile;
@@ -1847,12 +2343,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;
-  baseaddr = pst -> addr;
-  if (bfd_seek (abfd, foffset, 0) ||
-      (bfd_read (dbbase, DBLENGTH(pst), 1, abfd) != DBLENGTH(pst)))
+  base_section_offsets = pst->section_offsets;
+  baseaddr = ANOFFSET (pst->section_offsets, 0);
+  if (bfd_seek (abfd, foffset, SEEK_SET) ||
+      (bfd_read (dbbase, dbsize, 1, abfd) != dbsize))
     {
       free (dbbase);
       error ("can't read DWARF data");
@@ -1860,22 +2358,23 @@ read_ofile_symtab (pst)
   back_to = make_cleanup (free, dbbase);
 
   /* If there is a line number table associated with this compilation unit
-     then read the first long word from the line number table fragment, which
-     contains the size of the fragment in bytes (including the long word
-     itself).  Allocate a buffer for the fragment and read it in for future
+     then read the size of this fragment in bytes, from the fragment itself.
+     Allocate a buffer for the fragment and read it in for future 
      processing. */
 
   lnbase = NULL;
   if (LNFOFF (pst))
     {
-      if (bfd_seek (abfd, LNFOFF (pst), 0) ||
-         (bfd_read ((PTR)&lnsize, sizeof(long), 1, abfd) != sizeof(long)))
+      if (bfd_seek (abfd, LNFOFF (pst), SEEK_SET) ||
+         (bfd_read ((PTR) lnsizedata, sizeof (lnsizedata), 1, abfd) !=
+          sizeof (lnsizedata)))
        {
          error ("can't read DWARF line number table size");
        }
-      lnsize = bfd_h_get_32 (abfd, (unsigned char *) &lnsize);
+      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), SEEK_SET) ||
          (bfd_read (lnbase, lnsize, 1, abfd) != lnsize))
        {
          free (lnbase);
@@ -1884,10 +2383,10 @@ 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);
+  pst -> symtab = pst -> objfile -> symtabs;
 }
 
 /*
@@ -1912,6 +2411,7 @@ psymtab_to_symtab_1 (pst)
      struct partial_symtab *pst;
 {
   int i;
+  struct cleanup *old_chain;
   
   if (pst != NULL)
     {
@@ -1930,28 +2430,31 @@ psymtab_to_symtab_1 (pst)
                  /* Inform about additional files that need to be read in. */
                  if (info_verbose)
                    {
-                     fputs_filtered (" ", stdout);
+                     fputs_filtered (" ", gdb_stdout);
                      wrap_here ("");
-                     fputs_filtered ("and ", stdout);
+                     fputs_filtered ("and ", gdb_stdout);
                      wrap_here ("");
                      printf_filtered ("%s...",
                                       pst -> dependencies[i] -> filename);
                      wrap_here ("");
-                     fflush (stdout);          /* Flush output */
+                     gdb_flush (gdb_stdout);           /* Flush output */
                    }
                  psymtab_to_symtab_1 (pst -> dependencies[i]);
                }
            }     
          if (DBLENGTH (pst))           /* Otherwise it's a dummy */
            {
-             pst -> symtab = read_ofile_symtab (pst);
+             buildsym_init ();
+             old_chain = make_cleanup (really_free_pendings, 0);
+             read_ofile_symtab (pst);
              if (info_verbose)
                {
                  printf_filtered ("%d DIE's, sorting...", diecount);
                  wrap_here ("");
-                 fflush (stdout);
+                 gdb_flush (gdb_stdout);
                }
              sort_symtab_syms (pst -> symtab);
+             do_cleanups (old_chain);
            }
          pst -> readin = 1;
        }
@@ -1998,7 +2501,7 @@ dwarf_psymtab_to_symtab (pst)
                {
                  printf_filtered ("Reading in symbols for %s...",
                                   pst -> filename);
-                 fflush (stdout);
+                 gdb_flush (gdb_stdout);
                }
              
              psymtab_to_symtab_1 (pst);
@@ -2016,7 +2519,7 @@ dwarf_psymtab_to_symtab (pst)
              if (info_verbose)
                {
                  printf_filtered ("done.\n");
-                 fflush (stdout);
+                 gdb_flush (gdb_stdout);
                }
            }
        }
@@ -2025,54 +2528,6 @@ dwarf_psymtab_to_symtab (pst)
 
 /*
 
-LOCAL FUNCTION
-
-       init_psymbol_list -- initialize storage for partial symbols
-
-SYNOPSIS
-
-       static void init_psymbol_list (struct objfile *objfile, int total_symbols)
-
-DESCRIPTION
-
-       Initializes storage for all of the partial symbols that will be
-       created by dwarf_build_psymtabs and subsidiaries.
- */
-
-static void
-init_psymbol_list (objfile, total_symbols)
-     struct objfile *objfile;
-     int total_symbols;
-{
-  /* Free any previously allocated psymbol lists.  */
-  
-  if (objfile -> global_psymbols.list)
-    {
-      mfree (objfile -> md, (PTR)objfile -> global_psymbols.list);
-    }
-  if (objfile -> static_psymbols.list)
-    {
-      mfree (objfile -> md, (PTR)objfile -> static_psymbols.list);
-    }
-  
-  /* Current best guess is that there are approximately a twentieth
-     of the total symbols (in a debugging file) are global or static
-     oriented symbols */
-  
-  objfile -> global_psymbols.size = total_symbols / 10;
-  objfile -> static_psymbols.size = total_symbols / 10;
-  objfile -> global_psymbols.next =
-    objfile -> global_psymbols.list = (struct partial_symbol *)
-      xmmalloc (objfile -> md, objfile -> global_psymbols.size
-                            * sizeof (struct partial_symbol));
-  objfile -> static_psymbols.next =
-    objfile -> static_psymbols.list = (struct partial_symbol *)
-      xmmalloc (objfile -> md, objfile -> static_psymbols.size
-                            * sizeof (struct partial_symbol));
-}
-
-/*
-
 LOCAL FUNCTION
 
        add_enum_psymbol -- add enumeration members to partial symbol table
@@ -2091,28 +2546,28 @@ add_enum_psymbol (dip, objfile)
 {
   char *scan;
   char *listend;
-  long ltemp;
-  short stemp;
+  unsigned short blocksz;
+  int nbytes;
   
   if ((scan = dip -> at_element_list) != NULL)
     {
       if (dip -> short_element_list)
        {
-         SWAPIN (stemp, scan, objfile);
-         listend = scan + stemp + sizeof (stemp);
-         scan += sizeof (stemp);
+         nbytes = attribute_size (AT_short_element_list);
        }
       else
        {
-         SWAPIN (ltemp, scan, objfile);
-         listend = scan + ltemp + sizeof (ltemp);
-         scan += sizeof (ltemp);
+         nbytes = attribute_size (AT_element_list);
        }
+      blocksz = target_to_host (scan, nbytes, GET_UNSIGNED, objfile);
+      scan += nbytes;
+      listend = scan + blocksz;
       while (scan < listend)
        {
-         scan += sizeof (long);
-         ADD_PSYMBOL_TO_LIST (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST,
-                              objfile -> static_psymbols, 0);
+         scan += TARGET_FT_LONG_SIZE (objfile);
+         add_psymbol_to_list (scan, strlen (scan), VAR_NAMESPACE, LOC_CONST,
+                              &objfile -> static_psymbols, 0, 0, cu_language,
+                              objfile);
          scan += strlen (scan) + 1;
        }
     }
@@ -2130,6 +2585,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
@@ -2137,58 +2595,57 @@ add_partial_symbol (dip, objfile)
      struct dieinfo *dip;
      struct objfile *objfile;
 {
-  switch (dip -> dietag)
+  switch (dip -> die_tag)
     {
     case TAG_global_subroutine:
-      record_minimal_symbol (dip -> at_name, dip -> at_low_pc, mst_text,
-                           objfile);
-      ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
-                          VAR_NAMESPACE, LOC_BLOCK,
-                          objfile -> global_psymbols,
-                          dip -> at_low_pc);
+      add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name),
+                               VAR_NAMESPACE, LOC_BLOCK,
+                               &objfile -> global_psymbols,
+                               0, dip -> at_low_pc, cu_language, objfile);
       break;
     case TAG_global_variable:
-      record_minimal_symbol (dip -> at_name, locval (dip -> at_location),
-                           mst_data, objfile);
-      ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+      add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name),
                           VAR_NAMESPACE, LOC_STATIC,
-                          objfile -> global_psymbols,
-                          0);
+                          &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);
+      add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name),
+                               VAR_NAMESPACE, LOC_BLOCK,
+                               &objfile -> static_psymbols,
+                               0, dip -> at_low_pc, cu_language, objfile);
       break;
     case TAG_local_variable:
-      ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+      add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name),
                           VAR_NAMESPACE, LOC_STATIC,
-                          objfile -> static_psymbols,
-                          0);
+                          &objfile -> static_psymbols,
+                          0, 0, cu_language, objfile);
       break;
     case TAG_typedef:
-      ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
+      add_psymbol_to_list (dip -> at_name, strlen (dip -> at_name),
                           VAR_NAMESPACE, LOC_TYPEDEF,
-                          objfile -> static_psymbols,
-                          0);
+                          &objfile -> static_psymbols,
+                          0, 0, cu_language, objfile);
       break;
+    case TAG_class_type:
     case TAG_structure_type:
     case TAG_union_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)
+      /* Do not add opaque aggregate definitions to the psymtab.  */
+      if (!dip -> has_at_byte_size)
+       break;
+      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)
        {
-         ADD_PSYMBOL_TO_LIST (dip -> at_name, strlen (dip -> at_name),
-                              STRUCT_NAMESPACE, LOC_TYPEDEF,
-                              objfile -> static_psymbols,
-                              0);
+         /* 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);
        }
-      add_enum_psymbol (dip, objfile);
       break;
     }
 }
@@ -2203,15 +2660,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
@@ -2229,24 +2721,48 @@ scan_partial_symbols (thisdie, enddie, objfile)
      struct objfile *objfile;
 {
   char *nextdie;
+  char *temp;
   struct dieinfo di;
   
   while (thisdie < enddie)
     {
       basicdieinfo (&di, thisdie, objfile);
-      if (di.dielength < sizeof (long))
+      if (di.die_length < SIZEOF_DIE_LENGTH)
        {
          break;
        }
       else
        {
-         nextdie = thisdie + di.dielength;
+         nextdie = thisdie + di.die_length;
          /* To avoid getting complete die information for every die, we
             only do it (below) for the cases we are interested in. */
-         switch (di.dietag)
+         switch (di.die_tag)
            {
            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);
@@ -2256,6 +2772,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);
@@ -2266,7 +2783,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;
            }
        }
@@ -2318,12 +2839,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;
@@ -2331,29 +2851,30 @@ 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)
     {
       basicdieinfo (&di, thisdie, objfile);
-      if (di.dielength < sizeof (long))
+      if (di.die_length < SIZEOF_DIE_LENGTH)
        {
          break;
        }
-      else if (di.dietag != TAG_compile_unit)
+      else if (di.die_tag != TAG_compile_unit)
        {
-         nextdie = thisdie + di.dielength;
+         nextdie = thisdie + di.die_length;
        }
       else
        {
          completedieinfo (&di, objfile);
+         set_cu_language (&di);
          if (di.at_sibling != 0)
            {
              nextdie = dbbase + di.at_sibling - dbroff;
            }
          else
            {
-             nextdie = thisdie + di.dielength;
+             nextdie = thisdie + di.die_length;
            }
          curoff = thisdie - dbbase;
          culength = nextdie - thisdie;
@@ -2361,8 +2882,8 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
 
          /* First allocate a new partial symbol table structure */
 
-         pst = start_psymtab_common (objfile, baseaddr, 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);
 
@@ -2378,7 +2899,7 @@ scan_compilation_units (filename, thisdie, enddie, dbfoff, lnoffset, objfile)
 
          /* Now look for partial symbols */
 
-         scan_partial_symbols (thisdie + di.dielength, nextdie, objfile);
+         scan_partial_symbols (thisdie + di.die_length, nextdie, objfile);
 
          pst -> n_global_syms = objfile -> global_psymbols.next -
            (objfile -> global_psymbols.list + pst -> globals_offset);
@@ -2423,24 +2944,36 @@ new_symbol (dip, objfile)
     {
       sym = (struct symbol *) obstack_alloc (&objfile -> symbol_obstack,
                                             sizeof (struct symbol));
-      (void) memset (sym, 0, sizeof (struct symbol));
-      SYMBOL_NAME (sym) = create_name (dip -> at_name, &objfile->symbol_obstack);
+      OBJSTAT (objfile, n_syms++);
+      memset (sym, 0, sizeof (struct symbol));
+      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);
-      switch (dip -> dietag)
+
+      /* 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:
-         SYMBOL_VALUE (sym) = dip -> at_low_pc;
+         SYMBOL_VALUE_ADDRESS (sym) = dip -> at_low_pc;
          SYMBOL_CLASS (sym) = LOC_LABEL;
          break;
        case TAG_global_subroutine:
        case TAG_subroutine:
-         SYMBOL_VALUE (sym) = dip -> at_low_pc;
+         SYMBOL_VALUE_ADDRESS (sym) = dip -> at_low_pc;
          SYMBOL_TYPE (sym) = lookup_function_type (SYMBOL_TYPE (sym));
+         if (dip -> at_prototyped)
+           TYPE_FLAGS (SYMBOL_TYPE (sym)) |= TYPE_FLAG_PROTOTYPED;
          SYMBOL_CLASS (sym) = LOC_BLOCK;
-         if (dip -> dietag == TAG_global_subroutine)
+         if (dip -> die_tag == TAG_global_subroutine)
            {
              add_symbol_to_list (sym, &global_symbols);
            }
@@ -2452,7 +2985,7 @@ new_symbol (dip, objfile)
        case TAG_global_variable:
          if (dip -> at_location != NULL)
            {
-             SYMBOL_VALUE (sym) = locval (dip -> at_location);
+             SYMBOL_VALUE_ADDRESS (sym) = locval (dip);
              add_symbol_to_list (sym, &global_symbols);
              SYMBOL_CLASS (sym) = LOC_STATIC;
              SYMBOL_VALUE (sym) += baseaddr;
@@ -2461,33 +2994,53 @@ new_symbol (dip, objfile)
        case TAG_local_variable:
          if (dip -> at_location != NULL)
            {
-             SYMBOL_VALUE (sym) = locval (dip -> at_location);
-             add_symbol_to_list (sym, list_in_scope);
-             if (isreg)
+             int loc = locval (dip);
+             if (dip -> optimized_out)
+               {
+                 SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+               }
+             else if (dip -> isreg)
                {
                  SYMBOL_CLASS (sym) = LOC_REGISTER;
                }
-             else if (offreg)
+             else if (dip -> offreg)
                {
-                 SYMBOL_CLASS (sym) = LOC_LOCAL;
+                 SYMBOL_CLASS (sym) = LOC_BASEREG;
+                 SYMBOL_BASEREG (sym) = dip -> basereg;
                }
              else
                {
                  SYMBOL_CLASS (sym) = LOC_STATIC;
                  SYMBOL_VALUE (sym) += baseaddr;
                }
+             if (SYMBOL_CLASS (sym) == LOC_STATIC)
+               {
+                 /* LOC_STATIC address class MUST use SYMBOL_VALUE_ADDRESS,
+                    which may store to a bigger location than SYMBOL_VALUE. */
+                 SYMBOL_VALUE_ADDRESS (sym) = loc;
+               }
+             else
+               {
+                 SYMBOL_VALUE (sym) = loc;
+               }
+             add_symbol_to_list (sym, list_in_scope);
            }
          break;
        case TAG_formal_parameter:
          if (dip -> at_location != NULL)
            {
-             SYMBOL_VALUE (sym) = locval (dip -> at_location);
+             SYMBOL_VALUE (sym) = locval (dip);
            }
          add_symbol_to_list (sym, list_in_scope);
-         if (isreg)
+         if (dip -> isreg)
            {
              SYMBOL_CLASS (sym) = LOC_REGPARM;
            }
+         else if (dip -> offreg)
+           {
+             SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+             SYMBOL_BASEREG (sym) = dip -> basereg;
+           }
          else
            {
              SYMBOL_CLASS (sym) = LOC_ARG;
@@ -2497,6 +3050,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:
@@ -2521,6 +3075,52 @@ 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));
+      OBJSTAT (objfile, n_syms++);
+      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
@@ -2533,9 +3133,9 @@ DESCRIPTION
 
        Decode a block of data containing a modified fundamental
        type specification.  TYPEDATA is a pointer to the block,
-       which consists of a two byte length, containing the size
-       of the rest of the block.  At the end of the block is a
-       two byte value that gives the fundamental type.  Everything
+       which starts with a length containing the size of the rest
+       of the block.  At the end of the block is a fundmental type
+       code value that gives the fundamental type.  Everything
        in between are type modifiers.
 
        We simply compute the number of modifiers and call the general
@@ -2548,16 +3148,21 @@ decode_mod_fund_type (typedata)
 {
   struct type *typep = NULL;
   unsigned short modcount;
-  unsigned char *modifiers;
+  int nbytes;
   
   /* Get the total size of the block, exclusive of the size itself */
-  SWAPIN (modcount, typedata, current_objfile);
+
+  nbytes = attribute_size (AT_mod_fund_type);
+  modcount = target_to_host (typedata, nbytes, GET_UNSIGNED, current_objfile);
+  typedata += nbytes;
+
   /* Deduct the size of the fundamental type bytes at the end of the block. */
-  modcount -= sizeof (short);
-  /* Skip over the two size bytes at the beginning of the block. */
-  modifiers = (unsigned char *) typedata + sizeof (short);
+
+  modcount -= attribute_size (AT_fund_type);
+
   /* Now do the actual decoding */
-  typep = decode_modified_type (modifiers, modcount, AT_mod_fund_type);
+
+  typep = decode_modified_type (typedata, modcount, AT_mod_fund_type);
   return (typep);
 }
 
@@ -2590,16 +3195,21 @@ decode_mod_u_d_type (typedata)
 {
   struct type *typep = NULL;
   unsigned short modcount;
-  unsigned char *modifiers;
+  int nbytes;
   
   /* Get the total size of the block, exclusive of the size itself */
-  SWAPIN (modcount, typedata, current_objfile);
+
+  nbytes = attribute_size (AT_mod_u_d_type);
+  modcount = target_to_host (typedata, nbytes, GET_UNSIGNED, current_objfile);
+  typedata += nbytes;
+
   /* Deduct the size of the reference type bytes at the end of the block. */
-  modcount -= sizeof (long);
-  /* Skip over the two size bytes at the beginning of the block. */
-  modifiers = (unsigned char *) typedata + sizeof (short);
+
+  modcount -= attribute_size (AT_user_def_type);
+
   /* Now do the actual decoding */
-  typep = decode_modified_type (modifiers, modcount, AT_mod_u_d_type);
+
+  typep = decode_modified_type (typedata, modcount, AT_mod_u_d_type);
   return (typep);
 }
 
@@ -2611,7 +3221,7 @@ LOCAL FUNCTION
 
 SYNOPSIS
 
-       static struct type *decode_modified_type (unsigned char *modifiers,
+       static struct type *decode_modified_type (char *modifiers,
            unsigned short modcount, int mtype)
 
 DESCRIPTION
@@ -2645,33 +3255,38 @@ BUGS
 
 static struct type *
 decode_modified_type (modifiers, modcount, mtype)
-     unsigned char *modifiers;
+     char *modifiers;
      unsigned int modcount;
      int mtype;
 {
   struct type *typep = NULL;
   unsigned short fundtype;
-  DIEREF dieref;
-  unsigned char modifier;
+  DIE_REF die_ref;
+  char modifier;
+  int nbytes;
   
   if (modcount == 0)
     {
       switch (mtype)
        {
        case AT_mod_fund_type:
-         SWAPIN (fundtype, modifiers, current_objfile);
+         nbytes = attribute_size (AT_fund_type);
+         fundtype = target_to_host (modifiers, nbytes, GET_UNSIGNED,
+                                    current_objfile);
          typep = decode_fund_type (fundtype);
          break;
        case AT_mod_u_d_type:
-         SWAPIN (dieref, modifiers, current_objfile);
-         if ((typep = lookup_utype (dieref)) == NULL)
+         nbytes = attribute_size (AT_user_def_type);
+         die_ref = target_to_host (modifiers, nbytes, GET_UNSIGNED,
+                                   current_objfile);
+         if ((typep = lookup_utype (die_ref)) == NULL)
            {
-             typep = alloc_utype (dieref, NULL);
+             typep = alloc_utype (die_ref, NULL);
            }
          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;
        }
     }
@@ -2681,24 +3296,25 @@ decode_modified_type (modifiers, modcount, mtype)
       typep = decode_modified_type (modifiers, --modcount, mtype);
       switch (modifier)
        {
-       case MOD_pointer_to:
-         typep = lookup_pointer_type (typep);
-         break;
-       case MOD_reference_to:
-         typep = lookup_reference_type (typep);
-         break;
-       case MOD_const:
-         SQUAWK (("type modifier 'const' ignored"));   /* FIXME */
-         break;
-       case MOD_volatile:
-         SQUAWK (("type modifier 'volatile' ignored"));        /* FIXME */
-         break;
-       default:
-         if (!(MOD_lo_user <= modifier && modifier <= MOD_hi_user))
-           {
-             SQUAWK (("unknown type modifier %u", modifier));
-           }
-         break;
+         case MOD_pointer_to:
+           typep = lookup_pointer_type (typep);
+           break;
+         case MOD_reference_to:
+           typep = lookup_reference_type (typep);
+           break;
+         case MOD_const:
+           complain (&const_ignored, DIE_ID, DIE_NAME);  /* FIXME */
+           break;
+         case MOD_volatile:
+           complain (&volatile_ignored, DIE_ID, DIE_NAME); /* FIXME */
+           break;
+         default:
+           if (!(MOD_lo_user <= (unsigned char) modifier
+                 && (unsigned char) modifier <= MOD_hi_user))
+             {
+               complain (&unknown_type_modifier, DIE_ID, DIE_NAME, modifier);
+             }
+           break;
        }
     }
   return (typep);
@@ -2718,10 +3334,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 *
@@ -2734,108 +3352,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);
@@ -2864,7 +3485,7 @@ create_name (name, obstackp)
 
   length = strlen (name) + 1;
   newname = (char *) obstack_alloc (obstackp, length);
-  (void) strcpy (newname, name);
+  strcpy (newname, name);
   return (newname);
 }
 
@@ -2906,14 +3527,20 @@ DESCRIPTION
 NOTES
 
        All DIE's must have at least a valid length, thus the minimum
-       DIE size is sizeof (long).  In order to have a valid tag, the
-       DIE size must be at least sizeof (short) larger, otherwise they
+       DIE size is SIZEOF_DIE_LENGTH.  In order to have a valid tag, the
+       DIE size must be at least SIZEOF_DIE_TAG larger, otherwise they
        are forced to be TAG_padding DIES.
 
-       Padding DIES must be at least sizeof(long) in length, implying that
-       if a padding DIE is used for alignment and the amount needed is less
-       than sizeof(long) then the padding DIE has to be big enough to align
-       to the next alignment boundry.
+       Padding DIES must be at least SIZEOF_DIE_LENGTH in length, implying
+       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
@@ -2923,21 +3550,26 @@ basicdieinfo (dip, diep, objfile)
      struct objfile *objfile;
 {
   curdie = dip;
-  (void) memset (dip, 0, sizeof (struct dieinfo));
+  memset (dip, 0, sizeof (struct dieinfo));
   dip -> die = diep;
-  dip -> dieref = dbroff + (diep - dbbase);
-  SWAPIN (dip -> dielength, diep, objfile);
-  if (dip -> dielength < sizeof (long))
+  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) ||
+      ((diep + dip -> die_length) > (dbbase + dbsize)))
     {
-      dwarfwarn ("malformed DIE, bad length (%d bytes)", dip -> dielength);
+      complain (&malformed_die, DIE_ID, DIE_NAME, dip -> die_length);
+      dip -> die_length = 0;
     }
-  else if (dip -> dielength < (sizeof (long) + sizeof (short)))
+  else if (dip -> die_length < (SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG))
     {
-      dip -> dietag = TAG_padding;
+      dip -> die_tag = TAG_padding;
     }
   else
     {
-      SWAPIN (dip -> dietag, diep + sizeof (long), objfile);
+      diep += SIZEOF_DIE_LENGTH;
+      dip -> die_tag = target_to_host (diep, SIZEOF_DIE_TAG, GET_UNSIGNED,
+                                      objfile);
     }
 }
 
@@ -2982,67 +3614,80 @@ completedieinfo (dip, objfile)
   char *end;                   /* Terminate DIE scan here */
   unsigned short attr;         /* Current attribute being scanned */
   unsigned short form;         /* Form of the attribute */
-  short block2sz;              /* Size of a block2 attribute field */
-  long block4sz;               /* Size of a block4 attribute field */
+  int nbytes;                  /* Size of next field to read */
   
   diecount++;
   diep = dip -> die;
-  end = diep + dip -> dielength;
-  diep += sizeof (long) + sizeof (short);
+  end = diep + dip -> die_length;
+  diep += SIZEOF_DIE_LENGTH + SIZEOF_DIE_TAG;
   while (diep < end)
     {
-      SWAPIN (attr, diep, objfile);
-      diep += sizeof (short);
+      attr = target_to_host (diep, SIZEOF_ATTRIBUTE, GET_UNSIGNED, objfile);
+      diep += SIZEOF_ATTRIBUTE;
+      if ((nbytes = attribute_size (attr)) == -1)
+       {
+         complain (&unknown_attribute_length, DIE_ID, DIE_NAME);
+         diep = end;
+         continue;
+       }
       switch (attr)
        {
        case AT_fund_type:
-         SWAPIN (dip -> at_fund_type, diep, objfile);
+         dip -> at_fund_type = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                               objfile);
          break;
        case AT_ordering:
-         SWAPIN (dip -> at_ordering, diep, objfile);
+         dip -> at_ordering = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                              objfile);
          break;
        case AT_bit_offset:
-         SWAPIN (dip -> at_bit_offset, diep, objfile);
-         break;
-       case AT_visibility:
-         SWAPIN (dip -> at_visibility, diep, objfile);
+         dip -> at_bit_offset = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                                objfile);
          break;
        case AT_sibling:
-         SWAPIN (dip -> at_sibling, diep, objfile);
+         dip -> at_sibling = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                             objfile);
          break;
        case AT_stmt_list:
-         SWAPIN (dip -> at_stmt_list, diep, objfile);
+         dip -> at_stmt_list = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                               objfile);
          dip -> has_at_stmt_list = 1;
          break;
        case AT_low_pc:
-         SWAPIN (dip -> at_low_pc, diep, objfile);
+         dip -> at_low_pc = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                            objfile);
          dip -> at_low_pc += baseaddr;
          dip -> has_at_low_pc = 1;
          break;
        case AT_high_pc:
-         SWAPIN (dip -> at_high_pc, diep, objfile);
+         dip -> at_high_pc = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                             objfile);
          dip -> at_high_pc += baseaddr;
          break;
        case AT_language:
-         SWAPIN (dip -> at_language, diep, objfile);
+         dip -> at_language = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                              objfile);
          break;
        case AT_user_def_type:
-         SWAPIN (dip -> at_user_def_type, diep, objfile);
+         dip -> at_user_def_type = target_to_host (diep, nbytes,
+                                                   GET_UNSIGNED, objfile);
          break;
        case AT_byte_size:
-         SWAPIN (dip -> at_byte_size, diep, objfile);
+         dip -> at_byte_size = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                               objfile);
+         dip -> has_at_byte_size = 1;
          break;
        case AT_bit_size:
-         SWAPIN (dip -> at_bit_size, diep, objfile);
+         dip -> at_bit_size = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                              objfile);
          break;
        case AT_member:
-         SWAPIN (dip -> at_member, diep, objfile);
+         dip -> at_member = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                            objfile);
          break;
        case AT_discr:
-         SWAPIN (dip -> at_discr, diep, objfile);
-         break;
-       case AT_import:
-         SWAPIN (dip -> at_import, diep, objfile);
+         dip -> at_discr = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                           objfile);
          break;
        case AT_location:
          dip -> at_location = diep;
@@ -3074,25 +3719,35 @@ 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:
-         SWAPIN (dip -> at_frame_base, diep, objfile);
-         break;
        case AT_start_scope:
-         SWAPIN (dip -> at_start_scope, diep, objfile);
+         dip -> at_start_scope = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                                 objfile);
          break;
        case AT_stride_size:
-         SWAPIN (dip -> at_stride_size, diep, objfile);
+         dip -> at_stride_size = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                                 objfile);
          break;
        case AT_src_info:
-         SWAPIN (dip -> at_src_info, diep, objfile);
+         dip -> at_src_info = target_to_host (diep, nbytes, GET_UNSIGNED,
+                                              objfile);
          break;
        case AT_prototyped:
-         SWAPIN (dip -> at_prototyped, diep, objfile);
+         dip -> at_prototyped = diep;
          break;
        default:
          /* Found an attribute that we are unprepared to handle.  However
@@ -3102,75 +3757,151 @@ completedieinfo (dip, objfile)
             we can just ignore the unknown attribute. */
          break;
        }
-      form = attr & 0xF;
+      form = FORM_FROM_ATTR (attr);
       switch (form)
        {
        case FORM_DATA2:
-         diep += sizeof (short);
+         diep += 2;
          break;
        case FORM_DATA4:
-         diep += sizeof (long);
+       case FORM_REF:
+         diep += 4;
          break;
        case FORM_DATA8:
-         diep += 8 * sizeof (char);    /* sizeof (long long) ? */
+         diep += 8;
          break;
        case FORM_ADDR:
-       case FORM_REF:
-         diep += sizeof (long);
+         diep += TARGET_FT_POINTER_SIZE (objfile);
          break;
        case FORM_BLOCK2:
-         SWAPIN (block2sz, diep, objfile);
-         block2sz += sizeof (short);
-         diep += block2sz;
+         diep += 2 + target_to_host (diep, nbytes, GET_UNSIGNED, objfile);
          break;
        case FORM_BLOCK4:
-         SWAPIN (block4sz, diep, objfile);
-         block4sz += sizeof (long);
-         diep += block4sz;
+         diep += 4 + target_to_host (diep, nbytes, GET_UNSIGNED, objfile);
          break;
        case FORM_STRING:
          diep += strlen (diep) + 1;
          break;
        default:
-         SQUAWK (("unknown attribute form (0x%x), skipped rest", form));
+         complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form);
          diep = end;
          break;
        }
     }
 }
 
+/*
 
-static void
-swapin (to, from, nbytes, objfile)
-     char *to;
+LOCAL FUNCTION
+
+       target_to_host -- swap in target data to host
+
+SYNOPSIS
+
+       target_to_host (char *from, int nbytes, int signextend,
+                       struct objfile *objfile)
+
+DESCRIPTION
+
+       Given pointer to data in target format in FROM, a byte count for
+       the size of the data in NBYTES, a flag indicating whether or not
+       the data is signed in SIGNEXTEND, and a pointer to the current
+       objfile in OBJFILE, convert the data to host format and return
+       the converted value.
+
+NOTES
+
+       FIXME:  If we read data that is known to be signed, and expect to
+       use it as signed data, then we need to explicitly sign extend the
+       result until the bfd library is able to do this for us.
+
+       FIXME: Would a 32 bit target ever need an 8 byte result?
+
+ */
+
+static CORE_ADDR
+target_to_host (from, nbytes, signextend, objfile)
      char *from;
      int nbytes;
+     int signextend;           /* FIXME:  Unused */
      struct objfile *objfile;
 {
+  CORE_ADDR rtnval;
 
   switch (nbytes)
     {
-#if defined (LONG_LONG)
       case 8:
-        *(long long *)to = 
-         bfd_h_get_64 (objfile -> obfd, (unsigned char *) from);
+        rtnval = bfd_get_64 (objfile -> obfd, (bfd_byte *) from);
        break;
-#endif
       case 4:
-        *(long *)to = bfd_h_get_32 (objfile -> obfd, (unsigned char *) from);
+       rtnval = bfd_get_32 (objfile -> obfd, (bfd_byte *) from);
        break;
       case 2:
-       *(short *)to = bfd_h_get_16 (objfile -> obfd, (unsigned char *) from);
+       rtnval = bfd_get_16 (objfile -> obfd, (bfd_byte *) from);
        break;
       case 1:
-       *to = bfd_h_get_8 (objfile -> obfd, (unsigned char *) from);
+       rtnval = bfd_get_8 (objfile -> obfd, (bfd_byte *) from);
        break;
       default:
-       /* For objects bigger than we know how to swap in, just copy
-          them without any swapping.  We should probably warn about this.
-          FIXME. */
-       (void) memcpy (to, from, nbytes);
+       complain (&no_bfd_get_N, DIE_ID, DIE_NAME, nbytes);
+       rtnval = 0;
        break;
     }
+  return (rtnval);
 }
 
+/*
+
+LOCAL FUNCTION
+
+       attribute_size -- compute size of data for a DWARF attribute
+
+SYNOPSIS
+
+       static int attribute_size (unsigned int attr)
+
+DESCRIPTION
+
+       Given a DWARF attribute in ATTR, compute the size of the first
+       piece of data associated with this attribute and return that
+       size.
+
+       Returns -1 for unrecognized attributes.
+
+ */
+
+static int
+attribute_size (attr)
+     unsigned int attr;
+{
+  int nbytes;                  /* Size of next data for this attribute */
+  unsigned short form;         /* Form of the attribute */
+
+  form = FORM_FROM_ATTR (attr);
+  switch (form)
+    {
+      case FORM_STRING:                /* A variable length field is next */
+        nbytes = 0;
+       break;
+      case FORM_DATA2:         /* Next 2 byte field is the data itself */
+      case FORM_BLOCK2:                /* Next 2 byte field is a block length */
+       nbytes = 2;
+       break;
+      case FORM_DATA4:         /* Next 4 byte field is the data itself */
+      case FORM_BLOCK4:                /* Next 4 byte field is a block length */
+      case FORM_REF:           /* Next 4 byte field is a DIE offset */
+       nbytes = 4;
+       break;
+      case FORM_DATA8:         /* Next 8 byte field is the data itself */
+       nbytes = 8;
+       break;
+      case FORM_ADDR:          /* Next field size is target sizeof(void *) */
+       nbytes = TARGET_FT_POINTER_SIZE (objfile);
+       break;
+      default:
+       complain (&unknown_attribute_form, DIE_ID, DIE_NAME, form);
+       nbytes = -1;
+       break;
+      }
+  return (nbytes);
+}
This page took 0.069683 seconds and 4 git commands to generate.