Whoops, forgot to commit this yesterday:
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index 1dfcfe3656de23a6cfe469dd6a5649ea68287d24..16a3e23080e608f033e7272c42820e0f70dadf2c 100644 (file)
@@ -1,5 +1,6 @@
 /* DWARF 2 debugging format support for GDB.
-   Copyright 1994, 1995, 1996 Free Software Foundation, Inc.
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+   Free Software Foundation, Inc.
 
    Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
    Inc.  with support from Florida State University (under contract
@@ -8,21 +9,22 @@
    based on Fred Fish's (Cygnus Support) implementation of DWARF 1
    support in dwarfread.c
 
-This file is part of GDB.
+   This file is part of GDB.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or (at
-your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or (at
+   your option) any later version.
 
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-General Public License for more details.
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   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., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 #include "bfd.h"
@@ -34,13 +36,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 #include "buildsym.h"
 #include "demangle.h"
 #include "expression.h"
-#include "language.h"
+#include "filenames.h" /* for DOSish file names */
 
+#include "language.h"
+#include "complaints.h"
+#include "bcache.h"
 #include <fcntl.h>
 #include "gdb_string.h"
 #include <sys/types.h>
 
-/* .debug_info header for a compilation unit 
+#ifndef DWARF2_REG_TO_REGNUM
+#define DWARF2_REG_TO_REGNUM(REG) (REG)
+#endif
+
+#if 0
+/* .debug_info header for a compilation unit
    Because of alignment constraints, this structure has padding and cannot
    be mapped directly onto the beginning of the .debug_info section.  */
 typedef struct comp_unit_header
@@ -54,6 +64,7 @@ typedef struct comp_unit_header
   }
 _COMP_UNIT_HEADER;
 #define _ACTUAL_COMP_UNIT_HEADER_SIZE 11
+#endif
 
 /* .debug_pubnames header
    Because of alignment constraints, this structure has padding and cannot
@@ -141,23 +152,20 @@ static unsigned int dwarf_str_size;
 #define MACINFO_SECTION  ".debug_macinfo"
 #define STR_SECTION      ".debug_str"
 
-/* Get at parts of an attribute structure */
-
-#define DW_STRING(attr)    ((attr)->u.str)
-#define DW_UNSND(attr)     ((attr)->u.unsnd)
-#define DW_BLOCK(attr)     ((attr)->u.blk)
-#define DW_SND(attr)       ((attr)->u.snd)
-#define DW_ADDR(attr)     ((attr)->u.addr)
-
 /* local data types */
 
-/* The data in a compilation unit header looks like this.  */
+/* The data in a compilation unit header, after target2host
+   translation, looks like this.  */
 struct comp_unit_head
   {
-    int length;
+    unsigned long length;
     short version;
-    int abbrev_offset;
+    unsigned int abbrev_offset;
     unsigned char addr_size;
+    unsigned char signed_addr_p;
+    unsigned int offset_size;  /* size of file offsets; either 4 or 8 */
+    unsigned int initial_length_size; /* size of the length field; either
+                                         4 or 12 */
   };
 
 /* The data in the .debug_line statement prologue looks like this.  */
@@ -168,7 +176,7 @@ struct line_head
     unsigned int prologue_length;
     unsigned char minimum_instruction_length;
     unsigned char default_is_stmt;
-    char line_base;
+    int line_base;
     unsigned char line_range;
     unsigned char opcode_base;
     unsigned char *standard_opcode_lengths;
@@ -178,24 +186,27 @@ struct line_head
    need this much information. */
 struct partial_die_info
   {
-    unsigned short tag;
+    enum dwarf_tag tag;
     unsigned char has_children;
     unsigned char is_external;
+    unsigned char is_declaration;
+    unsigned char has_type;
     unsigned int offset;
     unsigned int abbrev;
     char *name;
+    int has_pc_info;
     CORE_ADDR lowpc;
     CORE_ADDR highpc;
     struct dwarf_block *locdesc;
     unsigned int language;
-    int value;
+    char *sibling;
   };
 
 /* This data structure holds the information of an abbrev. */
 struct abbrev_info
   {
     unsigned int number;       /* number identifying abbrev */
-    unsigned int tag;          /* dwarf tag */
+    enum dwarf_tag tag;                /* dwarf tag */
     int has_children;          /* boolean */
     unsigned int num_attrs;    /* number of attributes */
     struct attr_abbrev *attrs; /* an array of attribute descriptions */
@@ -204,40 +215,48 @@ struct abbrev_info
 
 struct attr_abbrev
   {
-    unsigned int name;
-    unsigned int form;
+    enum dwarf_attribute name;
+    enum dwarf_form form;
   };
 
 /* This data structure holds a complete die structure. */
 struct die_info
   {
-    unsigned short tag;                 /* Tag indicating type of die */
-    unsigned short has_children; /* Does the die have children */
-    unsigned int abbrev;        /* Abbrev number */
-    unsigned int offset;        /* Offset in .debug_info section */
-    unsigned int num_attrs;     /* Number of attributes */
-    struct attribute *attrs;    /* An array of attributes */
-    struct die_info *next_ref;  /* Next die in ref hash table */
-    struct die_info *next;      /* Next die in linked list */
-    struct type *type;          /* Cached type information */
+    enum dwarf_tag tag;                /* Tag indicating type of die */
+    unsigned short has_children;       /* Does the die have children */
+    unsigned int abbrev;       /* Abbrev number */
+    unsigned int offset;       /* Offset in .debug_info section */
+    unsigned int num_attrs;    /* Number of attributes */
+    struct attribute *attrs;   /* An array of attributes */
+    struct die_info *next_ref; /* Next die in ref hash table */
+    struct die_info *next;     /* Next die in linked list */
+    struct type *type;         /* Cached type information */
   };
 
 /* Attributes have a name and a value */
 struct attribute
   {
-    unsigned short name;
-    unsigned short form;
+    enum dwarf_attribute name;
+    enum dwarf_form form;
     union
       {
        char *str;
        struct dwarf_block *blk;
-       unsigned int unsnd;
-       int snd;
+       unsigned long unsnd;
+       long int snd;
        CORE_ADDR addr;
       }
     u;
   };
 
+/* Get at parts of an attribute structure */
+
+#define DW_STRING(attr)    ((attr)->u.str)
+#define DW_UNSND(attr)     ((attr)->u.unsnd)
+#define DW_BLOCK(attr)     ((attr)->u.blk)
+#define DW_SND(attr)       ((attr)->u.snd)
+#define DW_ADDR(attr)     ((attr)->u.addr)
+
 /* Blocks are a bunch of untyped bytes. */
 struct dwarf_block
   {
@@ -254,12 +273,6 @@ struct dwarf_block
 #define ATTR_ALLOC_CHUNK 4
 #endif
 
-/* FIXME: do away with this */
-
-#ifndef DWARF2_MAX_STRING_SIZE
-#define DWARF2_MAX_STRING_SIZE 1024
-#endif
-
 static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
 
 /* A hash table of die offsets for following references.  */
@@ -269,6 +282,13 @@ static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
 
 static struct die_info *die_ref_table[REF_HASH_SIZE];
 
+/* Obstack for allocating temporary storage used during symbol reading.  */
+static struct obstack dwarf2_tmp_obstack;
+
+/* Offset to the first byte of the current compilation unit header,
+   for resolving relative reference dies. */
+static unsigned int cu_header_offset;
+
 /* Allocate fields for structs, unions and enums in this size.  */
 #ifndef DW_FIELD_ALLOC_CHUNK
 #define DW_FIELD_ALLOC_CHUNK 4
@@ -283,9 +303,8 @@ static char *dwarf_info_buffer;
 static char *dwarf_abbrev_buffer;
 static char *dwarf_line_buffer;
 
-/* A zeroed version of several structures for initialization purposes.  */
+/* A zeroed version of a partial die for initialization purposes.  */
 static struct partial_die_info zeroed_partial_die;
-static struct die_info zeroed_die;
 
 /* The generic symbol table building routines have separate lists for
    file scope symbols and all all other scopes (local scopes).  So
@@ -297,16 +316,82 @@ static struct die_info zeroed_die;
    fine.  Check to see if we really need to distinguish these
    in buildsym.c.  */
 static struct pending **list_in_scope = &file_symbols;
-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 
+/* FIXME: decode_locdesc sets these variables to describe the location
+   to the caller.  These ought to be a structure or something.   If
+   none of the flags are set, the object lives at the address returned
+   by decode_locdesc.  */
+
+static int optimized_out;      /* No ops in location in expression,
+                                  so object was optimized out.  */
+static int isreg;              /* Object lives in register.
+                                  decode_locdesc's return value is
+                                  the register number.  */
+static int offreg;             /* Object's address is the sum of the
+                                  register specified by basereg, plus
+                                  the offset returned.  */
+static int basereg;            /* See `offreg'.  */
+static int isderef;            /* Value described by flags above is
+                                  the address of a pointer to the object.  */
+static int islocal;            /* Variable is at the returned offset
+                                  from the frame start, but there's
+                                  no identified frame pointer for
+                                  this function, so we can't say
+                                  which register it's relative to;
+                                  use LOC_LOCAL.  */
+
+/* DW_AT_frame_base values for the current function.
+   frame_base_reg is -1 if DW_AT_frame_base is missing, otherwise it
+   contains the register number for the frame register.
+   frame_base_offset is the offset from the frame register to the
+   virtual stack frame. */
+static int frame_base_reg;
+static CORE_ADDR frame_base_offset;
+
+/* 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 */
 
+/* We put a pointer to this structure in the read_symtab_private field
+   of the psymtab.
+   The complete dwarf information for an objfile is kept in the
+   psymbol_obstack, so that absolute die references can be handled.
+   Most of the information in this structure is related to an entire
+   object file and could be passed via the sym_private field of the objfile.
+   It is however conceivable that dwarf2 might not be the only type
+   of symbols read from an object file.  */
+
+struct dwarf2_pinfo
+  {
+    /* Pointer to start of dwarf info buffer for the objfile.  */
+
+    char *dwarf_info_buffer;
+
+    /* Offset in dwarf_info_buffer for this compilation unit. */
+
+    unsigned long dwarf_info_offset;
+
+    /* Pointer to start of dwarf abbreviation buffer for the objfile.  */
+
+    char *dwarf_abbrev_buffer;
+
+    /* Size of dwarf abbreviation section for the objfile.  */
+
+    unsigned int dwarf_abbrev_size;
+
+    /* Pointer to start of dwarf line buffer for the objfile.  */
+
+    char *dwarf_line_buffer;
+  };
+
+#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
+#define DWARF_INFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_info_buffer)
+#define DWARF_INFO_OFFSET(p) (PST_PRIVATE(p)->dwarf_info_offset)
+#define DWARF_ABBREV_BUFFER(p) (PST_PRIVATE(p)->dwarf_abbrev_buffer)
+#define DWARF_ABBREV_SIZE(p) (PST_PRIVATE(p)->dwarf_abbrev_size)
+#define DWARF_LINE_BUFFER(p) (PST_PRIVATE(p)->dwarf_line_buffer)
+
 /* 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
@@ -318,205 +403,393 @@ static CORE_ADDR baseaddr;      /* Add to each symbol value */
    fundamental types gdb knows how to construct.  */
 static struct type *ftypes[FT_NUM_MEMBERS];    /* Fundamental types */
 
-/* FIXME - set from bfd function */
+/* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte,
+   but this would require a corresponding change in unpack_field_as_long
+   and friends.  */
 static int bits_per_byte = 8;
 
-/* Keep track of whether we have given a warning about not
-   handling DW_TAG_const_type dies.  */
-static int tag_const_warning_given = 0;
+/* The routines that read and process dies for a C struct or C++ class
+   pass lists of data member fields and lists of member function fields
+   in an instance of a field_info structure, as defined below.  */
+struct field_info
+  {
+    /* List of data member and baseclasses fields. */
+    struct nextfield
+      {
+       struct nextfield *next;
+       int accessibility;
+       int virtuality;
+       struct field field;
+      }
+     *fields;
+
+    /* Number of fields.  */
+    int nfields;
+
+    /* Number of baseclasses.  */
+    int nbaseclasses;
+
+    /* Set if the accesibility of one of the fields is not public.  */
+    int non_public_fields;
 
-/* Keep track of whether we have given a warning about not
-   handling DW_TAG_volatile_type dies.  */
-static int tag_volatile_warning_given = 0;
+    /* Member function fields array, entries are allocated in the order they
+       are encountered in the object file.  */
+    struct nextfnfield
+      {
+       struct nextfnfield *next;
+       struct fn_field fnfield;
+      }
+     *fnfields;
+
+    /* Member function fieldlist array, contains name of possibly overloaded
+       member function, number of overloaded member functions and a pointer
+       to the head of the member function field chain.  */
+    struct fnfieldlist
+      {
+       char *name;
+       int length;
+       struct nextfnfield *head;
+      }
+     *fnfieldlists;
+
+    /* Number of entries in the fnfieldlists array.  */
+    int nfnfields;
+  };
+
+/* FIXME: Kludge to mark a varargs function type for C++ member function
+   argument processing.  */
+#define TYPE_FLAG_VARARGS      (1 << 10)
 
-/* Keep track of constant array bound warning.  */
-static int array_bound_warning_given = 0;
+/* Dwarf2 has no clean way to discern C++ static and non-static member
+   functions. G++ helps GDB by marking the first parameter for non-static
+   member functions (which is the this pointer) as artificial.
+   We pass this information between dwarf2_add_member_fn and
+   read_subroutine_type via TYPE_FIELD_ARTIFICIAL.  */
+#define TYPE_FIELD_ARTIFICIAL  TYPE_FIELD_BITPOS
 
-/* Remember the addr_size read from the dwarf.
-   If a target expects to link compilation units with differing address
-   sizes, gdb needs to be sure that the appropriate size is here for
-   whatever scope is currently getting read. */
-static int address_size;
+/* Various complaints about symbol reading that don't abort the process */
 
-/* Externals references.  */
-extern int info_verbose;       /* From main.c; nonzero => verbose */
+static struct complaint dwarf2_const_ignored =
+{
+  "type qualifier 'const' ignored", 0, 0
+};
+static struct complaint dwarf2_volatile_ignored =
+{
+  "type qualifier 'volatile' ignored", 0, 0
+};
+static struct complaint dwarf2_non_const_array_bound_ignored =
+{
+  "non-constant array bounds form '%s' ignored", 0, 0
+};
+static struct complaint dwarf2_missing_line_number_section =
+{
+  "missing .debug_line section", 0, 0
+};
+static struct complaint dwarf2_mangled_line_number_section =
+{
+  "mangled .debug_line section", 0, 0
+};
+static struct complaint dwarf2_unsupported_die_ref_attr =
+{
+  "unsupported die ref attribute form: '%s'", 0, 0
+};
+static struct complaint dwarf2_unsupported_stack_op =
+{
+  "unsupported stack op: '%s'", 0, 0
+};
+static struct complaint dwarf2_complex_location_expr =
+{
+  "location expression too complex", 0, 0
+};
+static struct complaint dwarf2_unsupported_tag =
+{
+  "unsupported tag: '%s'", 0, 0
+};
+static struct complaint dwarf2_unsupported_at_encoding =
+{
+  "unsupported DW_AT_encoding: '%s'", 0, 0
+};
+static struct complaint dwarf2_unsupported_at_frame_base =
+{
+  "unsupported DW_AT_frame_base for function '%s'", 0, 0
+};
+static struct complaint dwarf2_unexpected_tag =
+{
+  "unexepected tag in read_type_die: '%s'", 0, 0
+};
+static struct complaint dwarf2_missing_at_frame_base =
+{
+  "DW_AT_frame_base missing for DW_OP_fbreg", 0, 0
+};
+static struct complaint dwarf2_bad_static_member_name =
+{
+  "unrecognized static data member name '%s'", 0, 0
+};
+static struct complaint dwarf2_unsupported_accessibility =
+{
+  "unsupported accessibility %d", 0, 0
+};
+static struct complaint dwarf2_bad_member_name_complaint =
+{
+  "cannot extract member name from '%s'", 0, 0
+};
+static struct complaint dwarf2_missing_member_fn_type_complaint =
+{
+  "member function type missing for '%s'", 0, 0
+};
+static struct complaint dwarf2_vtbl_not_found_complaint =
+{
+  "virtual function table pointer not found when defining class '%s'", 0, 0
+};
+static struct complaint dwarf2_absolute_sibling_complaint =
+{
+  "ignoring absolute DW_AT_sibling", 0, 0
+};
+static struct complaint dwarf2_const_value_length_mismatch =
+{
+  "const value length mismatch for '%s', got %d, expected %d", 0, 0
+};
+static struct complaint dwarf2_unsupported_const_value_attr =
+{
+  "unsupported const value attribute form: '%s'", 0, 0
+};
 
 /* local function prototypes */
 
-static void dwarf2_locate_sections PARAMS ((bfd *, asection *, PTR));
+static void dwarf2_locate_sections (bfd *, asection *, PTR);
+
+#if 0
+static void dwarf2_build_psymtabs_easy (struct objfile *, int);
+#endif
+
+static void dwarf2_build_psymtabs_hard (struct objfile *, int);
+
+static char *scan_partial_symbols (char *, struct objfile *,
+                                  CORE_ADDR *, CORE_ADDR *,
+                                  const struct comp_unit_head *);
+
+static void add_partial_symbol (struct partial_die_info *, struct objfile *,
+                               const struct comp_unit_head *);
+
+static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
+
+static void psymtab_to_symtab_1 (struct partial_symtab *);
+
+static char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int);
+
+static void dwarf2_read_abbrevs (bfd *, unsigned int);
+
+static void dwarf2_empty_abbrev_table (PTR);
+
+static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int);
+
+static char *read_partial_die (struct partial_die_info *,
+                              bfd *, char *,
+                              const struct comp_unit_head *);
+
+static char *read_full_die (struct die_info **, bfd *, char *,
+                           const struct comp_unit_head *);
 
-static void dwarf2_build_psymtabs_easy PARAMS ((struct objfile *,
-                                               struct section_offsets *,
-                                               int));
-static void dwarf2_build_psymtabs_hard PARAMS ((struct objfile *,
-                                               struct section_offsets *,
-                                               int));
+static char *read_attribute (struct attribute *, struct attr_abbrev *,
+                            bfd *, char *, const struct comp_unit_head *);
 
-static char *scan_partial_symbols PARAMS ((char *, struct objfile *,
-                                          CORE_ADDR *, CORE_ADDR *));
+static unsigned int read_1_byte (bfd *, char *);
 
-static void add_partial_symbol PARAMS ((struct partial_die_info *,
-                                       struct objfile *));
+static int read_1_signed_byte (bfd *, char *);
 
-static void dwarf2_psymtab_to_symtab PARAMS ((struct partial_symtab *));
+static unsigned int read_2_bytes (bfd *, char *);
 
-static void psymtab_to_symtab_1 PARAMS ((struct partial_symtab *));
+static unsigned int read_4_bytes (bfd *, char *);
 
-static void add_die_to_symtab PARAMS ((struct die_info *, struct objfile *));
+static unsigned long read_8_bytes (bfd *, char *);
 
-static char *dwarf2_read_section PARAMS ((bfd *, file_ptr, unsigned int));
+static CORE_ADDR read_address (bfd *, char *ptr, const struct comp_unit_head *,
+                              int *bytes_read);
 
-static void dwarf2_read_abbrevs PARAMS ((bfd *, unsigned int));
+static LONGEST read_initial_length (bfd *, char *,
+                                    struct comp_unit_head *, int *bytes_read);
 
-static void dwarf2_empty_abbrev_table PARAMS ((void));
+static LONGEST read_offset (bfd *, char *, const struct comp_unit_head *,
+                            int *bytes_read);
 
-static struct abbrev_info *dwarf2_lookup_abbrev PARAMS ((unsigned int));
+static char *read_n_bytes (bfd *, char *, unsigned int);
 
-static char *read_partial_die PARAMS ((struct partial_die_info *,
-                                      bfd *, char *, int *));
+static char *read_string (bfd *, char *, unsigned int *);
 
-static char *read_full_die PARAMS ((struct die_info **, bfd *, char *));
+static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *);
 
-static unsigned int read_1_byte PARAMS ((bfd *, char *));
+static long read_signed_leb128 (bfd *, char *, unsigned int *);
 
-static unsigned int read_2_bytes PARAMS ((bfd *, char *));
+static void set_cu_language (unsigned int);
 
-static unsigned int read_4_bytes PARAMS ((bfd *, char *));
+static struct attribute *dwarf_attr (struct die_info *, unsigned int);
 
-static unsigned int read_8_bytes PARAMS ((bfd *, char *));
+static int die_is_declaration (struct die_info *);
 
-static CORE_ADDR read_address PARAMS ((bfd *, char *));
+static void dwarf_decode_lines (unsigned int, char *, bfd *,
+                               const struct comp_unit_head *);
 
-static char *read_n_bytes PARAMS ((bfd *, char *, unsigned int));
+static void dwarf2_start_subfile (char *, char *);
 
-static char *read_string PARAMS ((bfd *, char *, unsigned int *));
+static struct symbol *new_symbol (struct die_info *, struct type *,
+                                 struct objfile *, const struct comp_unit_head *);
 
-static unsigned int read_unsigned_leb128 PARAMS ((bfd *, char *,
-                                                 unsigned int *));
+static void dwarf2_const_value (struct attribute *, struct symbol *,
+                               struct objfile *, const struct comp_unit_head *);
 
-static int read_signed_leb128 PARAMS ((bfd *, char *, unsigned int *));
+static void dwarf2_const_value_data (struct attribute *attr,
+                                    struct symbol *sym,
+                                    int bits);
 
-static void set_cu_language PARAMS ((unsigned int));
+static struct type *die_type (struct die_info *, struct objfile *,
+                             const struct comp_unit_head *);
 
-static void record_minimal_symbol PARAMS ((char *, CORE_ADDR,
-                                          enum minimal_symbol_type,
-                                          struct objfile *));
+static struct type *die_containing_type (struct die_info *, struct objfile *,
+                                        const struct comp_unit_head *);
 
-static int convert_locdesc PARAMS ((struct dwarf_block *));
+#if 0
+static struct type *type_at_offset (unsigned int, struct objfile *);
+#endif
+
+static struct type *tag_type_to_type (struct die_info *, struct objfile *,
+                                     const struct comp_unit_head *);
+
+static void read_type_die (struct die_info *, struct objfile *,
+                          const struct comp_unit_head *);
 
-static struct attribute *dwarf_attr PARAMS ((struct die_info *,
-                                            unsigned int));
+static void read_typedef (struct die_info *, struct objfile *,
+                         const struct comp_unit_head *);
 
-static void dwarf_decode_lines PARAMS ((unsigned int, bfd *));
+static void read_base_type (struct die_info *, struct objfile *);
 
-static struct symbol *new_symbol PARAMS ((struct die_info * die, struct objfile * objfile));
+static void read_file_scope (struct die_info *, struct objfile *,
+                            const struct comp_unit_head *);
 
-static struct type *die_type PARAMS ((struct die_info * die, struct objfile * objfile));
+static void read_func_scope (struct die_info *, struct objfile *,
+                            const struct comp_unit_head *);
 
-static struct type *type_at_offset PARAMS ((unsigned int offset, struct objfile * objfile));
+static void read_lexical_block_scope (struct die_info *, struct objfile *,
+                                     const struct comp_unit_head *);
 
-static struct type *tag_type_to_type PARAMS ((struct die_info * die, struct objfile * objfile));
+static int dwarf2_get_pc_bounds (struct die_info *,
+                                CORE_ADDR *, CORE_ADDR *, struct objfile *);
 
-static void read_type_die PARAMS ((struct die_info * die, struct objfile * objfile));
+static void dwarf2_add_field (struct field_info *, struct die_info *,
+                             struct objfile *, const struct comp_unit_head *);
 
-static void read_typedef PARAMS ((struct die_info * die, struct objfile * objfile));
+static void dwarf2_attach_fields_to_type (struct field_info *,
+                                         struct type *, struct objfile *);
 
-static void read_base_type PARAMS ((struct die_info * die, struct objfile * objfile));
+static void dwarf2_add_member_fn (struct field_info *,
+                                 struct die_info *, struct type *,
+                                 struct objfile *objfile,
+                                 const struct comp_unit_head *);
 
-static void read_file_scope PARAMS ((struct die_info * die, struct objfile * objfile));
+static void dwarf2_attach_fn_fields_to_type (struct field_info *,
+                                            struct type *, struct objfile *);
 
-static void read_func_scope PARAMS ((struct die_info * die, struct objfile * objfile));
+static void read_structure_scope (struct die_info *, struct objfile *,
+                                 const struct comp_unit_head *);
 
-static void read_lexical_block_scope PARAMS ((struct die_info * die,
-                                             struct objfile * objfile));
+static void read_common_block (struct die_info *, struct objfile *,
+                              const struct comp_unit_head *);
 
-static void read_structure_scope PARAMS ((struct die_info * die, struct objfile * objfile));
+static void read_enumeration (struct die_info *, struct objfile *,
+                             const struct comp_unit_head *);
 
-static void read_common_block PARAMS ((struct die_info * die, struct objfile * objfile));
+static struct type *dwarf_base_type (int, int, struct objfile *);
 
-static void read_enumeration PARAMS ((struct die_info * die, struct objfile * objfile));
+static CORE_ADDR decode_locdesc (struct dwarf_block *, struct objfile *,
+                                const struct comp_unit_head *);
 
-static struct type * dwarf_base_type PARAMS ((int encoding, int size));
+static void read_array_type (struct die_info *, struct objfile *,
+                            const struct comp_unit_head *);
 
-static CORE_ADDR decode_locdesc PARAMS ((struct dwarf_block *,
-                                        struct objfile *));
+static void read_tag_pointer_type (struct die_info *, struct objfile *,
+                                  const struct comp_unit_head *);
 
-static char *create_name PARAMS ((char *, struct obstack *));
+static void read_tag_ptr_to_member_type (struct die_info *, struct objfile *,
+                                        const struct comp_unit_head *);
 
-static void dwarf_read_array_type PARAMS ((struct die_info * die,
-                                          struct objfile * objfile));
+static void read_tag_reference_type (struct die_info *, struct objfile *,
+                                    const struct comp_unit_head *);
 
-static void read_tag_pointer_type PARAMS ((struct die_info * die,
-                                          struct objfile * objfile));
+static void read_tag_const_type (struct die_info *, struct objfile *,
+                                const struct comp_unit_head *);
 
-static void read_tag_const_type PARAMS ((struct die_info * die,
-                                        struct objfile * objfile));
+static void read_tag_volatile_type (struct die_info *, struct objfile *,
+                                   const struct comp_unit_head *);
 
-static void read_tag_volatile_type PARAMS ((struct die_info * die,
-                                           struct objfile * objfile));
+static void read_tag_string_type (struct die_info *, struct objfile *);
 
-static void read_tag_string_type PARAMS ((struct die_info * die,
-                                         struct objfile * objfile));
+static void read_subroutine_type (struct die_info *, struct objfile *,
+                                 const struct comp_unit_head *);
 
-static void read_subroutine_type PARAMS ((struct die_info * die,
-                                         struct objfile * objfile));
+static struct die_info *read_comp_unit (char *, bfd *,
+                                        const struct comp_unit_head *);
 
-struct die_info *read_comp_unit PARAMS ((char *info_ptr, bfd * abfd));
+static void free_die_list (struct die_info *);
 
-static void free_die_list PARAMS ((struct die_info * dies));
+static struct cleanup *make_cleanup_free_die_list (struct die_info *);
 
-static void process_die PARAMS ((struct die_info *, struct objfile *));
+static void process_die (struct die_info *, struct objfile *,
+                        const struct comp_unit_head *);
 
-static char *dwarf_tag_name PARAMS ((unsigned tag));
+static char *dwarf2_linkage_name (struct die_info *);
 
-static char *dwarf_attr_name PARAMS ((unsigned attr));
+static char *dwarf_tag_name (unsigned int);
 
-static char *dwarf_form_name PARAMS ((unsigned form));
+static char *dwarf_attr_name (unsigned int);
 
-static char *dwarf_stack_op_name PARAMS ((unsigned op));
+static char *dwarf_form_name (unsigned int);
 
-static char *dwarf_bool_name PARAMS ((unsigned bool));
+static char *dwarf_stack_op_name (unsigned int);
 
-static char *dwarf_bool_name PARAMS ((unsigned tag));
+static char *dwarf_bool_name (unsigned int);
 
-static char *dwarf_type_encoding_name PARAMS ((unsigned enc));
+static char *dwarf_type_encoding_name (unsigned int);
+
+#if 0
+static char *dwarf_cfi_name (unsigned int);
+
+struct die_info *copy_die (struct die_info *);
+#endif
 
-static char *dwarf_cfi_name PARAMS ((unsigned cfi_opc));
+static struct die_info *sibling_die (struct die_info *);
 
-struct die_info *copy_die PARAMS ((struct die_info *old_die));
+static void dump_die (struct die_info *);
 
-struct die_info *sibling_die PARAMS ((struct die_info *die));
+static void dump_die_list (struct die_info *);
 
-void dump_die PARAMS ((struct die_info *die));
+static void store_in_ref_table (unsigned int, struct die_info *);
 
-void dump_die_list PARAMS ((struct die_info *dies));
+static void dwarf2_empty_hash_tables (void);
 
-void store_in_ref_table PARAMS ((unsigned int, struct die_info *));
+static unsigned int dwarf2_get_ref_die_offset (struct attribute *);
 
-struct die_info *follow_die_ref PARAMS ((unsigned int offset));
+static struct die_info *follow_die_ref (unsigned int);
 
-static struct type *dwarf2_fundamental_type PARAMS ((struct objfile *, int));
+static struct type *dwarf2_fundamental_type (struct objfile *, int);
 
 /* memory allocation interface */
 
-static struct type *dwarf_alloc_type PARAMS ((struct objfile *));
+static void dwarf2_free_tmp_obstack (PTR);
 
-static struct abbrev_info *dwarf_alloc_abbrev PARAMS ((void));
+static struct dwarf_block *dwarf_alloc_block (void);
 
-static struct dwarf_block *dwarf_alloc_block PARAMS ((void));
+static struct abbrev_info *dwarf_alloc_abbrev (void);
 
-static struct die_info *dwarf_alloc_die PARAMS ((void));
+static struct die_info *dwarf_alloc_die (void);
 
 /* Try to locate the sections we need for DWARF 2 debugging
    information and return true if we have enough to do something.  */
 
 int
-dwarf2_has_info (abfd)
-     bfd *abfd;
+dwarf2_has_info (bfd *abfd)
 {
   dwarf_info_offset = dwarf_abbrev_offset = dwarf_line_offset = 0;
   bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
-  if (dwarf_info_offset && dwarf_abbrev_offset && dwarf_line_offset)
+  if (dwarf_info_offset && dwarf_abbrev_offset)
     {
       return 1;
     }
@@ -531,10 +804,7 @@ dwarf2_has_info (abfd)
    in.  */
 
 static void
-dwarf2_locate_sections (ignore_abfd, sectp, ignore_ptr)
-     bfd *ignore_abfd;
-     asection *sectp;
-     PTR ignore_ptr;
+dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, PTR ignore_ptr)
 {
   if (STREQ (sectp->name, INFO_SECTION))
     {
@@ -581,28 +851,24 @@ dwarf2_locate_sections (ignore_abfd, sectp, ignore_ptr)
 /* Build a partial symbol table.  */
 
 void
-dwarf2_build_psymtabs (objfile, section_offsets, mainline)
-    struct objfile *objfile;
-    struct section_offsets *section_offsets;
-    int mainline;
+dwarf2_build_psymtabs (struct objfile *objfile, int mainline)
 {
-  bfd *abfd = objfile->obfd;
 
-  /* We definitely need the .debug_info, .debug_abbrev, and .debug_line
-     sections */
+  /* We definitely need the .debug_info and .debug_abbrev sections */
 
-  dwarf_info_buffer = dwarf2_read_section (abfd,
+  dwarf_info_buffer = dwarf2_read_section (objfile,
                                           dwarf_info_offset,
                                           dwarf_info_size);
-  dwarf_abbrev_buffer = dwarf2_read_section (abfd,
+  dwarf_abbrev_buffer = dwarf2_read_section (objfile,
                                             dwarf_abbrev_offset,
                                             dwarf_abbrev_size);
-  dwarf_line_buffer = dwarf2_read_section (abfd,
+  dwarf_line_buffer = dwarf2_read_section (objfile,
                                           dwarf_line_offset,
                                           dwarf_line_size);
 
-  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);
     }
@@ -610,42 +876,44 @@ dwarf2_build_psymtabs (objfile, section_offsets, mainline)
 #if 0
   if (dwarf_aranges_offset && dwarf_pubnames_offset)
     {
-      /* Things are significanlty easier if we have .debug_aranges and
+      /* Things are significantly easier if we have .debug_aranges and
          .debug_pubnames sections */
 
-      dwarf2_build_psymtabs_easy (objfile, section_offsets, mainline);
+      dwarf2_build_psymtabs_easy (objfile, mainline);
     }
   else
 #endif
     /* only test this case for now */
-    {          
+    {
       /* In this case we have to work a bit harder */
-      dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline);
+      dwarf2_build_psymtabs_hard (objfile, mainline);
     }
 }
 
+#if 0
 /* Build the partial symbol table from the information in the
    .debug_pubnames and .debug_aranges sections.  */
 
 static void
-dwarf2_build_psymtabs_easy (objfile, section_offsets, mainline)
-     struct objfile *objfile;
-     struct section_offsets *section_offsets;
-     int mainline;
+dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
 {
   bfd *abfd = objfile->obfd;
   char *aranges_buffer, *pubnames_buffer;
   char *aranges_ptr, *pubnames_ptr;
   unsigned int entry_length, version, info_offset, info_size;
 
-  pubnames_buffer = dwarf2_read_section (abfd,
+  pubnames_buffer = dwarf2_read_section (objfile,
                                         dwarf_pubnames_offset,
                                         dwarf_pubnames_size);
   pubnames_ptr = pubnames_buffer;
   while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
     {
-      entry_length = read_4_bytes (abfd, pubnames_ptr);
-      pubnames_ptr += 4;
+      struct comp_unit_head cu_header;
+      int bytes_read;
+
+      entry_length = read_initial_length (abfd, pubnames_ptr, &cu_header,
+                                         &bytes_read);
+      pubnames_ptr += bytes_read;
       version = read_1_byte (abfd, pubnames_ptr);
       pubnames_ptr += 1;
       info_offset = read_4_bytes (abfd, pubnames_ptr);
@@ -654,95 +922,178 @@ dwarf2_build_psymtabs_easy (objfile, section_offsets, mainline)
       pubnames_ptr += 4;
     }
 
-  aranges_buffer = dwarf2_read_section (abfd,
+  aranges_buffer = dwarf2_read_section (objfile,
                                        dwarf_aranges_offset,
                                        dwarf_aranges_size);
 
 }
+#endif
+
+/* Read in the comp unit header information from the debug_info at
+   info_ptr. */
+
+static char *
+read_comp_unit_head (struct comp_unit_head *cu_header,
+                    char *info_ptr, bfd *abfd)
+{
+  int signed_addr;
+  int bytes_read;
+  cu_header->length = read_initial_length (abfd, info_ptr, cu_header,
+                                           &bytes_read);
+  info_ptr += bytes_read;
+  cu_header->version = read_2_bytes (abfd, info_ptr);
+  info_ptr += 2;
+  cu_header->abbrev_offset = read_offset (abfd, info_ptr, cu_header,
+                                          &bytes_read);
+  info_ptr += bytes_read;
+  cu_header->addr_size = read_1_byte (abfd, info_ptr);
+  info_ptr += 1;
+  signed_addr = bfd_get_sign_extend_vma (abfd);
+  if (signed_addr < 0)
+    internal_error (__FILE__, __LINE__,
+                   "read_comp_unit_head: dwarf from non elf file");
+  cu_header->signed_addr_p = signed_addr;
+  return info_ptr;
+}
 
 /* Build the partial symbol table by doing a quick pass through the
    .debug_info and .debug_abbrev sections.  */
 
 static void
-dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline)
-     struct objfile *objfile;
-     struct section_offsets *section_offsets;
-     int mainline;
+dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
 {
   /* Instead of reading this into a big buffer, we should probably use
      mmap()  on architectures that support it. (FIXME) */
   bfd *abfd = objfile->obfd;
   char *info_ptr, *abbrev_ptr;
-  char *beg_of_comp_unit, *comp_unit_die_offset;
-  struct comp_unit_head cu_header;
+  char *beg_of_comp_unit;
   struct partial_die_info comp_unit_die;
   struct partial_symtab *pst;
   struct cleanup *back_to;
-  int comp_unit_has_pc_info;
-  int has_pc_info;
   CORE_ADDR lowpc, highpc;
 
-  comp_unit_die = zeroed_partial_die;
   info_ptr = dwarf_info_buffer;
   abbrev_ptr = dwarf_abbrev_buffer;
 
-  while ((info_ptr - dwarf_info_buffer)
-         + ((info_ptr - dwarf_info_buffer) % 4) < dwarf_info_size)
+  /* We use dwarf2_tmp_obstack for objects that don't need to survive
+     the partial symbol scan, like attribute values.
+
+     We could reduce our peak memory consumption during partial symbol
+     table construction by freeing stuff from this obstack more often
+     --- say, after processing each compilation unit, or each die ---
+     but it turns out that this saves almost nothing.  For an
+     executable with 11Mb of Dwarf 2 data, I found about 64k allocated
+     on dwarf2_tmp_obstack.  Some investigation showed:
+
+     1) 69% of the attributes used forms DW_FORM_addr, DW_FORM_data*,
+        DW_FORM_flag, DW_FORM_[su]data, and DW_FORM_ref*.  These are
+        all fixed-length values not requiring dynamic allocation.
+
+     2) 30% of the attributes used the form DW_FORM_string.  For
+        DW_FORM_string, read_attribute simply hands back a pointer to
+        the null-terminated string in dwarf_info_buffer, so no dynamic
+        allocation is needed there either.
+
+     3) The remaining 1% of the attributes all used DW_FORM_block1.
+        75% of those were DW_AT_frame_base location lists for
+        functions; the rest were DW_AT_location attributes, probably
+        for the global variables.
+
+     Anyway, what this all means is that the memory the dwarf2
+     reader uses as temporary space reading partial symbols is about
+     0.5% as much as we use for dwarf_*_buffer.  That's noise.  */
+
+  obstack_init (&dwarf2_tmp_obstack);
+  back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
+
+  /* Since the objects we're extracting from dwarf_info_buffer vary in
+     length, only the individual functions to extract them (like
+     read_comp_unit_head and read_partial_die) can really know whether
+     the buffer is large enough to hold another complete object.
+
+     At the moment, they don't actually check that.  If
+     dwarf_info_buffer holds just one extra byte after the last
+     compilation unit's dies, then read_comp_unit_head will happily
+     read off the end of the buffer.  read_partial_die is similarly
+     casual.  Those functions should be fixed.
+
+     For this loop condition, simply checking whether there's any data
+     left at all should be sufficient.  */
+  while (info_ptr < dwarf_info_buffer + dwarf_info_size)
     {
+      struct comp_unit_head cu_header;
       beg_of_comp_unit = info_ptr;
-      cu_header.length = read_4_bytes (abfd, info_ptr);
-      info_ptr += 4;
-      cu_header.version = read_2_bytes (abfd, info_ptr);
-      info_ptr += 2;
-      cu_header.abbrev_offset = read_4_bytes (abfd, info_ptr);
-      info_ptr += 4;
-      cu_header.addr_size = read_1_byte (abfd, info_ptr);
-      info_ptr += 1;
-      address_size = cu_header.addr_size;
+      info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd);
 
       if (cu_header.version != 2)
        {
          error ("Dwarf Error: wrong version in compilation unit header.");
          return;
        }
-
+      if (cu_header.abbrev_offset >= dwarf_abbrev_size)
+       {
+         error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).",
+                (long) cu_header.abbrev_offset,
+                (long) (beg_of_comp_unit - dwarf_info_buffer));
+         return;
+       }
+      if (beg_of_comp_unit + cu_header.length + cu_header.initial_length_size
+         > dwarf_info_buffer + dwarf_info_size)
+       {
+         error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
+                (long) cu_header.length,
+                (long) (beg_of_comp_unit - dwarf_info_buffer));
+         return;
+       }
       /* Read the abbrevs for this compilation unit into a table */
       dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
-      back_to = make_cleanup (dwarf2_empty_abbrev_table, NULL);
+      make_cleanup (dwarf2_empty_abbrev_table, NULL);
 
       /* Read the compilation unit die */
-      info_ptr = read_partial_die (&comp_unit_die, abfd,
-                                  info_ptr, &comp_unit_has_pc_info);
+      info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr,
+                                  &cu_header);
 
       /* Set the language we're debugging */
       set_cu_language (comp_unit_die.language);
 
       /* Allocate a new partial symbol table structure */
-      pst = start_psymtab_common (objfile, section_offsets,
-                                 comp_unit_die.name,
+      pst = start_psymtab_common (objfile, objfile->section_offsets,
+                                 comp_unit_die.name ? comp_unit_die.name : "",
                                  comp_unit_die.lowpc,
                                  objfile->global_psymbols.next,
                                  objfile->static_psymbols.next);
 
-      /* Store offset in the .debug_info section of the comp_unit_die.  */
       pst->read_symtab_private = (char *)
-                                (beg_of_comp_unit - dwarf_info_buffer);
+       obstack_alloc (&objfile->psymbol_obstack, sizeof (struct dwarf2_pinfo));
+      cu_header_offset = beg_of_comp_unit - dwarf_info_buffer;
+      DWARF_INFO_BUFFER (pst) = dwarf_info_buffer;
+      DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf_info_buffer;
+      DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer;
+      DWARF_ABBREV_SIZE (pst) = dwarf_abbrev_size;
+      DWARF_LINE_BUFFER (pst) = dwarf_line_buffer;
+      baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
       /* Store the function that reads in the rest of the symbol table */
       pst->read_symtab = dwarf2_psymtab_to_symtab;
 
-      /* Read the rest of the partial symbols from this comp unit */
-      info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc);
-
-      /* If the compilation unit didn't have an explicit address range,
-        then use the information extracted from its child dies.  */
-      if (!comp_unit_has_pc_info)
+      /* Check if comp unit has_children.
+         If so, read the rest of the partial symbols from this comp unit.
+         If not, there's no more debug_info for this comp unit. */
+      if (comp_unit_die.has_children)
        {
-         comp_unit_die.lowpc  = lowpc;
-         comp_unit_die.highpc = highpc;
-        }
-      pst->textlow  = comp_unit_die.lowpc;
-      pst->texthigh = comp_unit_die.highpc;
+         info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc,
+                                          &cu_header);
+
+         /* If the compilation unit didn't have an explicit address range,
+            then use the information extracted from its child dies.  */
+         if (! comp_unit_die.has_pc_info)
+           {
+             comp_unit_die.lowpc = lowpc;
+             comp_unit_die.highpc = highpc;
+           }
+       }
+      pst->textlow = comp_unit_die.lowpc + baseaddr;
+      pst->texthigh = comp_unit_die.highpc + baseaddr;
 
       pst->n_global_syms = objfile->global_psymbols.next -
        (objfile->global_psymbols.list + pst->globals_offset);
@@ -755,7 +1106,8 @@ dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline)
          also happen.) This happens in VxWorks.  */
       free_named_symtabs (pst->filename);
 
-      info_ptr = beg_of_comp_unit + cu_header.length + 4;
+      info_ptr = beg_of_comp_unit + cu_header.length 
+                                  + cu_header.initial_length_size;
     }
   do_cleanups (back_to);
 }
@@ -763,140 +1115,216 @@ dwarf2_build_psymtabs_hard (objfile, section_offsets, mainline)
 /* Read in all interesting dies to the end of the compilation unit.  */
 
 static char *
-scan_partial_symbols (info_ptr, objfile, lowpc, highpc)
-     char *info_ptr;
-     struct objfile *objfile;
-     CORE_ADDR *lowpc;
-     CORE_ADDR *highpc;
+scan_partial_symbols (char *info_ptr, struct objfile *objfile,
+                     CORE_ADDR *lowpc, CORE_ADDR *highpc,
+                     const struct comp_unit_head *cu_header)
 {
-  /* FIXME: This should free the attributes of the partial die structure
-     when it is done with them (is there a more efficient way
-     to do this). */
   bfd *abfd = objfile->obfd;
   struct partial_die_info pdi;
-  int nesting_level = 1;       /* we've already read in comp_unit_die */
-  int has_pc_info;
 
-  pdi = zeroed_partial_die;
-  *lowpc  = ((CORE_ADDR) -1);
+  /* This function is called after we've read in the comp_unit_die in
+     order to read its children.  We start the nesting level at 1 since
+     we have pushed 1 level down in order to read the comp unit's children.
+     The comp unit itself is at level 0, so we stop reading when we pop
+     back to that level. */
+
+  int nesting_level = 1;
+
+  *lowpc = ((CORE_ADDR) -1);
   *highpc = ((CORE_ADDR) 0);
-  do
+
+  while (nesting_level)
     {
-      info_ptr = read_partial_die (&pdi, abfd, info_ptr, &has_pc_info);
-      switch (pdi.tag)
+      info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
+
+      if (pdi.name)
        {
-       case DW_TAG_subprogram:
-       case DW_TAG_variable:
-       case DW_TAG_typedef:
-       case DW_TAG_class_type:
-       case DW_TAG_structure_type:
-       case DW_TAG_union_type:
-         if (pdi.is_external || nesting_level == 1)
+         switch (pdi.tag)
            {
-             if (pdi.name)
+           case DW_TAG_subprogram:
+             if (pdi.has_pc_info)
+               {
+                 if (pdi.lowpc < *lowpc)
+                   {
+                     *lowpc = pdi.lowpc;
+                   }
+                 if (pdi.highpc > *highpc)
+                   {
+                     *highpc = pdi.highpc;
+                   }
+                 if ((pdi.is_external || nesting_level == 1)
+                     && !pdi.is_declaration)
+                   {
+                     add_partial_symbol (&pdi, objfile, cu_header);
+                   }
+               }
+             break;
+           case DW_TAG_variable:
+           case DW_TAG_typedef:
+           case DW_TAG_class_type:
+           case DW_TAG_structure_type:
+           case DW_TAG_union_type:
+           case DW_TAG_enumeration_type:
+             if ((pdi.is_external || nesting_level == 1)
+                 && !pdi.is_declaration)
                {
-                 add_partial_symbol (&pdi, objfile);
+                 add_partial_symbol (&pdi, objfile, cu_header);
                }
+             break;
+           case DW_TAG_enumerator:
+             /* File scope enumerators are added to the partial symbol
+                table.  */
+             if (nesting_level == 2)
+               add_partial_symbol (&pdi, objfile, cu_header);
+             break;
+           case DW_TAG_base_type:
+             /* File scope base type definitions are added to the partial
+                symbol table.  */
+             if (nesting_level == 1)
+               add_partial_symbol (&pdi, objfile, cu_header);
+             break;
+           default:
+             break;
            }
-          if (has_pc_info)
-            {
-              if (pdi.lowpc < *lowpc)
-                {
-                  *lowpc = pdi.lowpc;
-                }
-              if (pdi.highpc > *lowpc)
-                {
-                  *highpc = pdi.highpc;
-                }
-            }
        }
-      if (pdi.has_children)
+
+      /* If the die has a sibling, skip to the sibling.
+         Do not skip enumeration types, we want to record their
+         enumerators.  */
+      if (pdi.sibling && pdi.tag != DW_TAG_enumeration_type)
+       {
+         info_ptr = pdi.sibling;
+       }
+      else if (pdi.has_children)
        {
+         /* Die has children, but the optional DW_AT_sibling attribute
+            is missing.  */
          nesting_level++;
        }
+
       if (pdi.tag == 0)
        {
          nesting_level--;
        }
     }
-  while (nesting_level);
+
+  /* If we didn't find a lowpc, set it to highpc to avoid complaints
+     from `maint check'.  */
+  if (*lowpc == ((CORE_ADDR) -1))
+    *lowpc = *highpc;
   return info_ptr;
 }
 
 static void
-add_partial_symbol (pdi, objfile)
-     struct partial_die_info *pdi;
-     struct objfile *objfile;
+add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
+                   const struct comp_unit_head *cu_header)
 {
+  CORE_ADDR addr = 0;
+
   switch (pdi->tag)
     {
     case DW_TAG_subprogram:
       if (pdi->is_external)
        {
-         record_minimal_symbol (pdi->name, pdi->lowpc,
-                                mst_text, objfile);
+         /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+            mst_text, objfile); */
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
                               VAR_NAMESPACE, LOC_BLOCK,
                               &objfile->global_psymbols,
-                              0, pdi->lowpc, cu_language, objfile);
+                           0, pdi->lowpc + baseaddr, cu_language, objfile);
        }
       else
        {
+         /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+            mst_file_text, objfile); */
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
                               VAR_NAMESPACE, LOC_BLOCK,
                               &objfile->static_psymbols,
-                              0, pdi->lowpc, cu_language, objfile);
+                           0, pdi->lowpc + baseaddr, cu_language, objfile);
        }
       break;
     case DW_TAG_variable:
       if (pdi->is_external)
        {
-         record_minimal_symbol (pdi->name, convert_locdesc (pdi->locdesc),
-                                mst_data, objfile);
-         add_psymbol_to_list (pdi->name, strlen (pdi->name),
-                              VAR_NAMESPACE, LOC_STATIC,
-                              &objfile->global_psymbols,
-                              0, 0, cu_language, objfile);
+         /* Global Variable.
+            Don't enter into the minimal symbol tables as there is
+            a minimal symbol table entry from the ELF symbols already.
+            Enter into partial symbol table if it has a location
+            descriptor or a type.
+            If the location descriptor is missing, new_symbol will create
+            a LOC_UNRESOLVED symbol, the address of the variable will then
+            be determined from the minimal symbol table whenever the variable
+            is referenced.
+            The address for the partial symbol table entry is not
+            used by GDB, but it comes in handy for debugging partial symbol
+            table building.  */
+
+         if (pdi->locdesc)
+           addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
+         if (pdi->locdesc || pdi->has_type)
+           add_psymbol_to_list (pdi->name, strlen (pdi->name),
+                                VAR_NAMESPACE, LOC_STATIC,
+                                &objfile->global_psymbols,
+                                0, addr + baseaddr, cu_language, objfile);
        }
       else
        {
+         /* Static Variable. Skip symbols without location descriptors.  */
+         if (pdi->locdesc == NULL)
+           return;
+         addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
+         /*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
+            mst_file_data, objfile); */
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
                               VAR_NAMESPACE, LOC_STATIC,
                               &objfile->static_psymbols,
-                              0, 0, cu_language, objfile);
+                              0, addr + baseaddr, cu_language, objfile);
        }
       break;
     case DW_TAG_typedef:
+    case DW_TAG_base_type:
       add_psymbol_to_list (pdi->name, strlen (pdi->name),
                           VAR_NAMESPACE, LOC_TYPEDEF,
                           &objfile->static_psymbols,
-                          0, 0, cu_language, objfile);
+                          0, (CORE_ADDR) 0, cu_language, objfile);
       break;
     case DW_TAG_class_type:
     case DW_TAG_structure_type:
     case DW_TAG_union_type:
     case DW_TAG_enumeration_type:
+      /* Skip aggregate types without children, these are external
+         references.  */
+      if (pdi->has_children == 0)
+       return;
       add_psymbol_to_list (pdi->name, strlen (pdi->name),
                           STRUCT_NAMESPACE, LOC_TYPEDEF,
                           &objfile->static_psymbols,
-                          0, 0, cu_language, objfile);
+                          0, (CORE_ADDR) 0, cu_language, objfile);
+
       if (cu_language == language_cplus)
        {
          /* For C++, these implicitly act as typedefs as well. */
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
                               VAR_NAMESPACE, LOC_TYPEDEF,
                               &objfile->static_psymbols,
-                              0, 0, cu_language, objfile);
+                              0, (CORE_ADDR) 0, cu_language, objfile);
        }
       break;
+    case DW_TAG_enumerator:
+      add_psymbol_to_list (pdi->name, strlen (pdi->name),
+                          VAR_NAMESPACE, LOC_CONST,
+                          &objfile->static_psymbols,
+                          0, (CORE_ADDR) 0, cu_language, objfile);
+      break;
+    default:
+      break;
     }
 }
 
 /* Expand this partial symbol table into a full symbol table.  */
 
 static void
-dwarf2_psymtab_to_symtab (pst)
-     struct partial_symtab *pst;
+dwarf2_psymtab_to_symtab (struct partial_symtab *pst)
 {
   /* FIXME: This is barely more than a stub.  */
   if (pst != NULL)
@@ -907,65 +1335,70 @@ dwarf2_psymtab_to_symtab (pst)
        }
       else
        {
+         if (info_verbose)
+           {
+             printf_filtered ("Reading in symbols for %s...", pst->filename);
+             gdb_flush (gdb_stdout);
+           }
+
          psymtab_to_symtab_1 (pst);
+
+         /* Finish up the debug error message.  */
+         if (info_verbose)
+           printf_filtered ("done.\n");
        }
     }
 }
 
 static void
-psymtab_to_symtab_1 (pst)
-     struct partial_symtab *pst;
+psymtab_to_symtab_1 (struct partial_symtab *pst)
 {
   struct objfile *objfile = pst->objfile;
   bfd *abfd = objfile->obfd;
   struct comp_unit_head cu_header;
   struct die_info *dies;
-  struct attribute *attr;
   unsigned long offset;
-  unsigned long int nesting_level;
-  CORE_ADDR highpc;
-  struct attribute *high_pc_attr;
+  CORE_ADDR lowpc, highpc;
   struct die_info *child_die;
   char *info_ptr;
-  struct context_stack *context;
   struct symtab *symtab;
-  struct cleanup *abbrev_cleanup, *die_cleanup;
+  struct cleanup *back_to;
 
-  /* Get the offset of this compilation units debug info  */
-  offset = (unsigned long) pst->read_symtab_private;
+  /* Set local variables from the partial symbol table info.  */
+  offset = DWARF_INFO_OFFSET (pst);
+  dwarf_info_buffer = DWARF_INFO_BUFFER (pst);
+  dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst);
+  dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst);
+  dwarf_line_buffer = DWARF_LINE_BUFFER (pst);
+  baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
+  cu_header_offset = offset;
   info_ptr = dwarf_info_buffer + offset;
 
+  obstack_init (&dwarf2_tmp_obstack);
+  back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
+
+  buildsym_init ();
+  make_cleanup (really_free_pendings, NULL);
+
   /* read in the comp_unit header  */
-  cu_header.length = read_4_bytes (abfd, info_ptr);
-  info_ptr += 4;
-  cu_header.version = read_2_bytes (abfd, info_ptr);
-  info_ptr += 2;
-  cu_header.abbrev_offset = read_4_bytes (abfd, info_ptr);
-  info_ptr += 4;
-  cu_header.addr_size = read_1_byte (abfd, info_ptr);
-  info_ptr += 1;
+  info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd);
 
   /* Read the abbrevs for this compilation unit  */
   dwarf2_read_abbrevs (abfd, cu_header.abbrev_offset);
-  abbrev_cleanup = make_cleanup (dwarf2_empty_abbrev_table, NULL);
+  make_cleanup (dwarf2_empty_abbrev_table, NULL);
 
-  dies = read_comp_unit (info_ptr, abfd);
+  dies = read_comp_unit (info_ptr, abfd, &cu_header);
 
-  die_cleanup = make_cleanup (free_die_list, dies);
+  make_cleanup_free_die_list (dies);
 
   /* Do line number decoding in read_file_scope () */
-  process_die (dies, objfile);
+  process_die (dies, objfile, &cu_header);
 
-  attr = dwarf_attr (dies, DW_AT_high_pc);
-  if (attr)
-    {
-      highpc = DW_ADDR (attr);
-    }
-  else
+  if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
     {
       /* Some compilers don't define a DW_AT_high_pc attribute for
-        the compilation unit.   If the DW_AT_high_pc is missing,
-        synthesize it, by scanning the DIE's below the compilation unit.  */
+         the compilation unit.   If the DW_AT_high_pc is missing,
+         synthesize it, by scanning the DIE's below the compilation unit.  */
       highpc = 0;
       if (dies->has_children)
        {
@@ -974,116 +1407,118 @@ psymtab_to_symtab_1 (pst)
            {
              if (child_die->tag == DW_TAG_subprogram)
                {
-                 high_pc_attr = dwarf_attr (child_die, DW_AT_high_pc);
-                 if (high_pc_attr)
+                 CORE_ADDR low, high;
+
+                 if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
                    {
-                     highpc = max (highpc, DW_ADDR (high_pc_attr));
+                     highpc = max (highpc, high);
                    }
                }
              child_die = sibling_die (child_die);
            }
        }
     }
+  symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
 
-  symtab = end_symtab (highpc, objfile, 0);
-  if (symtab != NULL)
+  /* Set symtab language to language from DW_AT_language.
+     If the compilation is from a C file generated by language preprocessors,
+     do not set the language if it was already deduced by start_subfile.  */
+  if (symtab != NULL
+      && !(cu_language == language_c && symtab->language != language_c))
     {
       symtab->language = cu_language;
     }
   pst->symtab = symtab;
   pst->readin = 1;
-  if (info_verbose)
-    {
-      printf_filtered ("Sorting symbol table...");
-      wrap_here ("");
-      fflush (stdout);
-    }
   sort_symtab_syms (pst->symtab);
-  do_cleanups (abbrev_cleanup);
+
+  do_cleanups (back_to);
 }
 
 /* Process a die and its children.  */
 
 static void
-process_die (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+process_die (struct die_info *die, struct objfile *objfile,
+            const struct comp_unit_head *cu_header)
 {
   switch (die->tag)
     {
     case DW_TAG_padding:
       break;
     case DW_TAG_compile_unit:
-      read_file_scope (die, objfile);
+      read_file_scope (die, objfile, cu_header);
       break;
     case DW_TAG_subprogram:
-      if (dwarf_attr (die, DW_AT_low_pc))
-       {
-         read_func_scope (die, objfile);
-       }
+      read_subroutine_type (die, objfile, cu_header);
+      read_func_scope (die, objfile, cu_header);
+      break;
+    case DW_TAG_inlined_subroutine:
+      /* FIXME:  These are ignored for now.
+         They could be used to set breakpoints on all inlined instances
+         of a function and make GDB `next' properly over inlined functions.  */
       break;
     case DW_TAG_lexical_block:
-      read_lexical_block_scope (die, objfile);
+      read_lexical_block_scope (die, objfile, cu_header);
       break;
     case DW_TAG_class_type:
     case DW_TAG_structure_type:
     case DW_TAG_union_type:
-      read_structure_scope (die, objfile);
+      read_structure_scope (die, objfile, cu_header);
       break;
     case DW_TAG_enumeration_type:
-      read_enumeration (die, objfile);
+      read_enumeration (die, objfile, cu_header);
       break;
     case DW_TAG_subroutine_type:
-      read_subroutine_type (die, objfile);
+      read_subroutine_type (die, objfile, cu_header);
       break;
     case DW_TAG_array_type:
-      dwarf_read_array_type (die, objfile);
+      read_array_type (die, objfile, cu_header);
       break;
     case DW_TAG_pointer_type:
-      read_tag_pointer_type (die, objfile);
+      read_tag_pointer_type (die, objfile, cu_header);
+      break;
+    case DW_TAG_ptr_to_member_type:
+      read_tag_ptr_to_member_type (die, objfile, cu_header);
+      break;
+    case DW_TAG_reference_type:
+      read_tag_reference_type (die, objfile, cu_header);
       break;
     case DW_TAG_string_type:
       read_tag_string_type (die, objfile);
       break;
     case DW_TAG_base_type:
       read_base_type (die, objfile);
+      if (dwarf_attr (die, DW_AT_name))
+       {
+         /* Add a typedef symbol for the base type definition.  */
+         new_symbol (die, die->type, objfile, cu_header);
+       }
       break;
     case DW_TAG_common_block:
-      read_common_block (die, objfile);
+      read_common_block (die, objfile, cu_header);
       break;
     case DW_TAG_common_inclusion:
       break;
     default:
-      new_symbol (die, objfile);
+      new_symbol (die, NULL, objfile, cu_header);
       break;
     }
 }
 
 static void
-read_file_scope (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_file_scope (struct die_info *die, struct objfile *objfile,
+                const struct comp_unit_head *cu_header)
 {
   unsigned int line_offset = 0;
-  CORE_ADDR lowpc  = ((CORE_ADDR) -1);
+  CORE_ADDR lowpc = ((CORE_ADDR) -1);
   CORE_ADDR highpc = ((CORE_ADDR) 0);
-  struct attribute *attr, *low_pc_attr, *high_pc_attr;
-  char *name = NULL;
+  struct attribute *attr;
+  char *name = "<unknown>";
   char *comp_dir = NULL;
   struct die_info *child_die;
   bfd *abfd = objfile->obfd;
 
-  low_pc_attr = dwarf_attr (die, DW_AT_low_pc);
-  if (low_pc_attr)
-    {
-      lowpc = DW_ADDR (low_pc_attr);
-    }
-  high_pc_attr = dwarf_attr (die, DW_AT_high_pc);
-  if (high_pc_attr)
-    {
-      highpc = DW_ADDR (high_pc_attr);
-    }
-  if (!low_pc_attr || !high_pc_attr)
+  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
     {
       if (die->has_children)
        {
@@ -1092,15 +1527,12 @@ read_file_scope (die, objfile)
            {
              if (child_die->tag == DW_TAG_subprogram)
                {
-                 low_pc_attr = dwarf_attr (child_die, DW_AT_low_pc);
-                 if (low_pc_attr)
-                   {
-                     lowpc = min (lowpc, DW_ADDR (low_pc_attr));
-                   }
-                 high_pc_attr = dwarf_attr (child_die, DW_AT_high_pc);
-                 if (high_pc_attr)
+                 CORE_ADDR low, high;
+
+                 if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
                    {
-                     highpc = max (highpc, DW_ADDR (high_pc_attr));
+                     lowpc = min (lowpc, low);
+                     highpc = max (highpc, high);
                    }
                }
              child_die = sibling_die (child_die);
@@ -1108,6 +1540,13 @@ read_file_scope (die, objfile)
        }
     }
 
+  /* If we didn't find a lowpc, set it to highpc to avoid complaints
+     from finish_block.  */
+  if (lowpc == ((CORE_ADDR) -1))
+    lowpc = highpc;
+  lowpc += baseaddr;
+  highpc += baseaddr;
+
   attr = dwarf_attr (die, DW_AT_name);
   if (attr)
     {
@@ -1117,6 +1556,15 @@ read_file_scope (die, objfile)
   if (attr)
     {
       comp_dir = DW_STRING (attr);
+      if (comp_dir)
+       {
+         /* Irix 6.2 native cc prepends <machine>.: to the compilation
+            directory, get rid of it.  */
+         char *cp = strchr (comp_dir, ':');
+
+         if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
+           comp_dir = cp + 1;
+       }
     }
 
   if (objfile->ei.entry_point >= lowpc &&
@@ -1132,26 +1580,30 @@ read_file_scope (die, objfile)
       set_cu_language (DW_UNSND (attr));
     }
 
+  /* We assume that we're processing GCC output. */
+  processing_gcc_compilation = 2;
 #if 0
-    /* FIXME:Do something here.  */
-    if (dip->at_producer != NULL)
+  /* FIXME:Do something here.  */
+  if (dip->at_producer != NULL)
     {
       handle_producer (dip->at_producer);
     }
 #endif
 
+  /* The compilation unit may be in a different language or objfile,
+     zero out all remembered fundamental types.  */
+  memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
+
   start_symtab (name, comp_dir, lowpc);
+  record_debugformat ("DWARF 2");
 
-  /* Decode line number information.  */
+  /* Decode line number information if present.  */
   attr = dwarf_attr (die, DW_AT_stmt_list);
-  if (!attr)
+  if (attr)
     {
-      error (
-        "Dwarf Error: No line number information for compilation unit: %s.",
-        name);
+      line_offset = DW_UNSND (attr);
+      dwarf_decode_lines (line_offset, comp_dir, abfd, cu_header);
     }
-  line_offset = DW_UNSND (attr);
-  dwarf_decode_lines (line_offset, abfd);
 
   /* Process all dies in compilation unit.  */
   if (die->has_children)
@@ -1159,42 +1611,32 @@ read_file_scope (die, objfile)
       child_die = die->next;
       while (child_die && child_die->tag)
        {
-         process_die (child_die, objfile);
+         process_die (child_die, objfile, cu_header);
          child_die = sibling_die (child_die);
        }
     }
 }
 
 static void
-read_func_scope (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_func_scope (struct die_info *die, struct objfile *objfile,
+                const struct comp_unit_head *cu_header)
 {
   register struct context_stack *new;
-  CORE_ADDR lowpc  = 0;
-  CORE_ADDR highpc = 0;
+  CORE_ADDR lowpc;
+  CORE_ADDR highpc;
   struct die_info *child_die;
   struct attribute *attr;
-  struct minimal_symbol *min_sym;
-  char *name = NULL;
+  char *name;
 
-  attr = dwarf_attr (die, DW_AT_name);
-  if (attr)
-    {
-      name = DW_STRING (attr);
-    }
+  name = dwarf2_linkage_name (die);
 
-  attr = dwarf_attr (die, DW_AT_low_pc);
-  if (attr)
-    {
-      lowpc = DW_ADDR (attr);
-    }
+  /* Ignore functions with missing or empty names and functions with
+     missing or invalid low and high pc attributes.  */
+  if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+    return;
 
-  attr = dwarf_attr (die, DW_AT_high_pc);
-  if (attr)
-    {
-      highpc = DW_ADDR (attr);
-    }
+  lowpc += baseaddr;
+  highpc += baseaddr;
 
   if (objfile->ei.entry_point >= lowpc &&
       objfile->ei.entry_point < highpc)
@@ -1203,13 +1645,29 @@ read_func_scope (die, objfile)
       objfile->ei.entry_func_highpc = highpc;
     }
 
-  if (STREQ (name, "main"))    /* FIXME: hardwired name */
+  /* Decode DW_AT_frame_base location descriptor if present, keep result
+     for DW_OP_fbreg operands in decode_locdesc.  */
+  frame_base_reg = -1;
+  frame_base_offset = 0;
+  attr = dwarf_attr (die, DW_AT_frame_base);
+  if (attr)
     {
-      objfile->ei.main_func_lowpc = lowpc;
-      objfile->ei.main_func_highpc = highpc;
+      CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+      if (isderef)
+       complain (&dwarf2_unsupported_at_frame_base, name);
+      else if (isreg)
+       frame_base_reg = addr;
+      else if (offreg)
+       {
+         frame_base_reg = basereg;
+         frame_base_offset = addr;
+       }
+      else
+       complain (&dwarf2_unsupported_at_frame_base, name);
     }
+
   new = push_context (0, lowpc);
-  new->name = new_symbol (die, objfile);
+  new->name = new_symbol (die, die->type, objfile, cu_header);
   list_in_scope = &local_symbols;
 
   if (die->has_children)
@@ -1217,7 +1675,7 @@ read_func_scope (die, objfile)
       child_die = die->next;
       while (child_die && child_die->tag)
        {
-         process_die (child_die, objfile);
+         process_die (child_die, objfile, cu_header);
          child_die = sibling_die (child_die);
        }
     }
@@ -1233,25 +1691,18 @@ read_func_scope (die, objfile)
    a new scope, process the dies, and then close the scope.  */
 
 static void
-read_lexical_block_scope (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_lexical_block_scope (struct die_info *die, struct objfile *objfile,
+                         const struct comp_unit_head *cu_header)
 {
   register struct context_stack *new;
-  CORE_ADDR lowpc = 0, highpc = 0;
-  struct attribute *attr;
+  CORE_ADDR lowpc, highpc;
   struct die_info *child_die;
 
-  attr = dwarf_attr (die, DW_AT_low_pc);
-  if (attr)
-    {
-      lowpc = DW_ADDR (attr);
-    }
-  attr = dwarf_attr (die, DW_AT_high_pc);
-  if (attr)
-    {
-      highpc = DW_ADDR (attr);
-    }
+  /* Ignore blocks with missing or invalid low and high pc attributes.  */
+  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+    return;
+  lowpc += baseaddr;
+  highpc += baseaddr;
 
   push_context (0, lowpc);
   if (die->has_children)
@@ -1259,7 +1710,7 @@ read_lexical_block_scope (die, objfile)
       child_die = die->next;
       while (child_die && child_die->tag)
        {
-         process_die (child_die, objfile);
+         process_die (child_die, objfile, cu_header);
          child_die = sibling_die (child_die);
        }
     }
@@ -1273,6 +1724,454 @@ read_lexical_block_scope (die, objfile)
   local_symbols = new->locals;
 }
 
+/* Get low and high pc attributes from a die.
+   Return 1 if the attributes are present and valid, otherwise, return 0.  */
+
+static int
+dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc,
+                     struct objfile *objfile)
+{
+  struct attribute *attr;
+  CORE_ADDR low;
+  CORE_ADDR high;
+
+  attr = dwarf_attr (die, DW_AT_low_pc);
+  if (attr)
+    low = DW_ADDR (attr);
+  else
+    return 0;
+  attr = dwarf_attr (die, DW_AT_high_pc);
+  if (attr)
+    high = DW_ADDR (attr);
+  else
+    return 0;
+
+  if (high < low)
+    return 0;
+
+  /* When using the GNU linker, .gnu.linkonce. sections are used to
+     eliminate duplicate copies of functions and vtables and such.
+     The linker will arbitrarily choose one and discard the others.
+     The AT_*_pc values for such functions refer to local labels in
+     these sections.  If the section from that file was discarded, the
+     labels are not in the output, so the relocs get a value of 0.
+     If this is a discarded function, mark the pc bounds as invalid,
+     so that GDB will ignore it.  */
+  if (low == 0 && (bfd_get_file_flags (objfile->obfd) & HAS_RELOC) == 0)
+    return 0;
+
+  *lowpc = low;
+  *highpc = high;
+  return 1;
+}
+
+/* Add an aggregate field to the field list.  */
+
+static void
+dwarf2_add_field (struct field_info *fip, struct die_info *die,
+                 struct objfile *objfile,
+                 const struct comp_unit_head *cu_header)
+{
+  struct nextfield *new_field;
+  struct attribute *attr;
+  struct field *fp;
+  char *fieldname = "";
+
+  /* Allocate a new field list entry and link it in.  */
+  new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
+  make_cleanup (xfree, new_field);
+  memset (new_field, 0, sizeof (struct nextfield));
+  new_field->next = fip->fields;
+  fip->fields = new_field;
+  fip->nfields++;
+
+  /* Handle accessibility and virtuality of field.
+     The default accessibility for members is public, the default
+     accessibility for inheritance is private.  */
+  if (die->tag != DW_TAG_inheritance)
+    new_field->accessibility = DW_ACCESS_public;
+  else
+    new_field->accessibility = DW_ACCESS_private;
+  new_field->virtuality = DW_VIRTUALITY_none;
+
+  attr = dwarf_attr (die, DW_AT_accessibility);
+  if (attr)
+    new_field->accessibility = DW_UNSND (attr);
+  if (new_field->accessibility != DW_ACCESS_public)
+    fip->non_public_fields = 1;
+  attr = dwarf_attr (die, DW_AT_virtuality);
+  if (attr)
+    new_field->virtuality = DW_UNSND (attr);
+
+  fp = &new_field->field;
+  if (die->tag == DW_TAG_member)
+    {
+      /* Get type of field.  */
+      fp->type = die_type (die, objfile, cu_header);
+
+      /* Get bit size of field (zero if none).  */
+      attr = dwarf_attr (die, DW_AT_bit_size);
+      if (attr)
+       {
+         FIELD_BITSIZE (*fp) = DW_UNSND (attr);
+       }
+      else
+       {
+         FIELD_BITSIZE (*fp) = 0;
+       }
+
+      /* Get bit offset of field.  */
+      attr = dwarf_attr (die, DW_AT_data_member_location);
+      if (attr)
+       {
+         FIELD_BITPOS (*fp) =
+           decode_locdesc (DW_BLOCK (attr), objfile, cu_header) * bits_per_byte;
+       }
+      else
+       FIELD_BITPOS (*fp) = 0;
+      attr = dwarf_attr (die, DW_AT_bit_offset);
+      if (attr)
+       {
+         if (BITS_BIG_ENDIAN)
+           {
+             /* For big endian bits, the DW_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 (*fp) += DW_UNSND (attr);
+           }
+         else
+           {
+             /* For little endian bits, 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.  */
+             int anonymous_size;
+             int bit_offset = DW_UNSND (attr);
+
+             attr = dwarf_attr (die, DW_AT_byte_size);
+             if (attr)
+               {
+                 /* The size of the anonymous object containing
+                    the bit field is explicit, so use the
+                    indicated size (in bytes).  */
+                 anonymous_size = DW_UNSND (attr);
+               }
+             else
+               {
+                 /* The size of the anonymous object containing
+                    the bit field must be inferred from the type
+                    attribute of the data member containing the
+                    bit field.  */
+                 anonymous_size = TYPE_LENGTH (fp->type);
+               }
+             FIELD_BITPOS (*fp) += anonymous_size * bits_per_byte
+               - bit_offset - FIELD_BITSIZE (*fp);
+           }
+       }
+
+      /* Get name of field.  */
+      attr = dwarf_attr (die, DW_AT_name);
+      if (attr && DW_STRING (attr))
+       fieldname = DW_STRING (attr);
+      fp->name = obsavestring (fieldname, strlen (fieldname),
+                              &objfile->type_obstack);
+
+      /* Change accessibility for artificial fields (e.g. virtual table
+         pointer or virtual base class pointer) to private.  */
+      if (dwarf_attr (die, DW_AT_artificial))
+       {
+         new_field->accessibility = DW_ACCESS_private;
+         fip->non_public_fields = 1;
+       }
+    }
+  else if (die->tag == DW_TAG_variable)
+    {
+      char *physname;
+
+      /* C++ static member.
+        Get name of field.  */
+      attr = dwarf_attr (die, DW_AT_name);
+      if (attr && DW_STRING (attr))
+       fieldname = DW_STRING (attr);
+      else
+       return;
+
+      /* Get physical name.  */
+      physname = dwarf2_linkage_name (die);
+
+      SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname),
+                                            &objfile->type_obstack));
+      FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
+      FIELD_NAME (*fp) = obsavestring (fieldname, strlen (fieldname),
+                                      &objfile->type_obstack);
+    }
+  else if (die->tag == DW_TAG_inheritance)
+    {
+      /* C++ base class field.  */
+      attr = dwarf_attr (die, DW_AT_data_member_location);
+      if (attr)
+       FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), objfile, cu_header)
+                             * bits_per_byte);
+      FIELD_BITSIZE (*fp) = 0;
+      FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
+      FIELD_NAME (*fp) = type_name_no_tag (fp->type);
+      fip->nbaseclasses++;
+    }
+}
+
+/* Create the vector of fields, and attach it to the type.  */
+
+static void
+dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
+                             struct objfile *objfile)
+{
+  int nfields = fip->nfields;
+
+  /* Record the field count, allocate space for the array of fields,
+     and create blank accessibility bitfields if necessary.  */
+  TYPE_NFIELDS (type) = nfields;
+  TYPE_FIELDS (type) = (struct field *)
+    TYPE_ALLOC (type, sizeof (struct field) * nfields);
+  memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
+
+  if (fip->non_public_fields)
+    {
+      ALLOCATE_CPLUS_STRUCT_TYPE (type);
+
+      TYPE_FIELD_PRIVATE_BITS (type) =
+       (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+      B_CLRALL (TYPE_FIELD_PRIVATE_BITS (type), nfields);
+
+      TYPE_FIELD_PROTECTED_BITS (type) =
+       (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+      B_CLRALL (TYPE_FIELD_PROTECTED_BITS (type), nfields);
+
+      TYPE_FIELD_IGNORE_BITS (type) =
+       (B_TYPE *) TYPE_ALLOC (type, B_BYTES (nfields));
+      B_CLRALL (TYPE_FIELD_IGNORE_BITS (type), nfields);
+    }
+
+  /* If the type has baseclasses, allocate and clear a bit vector for
+     TYPE_FIELD_VIRTUAL_BITS.  */
+  if (fip->nbaseclasses)
+    {
+      int num_bytes = B_BYTES (fip->nbaseclasses);
+      char *pointer;
+
+      ALLOCATE_CPLUS_STRUCT_TYPE (type);
+      pointer = (char *) TYPE_ALLOC (type, num_bytes);
+      TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
+      B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses);
+      TYPE_N_BASECLASSES (type) = fip->nbaseclasses;
+    }
+
+  /* Copy the saved-up fields into the field vector.  Start from the head
+     of the list, adding to the tail of the field array, so that they end
+     up in the same order in the array in which they were added to the list.  */
+  while (nfields-- > 0)
+    {
+      TYPE_FIELD (type, nfields) = fip->fields->field;
+      switch (fip->fields->accessibility)
+       {
+       case DW_ACCESS_private:
+         SET_TYPE_FIELD_PRIVATE (type, nfields);
+         break;
+
+       case DW_ACCESS_protected:
+         SET_TYPE_FIELD_PROTECTED (type, nfields);
+         break;
+
+       case DW_ACCESS_public:
+         break;
+
+       default:
+         /* Unknown accessibility.  Complain and treat it as public.  */
+         {
+           complain (&dwarf2_unsupported_accessibility,
+                     fip->fields->accessibility);
+         }
+         break;
+       }
+      if (nfields < fip->nbaseclasses)
+       {
+         switch (fip->fields->virtuality)
+           {
+           case DW_VIRTUALITY_virtual:
+           case DW_VIRTUALITY_pure_virtual:
+             SET_TYPE_FIELD_VIRTUAL (type, nfields);
+             break;
+           }
+       }
+      fip->fields = fip->fields->next;
+    }
+}
+
+/* Add a member function to the proper fieldlist.  */
+
+static void
+dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
+                     struct type *type, struct objfile *objfile,
+                     const struct comp_unit_head *cu_header)
+{
+  struct attribute *attr;
+  struct fnfieldlist *flp;
+  int i;
+  struct fn_field *fnp;
+  char *fieldname;
+  char *physname;
+  struct nextfnfield *new_fnfield;
+
+  /* Get name of member function.  */
+  attr = dwarf_attr (die, DW_AT_name);
+  if (attr && DW_STRING (attr))
+    fieldname = DW_STRING (attr);
+  else
+    return;
+
+  /* Get the mangled name.  */
+  physname = dwarf2_linkage_name (die);
+
+  /* Look up member function name in fieldlist.  */
+  for (i = 0; i < fip->nfnfields; i++)
+    {
+      if (STREQ (fip->fnfieldlists[i].name, fieldname))
+       break;
+    }
+
+  /* Create new list element if necessary.  */
+  if (i < fip->nfnfields)
+    flp = &fip->fnfieldlists[i];
+  else
+    {
+      if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0)
+       {
+         fip->fnfieldlists = (struct fnfieldlist *)
+           xrealloc (fip->fnfieldlists,
+                     (fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
+                     * sizeof (struct fnfieldlist));
+         if (fip->nfnfields == 0)
+           make_cleanup (free_current_contents, &fip->fnfieldlists);
+       }
+      flp = &fip->fnfieldlists[fip->nfnfields];
+      flp->name = fieldname;
+      flp->length = 0;
+      flp->head = NULL;
+      fip->nfnfields++;
+    }
+
+  /* Create a new member function field and chain it to the field list
+     entry. */
+  new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield));
+  make_cleanup (xfree, new_fnfield);
+  memset (new_fnfield, 0, sizeof (struct nextfnfield));
+  new_fnfield->next = flp->head;
+  flp->head = new_fnfield;
+  flp->length++;
+
+  /* Fill in the member function field info.  */
+  fnp = &new_fnfield->fnfield;
+  fnp->physname = obsavestring (physname, strlen (physname),
+                               &objfile->type_obstack);
+  fnp->type = alloc_type (objfile);
+  if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
+    {
+      struct type *return_type = TYPE_TARGET_TYPE (die->type);
+      struct type **arg_types;
+      int nparams = TYPE_NFIELDS (die->type);
+      int iparams;
+
+      /* Copy argument types from the subroutine type.  */
+      arg_types = (struct type **)
+       TYPE_ALLOC (fnp->type, (nparams + 1) * sizeof (struct type *));
+      for (iparams = 0; iparams < nparams; iparams++)
+       arg_types[iparams] = TYPE_FIELD_TYPE (die->type, iparams);
+
+      /* Set last entry in argument type vector.  */
+      if (TYPE_FLAGS (die->type) & TYPE_FLAG_VARARGS)
+       arg_types[nparams] = NULL;
+      else
+       arg_types[nparams] = dwarf2_fundamental_type (objfile, FT_VOID);
+
+      smash_to_method_type (fnp->type, type, return_type, arg_types);
+
+      /* Handle static member functions.
+         Dwarf2 has no clean way to discern C++ static and non-static
+         member functions. G++ helps GDB by marking the first
+         parameter for non-static member functions (which is the
+         this pointer) as artificial. We obtain this information
+         from read_subroutine_type via TYPE_FIELD_ARTIFICIAL.  */
+      if (nparams == 0 || TYPE_FIELD_ARTIFICIAL (die->type, 0) == 0)
+       fnp->voffset = VOFFSET_STATIC;
+    }
+  else
+    complain (&dwarf2_missing_member_fn_type_complaint, physname);
+
+  /* Get fcontext from DW_AT_containing_type if present.  */
+  if (dwarf_attr (die, DW_AT_containing_type) != NULL)
+    fnp->fcontext = die_containing_type (die, objfile, cu_header);
+
+  /* dwarf2 doesn't have stubbed physical names, so the setting of is_const
+     and is_volatile is irrelevant, as it is needed by gdb_mangle_name only.  */
+
+  /* Get accessibility.  */
+  attr = dwarf_attr (die, DW_AT_accessibility);
+  if (attr)
+    {
+      switch (DW_UNSND (attr))
+       {
+       case DW_ACCESS_private:
+         fnp->is_private = 1;
+         break;
+       case DW_ACCESS_protected:
+         fnp->is_protected = 1;
+         break;
+       }
+    }
+
+  /* Get index in virtual function table if it is a virtual member function.  */
+  attr = dwarf_attr (die, DW_AT_vtable_elem_location);
+  if (attr)
+    fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2;
+}
+
+/* Create the vector of member function fields, and attach it to the type.  */
+
+static void
+dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
+                                struct objfile *objfile)
+{
+  struct fnfieldlist *flp;
+  int total_length = 0;
+  int i;
+
+  ALLOCATE_CPLUS_STRUCT_TYPE (type);
+  TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
+    TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields);
+
+  for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++)
+    {
+      struct nextfnfield *nfp = flp->head;
+      struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i);
+      int k;
+
+      TYPE_FN_FIELDLIST_NAME (type, i) = flp->name;
+      TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length;
+      fn_flp->fn_fields = (struct fn_field *)
+       TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length);
+      for (k = flp->length; (k--, nfp); nfp = nfp->next)
+       fn_flp->fn_fields[k] = nfp->fnfield;
+
+      total_length += flp->length;
+    }
+
+  TYPE_NFN_FIELDS (type) = fip->nfnfields;
+  TYPE_NFN_FIELDS_TOTAL (type) = total_length;
+}
+
 /* Called when we find the DIE that starts a structure or union scope
    (definition) to process all dies that define the members of the
    structure or union.
@@ -1290,40 +2189,36 @@ read_lexical_block_scope (die, objfile)
    suppresses creating a symbol table entry itself).  */
 
 static void
-read_structure_scope (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_structure_scope (struct die_info *die, struct objfile *objfile,
+                     const struct comp_unit_head *cu_header)
 {
-  struct type *type, *member_type;
-  struct field *fields;
-  struct die_info *child_die;
+  struct type *type;
   struct attribute *attr;
-  struct symbol *sym;
-  int num_fields;
 
-  type = dwarf_alloc_type (objfile);
+  type = alloc_type (objfile);
 
   INIT_CPLUS_SPECIFIC (type);
   attr = dwarf_attr (die, DW_AT_name);
+  if (attr && DW_STRING (attr))
+    {
+      TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
+                                          strlen (DW_STRING (attr)),
+                                          &objfile->type_obstack);
+    }
 
   if (die->tag == DW_TAG_structure_type)
     {
       TYPE_CODE (type) = TYPE_CODE_STRUCT;
-      if (attr)
-       {
-         TYPE_NAME (type) = obconcat (&objfile->type_obstack,
-                                    "struct", " ", DW_STRING (attr));
-       }
     }
-  else
+  else if (die->tag == DW_TAG_union_type)
     {
-      /* die->tag == DW_TAG_union_type */
       TYPE_CODE (type) = TYPE_CODE_UNION;
-      if (attr)
-       {
-         TYPE_NAME (type) = obconcat (&objfile->type_obstack,
-                                      "union", " ", DW_STRING (attr));
-       }
+    }
+  else
+    {
+      /* FIXME: TYPE_CODE_CLASS is currently defined to TYPE_CODE_STRUCT
+         in gdbtypes.h.  */
+      TYPE_CODE (type) = TYPE_CODE_CLASS;
     }
 
   attr = dwarf_attr (die, DW_AT_byte_size);
@@ -1341,76 +2236,97 @@ read_structure_scope (die, objfile)
      type within the structure itself. */
   die->type = type;
 
-  num_fields = 0;
-  fields = NULL;
-  if (die->has_children)
+  if (die->has_children && ! die_is_declaration (die))
     {
+      struct field_info fi;
+      struct die_info *child_die;
+      struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
+
+      memset (&fi, 0, sizeof (struct field_info));
+
       child_die = die->next;
+
       while (child_die && child_die->tag)
        {
-         if (child_die->tag != DW_TAG_member)
+         if (child_die->tag == DW_TAG_member)
+           {
+             dwarf2_add_field (&fi, child_die, objfile, cu_header);
+           }
+         else if (child_die->tag == DW_TAG_variable)
+           {
+             /* C++ static member.  */
+             dwarf2_add_field (&fi, child_die, objfile, cu_header);
+           }
+         else if (child_die->tag == DW_TAG_subprogram)
+           {
+             /* C++ member function. */
+             process_die (child_die, objfile, cu_header);
+             dwarf2_add_member_fn (&fi, child_die, type, objfile, cu_header);
+           }
+         else if (child_die->tag == DW_TAG_inheritance)
            {
-             process_die (child_die, objfile);
+             /* C++ base class field.  */
+             dwarf2_add_field (&fi, child_die, objfile, cu_header);
            }
          else
            {
-             if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0)
-               {
-                 fields = (struct field *)
-                   xrealloc (fields,
-                             (num_fields + DW_FIELD_ALLOC_CHUNK)
-                              * sizeof (struct field));
-               }
+             process_die (child_die, objfile, cu_header);
+           }
+         child_die = sibling_die (child_die);
+       }
 
-             /* Get bit offset of field */
-             attr = dwarf_attr (child_die, DW_AT_bit_offset);
-             if (attr)
-               {
-                 fields[num_fields].bitpos = DW_UNSND (attr);
-               }
-             else
-               {
-                 fields[num_fields].bitpos = 0;
-               }
-             attr = dwarf_attr (child_die, DW_AT_data_member_location);
-             if (attr)
-               {
-                 fields[num_fields].bitpos +=
-                   decode_locdesc (DW_BLOCK (attr), objfile) * bits_per_byte;
-               }
+      /* Attach fields and member functions to the type.  */
+      if (fi.nfields)
+       dwarf2_attach_fields_to_type (&fi, type, objfile);
+      if (fi.nfnfields)
+       {
+         dwarf2_attach_fn_fields_to_type (&fi, type, objfile);
 
-             /* Get bit size of field (zero if none). */
-             attr = dwarf_attr (child_die, DW_AT_bit_size);
-             if (attr)
+         /* Get the type which refers to the base class (possibly this
+            class itself) which contains the vtable pointer for the current
+            class from the DW_AT_containing_type attribute.  */
+
+         if (dwarf_attr (die, DW_AT_containing_type) != NULL)
+           {
+             struct type *t = die_containing_type (die, objfile, cu_header);
+
+             TYPE_VPTR_BASETYPE (type) = t;
+             if (type == t)
                {
-                 fields[num_fields].bitsize = DW_UNSND (attr);
+                 static const char vptr_name[] =
+                 {'_', 'v', 'p', 't', 'r', '\0'};
+                 int i;
+
+                 /* Our own class provides vtbl ptr.  */
+                 for (i = TYPE_NFIELDS (t) - 1;
+                      i >= TYPE_N_BASECLASSES (t);
+                      --i)
+                   {
+                     char *fieldname = TYPE_FIELD_NAME (t, i);
+
+                     if (STREQN (fieldname, vptr_name, strlen (vptr_name) - 1)
+                         && is_cplus_marker (fieldname[strlen (vptr_name)]))
+                       {
+                         TYPE_VPTR_FIELDNO (type) = i;
+                         break;
+                       }
+                   }
+
+                 /* Complain if virtual function table field not found.  */
+                 if (i < TYPE_N_BASECLASSES (t))
+                   complain (&dwarf2_vtbl_not_found_complaint,
+                         TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) : "");
                }
              else
                {
-                 fields[num_fields].bitsize = 0;
+                 TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
                }
-
-             /* Get type of member. */
-             member_type = die_type (child_die, objfile);
-             fields[num_fields].type = member_type;
-
-             /* Get name of member. */
-             attr = dwarf_attr (child_die, DW_AT_name);
-             if (attr)
-               {
-                 fields[num_fields].name = obsavestring (DW_STRING (attr),
-                                           strlen (DW_STRING (attr)),
-                                             &objfile->type_obstack);
-#if 0
-                 fields[num_fields].name = strdup (DW_STRING (attr));
-#endif
-               }
-             num_fields++;
            }
-         child_die = sibling_die (child_die);
        }
-      type->nfields = num_fields;
-      type->fields = fields;
+
+      new_symbol (die, type, objfile, cu_header);
+
+      do_cleanups (back_to);
     }
   else
     {
@@ -1419,11 +2335,6 @@ read_structure_scope (die, objfile)
     }
 
   die->type = type;
-  sym = new_symbol (die, objfile);
-  if (sym != NULL)
-    {
-      SYMBOL_TYPE (sym) = type;
-    }
 }
 
 /* Given a pointer to a die which begins an enumeration, process all
@@ -1436,27 +2347,26 @@ read_structure_scope (die, objfile)
    NOTE: We reverse the order of the element list.  */
 
 static void
-read_enumeration (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_enumeration (struct die_info *die, struct objfile *objfile,
+                 const struct comp_unit_head *cu_header)
 {
   struct die_info *child_die;
   struct type *type;
   struct field *fields;
   struct attribute *attr;
   struct symbol *sym;
-  struct dwarf_block *blk;
   int num_fields;
-  unsigned int size, bytes_read, i;
+  int unsigned_enum = 1;
 
-  type = dwarf_alloc_type (objfile);
+  type = alloc_type (objfile);
 
   TYPE_CODE (type) = TYPE_CODE_ENUM;
   attr = dwarf_attr (die, DW_AT_name);
-  if (attr)
+  if (attr && DW_STRING (attr))
     {
-      TYPE_NAME (type) = obconcat (&objfile->type_obstack,
-                                  "enum ", " ", DW_STRING (attr));
+      TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
+                                          strlen (DW_STRING (attr)),
+                                          &objfile->type_obstack);
     }
 
   attr = dwarf_attr (die, DW_AT_byte_size);
@@ -1478,62 +2388,51 @@ read_enumeration (die, objfile)
        {
          if (child_die->tag != DW_TAG_enumerator)
            {
-             process_die (child_die, objfile);
+             process_die (child_die, objfile, cu_header);
            }
          else
            {
-             if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0)
-               {
-                 fields = (struct field *)
-                   xrealloc (fields,
-                     (num_fields + DW_FIELD_ALLOC_CHUNK)
-                       * sizeof (struct field));
-               }
-
-             /* Handcraft a new symbol for this enum member. */
-             sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
-                                             sizeof (struct symbol));
-             memset (sym, 0, sizeof (struct symbol));
-
-             fields[num_fields].type = NULL;
-             fields[num_fields].bitsize = 0;
              attr = dwarf_attr (child_die, DW_AT_name);
              if (attr)
                {
-                 fields[num_fields].name = strdup (DW_STRING (attr));
-                 SYMBOL_NAME (sym) = strdup (fields[num_fields].name);
-               }
-             attr = dwarf_attr (child_die, DW_AT_const_value);
-             if (attr)
-               {
-                 fields[num_fields].bitpos = DW_UNSND (attr);
-                 SYMBOL_VALUE (sym) = DW_UNSND (attr);
-               }
+                 sym = new_symbol (child_die, type, objfile, cu_header);
+                 if (SYMBOL_VALUE (sym) < 0)
+                   unsigned_enum = 0;
 
-#if 0
-             SYMBOL_NAME (sym) = create_name (elist->str,
-                                           &objfile->symbol_obstack);
-#endif
-             SYMBOL_INIT_LANGUAGE_SPECIFIC (sym, cu_language);
-             SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
-             SYMBOL_CLASS (sym) = LOC_CONST;
-             SYMBOL_TYPE (sym) = type;
-             add_symbol_to_list (sym, list_in_scope);
+                 if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0)
+                   {
+                     fields = (struct field *)
+                       xrealloc (fields,
+                                 (num_fields + DW_FIELD_ALLOC_CHUNK)
+                                 * sizeof (struct field));
+                   }
 
-             num_fields++;
+                 FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym);
+                 FIELD_TYPE (fields[num_fields]) = NULL;
+                 FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym);
+                 FIELD_BITSIZE (fields[num_fields]) = 0;
+
+                 num_fields++;
+               }
            }
 
          child_die = sibling_die (child_die);
        }
-      type->fields = fields;
-      type->nfields = num_fields;
+
+      if (num_fields)
+       {
+         TYPE_NFIELDS (type) = num_fields;
+         TYPE_FIELDS (type) = (struct field *)
+           TYPE_ALLOC (type, sizeof (struct field) * num_fields);
+         memcpy (TYPE_FIELDS (type), fields,
+                 sizeof (struct field) * num_fields);
+         xfree (fields);
+       }
+      if (unsigned_enum)
+       TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
     }
   die->type = type;
-  sym = new_symbol (die, objfile);
-  if (sym != NULL)
-    {
-      SYMBOL_TYPE (sym) = type;
-    }
+  new_symbol (die, type, objfile, cu_header);
 }
 
 /* Extract all information from a DW_TAG_array_type DIE and put it in
@@ -1541,17 +2440,16 @@ read_enumeration (die, objfile)
    arrays.  */
 
 static void
-dwarf_read_array_type (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_array_type (struct die_info *die, struct objfile *objfile,
+                const struct comp_unit_head *cu_header)
 {
   struct die_info *child_die;
-  struct type *type, *element_type, *range_type, *index_type;
+  struct type *type = NULL;
+  struct type *element_type, *range_type, *index_type;
+  struct type **range_types = NULL;
   struct attribute *attr;
-  struct dwarf_block *blk;
-  unsigned int size, i, type_form, bytes_read;
-  unsigned int index_spec, lo_spec, hi_spec, type_ref;
-  unsigned int low, high;
+  int ndim = 0;
+  struct cleanup *back_to;
 
   /* Return if we've already decoded this type. */
   if (die->type)
@@ -1559,22 +2457,36 @@ dwarf_read_array_type (die, objfile)
       return;
     }
 
-  element_type = die_type (die, objfile);
+  element_type = die_type (die, objfile, cu_header);
 
-  low = 0;
-  high = 1;
-  if (cu_language == DW_LANG_Fortran77 || cu_language == DW_LANG_Fortran90)
+  /* Irix 6.2 native cc creates array types without children for
+     arrays with unspecified length.  */
+  if (die->has_children == 0)
     {
-      /* FORTRAN implies a lower bound of 1, if not given.  */
-      low = 1;
+      index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
+      range_type = create_range_type (NULL, index_type, 0, -1);
+      die->type = create_array_type (NULL, element_type, range_type);
+      return;
     }
 
+  back_to = make_cleanup (null_cleanup, NULL);
   child_die = die->next;
   while (child_die && child_die->tag)
     {
       if (child_die->tag == DW_TAG_subrange_type)
        {
-         index_type = die_type (child_die, objfile);
+         unsigned int low, high;
+
+         /* Default bounds to an array with unspecified length.  */
+         low = 0;
+         high = -1;
+         if (cu_language == language_fortran)
+           {
+             /* FORTRAN implies a lower bound of 1, if not given.  */
+             low = 1;
+           }
+
+         index_type = die_type (child_die, objfile, cu_header);
          attr = dwarf_attr (child_die, DW_AT_lower_bound);
          if (attr)
            {
@@ -1583,28 +2495,19 @@ dwarf_read_array_type (die, objfile)
                  low = DW_SND (attr);
                }
              else if (attr->form == DW_FORM_udata
-                      || attr->form == DW_FORM_data1
-                      || attr->form == DW_FORM_data2
-                      || attr->form == DW_FORM_data4)
+                      || attr->form == DW_FORM_data1
+                      || attr->form == DW_FORM_data2
+                      || attr->form == DW_FORM_data4)
                {
                  low = DW_UNSND (attr);
                }
              else
                {
-                 if (!array_bound_warning_given)
-                   {
-                     warning ("Non-constant array bounds ignored.");
-                     array_bound_warning_given = 1;
-                   }
+                 complain (&dwarf2_non_const_array_bound_ignored,
+                           dwarf_form_name (attr->form));
 #ifdef FORTRAN_HACK
-                 type = dwarf_alloc_type (objfile);
-                 TYPE_TARGET_TYPE (type) = element_type;
-                 TYPE_OBJFILE (type) = objfile;
-                 TYPE_LENGTH (type) = 4;
-                 TYPE_CODE (type) = TYPE_CODE_PTR;
-                 TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
-                 TYPE_POINTER_TYPE (element_type) = type;
-                 goto done;
+                 die->type = lookup_pointer_type (element_type);
+                 return;
 #else
                  low = 0;
 #endif
@@ -1618,40 +2521,56 @@ dwarf_read_array_type (die, objfile)
                  high = DW_SND (attr);
                }
              else if (attr->form == DW_FORM_udata
-                      || attr->form == DW_FORM_data1
-                      || attr->form == DW_FORM_data2
-                      || attr->form == DW_FORM_data4)
+                      || attr->form == DW_FORM_data1
+                      || attr->form == DW_FORM_data2
+                      || attr->form == DW_FORM_data4)
                {
                  high = DW_UNSND (attr);
                }
+             else if (attr->form == DW_FORM_block1)
+               {
+                 /* GCC encodes arrays with unspecified or dynamic length
+                    with a DW_FORM_block1 attribute.
+                    FIXME: GDB does not yet know how to handle dynamic
+                    arrays properly, treat them as arrays with unspecified
+                    length for now.  */
+                 high = -1;
+               }
              else
                {
-                 if (!array_bound_warning_given)
-                   {
-                     warning ("Non-constant array bounds ignored.");
-                     array_bound_warning_given = 1;
-                   }
+                 complain (&dwarf2_non_const_array_bound_ignored,
+                           dwarf_form_name (attr->form));
 #ifdef FORTRAN_HACK
-                 type = dwarf_alloc_type (objfile);
-                 TYPE_TARGET_TYPE (type) = element_type;
-                 TYPE_OBJFILE (type) = objfile;
-                 TYPE_LENGTH (type) = 4;
-                 TYPE_CODE (type) = TYPE_CODE_PTR;
-                 TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
-                 TYPE_POINTER_TYPE (element_type) = type;
-                 goto done;
+                 die->type = lookup_pointer_type (element_type);
+                 return;
 #else
                  high = 1;
 #endif
                }
            }
+
+         /* Create a range type and save it for array type creation.  */
+         if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0)
+           {
+             range_types = (struct type **)
+               xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
+                         * sizeof (struct type *));
+             if (ndim == 0)
+               make_cleanup (free_current_contents, &range_types);
+           }
+         range_types[ndim++] = create_range_type (NULL, index_type, low, high);
        }
-      range_type = create_range_type (NULL, index_type, low, high);
-      type = create_array_type (NULL, element_type, range_type);
-      element_type = type;
       child_die = sibling_die (child_die);
     }
-done:
+
+  /* Dwarf2 dimensions are output from left to right, create the
+     necessary array types in backwards order.  */
+  type = element_type;
+  while (ndim-- > 0)
+    type = create_array_type (NULL, type, range_types[ndim]);
+
+  do_cleanups (back_to);
+
   /* Install the type in the die. */
   die->type = type;
 }
@@ -1659,31 +2578,30 @@ done:
 /* First cut: install each common block member as a global variable.  */
 
 static void
-read_common_block (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_common_block (struct die_info *die, struct objfile *objfile,
+                  const struct comp_unit_head *cu_header)
 {
   struct die_info *child_die;
   struct attribute *attr;
   struct symbol *sym;
-  CORE_ADDR base;
+  CORE_ADDR base = (CORE_ADDR) 0;
 
   attr = dwarf_attr (die, DW_AT_location);
   if (attr)
     {
-      base = decode_locdesc (DW_BLOCK (attr), objfile);
+      base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
     }
   if (die->has_children)
     {
       child_die = die->next;
       while (child_die && child_die->tag)
        {
-         sym = new_symbol (child_die, objfile);
+         sym = new_symbol (child_die, NULL, objfile, cu_header);
          attr = dwarf_attr (child_die, DW_AT_data_member_location);
          if (attr)
            {
              SYMBOL_VALUE_ADDRESS (sym) =
-               base + decode_locdesc (DW_BLOCK (attr), objfile);
+               base + decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
              add_symbol_to_list (sym, &global_symbols);
            }
          child_die = sibling_die (child_die);
@@ -1695,11 +2613,10 @@ read_common_block (die, objfile)
    the user defined type vector.  */
 
 static void
-read_tag_pointer_type (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_tag_pointer_type (struct die_info *die, struct objfile *objfile,
+                      const struct comp_unit_head *cu_header)
 {
-  struct type *type, *pointed_to_type;
+  struct type *type;
   struct attribute *attr;
 
   if (die->type)
@@ -1707,11 +2624,7 @@ read_tag_pointer_type (die, objfile)
       return;
     }
 
-  pointed_to_type = die_type (die, objfile);
-
-  type = dwarf_alloc_type (objfile);
-  TYPE_TARGET_TYPE (type) = pointed_to_type;
-  TYPE_OBJFILE (type) = objfile;
+  type = lookup_pointer_type (die_type (die, objfile, cu_header));
   attr = dwarf_attr (die, DW_AT_byte_size);
   if (attr)
     {
@@ -1719,12 +2632,32 @@ read_tag_pointer_type (die, objfile)
     }
   else
     {
-      TYPE_LENGTH (type) = address_size;
+      TYPE_LENGTH (type) = cu_header->addr_size;
     }
-  TYPE_CODE (type) = TYPE_CODE_PTR;
-  TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+  die->type = type;
+}
+
+/* Extract all information from a DW_TAG_ptr_to_member_type DIE and add to
+   the user defined type vector.  */
+
+static void
+read_tag_ptr_to_member_type (struct die_info *die, struct objfile *objfile,
+                            const struct comp_unit_head *cu_header)
+{
+  struct type *type;
+  struct type *to_type;
+  struct type *domain;
+
+  if (die->type)
+    {
+      return;
+    }
+
+  type = alloc_type (objfile);
+  to_type = die_type (die, objfile, cu_header);
+  domain = die_containing_type (die, objfile, cu_header);
+  smash_to_member_type (type, domain, to_type);
 
-  TYPE_POINTER_TYPE (pointed_to_type) = type;
   die->type = type;
 }
 
@@ -1732,11 +2665,10 @@ read_tag_pointer_type (die, objfile)
    the user defined type vector.  */
 
 static void
-read_tag_reference_type (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_tag_reference_type (struct die_info *die, struct objfile *objfile,
+                        const struct comp_unit_head *cu_header)
 {
-  struct type *type, *pointed_to_type;
+  struct type *type;
   struct attribute *attr;
 
   if (die->type)
@@ -1744,11 +2676,7 @@ read_tag_reference_type (die, objfile)
       return;
     }
 
-  pointed_to_type = die_type (die, objfile);
-
-  type = dwarf_alloc_type (objfile);
-  TYPE_TARGET_TYPE (type) = pointed_to_type;
-  TYPE_OBJFILE (type) = objfile;
+  type = lookup_reference_type (die_type (die, objfile, cu_header));
   attr = dwarf_attr (die, DW_AT_byte_size);
   if (attr)
     {
@@ -1756,51 +2684,39 @@ read_tag_reference_type (die, objfile)
     }
   else
     {
-      TYPE_LENGTH (type) = address_size;
+      TYPE_LENGTH (type) = cu_header->addr_size;
     }
-  TYPE_CODE (type) = TYPE_CODE_REF;
-  TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
-
-  TYPE_REFERENCE_TYPE (pointed_to_type) = type;
   die->type = type;
 }
 
 static void
-read_tag_const_type (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_tag_const_type (struct die_info *die, struct objfile *objfile,
+                    const struct comp_unit_head *cu_header)
 {
+  struct type *base_type;
+
   if (die->type)
     {
       return;
     }
 
-  if (!tag_const_warning_given)
-    {
-      warning ("gdb ignores `const' qualifiers.");
-      tag_const_warning_given = 1;
-    }
-
-  die->type = die_type (die, objfile);
+  base_type = die_type (die, objfile, cu_header);
+  die->type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
 }
 
 static void
-read_tag_volatile_type (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_tag_volatile_type (struct die_info *die, struct objfile *objfile,
+                       const struct comp_unit_head *cu_header)
 {
+  struct type *base_type;
+
   if (die->type)
     {
       return;
     }
 
-  if (!tag_volatile_warning_given)
-    {
-      warning ("gdb ignores `volatile' qualifiers.");
-      tag_volatile_warning_given = 1;
-    }
-
-  die->type = die_type (die, objfile);
+  base_type = die_type (die, objfile, cu_header);
+  die->type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
 }
 
 /* Extract all information from a DW_TAG_string_type DIE and add to
@@ -1809,9 +2725,7 @@ read_tag_volatile_type (die, objfile)
    attribute to reference it.  */
 
 static void
-read_tag_string_type (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_tag_string_type (struct die_info *die, struct objfile *objfile)
 {
   struct type *type, *range_type, *index_type, *char_type;
   struct attribute *attr;
@@ -1841,51 +2755,109 @@ read_tag_string_type (die, objfile)
 /* Handle DIES due to C code like:
 
    struct foo
-     {
-       int (*funcp)(int a, long l);
-       int b;
-     };
+   {
+   int (*funcp)(int a, long l);
+   int b;
+   };
 
    ('funcp' generates a DW_TAG_subroutine_type DIE)
-
-   NOTE: parameter DIES are currently ignored.  See if gdb has a way to
-   include this info in it's type system, and decode them if so.  Is
-   this what the type structure's "arg_types" field is for?  (FIXME) */
+ */
 
 static void
-read_subroutine_type (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_subroutine_type (struct die_info *die, struct objfile *objfile,
+                     const struct comp_unit_head *cu_header)
 {
   struct type *type;           /* Type that this function returns */
   struct type *ftype;          /* Function that returns above type */
+  struct attribute *attr;
 
   /* Decode the type that this subroutine returns */
   if (die->type)
     {
       return;
     }
-  type = die_type (die, objfile);
+  type = die_type (die, objfile, cu_header);
   ftype = lookup_function_type (type);
 
-  TYPE_TARGET_TYPE (ftype) = type;
-  TYPE_LENGTH (ftype) = 1;
-  TYPE_CODE (ftype) = TYPE_CODE_FUNC;
-  TYPE_OBJFILE (ftype) = objfile;
+  /* All functions in C++ have prototypes.  */
+  attr = dwarf_attr (die, DW_AT_prototyped);
+  if ((attr && (DW_UNSND (attr) != 0))
+      || cu_language == language_cplus)
+    TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
 
-  die->type = type;
+  if (die->has_children)
+    {
+      struct die_info *child_die;
+      int nparams = 0;
+      int iparams = 0;
+
+      /* Count the number of parameters.
+         FIXME: GDB currently ignores vararg functions, but knows about
+         vararg member functions.  */
+      child_die = die->next;
+      while (child_die && child_die->tag)
+       {
+         if (child_die->tag == DW_TAG_formal_parameter)
+           nparams++;
+         else if (child_die->tag == DW_TAG_unspecified_parameters)
+           TYPE_FLAGS (ftype) |= TYPE_FLAG_VARARGS;
+         child_die = sibling_die (child_die);
+       }
+
+      /* Allocate storage for parameters and fill them in.  */
+      TYPE_NFIELDS (ftype) = nparams;
+      TYPE_FIELDS (ftype) = (struct field *)
+       TYPE_ALLOC (ftype, nparams * sizeof (struct field));
+
+      child_die = die->next;
+      while (child_die && child_die->tag)
+       {
+         if (child_die->tag == DW_TAG_formal_parameter)
+           {
+             /* Dwarf2 has no clean way to discern C++ static and non-static
+                member functions. G++ helps GDB by marking the first
+                parameter for non-static member functions (which is the
+                this pointer) as artificial. We pass this information
+                to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL.  */
+             attr = dwarf_attr (child_die, DW_AT_artificial);
+             if (attr)
+               TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr);
+             else
+               TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0;
+             TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, objfile,
+                                                          cu_header);
+             iparams++;
+           }
+         child_die = sibling_die (child_die);
+       }
+    }
+
+  die->type = ftype;
 }
 
 static void
-read_typedef (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_typedef (struct die_info *die, struct objfile *objfile,
+             const struct comp_unit_head *cu_header)
 {
   struct type *type;
 
   if (!die->type)
     {
-      type = die_type (die, objfile);
+      struct attribute *attr;
+      struct type *xtype;
+
+      xtype = die_type (die, objfile, cu_header);
+
+      type = alloc_type (objfile);
+      TYPE_CODE (type) = TYPE_CODE_TYPEDEF;
+      TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB;
+      TYPE_TARGET_TYPE (type) = xtype;
+      attr = dwarf_attr (die, DW_AT_name);
+      if (attr && DW_STRING (attr))
+       TYPE_NAME (type) = obsavestring (DW_STRING (attr),
+                                        strlen (DW_STRING (attr)),
+                                        &objfile->type_obstack);
+
       die->type = type;
     }
 }
@@ -1894,9 +2866,7 @@ read_typedef (die, objfile)
    it in the TYPE field of the die.  */
 
 static void
-read_base_type (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_base_type (struct die_info *die, struct objfile *objfile)
 {
   struct type *type;
   struct attribute *attr;
@@ -1918,27 +2888,72 @@ read_base_type (die, objfile)
     {
       size = DW_UNSND (attr);
     }
-  type = dwarf_base_type (encoding, size);
+  attr = dwarf_attr (die, DW_AT_name);
+  if (attr && DW_STRING (attr))
+    {
+      enum type_code code = TYPE_CODE_INT;
+      int is_unsigned = 0;
+
+      switch (encoding)
+       {
+       case DW_ATE_address:
+         /* Turn DW_ATE_address into a void * pointer.  */
+         code = TYPE_CODE_PTR;
+         is_unsigned = 1;
+         break;
+       case DW_ATE_boolean:
+         code = TYPE_CODE_BOOL;
+         is_unsigned = 1;
+         break;
+       case DW_ATE_complex_float:
+         code = TYPE_CODE_COMPLEX;
+         break;
+       case DW_ATE_float:
+         code = TYPE_CODE_FLT;
+         break;
+       case DW_ATE_signed:
+       case DW_ATE_signed_char:
+         break;
+       case DW_ATE_unsigned:
+       case DW_ATE_unsigned_char:
+         is_unsigned = 1;
+         break;
+       default:
+         complain (&dwarf2_unsupported_at_encoding,
+                   dwarf_type_encoding_name (encoding));
+         break;
+       }
+      type = init_type (code, size, is_unsigned, DW_STRING (attr), objfile);
+      if (encoding == DW_ATE_address)
+       TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID);
+    }
+  else
+    {
+      type = dwarf_base_type (encoding, size, objfile);
+    }
   die->type = type;
 }
 
 /* Read a whole compilation unit into a linked list of dies.  */
 
-struct die_info *
-read_comp_unit (info_ptr, abfd)
-    char *info_ptr;
-    bfd *abfd;
+static struct die_info *
+read_comp_unit (char *info_ptr, bfd *abfd,
+               const struct comp_unit_head *cu_header)
 {
   struct die_info *first_die, *last_die, *die;
   char *cur_ptr;
   int nesting_level;
 
+  /* Reset die reference table; we are
+     building new ones now.  */
+  dwarf2_empty_hash_tables ();
+
   cur_ptr = info_ptr;
   nesting_level = 0;
   first_die = last_die = NULL;
   do
     {
-      cur_ptr = read_full_die (&die, abfd, cur_ptr);
+      cur_ptr = read_full_die (&die, abfd, cur_ptr, cu_header);
       if (die->has_children)
        {
          nesting_level++;
@@ -1970,8 +2985,7 @@ read_comp_unit (info_ptr, abfd)
 /* Free a linked list of dies.  */
 
 static void
-free_die_list (dies)
-     struct die_info *dies;
+free_die_list (struct die_info *dies)
 {
   struct die_info *die, *next;
 
@@ -1979,31 +2993,45 @@ free_die_list (dies)
   while (die)
     {
       next = die->next;
-      free (die->attrs);
-      free (die);
+      xfree (die->attrs);
+      xfree (die);
       die = next;
     }
 }
 
-/* Read the contents of the section at OFFSET and of size SIZE in the
-   object file specified by ABFD into a buffer of bytes and return it.  */
+static void
+do_free_die_list_cleanup (void *dies)
+{
+  free_die_list (dies);
+}
+
+static struct cleanup *
+make_cleanup_free_die_list (struct die_info *dies)
+{
+  return make_cleanup (do_free_die_list_cleanup, dies);
+}
+
+
+/* Read the contents of the section at OFFSET and of size SIZE from the
+   object file specified by OBJFILE into the psymbol_obstack and return it.  */
 
 static char *
-dwarf2_read_section (abfd, offset, size)
-     bfd * abfd;
-     file_ptr offset;
-     unsigned int size;
+dwarf2_read_section (struct objfile *objfile, file_ptr offset,
+                    unsigned int size)
 {
+  bfd *abfd = objfile->obfd;
   char *buf;
 
-  buf = xmalloc (size);
+  if (size == 0)
+    return NULL;
+
+  buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
   if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
-      (bfd_read (buf, size, 1, abfd) != size))
+      (bfd_bread (buf, size, abfd) != size))
     {
-      free (buf);
       buf = NULL;
       error ("Dwarf Error: Can't read DWARF data from '%s'",
-        bfd_get_filename (abfd));
+            bfd_get_filename (abfd));
     }
   return buf;
 }
@@ -2014,9 +3042,7 @@ dwarf2_read_section (abfd, offset, size)
    in a hash table.  */
 
 static void
-dwarf2_read_abbrevs (abfd, offset)
-     bfd * abfd;
-     unsigned int offset;
+dwarf2_read_abbrevs (bfd *abfd, unsigned int offset)
 {
   char *abbrev_ptr;
   struct abbrev_info *cur_abbrev;
@@ -2024,7 +3050,7 @@ dwarf2_read_abbrevs (abfd, offset)
   unsigned int abbrev_form, hash_number;
 
   /* empty the table */
-  dwarf2_empty_abbrev_table ();
+  dwarf2_empty_abbrev_table (NULL);
 
   abbrev_ptr = dwarf_abbrev_buffer + offset;
   abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
@@ -2051,9 +3077,10 @@ dwarf2_read_abbrevs (abfd, offset)
        {
          if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0)
            {
-             cur_abbrev->attrs = xrealloc (cur_abbrev->attrs,
-                           (cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK)
-                                      * sizeof (struct attr_abbrev));
+             cur_abbrev->attrs = (struct attr_abbrev *)
+               xrealloc (cur_abbrev->attrs,
+                         (cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK)
+                         * sizeof (struct attr_abbrev));
            }
          cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name;
          cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form;
@@ -2067,16 +3094,28 @@ dwarf2_read_abbrevs (abfd, offset)
       cur_abbrev->next = dwarf2_abbrevs[hash_number];
       dwarf2_abbrevs[hash_number] = cur_abbrev;
 
-      /* get next abbrev */
+      /* Get next abbreviation.
+         Under Irix6 the abbreviations for a compilation unit are not
+         always properly terminated with an abbrev number of 0.
+         Exit loop if we encounter an abbreviation which we have
+         already read (which means we are about to read the abbreviations
+         for the next compile unit) or if the end of the abbreviation
+         table is reached.  */
+      if ((unsigned int) (abbrev_ptr - dwarf_abbrev_buffer)
+         >= dwarf_abbrev_size)
+       break;
       abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
       abbrev_ptr += bytes_read;
+      if (dwarf2_lookup_abbrev (abbrev_number) != NULL)
+       break;
     }
 }
 
 /* Empty the abbrev table for a new compilation unit.  */
 
+/* ARGSUSED */
 static void
-dwarf2_empty_abbrev_table ()
+dwarf2_empty_abbrev_table (PTR ignore)
 {
   int i;
   struct abbrev_info *abbrev, *next;
@@ -2088,8 +3127,8 @@ dwarf2_empty_abbrev_table ()
       while (abbrev)
        {
          next = abbrev->next;
-         free (abbrev->attrs);
-         free (abbrev);
+         xfree (abbrev->attrs);
+         xfree (abbrev);
          abbrev = next;
        }
       dwarf2_abbrevs[i] = NULL;
@@ -2099,8 +3138,7 @@ dwarf2_empty_abbrev_table ()
 /* Lookup an abbrev_info structure in the abbrev hash table.  */
 
 static struct abbrev_info *
-dwarf2_lookup_abbrev (number)
-     unsigned int number;
+dwarf2_lookup_abbrev (unsigned int number)
 {
   unsigned int hash_number;
   struct abbrev_info *abbrev;
@@ -2121,28 +3159,22 @@ dwarf2_lookup_abbrev (number)
 /* Read a minimal amount of information into the minimal die structure.  */
 
 static char *
-read_partial_die (part_die, abfd, info_ptr, has_pc_info)
-     struct partial_die_info *part_die;
-     bfd * abfd;
-     char *info_ptr;
-     int *has_pc_info;
+read_partial_die (struct partial_die_info *part_die, bfd *abfd,
+                 char *info_ptr, const struct comp_unit_head *cu_header)
 {
   unsigned int abbrev_number, bytes_read, i;
   struct abbrev_info *abbrev;
-  char ebuf[256];
-  int has_low_pc_attr  = 0;
+  struct attribute attr;
+  struct attribute spec_attr;
+  int found_spec_attr = 0;
+  int has_low_pc_attr = 0;
   int has_high_pc_attr = 0;
 
-  *has_pc_info = 0;
+  *part_die = zeroed_partial_die;
   abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
   info_ptr += bytes_read;
   if (!abbrev_number)
-    {
-      part_die->tag = 0;
-      part_die->has_children = 0;
-      part_die->abbrev = abbrev_number;
-      return info_ptr;
-    }
+    return info_ptr;
 
   abbrev = dwarf2_lookup_abbrev (abbrev_number);
   if (!abbrev)
@@ -2152,140 +3184,102 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info)
   part_die->offset = info_ptr - dwarf_info_buffer;
   part_die->tag = abbrev->tag;
   part_die->has_children = abbrev->has_children;
-  part_die->is_external = 0;
   part_die->abbrev = abbrev_number;
 
-  {
-    char *str = "";
-    struct dwarf_block *blk = 0;
-    CORE_ADDR addr = ((CORE_ADDR) -1);
-    unsigned int unsnd = ((unsigned int) -1);
-    int snd = -1;
+  for (i = 0; i < abbrev->num_attrs; ++i)
+    {
+      info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd,
+                                info_ptr, cu_header);
 
-    for (i = 0; i < abbrev->num_attrs; ++i)
-      {
-       /* read the correct type of data */
-       switch (abbrev->attrs[i].form)
-         {
-         case DW_FORM_addr:
-           addr = read_address (abfd, info_ptr);
-           info_ptr += address_size;
-           break;
-         case DW_FORM_ref_addr:
-           addr = read_address (abfd, info_ptr);
-           info_ptr += address_size;
-           break;
-         case DW_FORM_block2:
-           blk = dwarf_alloc_block ();
-           blk->size = read_2_bytes (abfd, info_ptr);
-           info_ptr += 2;
-           blk->data = read_n_bytes (abfd, info_ptr, blk->size);
-           info_ptr += blk->size;
-           break;
-         case DW_FORM_block4:
-           blk = dwarf_alloc_block ();
-           blk->size = read_4_bytes (abfd, info_ptr);
-           info_ptr += 2;
-           blk->data = read_n_bytes (abfd, info_ptr, blk->size);
-           info_ptr += blk->size;
-           break;
-         case DW_FORM_data2:
-           unsnd = read_2_bytes (abfd, info_ptr);
-           info_ptr += 2;
-           break;
-         case DW_FORM_data4:
-           unsnd = read_4_bytes (abfd, info_ptr);
-           info_ptr += 4;
-           break;
-         case DW_FORM_data8:
-           unsnd = read_8_bytes (abfd, info_ptr);
-           info_ptr += 8;
-           break;
-         case DW_FORM_string:
-           str = read_string (abfd, info_ptr, &bytes_read);
-           info_ptr += bytes_read;
-           break;
-         case DW_FORM_block:
-           blk = dwarf_alloc_block ();
-           blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
-           info_ptr += bytes_read;
-           blk->data = read_n_bytes (abfd, info_ptr, blk->size);
-           info_ptr += blk->size;
-           break;
-         case DW_FORM_block1:
-           blk = dwarf_alloc_block ();
-           blk->size = read_1_byte (abfd, info_ptr);
-           info_ptr += 1;
-           blk->data = read_n_bytes (abfd, info_ptr, blk->size);
-           info_ptr += blk->size;
-           break;
-         case DW_FORM_data1:
-           unsnd = read_1_byte (abfd, info_ptr);
-           info_ptr += 1;
-           break;
-         case DW_FORM_ref1:
-           unsnd = read_1_byte (abfd, info_ptr);
-           info_ptr += 1;
-           break;
-         case DW_FORM_ref2:
-           unsnd = read_2_bytes (abfd, info_ptr);
-           info_ptr += 2;
-           break;
-         case DW_FORM_ref4:
-           unsnd = read_4_bytes (abfd, info_ptr);
-           info_ptr += 4;
-           break;
-         case DW_FORM_ref_udata:
-           unsnd = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
-           info_ptr += bytes_read;
-           break;
-         case DW_FORM_flag:
-           unsnd = read_1_byte (abfd, info_ptr);
-           info_ptr += 1;
-           break;
-         case DW_FORM_sdata:
-           snd = read_signed_leb128 (abfd, info_ptr, &bytes_read);
-           info_ptr += bytes_read;
-           break;
-         case DW_FORM_udata:
-           unsnd = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
-           info_ptr += bytes_read;
-           break;
-         case DW_FORM_indirect:
-         default:
-           sprintf (ebuf,
-                    "Dwarf Error: Cannot handle %s in DWARF reader.",
-                    dwarf_form_name (abbrev->attrs[i].form));
-           error (ebuf);
-         }
+      /* Store the data if it is of an attribute we want to keep in a
+         partial symbol table.  */
+      switch (attr.name)
+       {
+       case DW_AT_name:
 
-       /* store the data if it is of an attribute we want to keep in a
-          partial symbol table */
-       switch (abbrev->attrs[i].name)
-         {
-         case DW_AT_name:
-           part_die->name = str;
-           break;
-         case DW_AT_low_pc:
-           has_low_pc_attr = 1;
-           part_die->lowpc = addr;
-           break;
-         case DW_AT_high_pc:
-           has_high_pc_attr = 1;
-           part_die->highpc = addr;
-           break;
-         case DW_AT_location:
-           part_die->locdesc = blk;
-           break;
-         case DW_AT_language:
-           part_die->language = unsnd;
-           break;
-         case DW_AT_external:
-           part_die->is_external = unsnd;
-         }
-      }
-  }
-  *has_pc_info = has_low_pc_attr && has_high_pc_attr;
+         /* Prefer DW_AT_MIPS_linkage_name over DW_AT_name.  */
+         if (part_die->name == NULL)
+           part_die->name = DW_STRING (&attr);
+         break;
+       case DW_AT_MIPS_linkage_name:
+         part_die->name = DW_STRING (&attr);
+         break;
+       case DW_AT_low_pc:
+         has_low_pc_attr = 1;
+         part_die->lowpc = DW_ADDR (&attr);
+         break;
+       case DW_AT_high_pc:
+         has_high_pc_attr = 1;
+         part_die->highpc = DW_ADDR (&attr);
+         break;
+       case DW_AT_location:
+         part_die->locdesc = DW_BLOCK (&attr);
+         break;
+       case DW_AT_language:
+         part_die->language = DW_UNSND (&attr);
+         break;
+       case DW_AT_external:
+         part_die->is_external = DW_UNSND (&attr);
+         break;
+       case DW_AT_declaration:
+         part_die->is_declaration = DW_UNSND (&attr);
+         break;
+       case DW_AT_type:
+         part_die->has_type = 1;
+         break;
+       case DW_AT_abstract_origin:
+       case DW_AT_specification:
+         found_spec_attr = 1;
+         spec_attr = attr;
+         break;
+       case DW_AT_sibling:
+         /* Ignore absolute siblings, they might point outside of
+            the current compile unit.  */
+         if (attr.form == DW_FORM_ref_addr)
+           complain (&dwarf2_absolute_sibling_complaint);
+         else
+           part_die->sibling =
+             dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr);
+         break;
+       default:
+         break;
+       }
+    }
+
+  /* If we found a reference attribute and the die has no name, try
+     to find a name in the referred to die.  */
+
+  if (found_spec_attr && part_die->name == NULL)
+    {
+      struct partial_die_info spec_die;
+      char *spec_ptr;
+      int dummy;
+
+      spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr);
+      read_partial_die (&spec_die, abfd, spec_ptr, cu_header);
+      if (spec_die.name)
+       {
+         part_die->name = spec_die.name;
+
+         /* Copy DW_AT_external attribute if it is set.  */
+         if (spec_die.is_external)
+           part_die->is_external = spec_die.is_external;
+       }
+    }
+
+  /* When using the GNU linker, .gnu.linkonce. sections are used to
+     eliminate duplicate copies of functions and vtables and such.
+     The linker will arbitrarily choose one and discard the others.
+     The AT_*_pc values for such functions refer to local labels in
+     these sections.  If the section from that file was discarded, the
+     labels are not in the output, so the relocs get a value of 0.
+     If this is a discarded function, mark the pc bounds as invalid,
+     so that GDB will ignore it.  */
+  if (has_low_pc_attr && has_high_pc_attr
+      && part_die->lowpc < part_die->highpc
+      && (part_die->lowpc != 0
+         || (bfd_get_file_flags (abfd) & HAS_RELOC)))
+    part_die->has_pc_info = 1;
   return info_ptr;
 }
 
@@ -2293,15 +3287,12 @@ read_partial_die (part_die, abfd, info_ptr, has_pc_info)
    point to a newly allocated die with its information.  */
 
 static char *
-read_full_die (diep, abfd, info_ptr)
-     struct die_info **diep;
-     bfd *abfd;
-     char *info_ptr;
+read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
+              const struct comp_unit_head *cu_header)
 {
   unsigned int abbrev_number, bytes_read, i, offset;
   struct abbrev_info *abbrev;
   struct die_info *die;
-  char ebuf[256];
 
   offset = info_ptr - dwarf_info_buffer;
   abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
@@ -2321,242 +3312,376 @@ read_full_die (diep, abfd, info_ptr)
     {
       error ("Dwarf Error: could not find abbrev number %d.", abbrev_number);
     }
-  die = dwarf_alloc_die ();
-  die->offset = offset;
-  die->tag = abbrev->tag;
-  die->has_children = abbrev->has_children;
-  die->abbrev = abbrev_number;
-  die->type = NULL;
-
-  die->num_attrs = abbrev->num_attrs;
-  die->attrs = xmalloc (die->num_attrs * sizeof (struct attribute));
-
-  {
-    char *str;
-    struct dwarf_block *blk;
-    unsigned long addr;
-    unsigned int unsnd;
-    int snd;
-
-    for (i = 0; i < abbrev->num_attrs; ++i)
-      {
-       /* read the correct type of data */
-
-       die->attrs[i].name = abbrev->attrs[i].name;
-       die->attrs[i].form = abbrev->attrs[i].form;
-
-       switch (abbrev->attrs[i].form)
-         {
-         case DW_FORM_addr:
-         case DW_FORM_ref_addr:
-           die->attrs[i].u.addr = read_address (abfd, info_ptr);
-           info_ptr += address_size;
-           break;
-         case DW_FORM_block2:
-           blk = dwarf_alloc_block ();
-           blk->size = read_2_bytes (abfd, info_ptr);
-           info_ptr += 2;
-           blk->data = read_n_bytes (abfd, info_ptr, blk->size);
-           info_ptr += blk->size;
-           die->attrs[i].u.blk = blk;
-           break;
-         case DW_FORM_block4:
-           blk = dwarf_alloc_block ();
-           blk->size = read_4_bytes (abfd, info_ptr);
-           info_ptr += 2;
-           blk->data = read_n_bytes (abfd, info_ptr, blk->size);
-           info_ptr += blk->size;
-           die->attrs[i].u.blk = blk;
-           break;
-         case DW_FORM_data2:
-           die->attrs[i].u.unsnd = read_2_bytes (abfd, info_ptr);
-           info_ptr += 2;
-           break;
-         case DW_FORM_data4:
-           die->attrs[i].u.unsnd = read_4_bytes (abfd, info_ptr);
-           info_ptr += 4;
-           break;
-         case DW_FORM_data8:
-           die->attrs[i].u.unsnd = read_8_bytes (abfd, info_ptr);
-           info_ptr += 8;
-           break;
-         case DW_FORM_string:
-           die->attrs[i].u.str = read_string (abfd, info_ptr, &bytes_read);
-           info_ptr += bytes_read;
-           break;
-         case DW_FORM_block:
-           blk = dwarf_alloc_block ();
-           blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
-           info_ptr += bytes_read;
-           blk->data = read_n_bytes (abfd, info_ptr, blk->size);
-           info_ptr += blk->size;
-           die->attrs[i].u.blk = blk;
-           break;
-         case DW_FORM_block1:
-           blk = dwarf_alloc_block ();
-           blk->size = read_1_byte (abfd, info_ptr);
-           info_ptr += 1;
-           blk->data = read_n_bytes (abfd, info_ptr, blk->size);
-           info_ptr += blk->size;
-           die->attrs[i].u.blk = blk;
-           break;
-         case DW_FORM_data1:
-           die->attrs[i].u.unsnd = read_1_byte (abfd, info_ptr);
-           info_ptr += 1;
-           break;
-         case DW_FORM_ref1:
-           die->attrs[i].u.unsnd = read_1_byte (abfd, info_ptr);
-           info_ptr += 1;
-           break;
-         case DW_FORM_ref2:
-           die->attrs[i].u.unsnd = read_2_bytes (abfd, info_ptr);
-           info_ptr += 2;
-           break;
-         case DW_FORM_ref4:
-           die->attrs[i].u.unsnd = read_4_bytes (abfd, info_ptr);
-           info_ptr += 4;
-           break;
-         case DW_FORM_ref_udata:
-           die->attrs[i].u.unsnd = read_unsigned_leb128 (abfd,
-                                                         info_ptr,
-                                                         &bytes_read);
-           info_ptr += bytes_read;
-           break;
-         case DW_FORM_flag:
-           die->attrs[i].u.unsnd = read_1_byte (abfd, info_ptr);
-           info_ptr += 1;
-           break;
-         case DW_FORM_sdata:
-           die->attrs[i].u.snd = read_signed_leb128 (abfd,
-                                                     info_ptr,
-                                                     &bytes_read);
-           info_ptr += bytes_read;
-           break;
-         case DW_FORM_udata:
-           die->attrs[i].u.unsnd = read_unsigned_leb128 (abfd,
-                                                         info_ptr,
-                                                         &bytes_read);
-           info_ptr += bytes_read;
-           break;
-         case DW_FORM_indirect:
-         default:
-           sprintf (ebuf,
-                    "Dwarf Error: Cannot handle %s in DWARF reader.",
-                    dwarf_form_name (abbrev->attrs[i].form));
-           error (ebuf);
-         }
-
-      }
-  }
-  *diep = die;
+  die = dwarf_alloc_die ();
+  die->offset = offset;
+  die->tag = abbrev->tag;
+  die->has_children = abbrev->has_children;
+  die->abbrev = abbrev_number;
+  die->type = NULL;
+
+  die->num_attrs = abbrev->num_attrs;
+  die->attrs = (struct attribute *)
+    xmalloc (die->num_attrs * sizeof (struct attribute));
+
+  for (i = 0; i < abbrev->num_attrs; ++i)
+    {
+      info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
+                                abfd, info_ptr, cu_header);
+    }
+
+  *diep = die;
+  return info_ptr;
+}
+
+/* Read an attribute described by an abbreviated attribute.  */
+
+static char *
+read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
+               bfd *abfd, char *info_ptr,
+               const struct comp_unit_head *cu_header)
+{
+  unsigned int bytes_read;
+  struct dwarf_block *blk;
+
+  attr->name = abbrev->name;
+  attr->form = abbrev->form;
+  switch (abbrev->form)
+    {
+    case DW_FORM_addr:
+    case DW_FORM_ref_addr:
+      DW_ADDR (attr) = read_address (abfd, info_ptr, cu_header, &bytes_read);
+      info_ptr += bytes_read;
+      break;
+    case DW_FORM_block2:
+      blk = dwarf_alloc_block ();
+      blk->size = read_2_bytes (abfd, info_ptr);
+      info_ptr += 2;
+      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+      info_ptr += blk->size;
+      DW_BLOCK (attr) = blk;
+      break;
+    case DW_FORM_block4:
+      blk = dwarf_alloc_block ();
+      blk->size = read_4_bytes (abfd, info_ptr);
+      info_ptr += 4;
+      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+      info_ptr += blk->size;
+      DW_BLOCK (attr) = blk;
+      break;
+    case DW_FORM_data2:
+      DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
+      info_ptr += 2;
+      break;
+    case DW_FORM_data4:
+      DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
+      info_ptr += 4;
+      break;
+    case DW_FORM_data8:
+      DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
+      info_ptr += 8;
+      break;
+    case DW_FORM_string:
+      DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read);
+      info_ptr += bytes_read;
+      break;
+    case DW_FORM_block:
+      blk = dwarf_alloc_block ();
+      blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+      info_ptr += bytes_read;
+      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+      info_ptr += blk->size;
+      DW_BLOCK (attr) = blk;
+      break;
+    case DW_FORM_block1:
+      blk = dwarf_alloc_block ();
+      blk->size = read_1_byte (abfd, info_ptr);
+      info_ptr += 1;
+      blk->data = read_n_bytes (abfd, info_ptr, blk->size);
+      info_ptr += blk->size;
+      DW_BLOCK (attr) = blk;
+      break;
+    case DW_FORM_data1:
+      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
+      info_ptr += 1;
+      break;
+    case DW_FORM_flag:
+      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
+      info_ptr += 1;
+      break;
+    case DW_FORM_sdata:
+      DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read);
+      info_ptr += bytes_read;
+      break;
+    case DW_FORM_udata:
+      DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+      info_ptr += bytes_read;
+      break;
+    case DW_FORM_ref1:
+      DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
+      info_ptr += 1;
+      break;
+    case DW_FORM_ref2:
+      DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
+      info_ptr += 2;
+      break;
+    case DW_FORM_ref4:
+      DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
+      info_ptr += 4;
+      break;
+    case DW_FORM_ref8:
+      DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
+      info_ptr += 8;
+      break;
+    case DW_FORM_ref_udata:
+      DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+      info_ptr += bytes_read;
+      break;
+    case DW_FORM_strp:
+    case DW_FORM_indirect:
+    default:
+      error ("Dwarf Error: Cannot handle %s in DWARF reader.",
+            dwarf_form_name (abbrev->form));
+    }
   return info_ptr;
 }
 
 /* read dwarf information from a buffer */
 
 static unsigned int
-read_1_byte (abfd, buf)
-     bfd *abfd;
-     char *buf;
+read_1_byte (bfd *abfd, char *buf)
 {
   return bfd_get_8 (abfd, (bfd_byte *) buf);
 }
 
+static int
+read_1_signed_byte (bfd *abfd, char *buf)
+{
+  return bfd_get_signed_8 (abfd, (bfd_byte *) buf);
+}
+
 static unsigned int
-read_2_bytes (abfd, buf)
-     bfd *abfd;
-     char *buf;
+read_2_bytes (bfd *abfd, char *buf)
 {
   return bfd_get_16 (abfd, (bfd_byte *) buf);
 }
 
+static int
+read_2_signed_bytes (bfd *abfd, char *buf)
+{
+  return bfd_get_signed_16 (abfd, (bfd_byte *) buf);
+}
+
 static unsigned int
-read_4_bytes (abfd, buf)
-     bfd *abfd;
-     char *buf;
+read_4_bytes (bfd *abfd, char *buf)
 {
   return bfd_get_32 (abfd, (bfd_byte *) buf);
 }
 
-static unsigned int
-read_8_bytes (abfd, buf)
-     bfd *abfd;
-     char *buf;
+static int
+read_4_signed_bytes (bfd *abfd, char *buf)
+{
+  return bfd_get_signed_32 (abfd, (bfd_byte *) buf);
+}
+
+static unsigned long
+read_8_bytes (bfd *abfd, char *buf)
 {
   return bfd_get_64 (abfd, (bfd_byte *) buf);
 }
 
 static CORE_ADDR
-read_address (abfd, buf)
-     bfd *abfd;
-     char *buf;
+read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
+             int *bytes_read)
 {
   CORE_ADDR retval = 0;
 
-  if (address_size == 4)
+  if (cu_header->signed_addr_p)
+    {
+      switch (cu_header->addr_size)
+       {
+       case 2:
+         retval = bfd_get_signed_16 (abfd, (bfd_byte *) buf);
+         break;
+       case 4:
+         retval = bfd_get_signed_32 (abfd, (bfd_byte *) buf);
+         break;
+       case 8:
+         retval = bfd_get_signed_64 (abfd, (bfd_byte *) buf);
+         break;
+       default:
+         internal_error (__FILE__, __LINE__,
+                         "read_address: bad switch, signed");
+       }
+    }
+  else
+    {
+      switch (cu_header->addr_size)
+       {
+       case 2:
+         retval = bfd_get_16 (abfd, (bfd_byte *) buf);
+         break;
+       case 4:
+         retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+         break;
+       case 8:
+         retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+         break;
+       default:
+         internal_error (__FILE__, __LINE__,
+                         "read_address: bad switch, unsigned");
+       }
+    }
+
+  *bytes_read = cu_header->addr_size;
+  return retval;
+}
+
+/* Reads the initial length from a section.  The (draft) DWARF 2.1
+   specification allows the initial length to take up either 4 bytes
+   or 12 bytes.  If the first 4 bytes are 0xffffffff, then the next 8
+   bytes describe the length and all offsets will be 8 bytes in length
+   instead of 4.
+
+   The value returned via bytes_read should be used to increment
+   the relevant pointer after calling read_initial_length().
+   
+   As a side effect, this function sets the fields initial_length_size
+   and offset_size in cu_header to the values appropriate for the
+   length field.  (The format of the initial length field determines
+   the width of file offsets to be fetched later with fetch_offset().)
+   
+   [ Note:  read_initial_length() and read_offset() are based on the
+     document entitled "DWARF Debugging Information Format", revision
+     2.1, draft 4, dated July 20, 2000.  This document was obtained
+     from:
+
+       http://reality.sgi.com/dehnert_engr/dwarf/dwarf2p1-draft4-000720.pdf
+     
+     This document is only a draft and is subject to change.  (So beware.)
+
+     - Kevin, Aug 4, 2000
+   ] */
+
+static LONGEST
+read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header,
+                     int *bytes_read)
+{
+  LONGEST retval = 0;
+
+  retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+
+  if (retval == 0xffffffff)
+    {
+      retval = bfd_get_64 (abfd, (bfd_byte *) buf + 4);
+      *bytes_read = 12;
+      if (cu_header != NULL)
+       {
+         cu_header->initial_length_size = 12;
+         cu_header->offset_size = 8;
+       }
+    }
+  else
+    {
+      *bytes_read = 4;
+      if (cu_header != NULL)
+       {
+         cu_header->initial_length_size = 4;
+         cu_header->offset_size = 4;
+       }
+    }
+
+ return retval;
+}
+
+/* Read an offset from the data stream.  The size of the offset is
+   given by cu_header->offset_size. */
+
+static LONGEST
+read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
+             int *bytes_read)
+{
+  LONGEST retval = 0;
+
+  switch (cu_header->offset_size)
     {
+    case 4:
       retval = bfd_get_32 (abfd, (bfd_byte *) buf);
-    } else {                   /* *THE* alternative is 8, right? */
+      *bytes_read = 4;
+      break;
+    case 8:
       retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+      *bytes_read = 8;
+      break;
+    default:
+      internal_error (__FILE__, __LINE__,
+                     "read_offset: bad switch");
     }
-  return retval;
+
+ return retval;
 }
 
 static char *
-read_n_bytes (abfd, buf, size)
-     bfd * abfd;
-     char *buf;
-     unsigned int size;
+read_n_bytes (bfd *abfd, char *buf, unsigned int size)
 {
+  /* If the size of a host char is 8 bits, we can return a pointer
+     to the buffer, otherwise we have to copy the data to a buffer
+     allocated on the temporary obstack.  */
+#if HOST_CHAR_BIT == 8
+  return buf;
+#else
   char *ret;
   unsigned int i;
 
-  ret = xmalloc (size);
+  ret = obstack_alloc (&dwarf2_tmp_obstack, size);
   for (i = 0; i < size; ++i)
     {
       ret[i] = bfd_get_8 (abfd, (bfd_byte *) buf);
       buf++;
     }
   return ret;
+#endif
 }
 
-/* FIXME : hardwired string size limit */
-
 static char *
-read_string (abfd, buf, bytes_read_ptr)
-     bfd *abfd;
-     char *buf;
-     unsigned int *bytes_read_ptr;
+read_string (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
 {
-  char ret_buf[DWARF2_MAX_STRING_SIZE], *ret, byte;
-  unsigned int i;
+  /* If the size of a host char is 8 bits, we can return a pointer
+     to the string, otherwise we have to copy the string to a buffer
+     allocated on the temporary obstack.  */
+#if HOST_CHAR_BIT == 8
+  if (*buf == '\0')
+    {
+      *bytes_read_ptr = 1;
+      return NULL;
+    }
+  *bytes_read_ptr = strlen (buf) + 1;
+  return buf;
+#else
+  int byte;
+  unsigned int i = 0;
 
-  i = 0;
-  do
+  while ((byte = bfd_get_8 (abfd, (bfd_byte *) buf)) != 0)
     {
-      byte = bfd_get_8 (abfd, (bfd_byte *) buf);
+      obstack_1grow (&dwarf2_tmp_obstack, byte);
+      i++;
       buf++;
-      ret_buf[i++] = byte;
     }
-  while (byte);
-  if (i == 1)
+  if (i == 0)
     {
       *bytes_read_ptr = 1;
       return NULL;
     }
-  ret = xmalloc (i);
-  strncpy (ret, ret_buf, i);
-  *bytes_read_ptr = i;
-  return ret;
+  obstack_1grow (&dwarf2_tmp_obstack, '\0');
+  *bytes_read_ptr = i + 1;
+  return obstack_finish (&dwarf2_tmp_obstack);
+#endif
 }
 
-static unsigned int
-read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
-     bfd *abfd;
-     char *buf;
-     unsigned int *bytes_read_ptr;
+static unsigned long
+read_unsigned_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
 {
-  unsigned int result, num_read;
+  unsigned long result;
+  unsigned int num_read;
   int i, shift;
   unsigned char byte;
 
@@ -2569,7 +3694,7 @@ read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
       byte = bfd_get_8 (abfd, (bfd_byte *) buf);
       buf++;
       num_read++;
-      result |= ((byte & 127) << shift);
+      result |= ((unsigned long)(byte & 127) << shift);
       if ((byte & 128) == 0)
        {
          break;
@@ -2580,13 +3705,10 @@ read_unsigned_leb128 (abfd, buf, bytes_read_ptr)
   return result;
 }
 
-static int
-read_signed_leb128 (abfd, buf, bytes_read_ptr)
-     bfd *abfd;
-     char *buf;
-     unsigned int *bytes_read_ptr;
+static long
+read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
 {
-  int result;
+  long result;
   int i, shift, size, num_read;
   unsigned char byte;
 
@@ -2600,7 +3722,7 @@ read_signed_leb128 (abfd, buf, bytes_read_ptr)
       byte = bfd_get_8 (abfd, (bfd_byte *) buf);
       buf++;
       num_read++;
-      result |= ((byte & 127) << shift);
+      result |= ((long)(byte & 127) << shift);
       shift += 7;
       if ((byte & 128) == 0)
        {
@@ -2616,26 +3738,30 @@ read_signed_leb128 (abfd, buf, bytes_read_ptr)
 }
 
 static void
-set_cu_language (lang)
-     unsigned int lang;
+set_cu_language (unsigned int lang)
 {
   switch (lang)
     {
     case DW_LANG_C89:
     case DW_LANG_C:
-    case DW_LANG_Fortran77:
       cu_language = language_c;
       break;
     case DW_LANG_C_plus_plus:
       cu_language = language_cplus;
       break;
+    case DW_LANG_Fortran77:
+    case DW_LANG_Fortran90:
+      cu_language = language_fortran;
+      break;
+    case DW_LANG_Mips_Assembler:
+      cu_language = language_asm;
+      break;
+    case DW_LANG_Java:
+      cu_language = language_java;
+      break;
     case DW_LANG_Ada83:
     case DW_LANG_Cobol74:
     case DW_LANG_Cobol85:
-#if 0
-    case DW_LANG_Fortran77:    /* moved up top for now */
-#endif
-    case DW_LANG_Fortran90:
     case DW_LANG_Pascal83:
     case DW_LANG_Modula2:
     default:
@@ -2645,33 +3771,10 @@ set_cu_language (lang)
   cu_language_defn = language_def (cu_language);
 }
 
-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, objfile);
-}
-
-/* Converts a location description into gdb form.  */
-
-static int
-convert_locdesc (blk)
-     struct dwarf_block *blk;
-{
-  /* FIXME : this is only a stub! */
-  return 0;
-}
-
 /* Return the named attribute or NULL if not there.  */
 
 static struct attribute *
-dwarf_attr (die, name)
-     struct die_info *die;
-     unsigned int name;
+dwarf_attr (struct die_info *die, unsigned int name)
 {
   unsigned int i;
   struct attribute *spec = NULL;
@@ -2687,39 +3790,53 @@ dwarf_attr (die, name)
        spec = &die->attrs[i];
     }
   if (spec)
-    return dwarf_attr (follow_die_ref (DW_UNSND (spec)), name);
-    
+    {
+      struct die_info *ref_die =
+      follow_die_ref (dwarf2_get_ref_die_offset (spec));
+
+      if (ref_die)
+       return dwarf_attr (ref_die, name);
+    }
+
   return NULL;
 }
 
+static int
+die_is_declaration (struct die_info *die)
+{
+  return (dwarf_attr (die, DW_AT_declaration)
+         && ! dwarf_attr (die, DW_AT_specification));
+}
+
 /* Decode the line number information for the compilation unit whose
-   line number info is at OFFSET in the .debug_line section.  */
+   line number info is at OFFSET in the .debug_line section.
+   The compilation directory of the file is passed in COMP_DIR.  */
 
 struct filenames
 {
-  int num_files;
+  unsigned int num_files;
   struct fileinfo
-  {
-    char *name;
-    unsigned int dir;
-    unsigned int time;
-    unsigned int size;
-  }
-  *files;
+    {
+      char *name;
+      unsigned int dir;
+      unsigned int time;
+      unsigned int size;
+    }
+   *files;
 };
 
 struct directories
-{
-  int num_dirs;
-  char **dirs;
-};
+  {
+    unsigned int num_dirs;
+    char **dirs;
+  };
 
 static void
-dwarf_decode_lines (offset, abfd)
-     unsigned int offset;
-     bfd *abfd;
+dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
+                   const struct comp_unit_head *cu_header)
 {
   char *line_ptr;
+  char *line_end;
   struct line_head lh;
   struct cleanup *back_to;
   unsigned int i, bytes_read;
@@ -2732,15 +3849,11 @@ dwarf_decode_lines (offset, abfd)
   struct filenames files;
   struct directories dirs;
 
-  /* state machine registers  */
-  unsigned int address = 0;
-  unsigned int file = 1;
-  unsigned int line = 1;
-  unsigned int column = 0;
-  int is_stmt;                 /* initialized below */
-  int basic_block = 0;
-  int beg_of_comp_unit = 0;    /* is this right? */
-  int end_sequence = 0;
+  if (dwarf_line_buffer == NULL)
+    {
+      complain (&dwarf2_missing_line_number_section);
+      return;
+    }
 
   files.num_files = 0;
   files.files = NULL;
@@ -2751,18 +3864,18 @@ dwarf_decode_lines (offset, abfd)
   line_ptr = dwarf_line_buffer + offset;
 
   /* read in the prologue */
-  lh.total_length = read_4_bytes (abfd, line_ptr);
-  line_ptr += 4;
+  lh.total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
+  line_ptr += bytes_read;
+  line_end = line_ptr + lh.total_length;
   lh.version = read_2_bytes (abfd, line_ptr);
   line_ptr += 2;
-  lh.prologue_length = read_4_bytes (abfd, line_ptr);
-  line_ptr += 4;
+  lh.prologue_length = read_offset (abfd, line_ptr, cu_header, &bytes_read);
+  line_ptr += bytes_read;
   lh.minimum_instruction_length = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
   lh.default_is_stmt = read_1_byte (abfd, line_ptr);
-  is_stmt = lh.default_is_stmt;
   line_ptr += 1;
-  lh.line_base = read_1_byte (abfd, line_ptr);
+  lh.line_base = read_1_signed_byte (abfd, line_ptr);
   line_ptr += 1;
   lh.line_range = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
@@ -2770,7 +3883,7 @@ dwarf_decode_lines (offset, abfd)
   line_ptr += 1;
   lh.standard_opcode_lengths = (unsigned char *)
     xmalloc (lh.opcode_base * sizeof (unsigned char));
-  back_to = make_cleanup (freelh.standard_opcode_lengths);
+  back_to = make_cleanup (free_current_contents, &lh.standard_opcode_lengths);
 
   lh.standard_opcode_lengths[0] = 1;
   for (i = 1; i < lh.opcode_base; ++i)
@@ -2780,175 +3893,273 @@ dwarf_decode_lines (offset, abfd)
     }
 
   /* Read directory table  */
-  while (cur_dir = read_string (abfd, line_ptr, &bytes_read))
+  while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
     {
       line_ptr += bytes_read;
       if ((dirs.num_dirs % DIR_ALLOC_CHUNK) == 0)
        {
-         dirs.dirs = xrealloc (dirs.dirs,
-           (dirs.num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *));
+         dirs.dirs = (char **)
+           xrealloc (dirs.dirs,
+                     (dirs.num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *));
+         if (dirs.num_dirs == 0)
+           make_cleanup (free_current_contents, &dirs.dirs);
        }
       dirs.dirs[dirs.num_dirs++] = cur_dir;
     }
   line_ptr += bytes_read;
 
   /* Read file name table */
-  while (cur_file = read_string (abfd, line_ptr, &bytes_read))
+  while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
     {
       line_ptr += bytes_read;
       if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
        {
-         files.files = xrealloc (files.files,
-           (files.num_files + FILE_ALLOC_CHUNK) * sizeof (struct fileinfo));
+         files.files = (struct fileinfo *)
+           xrealloc (files.files,
+                     (files.num_files + FILE_ALLOC_CHUNK)
+                     * sizeof (struct fileinfo));
+         if (files.num_files == 0)
+           make_cleanup (free_current_contents, &files.files);
        }
       files.files[files.num_files].name = cur_file;
-      files.files[files.num_files].dir = read_unsigned_leb128 (abfd,
-                                          line_ptr, &bytes_read);
+      files.files[files.num_files].dir =
+       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
       line_ptr += bytes_read;
-      files.files[files.num_files].time = read_unsigned_leb128 (abfd,
-                                          line_ptr, &bytes_read);
+      files.files[files.num_files].time =
+       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
       line_ptr += bytes_read;
-      files.files[files.num_files].size = read_unsigned_leb128 (abfd,
-                                          line_ptr, &bytes_read);
+      files.files[files.num_files].size =
+       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
       line_ptr += bytes_read;
       files.num_files++;
     }
   line_ptr += bytes_read;
 
-  /* Decode the table. */
-  if (lh.total_length - (lh.prologue_length + 4 + 2) >= 4)
-    do
-      {
-       op_code = read_1_byte (abfd, line_ptr);
-       line_ptr += 1;
-       switch (op_code)
-         {
-         case DW_LNS_extended_op:
-           line_ptr += 1;      /* ignore length */
-           extended_op = read_1_byte (abfd, line_ptr);
-           line_ptr += 1;
-           switch (extended_op)
-             {
-             case DW_LNE_end_sequence:
-               end_sequence = 1;
-               record_line (current_subfile, line, address);
-               return;         /* return! */
-               break;
-             case DW_LNE_set_address:
-               address = read_address (abfd, line_ptr);
-               line_ptr += address_size;
-               break;
-             case DW_LNE_define_file:
-               cur_file = read_string (abfd, line_ptr, &bytes_read);
-               line_ptr += bytes_read;
-               if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
-                 {
-                   files.files = xrealloc (files.files,
-                     (files.num_files + FILE_ALLOC_CHUNK)
-                       * sizeof (struct fileinfo));
-                 }
-               files.files[files.num_files].name = cur_file;
-               files.files[files.num_files].dir = read_unsigned_leb128 (
-                 abfd, line_ptr, &bytes_read);
-               line_ptr += bytes_read;
-               files.files[files.num_files].time = read_unsigned_leb128 (abfd,
-                 line_ptr, &bytes_read);
-               line_ptr += bytes_read;
-               files.files[files.num_files].size = read_unsigned_leb128 (abfd,
-                 line_ptr, &bytes_read);
-               line_ptr += bytes_read;
-               break;
-             default:
-               error ("Dwarf Error: Mangled .debug_line section.");
-               return;
-             }
-           break;
-         case DW_LNS_copy:
-           record_line (current_subfile, line, address);
-           basic_block = 0;
-           break;
-         case DW_LNS_advance_pc:
-           address += lh.minimum_instruction_length
-             * read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-           line_ptr += bytes_read;
-           break;
-         case DW_LNS_advance_line:
-           line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
-           line_ptr += bytes_read;
-           break;
-         case DW_LNS_set_file:
-           /* The file table is 0 based and the references are 1
-              based, thus  the subtraction of `1' at the end of the
-              next line */
-           file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read) - 1;
-           start_subfile (files.files[file].name,
-                          (files.files[file].dir ?
-                            dirs.dirs[files.files[file].dir] : 0));
-           line_ptr += bytes_read;
-           break;
-         case DW_LNS_set_column:
-           column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-           line_ptr += bytes_read;
-           break;
-         case DW_LNS_negate_stmt:
-           is_stmt = (!is_stmt);
-           break;
-         case DW_LNS_set_basic_block:
-           basic_block = 1;
-           break;
-         case DW_LNS_const_add_pc:
-           address += (255 - lh.opcode_base) / lh.line_range;
-           break;
-         case DW_LNS_fixed_advance_pc:
-           address += read_2_bytes (abfd, line_ptr);
-           line_ptr += 2;
-           break;
-         default:              /* special operand */
-           adj_opcode = op_code - lh.opcode_base;
-           address += (adj_opcode / lh.line_range)
-             * lh.minimum_instruction_length;
-           line += lh.line_base + (adj_opcode % lh.line_range);
-           /* append row to matrix using current values */
-           record_line (current_subfile, line, address);
-           basic_block = 1;
-         }
-      }
-    while (1);
+  /* Read the statement sequences until there's nothing left.  */
+  while (line_ptr < line_end)
+    {
+      /* state machine registers  */
+      CORE_ADDR address = 0;
+      unsigned int file = 1;
+      unsigned int line = 1;
+      unsigned int column = 0;
+      int is_stmt = lh.default_is_stmt;
+      int basic_block = 0;
+      int end_sequence = 0;
+
+      /* Start a subfile for the current file of the state machine.  */
+      if (files.num_files >= file)
+       {
+         /* The file and directory tables are 0 based, the references
+            are 1 based.  */
+         dwarf2_start_subfile (files.files[file - 1].name,
+                               (files.files[file - 1].dir
+                                ? dirs.dirs[files.files[file - 1].dir - 1]
+                                : comp_dir));
+       }
+
+      /* Decode the table. */
+      while (!end_sequence)
+       {
+         op_code = read_1_byte (abfd, line_ptr);
+         line_ptr += 1;
+         switch (op_code)
+           {
+           case DW_LNS_extended_op:
+             line_ptr += 1;    /* ignore length */
+             extended_op = read_1_byte (abfd, line_ptr);
+             line_ptr += 1;
+             switch (extended_op)
+               {
+               case DW_LNE_end_sequence:
+                 end_sequence = 1;
+                 /* Don't call record_line here.  The end_sequence
+                    instruction provides the address of the first byte
+                    *after* the last line in the sequence; it's not the
+                    address of any real source line.  However, the GDB
+                    linetable structure only records the starts of lines,
+                    not the ends.  This is a weakness of GDB.  */
+                 break;
+               case DW_LNE_set_address:
+                 address = read_address (abfd, line_ptr, cu_header, &bytes_read);
+                 line_ptr += bytes_read;
+                 address += baseaddr;
+                 break;
+               case DW_LNE_define_file:
+                 cur_file = read_string (abfd, line_ptr, &bytes_read);
+                 line_ptr += bytes_read;
+                 if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
+                   {
+                     files.files = (struct fileinfo *)
+                       xrealloc (files.files,
+                                 (files.num_files + FILE_ALLOC_CHUNK)
+                                 * sizeof (struct fileinfo));
+                     if (files.num_files == 0)
+                       make_cleanup (free_current_contents, &files.files);
+                   }
+                 files.files[files.num_files].name = cur_file;
+                 files.files[files.num_files].dir =
+                   read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                 line_ptr += bytes_read;
+                 files.files[files.num_files].time =
+                   read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                 line_ptr += bytes_read;
+                 files.files[files.num_files].size =
+                   read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                 line_ptr += bytes_read;
+                 files.num_files++;
+                 break;
+               default:
+                 complain (&dwarf2_mangled_line_number_section);
+                 goto done;
+               }
+             break;
+           case DW_LNS_copy:
+             record_line (current_subfile, line, address);
+             basic_block = 0;
+             break;
+           case DW_LNS_advance_pc:
+             address += lh.minimum_instruction_length
+               * read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+             line_ptr += bytes_read;
+             break;
+           case DW_LNS_advance_line:
+             line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
+             line_ptr += bytes_read;
+             break;
+           case DW_LNS_set_file:
+             /* The file and directory tables are 0 based, the references
+                are 1 based.  */
+             file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+             line_ptr += bytes_read;
+             dwarf2_start_subfile
+               (files.files[file - 1].name,
+                (files.files[file - 1].dir
+                 ? dirs.dirs[files.files[file - 1].dir - 1]
+                 : comp_dir));
+             break;
+           case DW_LNS_set_column:
+             column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+             line_ptr += bytes_read;
+             break;
+           case DW_LNS_negate_stmt:
+             is_stmt = (!is_stmt);
+             break;
+           case DW_LNS_set_basic_block:
+             basic_block = 1;
+             break;
+           /* Add to the address register of the state machine the
+              address increment value corresponding to special opcode
+              255.  Ie, this value is scaled by the minimum instruction
+              length since special opcode 255 would have scaled the
+              the increment.  */
+           case DW_LNS_const_add_pc:
+             address += (lh.minimum_instruction_length
+                         * ((255 - lh.opcode_base) / lh.line_range));
+             break;
+           case DW_LNS_fixed_advance_pc:
+             address += read_2_bytes (abfd, line_ptr);
+             line_ptr += 2;
+             break;
+           default:            /* special operand */
+             adj_opcode = op_code - lh.opcode_base;
+             address += (adj_opcode / lh.line_range)
+               * lh.minimum_instruction_length;
+             line += lh.line_base + (adj_opcode % lh.line_range);
+             /* append row to matrix using current values */
+             record_line (current_subfile, line, address);
+             basic_block = 1;
+           }
+       }
+    }
+done:
   do_cleanups (back_to);
 }
 
+/* Start a subfile for DWARF.  FILENAME is the name of the file and
+   DIRNAME the name of the source directory which contains FILENAME
+   or NULL if not known.
+   This routine tries to keep line numbers from identical absolute and
+   relative file names in a common subfile.
+
+   Using the `list' example from the GDB testsuite, which resides in
+   /srcdir and compiling it with Irix6.2 cc in /compdir using a filename
+   of /srcdir/list0.c yields the following debugging information for list0.c:
+
+   DW_AT_name:          /srcdir/list0.c
+   DW_AT_comp_dir:              /compdir
+   files.files[0].name: list0.h
+   files.files[0].dir:  /srcdir
+   files.files[1].name: list0.c
+   files.files[1].dir:  /srcdir
+
+   The line number information for list0.c has to end up in a single
+   subfile, so that `break /srcdir/list0.c:1' works as expected.  */
+
+static void
+dwarf2_start_subfile (char *filename, char *dirname)
+{
+  /* If the filename isn't absolute, try to match an existing subfile
+     with the full pathname.  */
+
+  if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL)
+    {
+      struct subfile *subfile;
+      char *fullname = concat (dirname, "/", filename, NULL);
+
+      for (subfile = subfiles; subfile; subfile = subfile->next)
+       {
+         if (FILENAME_CMP (subfile->name, fullname) == 0)
+           {
+             current_subfile = subfile;
+             xfree (fullname);
+             return;
+           }
+       }
+      xfree (fullname);
+    }
+  start_subfile (filename, dirname);
+}
+
 /* Given a pointer to a DWARF information entry, figure out if we need
    to make a symbol table entry for it, and if so, create a new entry
-   and return a pointer to it.  */
+   and return a pointer to it.
+   If TYPE is NULL, determine symbol type from the die, otherwise
+   used the passed type.  */
 
 static struct symbol *
-new_symbol (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
+           const struct comp_unit_head *cu_header)
 {
   struct symbol *sym = NULL;
+  char *name;
   struct attribute *attr = NULL;
   struct attribute *attr2 = NULL;
   CORE_ADDR addr;
 
-  attr = dwarf_attr (die, DW_AT_name);
-  if (attr)
+  name = dwarf2_linkage_name (die);
+  if (name)
     {
-#if 0
       sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
                                             sizeof (struct symbol));
-#endif
-      sym = (struct symbol *) xmalloc (sizeof (struct symbol));
+      OBJSTAT (objfile, n_syms++);
       memset (sym, 0, sizeof (struct symbol));
-#if 0
-      SYMBOL_NAME (sym) = create_name (DW_STRING (attr),
-                                      &objfile->symbol_obstack);
-#endif
-      SYMBOL_NAME (sym) = strdup (DW_STRING (attr));
-      /* default assumptions */
+      SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
+                                       &objfile->symbol_obstack);
+
+      /* Default assumptions.
+         Use the passed type or decode it from the die.  */
       SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
       SYMBOL_CLASS (sym) = LOC_STATIC;
-      SYMBOL_TYPE (sym) = die_type (die, objfile);
+      if (type != NULL)
+       SYMBOL_TYPE (sym) = type;
+      else
+       SYMBOL_TYPE (sym) = die_type (die, objfile, cu_header);
+      attr = dwarf_attr (die, DW_AT_decl_line);
+      if (attr)
+       {
+         SYMBOL_LINE (sym) = DW_UNSND (attr);
+       }
 
       /* If this symbol is from a C++ compilation, then attempt to
          cache the demangled form for future reference.  This is a
@@ -2964,18 +4175,13 @@ new_symbol (die, objfile)
          attr = dwarf_attr (die, DW_AT_low_pc);
          if (attr)
            {
-             SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr);
+             SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr;
            }
          SYMBOL_CLASS (sym) = LOC_LABEL;
          break;
        case DW_TAG_subprogram:
-         attr = dwarf_attr (die, DW_AT_low_pc);
-         if (attr)
-           {
-             SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr);
-           }
-         SYMBOL_TYPE (sym) = make_function_type (die_type (die, objfile),
-                                                 NULL);
+         /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
+            finish_block.  */
          SYMBOL_CLASS (sym) = LOC_BLOCK;
          attr2 = dwarf_attr (die, DW_AT_external);
          if (attr2 && (DW_UNSND (attr2) != 0))
@@ -2988,6 +4194,25 @@ new_symbol (die, objfile)
            }
          break;
        case DW_TAG_variable:
+         /* Compilation with minimal debug info may result in variables
+            with missing type entries. Change the misleading `void' type
+            to something sensible.  */
+         if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID)
+           SYMBOL_TYPE (sym) = init_type (TYPE_CODE_INT,
+                                          TARGET_INT_BIT / HOST_CHAR_BIT, 0,
+                                          "<variable, no debug info>",
+                                          objfile);
+         attr = dwarf_attr (die, DW_AT_const_value);
+         if (attr)
+           {
+             dwarf2_const_value (attr, sym, objfile, cu_header);
+             attr2 = dwarf_attr (die, DW_AT_external);
+             if (attr2 && (DW_UNSND (attr2) != 0))
+               add_symbol_to_list (sym, &global_symbols);
+             else
+               add_symbol_to_list (sym, list_in_scope);
+             break;
+           }
          attr = dwarf_attr (die, DW_AT_location);
          if (attr)
            {
@@ -2995,47 +4220,115 @@ new_symbol (die, objfile)
              if (attr2 && (DW_UNSND (attr2) != 0))
                {
                  SYMBOL_VALUE_ADDRESS (sym) =
-                   decode_locdesc (DW_BLOCK (attr), objfile);
+                   decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
                  add_symbol_to_list (sym, &global_symbols);
-                 SYMBOL_CLASS (sym) = LOC_STATIC;
-                 SYMBOL_VALUE_ADDRESS (sym) += baseaddr;
+
+                 /* In shared libraries the address of the variable
+                    in the location descriptor might still be relocatable,
+                    so its value could be zero.
+                    Enter the symbol as a LOC_UNRESOLVED symbol, if its
+                    value is zero, the address of the variable will then
+                    be determined from the minimal symbol table whenever
+                    the variable is referenced.  */
+                 if (SYMBOL_VALUE_ADDRESS (sym))
+                   {
+                     fixup_symbol_section (sym, objfile);
+                     SYMBOL_VALUE_ADDRESS (sym) +=
+                       ANOFFSET (objfile->section_offsets,
+                                 SYMBOL_SECTION (sym));
+                     SYMBOL_CLASS (sym) = LOC_STATIC;
+                   }
+                 else
+                   SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
                }
              else
                {
                  SYMBOL_VALUE (sym) = addr =
-                   decode_locdesc (DW_BLOCK (attr), objfile);
+                   decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
                  add_symbol_to_list (sym, list_in_scope);
-                 if (isreg)
+                 if (optimized_out)
+                   {
+                     SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+                   }
+                 else if (isreg)
                    {
                      SYMBOL_CLASS (sym) = LOC_REGISTER;
+                     SYMBOL_VALUE (sym) = 
+                       DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
                    }
                  else if (offreg)
                    {
-                     SYMBOL_CLASS (sym) = LOC_LOCAL;
+                     SYMBOL_CLASS (sym) = LOC_BASEREG;
+                     SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
+                   }
+                 else if (islocal)
+                   {
+                     SYMBOL_CLASS (sym) = LOC_LOCAL;
+                   }
+                 else
+                   {
+                     fixup_symbol_section (sym, objfile);
+                     SYMBOL_VALUE_ADDRESS (sym) =
+                       addr + ANOFFSET (objfile->section_offsets,
+                                        SYMBOL_SECTION (sym));
+                     SYMBOL_CLASS (sym) = LOC_STATIC;
+                   }
+               }
+           }
+         else
+           {
+             /* We do not know the address of this symbol.
+                If it is an external symbol and we have type information
+                for it, enter the symbol as a LOC_UNRESOLVED symbol.
+                The address of the variable will then be determined from
+                the minimal symbol table whenever the variable is
+                referenced.  */
+             attr2 = dwarf_attr (die, DW_AT_external);
+             if (attr2 && (DW_UNSND (attr2) != 0)
+                 && dwarf_attr (die, DW_AT_type) != NULL)
+               {
+                 SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
+                 add_symbol_to_list (sym, &global_symbols);
+               }
+           }
+         break;
+       case DW_TAG_formal_parameter:
+         attr = dwarf_attr (die, DW_AT_location);
+         if (attr)
+           {
+             SYMBOL_VALUE (sym) =
+               decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+             if (isreg)
+               {
+                 SYMBOL_CLASS (sym) = LOC_REGPARM;
+                 SYMBOL_VALUE (sym) = 
+                   DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
+               }
+             else if (offreg)
+               {
+                 if (isderef)
+                   {
+                     if (basereg != frame_base_reg)
+                       complain (&dwarf2_complex_location_expr);
+                     SYMBOL_CLASS (sym) = LOC_REF_ARG;
                    }
                  else
                    {
-                     SYMBOL_CLASS (sym) = LOC_STATIC;
-                     SYMBOL_VALUE_ADDRESS (sym) = addr + baseaddr;
+                     SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
+                     SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
                    }
                }
+             else
+               {
+                 SYMBOL_CLASS (sym) = LOC_ARG;
+               }
            }
-         break;
-       case DW_TAG_formal_parameter:
-         attr = dwarf_attr (die, DW_AT_location);
-         if (attr != NULL)
+         attr = dwarf_attr (die, DW_AT_const_value);
+         if (attr)
            {
-             SYMBOL_VALUE (sym) = decode_locdesc (DW_BLOCK (attr), objfile);
+             dwarf2_const_value (attr, sym, objfile, cu_header);
            }
          add_symbol_to_list (sym, list_in_scope);
-         if (isreg)
-           {
-             SYMBOL_CLASS (sym) = LOC_REGPARM;
-           }
-         else
-           {
-             SYMBOL_CLASS (sym) = LOC_ARG;
-           }
          break;
        case DW_TAG_unspecified_parameters:
          /* From varargs functions; gdb doesn't seem to have any
@@ -3049,44 +4342,166 @@ new_symbol (die, objfile)
          SYMBOL_CLASS (sym) = LOC_TYPEDEF;
          SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
          add_symbol_to_list (sym, list_in_scope);
+
+         /* The semantics of C++ state that "struct foo { ... }" also
+            defines a typedef for "foo". Synthesize a typedef symbol so
+            that "ptype foo" works as expected.  */
+         if (cu_language == language_cplus)
+           {
+             struct symbol *typedef_sym = (struct symbol *)
+             obstack_alloc (&objfile->symbol_obstack,
+                            sizeof (struct symbol));
+             *typedef_sym = *sym;
+             SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
+             if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
+               TYPE_NAME (SYMBOL_TYPE (sym)) =
+                 obsavestring (SYMBOL_NAME (sym),
+                               strlen (SYMBOL_NAME (sym)),
+                               &objfile->type_obstack);
+             add_symbol_to_list (typedef_sym, list_in_scope);
+           }
          break;
        case DW_TAG_typedef:
+       case DW_TAG_base_type:
          SYMBOL_CLASS (sym) = LOC_TYPEDEF;
          SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
          add_symbol_to_list (sym, list_in_scope);
          break;
+       case DW_TAG_enumerator:
+         attr = dwarf_attr (die, DW_AT_const_value);
+         if (attr)
+           {
+             dwarf2_const_value (attr, sym, objfile, cu_header);
+           }
+         add_symbol_to_list (sym, list_in_scope);
+         break;
        default:
          /* Not a tag we recognize.  Hopefully we aren't processing
             trash data, but since we must specifically ignore things
             we don't recognize, there is nothing else we should do at
             this point. */
+         complain (&dwarf2_unsupported_tag, dwarf_tag_name (die->tag));
          break;
        }
     }
   return (sym);
 }
 
+/* Copy constant value from an attribute to a symbol.  */
+
+static void
+dwarf2_const_value (struct attribute *attr, struct symbol *sym,
+                   struct objfile *objfile,
+                   const struct comp_unit_head *cu_header)
+{
+  struct dwarf_block *blk;
+
+  switch (attr->form)
+    {
+    case DW_FORM_addr:
+      if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size)
+       complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
+                 cu_header->addr_size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
+      SYMBOL_VALUE_BYTES (sym) = (char *)
+       obstack_alloc (&objfile->symbol_obstack, cu_header->addr_size);
+      store_address (SYMBOL_VALUE_BYTES (sym), cu_header->addr_size,
+                    DW_ADDR (attr));
+      SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+      break;
+    case DW_FORM_block1:
+    case DW_FORM_block2:
+    case DW_FORM_block4:
+    case DW_FORM_block:
+      blk = DW_BLOCK (attr);
+      if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size)
+       complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
+                 blk->size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
+      SYMBOL_VALUE_BYTES (sym) = (char *)
+       obstack_alloc (&objfile->symbol_obstack, blk->size);
+      memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size);
+      SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
+      break;
+
+      /* The DW_AT_const_value attributes are supposed to carry the
+        symbol's value "represented as it would be on the target
+        architecture."  By the time we get here, it's already been
+        converted to host endianness, so we just need to sign- or
+        zero-extend it as appropriate.  */
+    case DW_FORM_data1:
+      dwarf2_const_value_data (attr, sym, 8);
+      break;
+    case DW_FORM_data2:
+      dwarf2_const_value_data (attr, sym, 16);
+      break;
+    case DW_FORM_data4:
+      dwarf2_const_value_data (attr, sym, 32);
+      break;
+    case DW_FORM_data8:
+      dwarf2_const_value_data (attr, sym, 64);
+      break;
+
+    case DW_FORM_sdata:
+      SYMBOL_VALUE (sym) = DW_SND (attr);
+      SYMBOL_CLASS (sym) = LOC_CONST;
+      break;
+
+    case DW_FORM_udata:
+      SYMBOL_VALUE (sym) = DW_UNSND (attr);
+      SYMBOL_CLASS (sym) = LOC_CONST;
+      break;
+
+    default:
+      complain (&dwarf2_unsupported_const_value_attr,
+               dwarf_form_name (attr->form));
+      SYMBOL_VALUE (sym) = 0;
+      SYMBOL_CLASS (sym) = LOC_CONST;
+      break;
+    }
+}
+
+
+/* Given an attr with a DW_FORM_dataN value in host byte order, sign-
+   or zero-extend it as appropriate for the symbol's type.  */
+static void
+dwarf2_const_value_data (struct attribute *attr,
+                        struct symbol *sym,
+                        int bits)
+{
+  LONGEST l = DW_UNSND (attr);
+
+  if (bits < sizeof (l) * 8)
+    {
+      if (TYPE_UNSIGNED (SYMBOL_TYPE (sym)))
+       l &= ((LONGEST) 1 << bits) - 1;
+      else
+       l = (l << (sizeof (l) * 8 - bits)) >> (sizeof (l) * 8 - bits);
+    }
+
+  SYMBOL_VALUE (sym) = l;
+  SYMBOL_CLASS (sym) = LOC_CONST;
+}
+
+
 /* Return the type of the die in question using its DW_AT_type attribute.  */
 
 static struct type *
-die_type (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+die_type (struct die_info *die, struct objfile *objfile,
+         const struct comp_unit_head *cu_header)
 {
   struct type *type;
-  struct attribute *attr, *type_attr;
+  struct attribute *type_attr;
   struct die_info *type_die;
-  unsigned int size = 0, encoding = 0, ref;
+  unsigned int ref;
 
   type_attr = dwarf_attr (die, DW_AT_type);
   if (!type_attr)
     {
-      type = dwarf_base_type (0, 0);
-      return type;
+      /* A missing DW_AT_type represents a void type.  */
+      return dwarf2_fundamental_type (objfile, FT_VOID);
     }
   else
     {
-      ref = DW_UNSND (type_attr);
+      ref = dwarf2_get_ref_die_offset (type_attr);
       type_die = follow_die_ref (ref);
       if (!type_die)
        {
@@ -3094,19 +4509,51 @@ die_type (die, objfile)
          return NULL;
        }
     }
-  type = tag_type_to_type (type_die, objfile);
+  type = tag_type_to_type (type_die, objfile, cu_header);
   if (!type)
     {
-      error ("Dwarf Error: Problem turning type die at offset into gdb type:");
       dump_die (type_die);
+      error ("Dwarf Error: Problem turning type die at offset into gdb type.");
+    }
+  return type;
+}
+
+/* Return the containing type of the die in question using its
+   DW_AT_containing_type attribute.  */
+
+static struct type *
+die_containing_type (struct die_info *die, struct objfile *objfile,
+                    const struct comp_unit_head *cu_header)
+{
+  struct type *type = NULL;
+  struct attribute *type_attr;
+  struct die_info *type_die = NULL;
+  unsigned int ref;
+
+  type_attr = dwarf_attr (die, DW_AT_containing_type);
+  if (type_attr)
+    {
+      ref = dwarf2_get_ref_die_offset (type_attr);
+      type_die = follow_die_ref (ref);
+      if (!type_die)
+       {
+         error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+         return NULL;
+       }
+      type = tag_type_to_type (type_die, objfile, cu_header);
+    }
+  if (!type)
+    {
+      if (type_die)
+       dump_die (type_die);
+      error ("Dwarf Error: Problem turning containing type into gdb type.");
     }
   return type;
 }
 
+#if 0
 static struct type *
-type_at_offset (offset, objfile)
-     unsigned int offset;
-     struct objfile *objfile;
+type_at_offset (unsigned int offset, struct objfile *objfile)
 {
   struct die_info *die;
   struct type *type;
@@ -3120,11 +4567,11 @@ type_at_offset (offset, objfile)
   type = tag_type_to_type (die, objfile);
   return type;
 }
+#endif
 
 static struct type *
-tag_type_to_type (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+tag_type_to_type (struct die_info *die, struct objfile *objfile,
+                 const struct comp_unit_head *cu_header)
 {
   if (die->type)
     {
@@ -3132,71 +4579,69 @@ tag_type_to_type (die, objfile)
     }
   else
     {
-      read_type_die (die, objfile);
+      read_type_die (die, objfile, cu_header);
       if (!die->type)
        {
          dump_die (die);
-         error ("Dwarf Error: Cannot find type of die:");
+         error ("Dwarf Error: Cannot find type of die.");
        }
       return die->type;
     }
 }
 
 static void
-read_type_die (die, objfile)
-     struct die_info *die;
-     struct objfile *objfile;
+read_type_die (struct die_info *die, struct objfile *objfile,
+              const struct comp_unit_head *cu_header)
 {
   switch (die->tag)
     {
     case DW_TAG_class_type:
     case DW_TAG_structure_type:
     case DW_TAG_union_type:
-      read_structure_scope (die, objfile);
+      read_structure_scope (die, objfile, cu_header);
       break;
     case DW_TAG_enumeration_type:
-      read_enumeration (die, objfile);
+      read_enumeration (die, objfile, cu_header);
       break;
+    case DW_TAG_subprogram:
     case DW_TAG_subroutine_type:
-      read_subroutine_type (die, objfile);
+      read_subroutine_type (die, objfile, cu_header);
       break;
     case DW_TAG_array_type:
-      dwarf_read_array_type (die, objfile);
+      read_array_type (die, objfile, cu_header);
       break;
     case DW_TAG_pointer_type:
-      read_tag_pointer_type (die, objfile);
+      read_tag_pointer_type (die, objfile, cu_header);
+      break;
+    case DW_TAG_ptr_to_member_type:
+      read_tag_ptr_to_member_type (die, objfile, cu_header);
       break;
     case DW_TAG_reference_type:
-      read_tag_reference_type (die, objfile);
+      read_tag_reference_type (die, objfile, cu_header);
       break;
     case DW_TAG_const_type:
-      read_tag_const_type (die, objfile);
+      read_tag_const_type (die, objfile, cu_header);
       break;
     case DW_TAG_volatile_type:
-      read_tag_volatile_type (die, objfile);
+      read_tag_volatile_type (die, objfile, cu_header);
       break;
     case DW_TAG_string_type:
       read_tag_string_type (die, objfile);
       break;
     case DW_TAG_typedef:
-      read_typedef (die, objfile);
+      read_typedef (die, objfile, cu_header);
       break;
     case DW_TAG_base_type:
       read_base_type (die, objfile);
       break;
-    case DW_TAG_padding:
-    case DW_TAG_compile_unit:
-    case DW_TAG_subprogram:
-    case DW_TAG_lexical_block:
     default:
+      complain (&dwarf2_unexpected_tag, dwarf_tag_name (die->tag));
       break;
     }
 }
 
 static struct type *
-dwarf_base_type (encoding, size)
-     int encoding;
-     int size;
+dwarf_base_type (int encoding, int size, struct objfile *objfile)
 {
   /* FIXME - this should not produce a new (struct type *)
      every time.  It should cache base types.  */
@@ -3204,93 +4649,76 @@ dwarf_base_type (encoding, size)
   switch (encoding)
     {
     case DW_ATE_address:
-      type = dwarf2_fundamental_type (current_objfile, FT_VOID);
+      type = dwarf2_fundamental_type (objfile, FT_VOID);
       return type;
     case DW_ATE_boolean:
-      type = dwarf2_fundamental_type (current_objfile, FT_BOOLEAN);
+      type = dwarf2_fundamental_type (objfile, FT_BOOLEAN);
       return type;
     case DW_ATE_complex_float:
       if (size == 16)
        {
-         type = dwarf2_fundamental_type (current_objfile, FT_DBL_PREC_COMPLEX);
+         type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX);
        }
       else
        {
-         type = dwarf2_fundamental_type (current_objfile, FT_COMPLEX);
+         type = dwarf2_fundamental_type (objfile, FT_COMPLEX);
        }
       return type;
     case DW_ATE_float:
       if (size == 8)
        {
-         type = dwarf2_fundamental_type (current_objfile, FT_DBL_PREC_FLOAT);
+         type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
        }
       else
        {
-         type = dwarf2_fundamental_type (current_objfile, FT_FLOAT);
+         type = dwarf2_fundamental_type (objfile, FT_FLOAT);
        }
       return type;
     case DW_ATE_signed:
       switch (size)
        {
        case 1:
-         type = dwarf2_fundamental_type (current_objfile, FT_SIGNED_CHAR);
+         type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
          break;
        case 2:
-         type = dwarf2_fundamental_type (current_objfile, FT_SIGNED_SHORT);
+         type = dwarf2_fundamental_type (objfile, FT_SIGNED_SHORT);
          break;
        default:
        case 4:
-         type = dwarf2_fundamental_type (current_objfile, FT_SIGNED_INTEGER);
+         type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
          break;
        }
       return type;
     case DW_ATE_signed_char:
-      type = dwarf2_fundamental_type (current_objfile, FT_SIGNED_CHAR);
+      type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
       return type;
     case DW_ATE_unsigned:
       switch (size)
        {
        case 1:
-         type = dwarf2_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
+         type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
          break;
        case 2:
-         type = dwarf2_fundamental_type (current_objfile, FT_SIGNED_SHORT);
+         type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_SHORT);
          break;
        default:
        case 4:
-         type = dwarf2_fundamental_type (current_objfile, FT_UNSIGNED_INTEGER);
+         type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_INTEGER);
          break;
        }
       return type;
     case DW_ATE_unsigned_char:
-      type = dwarf2_fundamental_type (current_objfile, FT_UNSIGNED_CHAR);
+      type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
       return type;
     default:
-      type = dwarf2_fundamental_type (current_objfile, FT_SIGNED_INTEGER);
+      type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
       return type;
     }
 }
 
-/* Given a pointer to a string and a pointer to an obstack, allocates
-   a fresh copy of the string on the specified obstack.  */
-
-static char *
-create_name (name, obstackp)
-     char *name;
-     struct obstack *obstackp;
-{
-  int length;
-  char *newname;
-
-  length = strlen (name) + 1;
-  newname = (char *) obstack_alloc (obstackp, length);
-  strcpy (newname, name);
-  return (newname);
-}
-
+#if 0
 struct die_info *
-copy_die (old_die)
-     struct die_info *old_die;
+copy_die (struct die_info *old_die)
 {
   struct die_info *new_die;
   int i, num_attrs;
@@ -3319,14 +4747,13 @@ copy_die (old_die)
   new_die->next = NULL;
   return new_die;
 }
+#endif
 
 /* Return sibling of die, NULL if no sibling.  */
 
-struct die_info *
-sibling_die (die)
-     struct die_info *die;
+static struct die_info *
+sibling_die (struct die_info *die)
 {
-  struct die_info *new;
   int nesting_level = 0;
 
   if (!die->has_children)
@@ -3366,11 +4793,26 @@ sibling_die (die)
     }
 }
 
+/* Get linkage name of a die, return NULL if not found.  */
+
+static char *
+dwarf2_linkage_name (struct die_info *die)
+{
+  struct attribute *attr;
+
+  attr = dwarf_attr (die, DW_AT_MIPS_linkage_name);
+  if (attr && DW_STRING (attr))
+    return DW_STRING (attr);
+  attr = dwarf_attr (die, DW_AT_name);
+  if (attr && DW_STRING (attr))
+    return DW_STRING (attr);
+  return NULL;
+}
+
 /* Convert a DIE tag into its string name.  */
 
 static char *
-dwarf_tag_name (tag)
-     register unsigned tag;
+dwarf_tag_name (register unsigned tag)
 {
   switch (tag)
     {
@@ -3486,8 +4928,7 @@ dwarf_tag_name (tag)
 /* Convert a DWARF attribute code into its string name.  */
 
 static char *
-dwarf_attr_name (attr)
-     register unsigned attr;
+dwarf_attr_name (register unsigned attr)
 {
   switch (attr)
     {
@@ -3653,8 +5094,7 @@ dwarf_attr_name (attr)
 /* Convert a DWARF value form code into its string name.  */
 
 static char *
-dwarf_form_name (form)
-     register unsigned form;
+dwarf_form_name (register unsigned form)
 {
   switch (form)
     {
@@ -3708,8 +5148,7 @@ dwarf_form_name (form)
 /* Convert a DWARF stack opcode into its string name.  */
 
 static char *
-dwarf_stack_op_name (op)
-     register unsigned op;
+dwarf_stack_op_name (register unsigned op)
 {
   switch (op)
     {
@@ -4009,10 +5448,9 @@ dwarf_stack_op_name (op)
 }
 
 static char *
-dwarf_bool_name (bool)
-     unsigned bool;
+dwarf_bool_name (unsigned mybool)
 {
-  if (bool)
+  if (mybool)
     return "TRUE";
   else
     return "FALSE";
@@ -4021,8 +5459,7 @@ dwarf_bool_name (bool)
 /* Convert a DWARF type code into its string name.  */
 
 static char *
-dwarf_type_encoding_name (enc)
-     register unsigned enc;
+dwarf_type_encoding_name (register unsigned enc)
 {
   switch (enc)
     {
@@ -4049,9 +5486,9 @@ dwarf_type_encoding_name (enc)
 
 /* Convert a DWARF call frame info operation to its string name. */
 
+#if 0
 static char *
-dwarf_cfi_name (cfi_opc)
-     register unsigned cfi_opc;
+dwarf_cfi_name (register unsigned cfi_opc)
 {
   switch (cfi_opc)
     {
@@ -4098,12 +5535,12 @@ dwarf_cfi_name (cfi_opc)
       return "DW_CFA_<unknown>";
     }
 }
+#endif
 
-void
-dump_die (die)
-     struct die_info *die;
+static void
+dump_die (struct die_info *die)
 {
-  int i;
+  unsigned int i;
 
   fprintf (stderr, "Die: %s (abbrev = %d, offset = %d)\n",
           dwarf_tag_name (die->tag), die->abbrev, die->offset);
@@ -4120,32 +5557,33 @@ dump_die (die)
        {
        case DW_FORM_ref_addr:
        case DW_FORM_addr:
-         fprintf (stderr, sizeof (CORE_ADDR) > sizeof (long) ?
-                  "address: 0x%LLx" : "address: 0x%x",
-                  die->attrs[i].u.addr);
+         fprintf (stderr, "address: ");
+         print_address_numeric (DW_ADDR (&die->attrs[i]), 1, gdb_stderr);
          break;
        case DW_FORM_block2:
        case DW_FORM_block4:
        case DW_FORM_block:
        case DW_FORM_block1:
-         fprintf (stderr, "block: size %d",
-                  die->attrs[i].u.blk->size);
+         fprintf (stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
          break;
        case DW_FORM_data1:
        case DW_FORM_data2:
        case DW_FORM_data4:
+       case DW_FORM_data8:
        case DW_FORM_ref1:
        case DW_FORM_ref2:
        case DW_FORM_ref4:
        case DW_FORM_udata:
        case DW_FORM_sdata:
-         fprintf (stderr, "constant: %d", die->attrs[i].u.unsnd);
+         fprintf (stderr, "constant: %ld", DW_UNSND (&die->attrs[i]));
          break;
        case DW_FORM_string:
-         fprintf (stderr, "string: \"%s\"", die->attrs[i].u.str);
+         fprintf (stderr, "string: \"%s\"",
+                  DW_STRING (&die->attrs[i])
+                  ? DW_STRING (&die->attrs[i]) : "");
          break;
        case DW_FORM_flag:
-         if (die->attrs[i].u.unsnd)
+         if (DW_UNSND (&die->attrs[i]))
            fprintf (stderr, "flag: TRUE");
          else
            fprintf (stderr, "flag: FALSE");
@@ -4153,17 +5591,16 @@ dump_die (die)
        case DW_FORM_strp:      /* we do not support separate string
                                   section yet */
        case DW_FORM_indirect:  /* we do not handle indirect yet */
-       case DW_FORM_data8:     /* we do not have 64 bit quantities */
-         error ("Dwarf Error: Unsupported attribute form: %d.",
-                die->attrs[i].form);
+       default:
+         fprintf (stderr, "unsupported attribute form: %d.",
+                  die->attrs[i].form);
        }
       fprintf (stderr, "\n");
     }
 }
 
-void
-dump_die_list (die)
-     struct die_info *die;
+static void
+dump_die_list (struct die_info *die)
 {
   while (die)
     {
@@ -4172,10 +5609,8 @@ dump_die_list (die)
     }
 }
 
-void
-store_in_ref_table (offset, die)
-     unsigned int offset;
-     struct die_info *die;
+static void
+store_in_ref_table (unsigned int offset, struct die_info *die)
 {
   int h;
   struct die_info *old;
@@ -4186,9 +5621,38 @@ store_in_ref_table (offset, die)
   die_ref_table[h] = die;
 }
 
-struct die_info *
-follow_die_ref (offset)
-     unsigned int offset;
+
+static void
+dwarf2_empty_hash_tables (void)
+{
+  memset (die_ref_table, 0, sizeof (die_ref_table));
+}
+
+static unsigned int
+dwarf2_get_ref_die_offset (struct attribute *attr)
+{
+  unsigned int result = 0;
+
+  switch (attr->form)
+    {
+    case DW_FORM_ref_addr:
+      result = DW_ADDR (attr);
+      break;
+    case DW_FORM_ref1:
+    case DW_FORM_ref2:
+    case DW_FORM_ref4:
+    case DW_FORM_ref8:
+    case DW_FORM_ref_udata:
+      result = cu_header_offset + DW_UNSND (attr);
+      break;
+    default:
+      complain (&dwarf2_unsupported_die_ref_attr, dwarf_form_name (attr->form));
+    }
+  return result;
+}
+
+static struct die_info *
+follow_die_ref (unsigned int offset)
 {
   struct die_info *die;
   int h;
@@ -4207,9 +5671,7 @@ follow_die_ref (offset)
 }
 
 static struct type *
-dwarf2_fundamental_type (objfile, typeid)
-     struct objfile *objfile;
-     int typeid;
+dwarf2_fundamental_type (struct objfile *objfile, int typeid)
 {
   if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
     {
@@ -4230,135 +5692,95 @@ dwarf2_fundamental_type (objfile, typeid)
 }
 
 /* Decode simple location descriptions.
-   There are three cases:
-       An address: return the address.
-       An address relative to frame pointer: return the offset.
-       A register: return register number and set isreg to true.
-       A constant followed by plus: return the constant.  */
+   Given a pointer to a dwarf block that defines a location, compute
+   the location and return the value.
+
+   FIXME: This is a kludge until we figure out a better
+   way to handle the location descriptions.
+   Gdb's design does not mesh well with the DWARF2 notion of a location
+   computing interpreter, which is a shame because the flexibility goes unused.
+   FIXME: Implement more operations as necessary.
+
+   A location description containing no operations indicates that the
+   object is optimized out. The global optimized_out flag is set for
+   those, the return value is meaningless.
+
+   When the result is a register number, the global isreg flag is set,
+   otherwise it is cleared.
+
+   When the result is a base register offset, the global offreg flag is set
+   and the register number is returned in basereg, otherwise it is cleared.
+
+   When the DW_OP_fbreg operation is encountered without a corresponding
+   DW_AT_frame_base attribute, the global islocal flag is set.
+   Hopefully the machine dependent code knows how to set up a virtual
+   frame pointer for the local references.
+
+   Note that stack[0] is unused except as a default error return.
+   Note that stack overflow is not yet handled.  */
 
 static CORE_ADDR
-decode_locdesc (blk, objfile)
-     struct dwarf_block *blk;
-     struct objfile *objfile;
+decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
+               const struct comp_unit_head *cu_header)
 {
-  int i, snd;
+  int i;
   int size = blk->size;
   char *data = blk->data;
+  CORE_ADDR stack[64];
+  int stacki;
   unsigned int bytes_read, unsnd;
   unsigned char op;
-  union
-    {
-      CORE_ADDR addr;
-      char bytes[sizeof (CORE_ADDR)];
-    }
-  u;
 
   i = 0;
+  stacki = 0;
+  stack[stacki] = 0;
   isreg = 0;
   offreg = 0;
+  isderef = 0;
+  islocal = 0;
+  optimized_out = 1;
 
-  /* FIXME: handle more general forms of location descriptors.  */
   while (i < size)
     {
+      optimized_out = 0;
       op = data[i++];
       switch (op)
        {
        case DW_OP_reg0:
-         isreg = 1;
-         return 0;
        case DW_OP_reg1:
-         isreg = 1;
-         return 1;
        case DW_OP_reg2:
-         isreg = 1;
-         return 2;
        case DW_OP_reg3:
-         isreg = 1;
-         return 3;
        case DW_OP_reg4:
-         isreg = 1;
-         return 4;
        case DW_OP_reg5:
-         isreg = 1;
-         return 5;
        case DW_OP_reg6:
-         isreg = 1;
-         return 6;
        case DW_OP_reg7:
-         isreg = 1;
-         return 7;
        case DW_OP_reg8:
-         isreg = 1;
-         return 8;
        case DW_OP_reg9:
-         isreg = 1;
-         return 9;
        case DW_OP_reg10:
-         isreg = 1;
-         return 10;
        case DW_OP_reg11:
-         isreg = 1;
-         return 11;
        case DW_OP_reg12:
-         isreg = 1;
-         return 12;
        case DW_OP_reg13:
-         isreg = 1;
-         return 13;
        case DW_OP_reg14:
-         isreg = 1;
-         return 14;
        case DW_OP_reg15:
-         isreg = 1;
-         return 15;
        case DW_OP_reg16:
-         isreg = 1;
-         return 16;
        case DW_OP_reg17:
-         isreg = 1;
-         return 17;
        case DW_OP_reg18:
-         isreg = 1;
-         return 18;
        case DW_OP_reg19:
-         isreg = 1;
-         return 19;
        case DW_OP_reg20:
-         isreg = 1;
-         return 20;
        case DW_OP_reg21:
-         isreg = 1;
-         return 21;
        case DW_OP_reg22:
-         isreg = 1;
-         return 22;
        case DW_OP_reg23:
-         isreg = 1;
-         return 23;
        case DW_OP_reg24:
-         isreg = 1;
-         return 24;
        case DW_OP_reg25:
-         isreg = 1;
-         return 25;
        case DW_OP_reg26:
-         isreg = 1;
-         return 26;
        case DW_OP_reg27:
-         isreg = 1;
-         return 27;
        case DW_OP_reg28:
-         isreg = 1;
-         return 28;
        case DW_OP_reg29:
-         isreg = 1;
-         return 29;
        case DW_OP_reg30:
-         isreg = 1;
-         return 30;
        case DW_OP_reg31:
          isreg = 1;
-         return 31;
+         stack[++stacki] = op - DW_OP_reg0;
+         break;
 
        case DW_OP_regx:
          isreg = 1;
@@ -4368,74 +5790,182 @@ decode_locdesc (blk, objfile)
          /* The Harris 88110 gdb ports have long kept their special reg
             numbers between their gp-regs and their x-regs.  This is
             not how our dwarf is generated.  Punt. */
-         return unsnd + 6;
-#else
-         return unsnd;
+         unsnd += 6;
 #endif
+         stack[++stacki] = unsnd;
+         break;
 
-       case DW_OP_fbreg:
+       case DW_OP_breg0:
+       case DW_OP_breg1:
+       case DW_OP_breg2:
+       case DW_OP_breg3:
+       case DW_OP_breg4:
+       case DW_OP_breg5:
+       case DW_OP_breg6:
+       case DW_OP_breg7:
+       case DW_OP_breg8:
+       case DW_OP_breg9:
+       case DW_OP_breg10:
+       case DW_OP_breg11:
+       case DW_OP_breg12:
+       case DW_OP_breg13:
+       case DW_OP_breg14:
+       case DW_OP_breg15:
+       case DW_OP_breg16:
+       case DW_OP_breg17:
+       case DW_OP_breg18:
+       case DW_OP_breg19:
+       case DW_OP_breg20:
+       case DW_OP_breg21:
+       case DW_OP_breg22:
+       case DW_OP_breg23:
+       case DW_OP_breg24:
+       case DW_OP_breg25:
+       case DW_OP_breg26:
+       case DW_OP_breg27:
+       case DW_OP_breg28:
+       case DW_OP_breg29:
+       case DW_OP_breg30:
        case DW_OP_breg31:
          offreg = 1;
-         snd = read_signed_leb128 (NULL, (data + i), &bytes_read);
+         basereg = op - DW_OP_breg0;
+         stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
+         i += bytes_read;
+         break;
+
+       case DW_OP_bregx:
+         offreg = 1;
+         basereg = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
+         i += bytes_read;
+         stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
          i += bytes_read;
-         return snd;
+         break;
+
+       case DW_OP_fbreg:
+         stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
+         i += bytes_read;
+         if (frame_base_reg >= 0)
+           {
+             offreg = 1;
+             basereg = frame_base_reg;
+             stack[stacki] += frame_base_offset;
+           }
+         else
+           {
+             complain (&dwarf2_missing_at_frame_base);
+             islocal = 1;
+           }
+         break;
 
        case DW_OP_addr:
-         isreg = 0;
-         return read_address (objfile->obfd, &data[i]);
+         stack[++stacki] = read_address (objfile->obfd, &data[i],
+                                         cu_header, &bytes_read);
+         i += bytes_read;
+         break;
+
+       case DW_OP_const1u:
+         stack[++stacki] = read_1_byte (objfile->obfd, &data[i]);
+         i += 1;
+         break;
+
+       case DW_OP_const1s:
+         stack[++stacki] = read_1_signed_byte (objfile->obfd, &data[i]);
+         i += 1;
+         break;
+
+       case DW_OP_const2u:
+         stack[++stacki] = read_2_bytes (objfile->obfd, &data[i]);
+         i += 2;
+         break;
+
+       case DW_OP_const2s:
+         stack[++stacki] = read_2_signed_bytes (objfile->obfd, &data[i]);
+         i += 2;
+         break;
+
+       case DW_OP_const4u:
+         stack[++stacki] = read_4_bytes (objfile->obfd, &data[i]);
+         i += 4;
+         break;
+
+       case DW_OP_const4s:
+         stack[++stacki] = read_4_signed_bytes (objfile->obfd, &data[i]);
+         i += 4;
+         break;
 
        case DW_OP_constu:
-         unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
+         stack[++stacki] = read_unsigned_leb128 (NULL, (data + i),
+                                                 &bytes_read);
+         i += bytes_read;
+         break;
+
+       case DW_OP_consts:
+         stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
          i += bytes_read;
          break;
 
        case DW_OP_plus:
-         return unsnd;
+         stack[stacki - 1] += stack[stacki];
+         stacki--;
+         break;
+
+       case DW_OP_plus_uconst:
+         stack[stacki] += read_unsigned_leb128 (NULL, (data + i), &bytes_read);
+         i += bytes_read;
+         break;
 
+       case DW_OP_minus:
+         stack[stacki - 1] = stack[stacki] - stack[stacki - 1];
+         stacki--;
+         break;
+
+       case DW_OP_deref:
+         isderef = 1;
+         /* If we're not the last op, then we definitely can't encode
+            this using GDB's address_class enum.  */
+         if (i < size)
+           complain (&dwarf2_complex_location_expr);
+         break;
+
+       default:
+         complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name (op));
+         return (stack[stacki]);
        }
     }
-  return 0;
+  return (stack[stacki]);
 }
 
 /* memory allocation interface */
 
-static struct type *
-dwarf_alloc_type (objfile)
-     struct objfile *objfile;
+/* ARGSUSED */
+static void
+dwarf2_free_tmp_obstack (PTR ignore)
 {
-  struct type *type;
-
-  type = (struct type *) xmalloc (sizeof (struct type));
-  memset (type, 0, sizeof (struct type));
+  obstack_free (&dwarf2_tmp_obstack, NULL);
+}
 
-#if 0
-  type = alloc_type (objfile);
-#endif
+static struct dwarf_block *
+dwarf_alloc_block (void)
+{
+  struct dwarf_block *blk;
 
-  return (type);
+  blk = (struct dwarf_block *)
+    obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct dwarf_block));
+  return (blk);
 }
 
 static struct abbrev_info *
-dwarf_alloc_abbrev ()
+dwarf_alloc_abbrev (void)
 {
   struct abbrev_info *abbrev;
 
-  abbrev = xmalloc (sizeof (struct abbrev_info));
+  abbrev = (struct abbrev_info *) xmalloc (sizeof (struct abbrev_info));
   memset (abbrev, 0, sizeof (struct abbrev_info));
   return (abbrev);
 }
 
-static struct dwarf_block *
-dwarf_alloc_block ()
-{
-  struct dwarf_block *blk;
-
-  blk = (struct dwarf_block *) xmalloc (sizeof (struct dwarf_block));
-  return (blk);
-}
-
 static struct die_info *
-dwarf_alloc_die ()
+dwarf_alloc_die (void)
 {
   struct die_info *die;
 
This page took 0.09478 seconds and 4 git commands to generate.