(make_one_lib_file): For IDATA6 take the name from exp->internal_name if it
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index b62b0282b3ff305785590314f61863de3f594c24..49a003f57866f620c593437deaa68562659d4be6 100644 (file)
@@ -1,5 +1,6 @@
 /* DWARF 2 debugging format support for GDB.
-   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+   2004
    Free Software Foundation, Inc.
 
    Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
@@ -30,7 +31,6 @@
 #include "bfd.h"
 #include "symtab.h"
 #include "gdbtypes.h"
-#include "symfile.h"
 #include "objfiles.h"
 #include "elf/dwarf2.h"
 #include "buildsym.h"
 #include "expression.h"
 #include "filenames.h" /* for DOSish file names */
 #include "macrotab.h"
-
 #include "language.h"
 #include "complaints.h"
 #include "bcache.h"
+#include "dwarf2expr.h"
+#include "dwarf2loc.h"
+#include "cp-support.h"
+#include "hashtab.h"
+
 #include <fcntl.h>
 #include "gdb_string.h"
 #include "gdb_assert.h"
 #include <sys/types.h>
 
+/* A note on memory usage for this file.
+   
+   At the present time, this code reads the debug info sections into
+   the objfile's objfile_obstack.  A definite improvement for startup
+   time, on platforms which do not emit relocations for debug
+   sections, would be to use mmap instead.  The object's complete
+   debug information is loaded into memory, partly to simplify
+   absolute DIE references.
+
+   Whether using obstacks or mmap, the sections should remain loaded
+   until the objfile is released, and pointers into the section data
+   can be used for any other data associated to the objfile (symbol
+   names, type names, location expressions to name a few).  */
+
 #ifndef DWARF2_REG_TO_REGNUM
 #define DWARF2_REG_TO_REGNUM(REG) (REG)
 #endif
@@ -123,29 +141,46 @@ typedef struct statement_prologue
   }
 _STATEMENT_PROLOGUE;
 
-/* offsets and sizes of debugging sections */
-
-static file_ptr dwarf_info_offset;
-static file_ptr dwarf_abbrev_offset;
-static file_ptr dwarf_line_offset;
-static file_ptr dwarf_pubnames_offset;
-static file_ptr dwarf_aranges_offset;
-static file_ptr dwarf_loc_offset;
-static file_ptr dwarf_macinfo_offset;
-static file_ptr dwarf_str_offset;
-file_ptr dwarf_frame_offset;
-file_ptr dwarf_eh_frame_offset;
-
-static unsigned int dwarf_info_size;
-static unsigned int dwarf_abbrev_size;
-static unsigned int dwarf_line_size;
-static unsigned int dwarf_pubnames_size;
-static unsigned int dwarf_aranges_size;
-static unsigned int dwarf_loc_size;
-static unsigned int dwarf_macinfo_size;
-static unsigned int dwarf_str_size;
-unsigned int dwarf_frame_size;
-unsigned int dwarf_eh_frame_size;
+static const struct objfile_data *dwarf2_objfile_data_key;
+
+struct dwarf2_per_objfile
+{
+  /* Sizes of debugging sections.  */
+  unsigned int info_size;
+  unsigned int abbrev_size;
+  unsigned int line_size;
+  unsigned int pubnames_size;
+  unsigned int aranges_size;
+  unsigned int loc_size;
+  unsigned int macinfo_size;
+  unsigned int str_size;
+  unsigned int ranges_size;
+  unsigned int frame_size;
+  unsigned int eh_frame_size;
+
+  /* Loaded data from the sections.  */
+  char *info_buffer;
+  char *abbrev_buffer;
+  char *line_buffer;
+  char *str_buffer;
+  char *macinfo_buffer;
+  char *ranges_buffer;
+  char *loc_buffer;
+};
+
+static struct dwarf2_per_objfile *dwarf2_per_objfile;
+
+static asection *dwarf_info_section;
+static asection *dwarf_abbrev_section;
+static asection *dwarf_line_section;
+static asection *dwarf_pubnames_section;
+static asection *dwarf_aranges_section;
+static asection *dwarf_loc_section;
+static asection *dwarf_macinfo_section;
+static asection *dwarf_str_section;
+static asection *dwarf_ranges_section;
+asection *dwarf_frame_section;
+asection *dwarf_eh_frame_section;
 
 /* names of the debugging sections */
 
@@ -157,11 +192,17 @@ unsigned int dwarf_eh_frame_size;
 #define LOC_SECTION      ".debug_loc"
 #define MACINFO_SECTION  ".debug_macinfo"
 #define STR_SECTION      ".debug_str"
+#define RANGES_SECTION   ".debug_ranges"
 #define FRAME_SECTION    ".debug_frame"
 #define EH_FRAME_SECTION ".eh_frame"
 
 /* local data types */
 
+/* We hold several abbreviation tables in memory at the same time. */
+#ifndef ABBREV_HASH_SIZE
+#define ABBREV_HASH_SIZE 121
+#endif
+
 /* The data in a compilation unit header, after target2host
    translation, looks like this.  */
 struct comp_unit_head
@@ -174,8 +215,97 @@ struct comp_unit_head
     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 */
+
+    /* Offset to the first byte of this compilation unit header in the 
+     * .debug_info section, for resolving relative reference dies. */
+
+    unsigned int offset;
+
+    /* Pointer to this compilation unit header in the .debug_info
+     * section */
+
+    char *cu_head_ptr;
+
+    /* Pointer to the first die of this compilatio unit.  This will
+     * be the first byte following the compilation unit header. */
+
+    char *first_die_ptr;
+
+    /* Pointer to the next compilation unit header in the program. */
+
+    struct comp_unit_head *next;
+
+    /* Base address of this compilation unit.  */
+
+    CORE_ADDR base_address;
+
+    /* Non-zero if base_address has been set.  */
+
+    int base_known;
   };
 
+/* Internal state when decoding a particular compilation unit.  */
+struct dwarf2_cu
+{
+  /* The objfile containing this compilation unit.  */
+  struct objfile *objfile;
+
+  /* The header of the compilation unit.
+
+     FIXME drow/2003-11-10: Some of the things from the comp_unit_head
+     should logically be moved to the dwarf2_cu structure.  */
+  struct comp_unit_head header;
+
+  struct function_range *first_fn, *last_fn, *cached_fn;
+
+  /* The language we are debugging.  */
+  enum language language;
+  const struct language_defn *language_defn;
+
+  const char *producer;
+
+  /* The generic symbol table building routines have separate lists for
+     file scope symbols and all all other scopes (local scopes).  So
+     we need to select the right one to pass to add_symbol_to_list().
+     We do it by keeping a pointer to the correct list in list_in_scope.
+
+     FIXME: The original dwarf code just treated the file scope as the
+     first local scope, and all other local scopes as nested local
+     scopes, and worked fine.  Check to see if we really need to
+     distinguish these in buildsym.c.  */
+  struct pending **list_in_scope;
+
+  /* Maintain an array of referenced fundamental types for the current
+     compilation unit being read.  For DWARF version 1, we have to construct
+     the fundamental types on the fly, since no information about the
+     fundamental types is supplied.  Each such fundamental type is created by
+     calling a language dependent routine to create the type, and then a
+     pointer to that type is then placed in the array at the index specified
+     by it's FT_<TYPENAME> value.  The array has a fixed size set by the
+     FT_NUM_MEMBERS compile time constant, which is the number of predefined
+     fundamental types gdb knows how to construct.  */
+  struct type *ftypes[FT_NUM_MEMBERS]; /* Fundamental types */
+
+  /* DWARF abbreviation table associated with this compilation unit.  */
+  struct abbrev_info **dwarf2_abbrevs;
+
+  /* Storage for the abbrev table.  */
+  struct obstack abbrev_obstack;
+
+  /* Hash table holding all the loaded partial DIEs.  */
+  htab_t partial_dies;
+
+  /* Storage for things with the same lifetime as this read-in compilation
+     unit, including partial DIEs.  */
+  struct obstack comp_unit_obstack;
+
+  /* This flag will be set if this compilation unit includes any
+     DW_TAG_namespace DIEs.  If we know that there are explicit
+     DIEs for namespaces, we don't need to try to infer them
+     from mangled names.  */
+  unsigned int has_namespace_info : 1;
+};
+
 /* The line number information for a compilation unit (found in the
    .debug_line section) begins with a "statement program header",
    which contains the following information.  */
@@ -213,10 +343,11 @@ struct line_header
     unsigned int dir_index;
     unsigned int mod_time;
     unsigned int length;
+    int included_p; /* Non-zero if referenced by the Line Number Program.  */
   } *file_names;
 
   /* The start and end of the statement program following this
-     header.  These point into dwarf_line_buffer.  */
+     header.  These point into dwarf2_per_objfile->line_buffer.  */
   char *statement_program_start, *statement_program_end;
 };
 
@@ -224,20 +355,62 @@ struct line_header
    need this much information. */
 struct partial_die_info
   {
-    enum dwarf_tag tag;
-    unsigned char has_children;
-    unsigned char is_external;
-    unsigned char is_declaration;
-    unsigned char has_type;
+    /* Offset of this DIE.  */
     unsigned int offset;
-    unsigned int abbrev;
+
+    /* DWARF-2 tag for this DIE.  */
+    ENUM_BITFIELD(dwarf_tag) tag : 16;
+
+    /* Language code associated with this DIE.  This is only used
+       for the compilation unit DIE.  */
+    unsigned int language : 8;
+
+    /* Assorted flags describing the data found in this DIE.  */
+    unsigned int has_children : 1;
+    unsigned int is_external : 1;
+    unsigned int is_declaration : 1;
+    unsigned int has_type : 1;
+    unsigned int has_specification : 1;
+    unsigned int has_stmt_list : 1;
+    unsigned int has_pc_info : 1;
+
+    /* Flag set if the SCOPE field of this structure has been
+       computed.  */
+    unsigned int scope_set : 1;
+
+    /* The name of this DIE.  Normally the value of DW_AT_name, but
+       sometimes DW_TAG_MIPS_linkage_name or a string computed in some
+       other fashion.  */
     char *name;
-    int has_pc_info;
+    char *dirname;
+
+    /* The scope to prepend to our children.  This is generally
+       allocated on the comp_unit_obstack, so will disappear
+       when this compilation unit leaves the cache.  */
+    char *scope;
+
+    /* The location description associated with this DIE, if any.  */
+    struct dwarf_block *locdesc;
+
+    /* If HAS_PC_INFO, the PC range associated with this DIE.  */
     CORE_ADDR lowpc;
     CORE_ADDR highpc;
-    struct dwarf_block *locdesc;
-    unsigned int language;
+
+    /* Pointer into the info_buffer pointing at the target of
+       DW_AT_sibling, if any.  */
     char *sibling;
+
+    /* If HAS_SPECIFICATION, the offset of the DIE referred to by
+       DW_AT_specification (or DW_AT_abstract_origin or
+       DW_AT_extension).  */
+    unsigned int spec_offset;
+
+    /* If HAS_STMT_LIST, the offset of the Line Number Information data.  */
+    unsigned int line_offset;
+
+    /* Pointers to this DIE's parent, first child, and next sibling,
+       if any.  */
+    struct partial_die_info *die_parent, *die_child, *die_sibling;
   };
 
 /* This data structure holds the information of an abbrev. */
@@ -245,8 +418,8 @@ struct abbrev_info
   {
     unsigned int number;       /* number identifying abbrev */
     enum dwarf_tag tag;                /* dwarf tag */
-    int has_children;          /* boolean */
-    unsigned int num_attrs;    /* number of attributes */
+    unsigned short has_children;               /* boolean */
+    unsigned short num_attrs;  /* number of attributes */
     struct attr_abbrev *attrs; /* an array of attribute descriptions */
     struct abbrev_info *next;  /* next in chain */
   };
@@ -261,13 +434,21 @@ struct attr_abbrev
 struct die_info
   {
     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 */
+
+    /* The dies in a compilation unit form an n-ary tree.  PARENT
+       points to this die's parent; CHILD points to the first child of
+       this node; and all the children of a given node are chained
+       together via their SIBLING fields, terminated by a die whose
+       tag is zero.  */
+    struct die_info *child;    /* Its first child, if any.  */
+    struct die_info *sibling;  /* Its next sibling, if any.  */
+    struct die_info *parent;   /* Its parent, if any.  */
+
     struct type *type;         /* Cached type information */
   };
 
@@ -295,8 +476,6 @@ struct function_range
   struct function_range *next;
 };
 
-static struct function_range *cu_first_fn, *cu_last_fn, *cu_cached_fn;
-
 /* Get at parts of an attribute structure */
 
 #define DW_STRING(attr)    ((attr)->u.str)
@@ -312,17 +491,10 @@ struct dwarf_block
     char *data;
   };
 
-/* We only hold one compilation unit's abbrevs in
-   memory at any one time.  */
-#ifndef ABBREV_HASH_SIZE
-#define ABBREV_HASH_SIZE 121
-#endif
 #ifndef ATTR_ALLOC_CHUNK
 #define ATTR_ALLOC_CHUNK 4
 #endif
 
-static struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
-
 /* A hash table of die offsets for following references.  */
 #ifndef REF_HASH_SIZE
 #define REF_HASH_SIZE 1021
@@ -330,154 +502,35 @@ 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
 #endif
 
-/* The language we are debugging.  */
-static enum language cu_language;
-static const struct language_defn *cu_language_defn;
-
-/* Actually data from the sections.  */
-static char *dwarf_info_buffer;
-static char *dwarf_abbrev_buffer;
-static char *dwarf_line_buffer;
-static char *dwarf_str_buffer;
-static char *dwarf_macinfo_buffer;
-
 /* A zeroed version of a partial die for initialization purposes.  */
 static struct partial_die_info zeroed_partial_die;
 
-/* The generic symbol table building routines have separate lists for
-   file scope symbols and all all other scopes (local scopes).  So
-   we need to select the right one to pass to add_symbol_to_list().
-   We do it by keeping a pointer to the correct list in list_in_scope.
-
-   FIXME:  The original dwarf code just treated the file scope as the first
-   local scope, and all other local scopes as nested local scopes, and worked
-   fine.  Check to see if we really need to distinguish these
-   in buildsym.c.  */
-static struct pending **list_in_scope = &file_symbols;
-
 /* 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.  */
+   of the psymtab.  */
 
 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. */
+    /* Offset in .debug_info 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;
-
-    /* Size of dwarf_line_buffer, in bytes.  */
-    
-    unsigned int dwarf_line_size;
-
-    /* Pointer to start of dwarf string buffer for the objfile.  */
-
-    char *dwarf_str_buffer;
-
-    /* Size of dwarf string section for the objfile.  */
-
-    unsigned int dwarf_str_size;
-
-    /* Pointer to start of dwarf macro buffer for the objfile.  */
-
-    char *dwarf_macinfo_buffer;
-
-    /* Size of dwarf macinfo section for the objfile.  */
-    
-    unsigned int dwarf_macinfo_size;
-
   };
 
 #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)
-#define DWARF_LINE_SIZE(p)   (PST_PRIVATE(p)->dwarf_line_size)
-#define DWARF_STR_BUFFER(p)  (PST_PRIVATE(p)->dwarf_str_buffer)
-#define DWARF_STR_SIZE(p)    (PST_PRIVATE(p)->dwarf_str_size)
-#define DWARF_MACINFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_macinfo_buffer)
-#define DWARF_MACINFO_SIZE(p)   (PST_PRIVATE(p)->dwarf_macinfo_size)
-
-/* Maintain an array of referenced fundamental types for the current
-   compilation unit being read.  For DWARF version 1, we have to construct
-   the fundamental types on the fly, since no information about the
-   fundamental types is supplied.  Each such fundamental type is created by
-   calling a language dependent routine to create the type, and then a
-   pointer to that type is then placed in the array at the index specified
-   by it's FT_<TYPENAME> value.  The array has a fixed size set by the
-   FT_NUM_MEMBERS compile time constant, which is the number of predefined
-   fundamental types gdb knows how to construct.  */
-static struct type *ftypes[FT_NUM_MEMBERS];    /* Fundamental types */
 
 /* 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
@@ -534,176 +587,125 @@ struct field_info
 
 /* Various complaints about symbol reading that don't abort the process */
 
-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_statement_list_fits_in_line_number_section =
-{
-  "statement list doesn't fit in .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
-};
-static struct complaint dwarf2_misplaced_line_number =
-{
-  "misplaced first line number at 0x%lx for '%s'", 0, 0
-};
-static struct complaint dwarf2_line_header_too_long =
-{
-  "line number info header doesn't fit in `.debug_line' section", 0, 0
-};
-static struct complaint dwarf2_missing_macinfo_section =
-{
-  "missing .debug_macinfo section", 0, 0
-};
-static struct complaint dwarf2_macros_too_long =
-{
-  "macro info runs off end of `.debug_macinfo' section", 0, 0
-};
-static struct complaint dwarf2_macros_not_terminated =
+static void
+dwarf2_statement_list_fits_in_line_number_section_complaint (void)
 {
-  "no terminating 0-type entry for macros in `.debug_macinfo' section", 0, 0
-};
-static struct complaint dwarf2_macro_outside_file =
+  complaint (&symfile_complaints,
+            "statement list doesn't fit in .debug_line section");
+}
+
+static void
+dwarf2_complex_location_expr_complaint (void)
 {
-  "debug info gives macro %s outside of any file: %s", 0, 0
-};
-static struct complaint dwarf2_macro_unmatched_end_file =
+  complaint (&symfile_complaints, "location expression too complex");
+}
+
+static void
+dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2,
+                                             int arg3)
 {
-  "macro debug info has an unmatched `close_file' directive", 0, 0
-};
-static struct complaint dwarf2_macro_malformed_definition =
+  complaint (&symfile_complaints,
+            "const value length mismatch for '%s', got %d, expected %d", arg1,
+            arg2, arg3);
+}
+
+static void
+dwarf2_macros_too_long_complaint (void)
 {
-  "macro debug info contains a malformed macro definition:\n`%s'", 0, 0
-};
-static struct complaint dwarf2_macro_spaces_in_definition =
+  complaint (&symfile_complaints,
+            "macro info runs off end of `.debug_macinfo' section");
+}
+
+static void
+dwarf2_macro_malformed_definition_complaint (const char *arg1)
 {
-  "macro definition contains spaces in formal argument list:\n`%s'", 0, 0
-};
-static struct complaint dwarf2_invalid_attrib_class =
+  complaint (&symfile_complaints,
+            "macro debug info contains a malformed macro definition:\n`%s'",
+            arg1);
+}
+
+static void
+dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
 {
-  "invalid attribute class or form for '%s' in '%s'", 0, 0
-};
+  complaint (&symfile_complaints,
+            "invalid attribute class or form for '%s' in '%s'", arg1, arg2);
+}
 
 /* local function prototypes */
 
-static void dwarf2_locate_sections (bfd *, asection *, PTR);
+static void dwarf2_locate_sections (bfd *, asection *, void *);
 
 #if 0
 static void dwarf2_build_psymtabs_easy (struct objfile *, int);
 #endif
 
+static void dwarf2_create_include_psymtab (char *, struct partial_symtab *,
+                                           struct objfile *);
+
+static void dwarf2_build_include_psymtabs (struct dwarf2_cu *,
+                                           struct partial_die_info *,
+                                           struct partial_symtab *);
+
 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 scan_partial_symbols (struct partial_die_info *,
+                                 CORE_ADDR *, CORE_ADDR *,
+                                 struct dwarf2_cu *);
+
+static void add_partial_symbol (struct partial_die_info *,
+                               struct dwarf2_cu *);
 
-static void add_partial_symbol (struct partial_die_info *, struct objfile *,
-                               const struct comp_unit_head *);
+static int pdi_needs_namespace (enum dwarf_tag tag);
+
+static void add_partial_namespace (struct partial_die_info *pdi,
+                                  CORE_ADDR *lowpc, CORE_ADDR *highpc,
+                                  struct dwarf2_cu *cu);
+
+static void add_partial_enumeration (struct partial_die_info *enum_pdi,
+                                    struct dwarf2_cu *cu);
+
+static char *locate_pdi_sibling (struct partial_die_info *orig_pdi,
+                                char *info_ptr,
+                                bfd *abfd,
+                                struct dwarf2_cu *cu);
 
 static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
 
 static void psymtab_to_symtab_1 (struct partial_symtab *);
 
-char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int);
+char *dwarf2_read_section (struct objfile *, asection *);
+
+static void dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu);
 
-static void dwarf2_read_abbrevs (bfd *, unsigned int);
+static void dwarf2_free_abbrev_table (void *);
 
-static void dwarf2_empty_abbrev_table (PTR);
+static struct abbrev_info *peek_die_abbrev (char *, int *, struct dwarf2_cu *);
 
-static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int);
+static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int,
+                                                struct dwarf2_cu *);
+
+static struct partial_die_info *load_partial_dies (bfd *, char *, int,
+                                                  struct dwarf2_cu *);
 
 static char *read_partial_die (struct partial_die_info *,
-                              bfd *, char *,
-                              const struct comp_unit_head *);
+                              struct abbrev_info *abbrev, unsigned int,
+                              bfd *, char *, struct dwarf2_cu *);
+
+static struct partial_die_info *find_partial_die (unsigned long,
+                                                 struct dwarf2_cu *,
+                                                 struct dwarf2_cu **);
+
+static void fixup_partial_die (struct partial_die_info *,
+                              struct dwarf2_cu *);
 
 static char *read_full_die (struct die_info **, bfd *, char *,
-                           const struct comp_unit_head *);
+                           struct dwarf2_cu *, int *);
 
 static char *read_attribute (struct attribute *, struct attr_abbrev *,
-                            bfd *, char *, const struct comp_unit_head *);
+                            bfd *, char *, struct dwarf2_cu *);
 
 static char *read_attribute_value (struct attribute *, unsigned,
-                            bfd *, char *, const struct comp_unit_head *);
+                            bfd *, char *, struct dwarf2_cu *);
 
 static unsigned int read_1_byte (bfd *, char *);
 
@@ -715,7 +717,7 @@ static unsigned int read_4_bytes (bfd *, char *);
 
 static unsigned long read_8_bytes (bfd *, char *);
 
-static CORE_ADDR read_address (bfd *, char *ptr, const struct comp_unit_head *,
+static CORE_ADDR read_address (bfd *, char *ptr, struct dwarf2_cu *,
                               int *bytes_read);
 
 static LONGEST read_initial_length (bfd *, char *,
@@ -735,129 +737,159 @@ static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *);
 
 static long read_signed_leb128 (bfd *, char *, unsigned int *);
 
-static void set_cu_language (unsigned int);
+static char *skip_leb128 (bfd *, char *);
+
+static void set_cu_language (unsigned int, struct dwarf2_cu *);
 
-static struct attribute *dwarf_attr (struct die_info *, unsigned int);
+static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
+                                     struct dwarf2_cu *);
 
-static int die_is_declaration (struct die_info *);
+static int dwarf2_flag_true_p (struct die_info *die, unsigned name,
+                               struct dwarf2_cu *cu);
+
+static int die_is_declaration (struct die_info *, struct dwarf2_cu *cu);
+
+static struct die_info *die_specification (struct die_info *die,
+                                          struct dwarf2_cu *);
 
 static void free_line_header (struct line_header *lh);
 
+static void add_file_name (struct line_header *, char *, unsigned int,
+                           unsigned int, unsigned int);
+
 static struct line_header *(dwarf_decode_line_header
                             (unsigned int offset,
-                             bfd *abfd,
-                             const struct comp_unit_head *cu_header));
+                             bfd *abfd, struct dwarf2_cu *cu));
 
 static void dwarf_decode_lines (struct line_header *, char *, bfd *,
-                               const struct comp_unit_head *);
+                               struct dwarf2_cu *, struct partial_symtab *);
 
 static void dwarf2_start_subfile (char *, char *);
 
 static struct symbol *new_symbol (struct die_info *, struct type *,
-                                 struct objfile *, const struct comp_unit_head *);
+                                 struct dwarf2_cu *);
 
 static void dwarf2_const_value (struct attribute *, struct symbol *,
-                               struct objfile *, const struct comp_unit_head *);
+                               struct dwarf2_cu *);
 
 static void dwarf2_const_value_data (struct attribute *attr,
                                     struct symbol *sym,
                                     int bits);
 
-static struct type *die_type (struct die_info *, struct objfile *,
-                             const struct comp_unit_head *);
+static struct type *die_type (struct die_info *, struct dwarf2_cu *);
 
-static struct type *die_containing_type (struct die_info *, struct objfile *,
-                                        const struct comp_unit_head *);
+static struct type *die_containing_type (struct die_info *,
+                                        struct dwarf2_cu *);
 
 #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 struct type *tag_type_to_type (struct die_info *, struct dwarf2_cu *);
+
+static void read_type_die (struct die_info *, struct dwarf2_cu *);
 
-static void read_type_die (struct die_info *, struct objfile *,
-                          const struct comp_unit_head *);
+static char *determine_prefix (struct die_info *die, struct dwarf2_cu *);
 
-static void read_typedef (struct die_info *, struct objfile *,
-                         const struct comp_unit_head *);
+static char *typename_concat (const char *prefix, const char *suffix);
 
-static void read_base_type (struct die_info *, struct objfile *);
+static void read_typedef (struct die_info *, struct dwarf2_cu *);
 
-static void read_file_scope (struct die_info *, struct objfile *,
-                            const struct comp_unit_head *);
+static void read_base_type (struct die_info *, struct dwarf2_cu *);
 
-static void read_func_scope (struct die_info *, struct objfile *,
-                            const struct comp_unit_head *);
+static void read_subrange_type (struct die_info *die, struct dwarf2_cu *cu);
 
-static void read_lexical_block_scope (struct die_info *, struct objfile *,
-                                     const struct comp_unit_head *);
+static void read_file_scope (struct die_info *, struct dwarf2_cu *);
+
+static void read_func_scope (struct die_info *, struct dwarf2_cu *);
+
+static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *);
 
 static int dwarf2_get_pc_bounds (struct die_info *,
-                                CORE_ADDR *, CORE_ADDR *, struct objfile *);
+                                CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *);
+
+static void get_scope_pc_bounds (struct die_info *,
+                                CORE_ADDR *, CORE_ADDR *,
+                                struct dwarf2_cu *);
 
 static void dwarf2_add_field (struct field_info *, struct die_info *,
-                             struct objfile *, const struct comp_unit_head *);
+                             struct dwarf2_cu *);
 
 static void dwarf2_attach_fields_to_type (struct field_info *,
-                                         struct type *, struct objfile *);
+                                         struct type *, struct dwarf2_cu *);
 
 static void dwarf2_add_member_fn (struct field_info *,
                                  struct die_info *, struct type *,
-                                 struct objfile *objfile,
-                                 const struct comp_unit_head *);
+                                 struct dwarf2_cu *);
 
 static void dwarf2_attach_fn_fields_to_type (struct field_info *,
-                                            struct type *, struct objfile *);
+                                            struct type *, struct dwarf2_cu *);
+
+static void read_structure_type (struct die_info *, struct dwarf2_cu *);
 
-static void read_structure_scope (struct die_info *, struct objfile *,
-                                 const struct comp_unit_head *);
+static void process_structure_scope (struct die_info *, struct dwarf2_cu *);
 
-static void read_common_block (struct die_info *, struct objfile *,
-                              const struct comp_unit_head *);
+static char *determine_class_name (struct die_info *die, struct dwarf2_cu *cu);
 
-static void read_enumeration (struct die_info *, struct objfile *,
-                             const struct comp_unit_head *);
+static void read_common_block (struct die_info *, struct dwarf2_cu *);
 
-static struct type *dwarf_base_type (int, int, struct objfile *);
+static void read_namespace (struct die_info *die, struct dwarf2_cu *);
 
-static CORE_ADDR decode_locdesc (struct dwarf_block *, struct objfile *,
-                                const struct comp_unit_head *);
+static const char *namespace_name (struct die_info *die,
+                                  int *is_anonymous, struct dwarf2_cu *);
 
-static void read_array_type (struct die_info *, struct objfile *,
-                            const struct comp_unit_head *);
+static void read_enumeration_type (struct die_info *, struct dwarf2_cu *);
 
-static void read_tag_pointer_type (struct die_info *, struct objfile *,
-                                  const struct comp_unit_head *);
+static void process_enumeration_scope (struct die_info *, struct dwarf2_cu *);
 
-static void read_tag_ptr_to_member_type (struct die_info *, struct objfile *,
-                                        const struct comp_unit_head *);
+static struct type *dwarf_base_type (int, int, struct dwarf2_cu *);
 
-static void read_tag_reference_type (struct die_info *, struct objfile *,
-                                    const struct comp_unit_head *);
+static CORE_ADDR decode_locdesc (struct dwarf_block *, struct dwarf2_cu *);
 
-static void read_tag_const_type (struct die_info *, struct objfile *,
-                                const struct comp_unit_head *);
+static void read_array_type (struct die_info *, struct dwarf2_cu *);
 
-static void read_tag_volatile_type (struct die_info *, struct objfile *,
-                                   const struct comp_unit_head *);
+static enum dwarf_array_dim_ordering read_array_order (struct die_info *, 
+                                                      struct dwarf2_cu *);
 
-static void read_tag_string_type (struct die_info *, struct objfile *);
+static void read_tag_pointer_type (struct die_info *, struct dwarf2_cu *);
 
-static void read_subroutine_type (struct die_info *, struct objfile *,
-                                 const struct comp_unit_head *);
+static void read_tag_ptr_to_member_type (struct die_info *,
+                                        struct dwarf2_cu *);
 
-static struct die_info *read_comp_unit (char *, bfd *,
-                                        const struct comp_unit_head *);
+static void read_tag_reference_type (struct die_info *, struct dwarf2_cu *);
+
+static void read_tag_const_type (struct die_info *, struct dwarf2_cu *);
+
+static void read_tag_volatile_type (struct die_info *, struct dwarf2_cu *);
+
+static void read_tag_string_type (struct die_info *, struct dwarf2_cu *);
+
+static void read_subroutine_type (struct die_info *, struct dwarf2_cu *);
+
+static struct die_info *read_comp_unit (char *, bfd *, struct dwarf2_cu *);
+
+static struct die_info *read_die_and_children (char *info_ptr, bfd *abfd,
+                                              struct dwarf2_cu *,
+                                              char **new_info_ptr,
+                                              struct die_info *parent);
+
+static struct die_info *read_die_and_siblings (char *info_ptr, bfd *abfd,
+                                              struct dwarf2_cu *,
+                                              char **new_info_ptr,
+                                              struct die_info *parent);
 
 static void free_die_list (struct die_info *);
 
 static struct cleanup *make_cleanup_free_die_list (struct die_info *);
 
-static void process_die (struct die_info *, struct objfile *,
-                        const struct comp_unit_head *);
+static void process_die (struct die_info *, struct dwarf2_cu *);
+
+static char *dwarf2_linkage_name (struct die_info *, struct dwarf2_cu *);
 
-static char *dwarf2_linkage_name (struct die_info *);
+static char *dwarf2_name (struct die_info *die, struct dwarf2_cu *);
+
+static struct die_info *dwarf2_extension (struct die_info *die,
+                                         struct dwarf2_cu *);
 
 static char *dwarf_tag_name (unsigned int);
 
@@ -887,54 +919,77 @@ static void store_in_ref_table (unsigned int, struct die_info *);
 
 static void dwarf2_empty_hash_tables (void);
 
-static unsigned int dwarf2_get_ref_die_offset (struct attribute *);
+static unsigned int dwarf2_get_ref_die_offset (struct attribute *,
+                                              struct dwarf2_cu *);
+
+static int dwarf2_get_attr_constant_value (struct attribute *, int);
 
 static struct die_info *follow_die_ref (unsigned int);
 
-static struct type *dwarf2_fundamental_type (struct objfile *, int);
+static struct type *dwarf2_fundamental_type (struct objfile *, int,
+                                            struct dwarf2_cu *);
 
 /* memory allocation interface */
 
-static void dwarf2_free_tmp_obstack (PTR);
+static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *);
 
-static struct dwarf_block *dwarf_alloc_block (void);
-
-static struct abbrev_info *dwarf_alloc_abbrev (void);
+static struct abbrev_info *dwarf_alloc_abbrev (struct dwarf2_cu *);
 
 static struct die_info *dwarf_alloc_die (void);
 
-static void initialize_cu_func_list (void);
+static void initialize_cu_func_list (struct dwarf2_cu *);
 
-static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR);
+static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR,
+                                struct dwarf2_cu *);
 
 static void dwarf_decode_macros (struct line_header *, unsigned int,
-                                 char *, bfd *, const struct comp_unit_head *,
-                                 struct objfile *);
+                                 char *, bfd *, struct dwarf2_cu *);
 
 static int attr_form_is_block (struct attribute *);
 
+static void
+dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+                            struct dwarf2_cu *cu);
+
+static char *skip_one_die (char *info_ptr, struct abbrev_info *abbrev,
+                          struct dwarf2_cu *cu);
+
+static void free_stack_comp_unit (void *);
+
+static void *hashtab_obstack_allocate (void *data, size_t size, size_t count);
+
+static void dummy_obstack_deallocate (void *object, void *data);
+
+static hashval_t partial_die_hash (const void *item);
+
+static int partial_die_eq (const void *item_lhs, const void *item_rhs);
+
 /* 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 (bfd *abfd)
-{
-  dwarf_info_offset = 0;
-  dwarf_abbrev_offset = 0;
-  dwarf_line_offset = 0;
-  dwarf_str_offset = 0;
-  dwarf_macinfo_offset = 0;
-  dwarf_frame_offset = 0;
-  dwarf_eh_frame_offset = 0;
-  bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
-  if (dwarf_info_offset && dwarf_abbrev_offset)
-    {
-      return 1;
-    }
-  else
-    {
-      return 0;
-    }
+dwarf2_has_info (struct objfile *objfile)
+{
+  struct dwarf2_per_objfile *data;
+
+  /* Initialize per-objfile state.  */
+  data = obstack_alloc (&objfile->objfile_obstack, sizeof (*data));
+  memset (data, 0, sizeof (*data));
+  set_objfile_data (objfile, dwarf2_objfile_data_key, data);
+  dwarf2_per_objfile = data;
+
+  dwarf_info_section = 0;
+  dwarf_abbrev_section = 0;
+  dwarf_line_section = 0;
+  dwarf_str_section = 0;
+  dwarf_macinfo_section = 0;
+  dwarf_frame_section = 0;
+  dwarf_eh_frame_section = 0;
+  dwarf_ranges_section = 0;
+  dwarf_loc_section = 0;
+  
+  bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL);
+  return (dwarf_info_section != NULL && dwarf_abbrev_section != NULL);
 }
 
 /* This function is mapped across the sections and remembers the
@@ -942,57 +997,66 @@ dwarf2_has_info (bfd *abfd)
    in.  */
 
 static void
-dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, PTR ignore_ptr)
+dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, void *ignore_ptr)
 {
-  if (STREQ (sectp->name, INFO_SECTION))
+  if (strcmp (sectp->name, INFO_SECTION) == 0)
+    {
+      dwarf2_per_objfile->info_size = bfd_get_section_size (sectp);
+      dwarf_info_section = sectp;
+    }
+  else if (strcmp (sectp->name, ABBREV_SECTION) == 0)
     {
-      dwarf_info_offset = sectp->filepos;
-      dwarf_info_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf2_per_objfile->abbrev_size = bfd_get_section_size (sectp);
+      dwarf_abbrev_section = sectp;
     }
-  else if (STREQ (sectp->name, ABBREV_SECTION))
+  else if (strcmp (sectp->name, LINE_SECTION) == 0)
     {
-      dwarf_abbrev_offset = sectp->filepos;
-      dwarf_abbrev_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf2_per_objfile->line_size = bfd_get_section_size (sectp);
+      dwarf_line_section = sectp;
     }
-  else if (STREQ (sectp->name, LINE_SECTION))
+  else if (strcmp (sectp->name, PUBNAMES_SECTION) == 0)
     {
-      dwarf_line_offset = sectp->filepos;
-      dwarf_line_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf2_per_objfile->pubnames_size = bfd_get_section_size (sectp);
+      dwarf_pubnames_section = sectp;
     }
-  else if (STREQ (sectp->name, PUBNAMES_SECTION))
+  else if (strcmp (sectp->name, ARANGES_SECTION) == 0)
     {
-      dwarf_pubnames_offset = sectp->filepos;
-      dwarf_pubnames_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf2_per_objfile->aranges_size = bfd_get_section_size (sectp);
+      dwarf_aranges_section = sectp;
     }
-  else if (STREQ (sectp->name, ARANGES_SECTION))
+  else if (strcmp (sectp->name, LOC_SECTION) == 0)
     {
-      dwarf_aranges_offset = sectp->filepos;
-      dwarf_aranges_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf2_per_objfile->loc_size = bfd_get_section_size (sectp);
+      dwarf_loc_section = sectp;
     }
-  else if (STREQ (sectp->name, LOC_SECTION))
+  else if (strcmp (sectp->name, MACINFO_SECTION) == 0)
     {
-      dwarf_loc_offset = sectp->filepos;
-      dwarf_loc_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf2_per_objfile->macinfo_size = bfd_get_section_size (sectp);
+      dwarf_macinfo_section = sectp;
     }
-  else if (STREQ (sectp->name, MACINFO_SECTION))
+  else if (strcmp (sectp->name, STR_SECTION) == 0)
     {
-      dwarf_macinfo_offset = sectp->filepos;
-      dwarf_macinfo_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf2_per_objfile->str_size = bfd_get_section_size (sectp);
+      dwarf_str_section = sectp;
     }
-  else if (STREQ (sectp->name, STR_SECTION))
+  else if (strcmp (sectp->name, FRAME_SECTION) == 0)
     {
-      dwarf_str_offset = sectp->filepos;
-      dwarf_str_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf2_per_objfile->frame_size = bfd_get_section_size (sectp);
+      dwarf_frame_section = sectp;
     }
-  else if (STREQ (sectp->name, FRAME_SECTION))
+  else if (strcmp (sectp->name, EH_FRAME_SECTION) == 0)
     {
-      dwarf_frame_offset = sectp->filepos;
-      dwarf_frame_size = bfd_get_section_size_before_reloc (sectp);
+      flagword aflag = bfd_get_section_flags (ignore_abfd, sectp);
+      if (aflag & SEC_HAS_CONTENTS)
+        {
+          dwarf2_per_objfile->eh_frame_size = bfd_get_section_size (sectp);
+          dwarf_eh_frame_section = sectp;
+        }
     }
-  else if (STREQ (sectp->name, EH_FRAME_SECTION))
+  else if (strcmp (sectp->name, RANGES_SECTION) == 0)
     {
-      dwarf_eh_frame_offset = sectp->filepos;
-      dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf2_per_objfile->ranges_size = bfd_get_section_size (sectp);
+      dwarf_ranges_section = sectp;
     }
 }
 
@@ -1001,36 +1065,36 @@ dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, PTR ignore_ptr)
 void
 dwarf2_build_psymtabs (struct objfile *objfile, int mainline)
 {
-
   /* We definitely need the .debug_info and .debug_abbrev sections */
 
-  dwarf_info_buffer = dwarf2_read_section (objfile,
-                                          dwarf_info_offset,
-                                          dwarf_info_size);
-  dwarf_abbrev_buffer = dwarf2_read_section (objfile,
-                                            dwarf_abbrev_offset,
-                                            dwarf_abbrev_size);
-
-  if (dwarf_line_offset)
-    dwarf_line_buffer = dwarf2_read_section (objfile,
-                                            dwarf_line_offset,
-                                            dwarf_line_size);
+  dwarf2_per_objfile->info_buffer = dwarf2_read_section (objfile, dwarf_info_section);
+  dwarf2_per_objfile->abbrev_buffer = dwarf2_read_section (objfile, dwarf_abbrev_section);
+
+  if (dwarf_line_section)
+    dwarf2_per_objfile->line_buffer = dwarf2_read_section (objfile, dwarf_line_section);
+  else
+    dwarf2_per_objfile->line_buffer = NULL;
+
+  if (dwarf_str_section)
+    dwarf2_per_objfile->str_buffer = dwarf2_read_section (objfile, dwarf_str_section);
+  else
+    dwarf2_per_objfile->str_buffer = NULL;
+
+  if (dwarf_macinfo_section)
+    dwarf2_per_objfile->macinfo_buffer = dwarf2_read_section (objfile,
+                                               dwarf_macinfo_section);
   else
-    dwarf_line_buffer = NULL;
+    dwarf2_per_objfile->macinfo_buffer = NULL;
 
-  if (dwarf_str_offset)
-    dwarf_str_buffer = dwarf2_read_section (objfile,
-                                           dwarf_str_offset,
-                                           dwarf_str_size);
+  if (dwarf_ranges_section)
+    dwarf2_per_objfile->ranges_buffer = dwarf2_read_section (objfile, dwarf_ranges_section);
   else
-    dwarf_str_buffer = NULL;
+    dwarf2_per_objfile->ranges_buffer = NULL;
 
-  if (dwarf_macinfo_offset)
-    dwarf_macinfo_buffer = dwarf2_read_section (objfile,
-                                                dwarf_macinfo_offset,
-                                                dwarf_macinfo_size);
+  if (dwarf_loc_section)
+    dwarf2_per_objfile->loc_buffer = dwarf2_read_section (objfile, dwarf_loc_section);
   else
-    dwarf_macinfo_buffer = NULL;
+    dwarf2_per_objfile->loc_buffer = NULL;
 
   if (mainline
       || (objfile->global_psymbols.size == 0
@@ -1069,10 +1133,9 @@ dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
   unsigned int entry_length, version, info_offset, info_size;
 
   pubnames_buffer = dwarf2_read_section (objfile,
-                                        dwarf_pubnames_offset,
-                                        dwarf_pubnames_size);
+                                        dwarf_pubnames_section);
   pubnames_ptr = pubnames_buffer;
-  while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
+  while ((pubnames_ptr - pubnames_buffer) < dwarf2_per_objfile->pubnames_size)
     {
       struct comp_unit_head cu_header;
       int bytes_read;
@@ -1089,8 +1152,7 @@ dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
     }
 
   aranges_buffer = dwarf2_read_section (objfile,
-                                       dwarf_aranges_offset,
-                                       dwarf_aranges_size);
+                                       dwarf_aranges_section);
 
 }
 #endif
@@ -1122,6 +1184,99 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
   return info_ptr;
 }
 
+static char *
+partial_read_comp_unit_head (struct comp_unit_head *header, char *info_ptr,
+                            bfd *abfd)
+{
+  char *beg_of_comp_unit = info_ptr;
+
+  info_ptr = read_comp_unit_head (header, info_ptr, abfd);
+
+  if (header->version != 2)
+    error ("Dwarf Error: wrong version in compilation unit header "
+          "(is %d, should be %d) [in module %s]", header->version,
+          2, bfd_get_filename (abfd));
+
+  if (header->abbrev_offset >= dwarf2_per_objfile->abbrev_size)
+    error ("Dwarf Error: bad offset (0x%lx) in compilation unit header "
+          "(offset 0x%lx + 6) [in module %s]",
+          (long) header->abbrev_offset,
+          (long) (beg_of_comp_unit - dwarf2_per_objfile->info_buffer),
+          bfd_get_filename (abfd));
+
+  if (beg_of_comp_unit + header->length + header->initial_length_size
+      > dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size)
+    error ("Dwarf Error: bad length (0x%lx) in compilation unit header "
+          "(offset 0x%lx + 0) [in module %s]",
+          (long) header->length,
+          (long) (beg_of_comp_unit - dwarf2_per_objfile->info_buffer),
+          bfd_get_filename (abfd));
+
+  return info_ptr;
+}
+
+/* Allocate a new partial symtab for file named NAME and mark this new
+   partial symtab as being an include of PST.  */
+
+static void
+dwarf2_create_include_psymtab (char *name, struct partial_symtab *pst,
+                               struct objfile *objfile)
+{
+  struct partial_symtab *subpst = allocate_psymtab (name, objfile);
+
+  subpst->section_offsets = pst->section_offsets;
+  subpst->textlow = 0;
+  subpst->texthigh = 0;
+
+  subpst->dependencies = (struct partial_symtab **)
+    obstack_alloc (&objfile->objfile_obstack,
+                   sizeof (struct partial_symtab *));
+  subpst->dependencies[0] = pst;
+  subpst->number_of_dependencies = 1;
+
+  subpst->globals_offset = 0;
+  subpst->n_global_syms = 0;
+  subpst->statics_offset = 0;
+  subpst->n_static_syms = 0;
+  subpst->symtab = NULL;
+  subpst->read_symtab = pst->read_symtab;
+  subpst->readin = 0;
+
+  /* No private part is necessary for include psymtabs.  This property
+     can be used to differentiate between such include psymtabs and
+     the regular ones.  If it ever happens that a regular psymtab can
+     legitimally have a NULL private part, then we'll have to add a
+     dedicated field for that in the dwarf2_pinfo structure.  */
+  subpst->read_symtab_private = NULL;
+}
+
+/* Read the Line Number Program data and extract the list of files
+   included by the source file represented by PST.  Build an include
+   partial symtab for each of these included files.
+   
+   This procedure assumes that there *is* a Line Number Program in
+   the given CU.  Callers should check that PDI->HAS_STMT_LIST is set
+   before calling this procedure.  */
+
+static void
+dwarf2_build_include_psymtabs (struct dwarf2_cu *cu,
+                               struct partial_die_info *pdi,
+                               struct partial_symtab *pst)
+{
+  struct objfile *objfile = cu->objfile;
+  bfd *abfd = objfile->obfd;
+  struct line_header *lh;
+
+  lh = dwarf_decode_line_header (pdi->line_offset, abfd, cu);
+  if (lh == NULL)
+    return;  /* No linetable, so no includes.  */
+
+  dwarf_decode_lines (lh, NULL, abfd, cu, pst);
+
+  free_line_header (lh);
+}
+
+
 /* Build the partial symbol table by doing a quick pass through the
    .debug_info and .debug_abbrev sections.  */
 
@@ -1131,96 +1286,67 @@ 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 *info_ptr;
   char *beg_of_comp_unit;
   struct partial_die_info comp_unit_die;
   struct partial_symtab *pst;
-  struct cleanup *back_to;
-  CORE_ADDR lowpc, highpc;
+  CORE_ADDR lowpc, highpc, baseaddr;
 
-  info_ptr = dwarf_info_buffer;
-  abbrev_ptr = dwarf_abbrev_buffer;
+  info_ptr = dwarf2_per_objfile->info_buffer;
 
-  /* We use dwarf2_tmp_obstack for objects that don't need to survive
-     the partial symbol scan, like attribute values.
+  /* Since the objects we're extracting from .debug_info vary in
+     length, only the individual functions to extract them (like
+     read_comp_unit_head and load_partial_die) can really know whether
+     the buffer is large enough to hold another complete object.
 
-     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:
+     At the moment, they don't actually check that.  If .debug_info
+     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.
 
-     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.
+     For this loop condition, simply checking whether there's any data
+     left at all should be sufficient.  */
+  while (info_ptr < (dwarf2_per_objfile->info_buffer
+                    + dwarf2_per_objfile->info_size))
+    {
+      struct cleanup *back_to_inner;
+      struct dwarf2_cu cu;
+      struct abbrev_info *abbrev;
+      unsigned int bytes_read;
+      struct dwarf2_per_cu_data *this_cu;
 
-     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.
+      beg_of_comp_unit = info_ptr;
 
-     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.
+      memset (&cu, 0, sizeof (cu));
 
-     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 (&cu.comp_unit_obstack);
 
-  obstack_init (&dwarf2_tmp_obstack);
-  back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
+      back_to_inner = make_cleanup (free_stack_comp_unit, &cu);
 
-  /* 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.
+      cu.objfile = objfile;
+      info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, abfd);
 
-     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.
+      /* Complete the cu_header */
+      cu.header.offset = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
+      cu.header.first_die_ptr = info_ptr;
+      cu.header.cu_head_ptr = beg_of_comp_unit;
 
-     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;
-      info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd);
+      cu.list_in_scope = &file_symbols;
+
+      cu.partial_dies = NULL;
 
-      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);
-      make_cleanup (dwarf2_empty_abbrev_table, NULL);
+      dwarf2_read_abbrevs (abfd, &cu);
+      make_cleanup (dwarf2_free_abbrev_table, &cu);
 
       /* Read the compilation unit die */
-      info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr,
-                                  &cu_header);
+      abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu);
+      info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read,
+                                  abfd, info_ptr, &cu);
 
       /* Set the language we're debugging */
-      set_cu_language (comp_unit_die.language);
+      set_cu_language (comp_unit_die.language, &cu);
 
       /* Allocate a new partial symbol table structure */
       pst = start_psymtab_common (objfile, objfile->section_offsets,
@@ -1229,19 +1355,12 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
                                  objfile->global_psymbols.next,
                                  objfile->static_psymbols.next);
 
+         if (comp_unit_die.dirname)
+        pst->dirname = xstrdup (comp_unit_die.dirname);
+
       pst->read_symtab_private = (char *)
-       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;
-      DWARF_LINE_SIZE (pst) = dwarf_line_size;
-      DWARF_STR_BUFFER (pst) = dwarf_str_buffer;
-      DWARF_STR_SIZE (pst) = dwarf_str_size;
-      DWARF_MACINFO_BUFFER (pst) = dwarf_macinfo_buffer;
-      DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size;
+       obstack_alloc (&objfile->objfile_obstack, sizeof (struct dwarf2_pinfo));
+      DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
       baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
       /* Store the function that reads in the rest of the symbol table */
@@ -1252,8 +1371,19 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
          If not, there's no more debug_info for this comp unit. */
       if (comp_unit_die.has_children)
        {
-         info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc,
-                                          &cu_header);
+         struct partial_die_info *first_die;
+
+         lowpc = ((CORE_ADDR) -1);
+         highpc = ((CORE_ADDR) 0);
+
+         first_die = load_partial_dies (abfd, info_ptr, 1, &cu);
+
+         scan_partial_symbols (first_die, &lowpc, &highpc, &cu);
+
+         /* If we didn't find a lowpc, set it to highpc to avoid
+            complaints from `maint check'.  */
+         if (lowpc == ((CORE_ADDR) -1))
+           lowpc = highpc;
 
          /* If the compilation unit didn't have an explicit address range,
             then use the information extracted from its child dies.  */
@@ -1277,141 +1407,248 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
          also happen.) This happens in VxWorks.  */
       free_named_symtabs (pst->filename);
 
-      info_ptr = beg_of_comp_unit + cu_header.length 
-                                  + cu_header.initial_length_size;
+      if (comp_unit_die.has_stmt_list)
+        {
+          /* Get the list of files included in the current compilation unit,
+             and build a psymtab for each of them.  */
+          dwarf2_build_include_psymtabs (&cu, &comp_unit_die, pst);
+        }
+
+      info_ptr = beg_of_comp_unit + cu.header.length
+                                  + cu.header.initial_length_size;
+
+      do_cleanups (back_to_inner);
     }
-  do_cleanups (back_to);
 }
 
-/* Read in all interesting dies to the end of the compilation unit.  */
+/* Process all loaded DIEs for compilation unit CU, starting at FIRST_DIE.
+   Also set *LOWPC and *HIGHPC to the lowest and highest PC values found
+   in CU.  */
 
-static char *
-scan_partial_symbols (char *info_ptr, struct objfile *objfile,
-                     CORE_ADDR *lowpc, CORE_ADDR *highpc,
-                     const struct comp_unit_head *cu_header)
+static void
+scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
+                     CORE_ADDR *highpc, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
   bfd *abfd = objfile->obfd;
-  struct partial_die_info pdi;
+  struct partial_die_info *pdi;
 
-  /* 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. */
+  /* Now, march along the PDI's, descending into ones which have
+     interesting children but skipping the children of the other ones,
+     until we reach the end of the compilation unit.  */
 
-  int nesting_level = 1;
-
-  *lowpc = ((CORE_ADDR) -1);
-  *highpc = ((CORE_ADDR) 0);
+  pdi = first_die;
 
-  while (nesting_level)
+  while (pdi != NULL)
     {
-      info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
+      fixup_partial_die (pdi, cu);
+
+      /* Anonymous namespaces have no name but have interesting
+        children, so we need to look at them.  Ditto for anonymous
+        enums.  */
 
-      if (pdi.name)
+      if (pdi->name != NULL || pdi->tag == DW_TAG_namespace
+         || pdi->tag == DW_TAG_enumeration_type)
        {
-         switch (pdi.tag)
+         switch (pdi->tag)
            {
            case DW_TAG_subprogram:
-             if (pdi.has_pc_info)
+             if (pdi->has_pc_info)
                {
-                 if (pdi.lowpc < *lowpc)
+                 if (pdi->lowpc < *lowpc)
                    {
-                     *lowpc = pdi.lowpc;
+                     *lowpc = pdi->lowpc;
                    }
-                 if (pdi.highpc > *highpc)
+                 if (pdi->highpc > *highpc)
                    {
-                     *highpc = pdi.highpc;
+                     *highpc = pdi->highpc;
                    }
-                 if ((pdi.is_external || nesting_level == 1)
-                     && !pdi.is_declaration)
+                 if (!pdi->is_declaration)
                    {
-                     add_partial_symbol (&pdi, objfile, cu_header);
+                     add_partial_symbol (pdi, cu);
                    }
                }
              break;
            case DW_TAG_variable:
            case DW_TAG_typedef:
+           case DW_TAG_union_type:
+             if (!pdi->is_declaration)
+               {
+                 add_partial_symbol (pdi, cu);
+               }
+             break;
            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)
+             if (!pdi->is_declaration)
                {
-                 add_partial_symbol (&pdi, objfile, cu_header);
+                 add_partial_symbol (pdi, cu);
                }
              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);
+           case DW_TAG_enumeration_type:
+             if (!pdi->is_declaration)
+               add_partial_enumeration (pdi, cu);
              break;
            case DW_TAG_base_type:
+            case DW_TAG_subrange_type:
              /* File scope base type definitions are added to the partial
                 symbol table.  */
-             if (nesting_level == 1)
-               add_partial_symbol (&pdi, objfile, cu_header);
+             add_partial_symbol (pdi, cu);
+             break;
+           case DW_TAG_namespace:
+             add_partial_namespace (pdi, lowpc, highpc, cu);
              break;
            default:
              break;
            }
        }
 
-      /* 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 the die has a sibling, skip to the sibling.  */
 
-      if (pdi.tag == 0)
-       {
-         nesting_level--;
-       }
+      pdi = pdi->die_sibling;
     }
+}
 
-  /* 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;
+/* Functions used to compute the fully scoped name of a partial DIE.
+
+   Normally, this is simple.  For C++, the parent DIE's fully scoped
+   name is concatenated with "::" and the partial DIE's name.
+   Enumerators are an exception; they use the scope of their parent
+   enumeration type, i.e. the name of the enumeration type is not
+   prepended to the enumerator.
+
+   There are two complexities.  One is DW_AT_specification; in this
+   case "parent" means the parent of the target of the specification,
+   instead of the direct parent of the DIE.  The other is compilers
+   which do not emit DW_TAG_namespace; in this case we try to guess
+   the fully qualified name of structure types from their members'
+   linkage names.  This must be done using the DIE's children rather
+   than the children of any DW_AT_specification target.  We only need
+   to do this for structures at the top level, i.e. if the target of
+   any DW_AT_specification (if any; otherwise the DIE itself) does not
+   have a parent.  */
+
+/* Compute the scope prefix associated with PDI's parent, in
+   compilation unit CU.  The result will be allocated on CU's
+   comp_unit_obstack, or a copy of the already allocated PDI->NAME
+   field.  NULL is returned if no prefix is necessary.  */
+static char *
+partial_die_parent_scope (struct partial_die_info *pdi,
+                         struct dwarf2_cu *cu)
+{
+  char *grandparent_scope;
+  struct partial_die_info *parent, *real_pdi;
+  struct dwarf2_cu *spec_cu;
+
+  /* We need to look at our parent DIE; if we have a DW_AT_specification,
+     then this means the parent of the specification DIE.  */
+
+  real_pdi = pdi;
+  spec_cu = cu;
+  while (real_pdi->has_specification)
+    real_pdi = find_partial_die (real_pdi->spec_offset, spec_cu, &spec_cu);
+
+  parent = real_pdi->die_parent;
+  if (parent == NULL)
+    return NULL;
+
+  if (parent->scope_set)
+    return parent->scope;
+
+  fixup_partial_die (parent, cu);
+
+  grandparent_scope = partial_die_parent_scope (parent, spec_cu);
+
+  if (parent->tag == DW_TAG_namespace
+      || parent->tag == DW_TAG_structure_type
+      || parent->tag == DW_TAG_class_type
+      || parent->tag == DW_TAG_union_type)
+    {
+      if (grandparent_scope == NULL)
+       parent->scope = parent->name;
+      else
+       parent->scope = obconcat (&cu->comp_unit_obstack, grandparent_scope,
+                                 "::", parent->name);
+    }
+  else if (parent->tag == DW_TAG_enumeration_type)
+    /* Enumerators should not get the name of the enumeration as a prefix.  */
+    parent->scope = grandparent_scope;
+  else
+    {
+      /* FIXME drow/2004-04-01: What should we be doing with
+        function-local names?  For partial symbols, we should probably be
+        ignoring them.  */
+      complaint (&symfile_complaints,
+                "unhandled containing DIE tag %d for DIE at %d",
+                parent->tag, pdi->offset);
+      parent->scope = grandparent_scope;
+    }
+
+  parent->scope_set = 1;
+  return parent->scope;
+}
+
+/* Return the fully scoped name associated with PDI, from compilation unit
+   CU.  The result will be allocated with malloc.  */
+static char *
+partial_die_full_name (struct partial_die_info *pdi,
+                      struct dwarf2_cu *cu)
+{
+  char *parent_scope;
+
+  parent_scope = partial_die_parent_scope (pdi, cu);
+  if (parent_scope == NULL)
+    return NULL;
+  else
+    return concat (parent_scope, "::", pdi->name, NULL);
 }
 
 static void
-add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
-                   const struct comp_unit_head *cu_header)
+add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
   CORE_ADDR addr = 0;
+  char *actual_name;
+  const char *my_prefix;
+  const struct partial_symbol *psym = NULL;
+  CORE_ADDR baseaddr;
+  int built_actual_name = 0;
+
+  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+  actual_name = NULL;
+
+  if (pdi_needs_namespace (pdi->tag))
+    {
+      actual_name = partial_die_full_name (pdi, cu);
+      if (actual_name)
+       built_actual_name = 1;
+    }
+
+  if (actual_name == NULL)
+    actual_name = pdi->name;
 
   switch (pdi->tag)
     {
     case DW_TAG_subprogram:
       if (pdi->is_external)
        {
-         /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+         /*prim_record_minimal_symbol (actual_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 + baseaddr, cu_language, objfile);
+         psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+                                     VAR_DOMAIN, LOC_BLOCK,
+                                     &objfile->global_psymbols,
+                                     0, pdi->lowpc + baseaddr,
+                                     cu->language, objfile);
        }
       else
        {
-         /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+         /*prim_record_minimal_symbol (actual_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 + baseaddr, cu_language, objfile);
+         psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+                                     VAR_DOMAIN, LOC_BLOCK,
+                                     &objfile->static_psymbols,
+                                     0, pdi->lowpc + baseaddr,
+                                     cu->language, objfile);
        }
       break;
     case DW_TAG_variable:
@@ -1431,33 +1668,42 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
             table building.  */
 
          if (pdi->locdesc)
-           addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
+           addr = decode_locdesc (pdi->locdesc, cu);
          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);
+           psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+                                       VAR_DOMAIN, 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,
+         addr = decode_locdesc (pdi->locdesc, cu);
+         /*prim_record_minimal_symbol (actual_name, addr + baseaddr,
             mst_file_data, objfile); */
-         add_psymbol_to_list (pdi->name, strlen (pdi->name),
-                              VAR_NAMESPACE, LOC_STATIC,
-                              &objfile->static_psymbols,
-                              0, addr + baseaddr, cu_language, objfile);
+         psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+                                     VAR_DOMAIN, LOC_STATIC,
+                                     &objfile->static_psymbols,
+                                     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,
+    case DW_TAG_subrange_type:
+      add_psymbol_to_list (actual_name, strlen (actual_name),
+                          VAR_DOMAIN, LOC_TYPEDEF,
                           &objfile->static_psymbols,
-                          0, (CORE_ADDR) 0, cu_language, objfile);
+                          0, (CORE_ADDR) 0, cu->language, objfile);
+      break;
+    case DW_TAG_namespace:
+      add_psymbol_to_list (actual_name, strlen (actual_name),
+                          VAR_DOMAIN, LOC_TYPEDEF,
+                          &objfile->global_psymbols,
+                          0, (CORE_ADDR) 0, cu->language, objfile);
       break;
     case DW_TAG_class_type:
     case DW_TAG_structure_type:
@@ -1465,31 +1711,349 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
     case DW_TAG_enumeration_type:
       /* Skip aggregate types without children, these are external
          references.  */
+      /* NOTE: carlton/2003-10-07: See comment in new_symbol about
+        static vs. global.  */
       if (pdi->has_children == 0)
        return;
-      add_psymbol_to_list (pdi->name, strlen (pdi->name),
-                          STRUCT_NAMESPACE, LOC_TYPEDEF,
-                          &objfile->static_psymbols,
-                          0, (CORE_ADDR) 0, cu_language, objfile);
-
-      if (cu_language == language_cplus)
+      add_psymbol_to_list (actual_name, strlen (actual_name),
+                          STRUCT_DOMAIN, LOC_TYPEDEF,
+                          cu->language == language_cplus
+                          ? &objfile->global_psymbols
+                          : &objfile->static_psymbols,
+                          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, (CORE_ADDR) 0, cu_language, objfile);
+         add_psymbol_to_list (actual_name, strlen (actual_name),
+                              VAR_DOMAIN, LOC_TYPEDEF,
+                              &objfile->global_psymbols,
+                              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);
+      add_psymbol_to_list (actual_name, strlen (actual_name),
+                          VAR_DOMAIN, LOC_CONST,
+                          cu->language == language_cplus
+                          ? &objfile->global_psymbols
+                          : &objfile->static_psymbols,
+                          0, (CORE_ADDR) 0, cu->language, objfile);
       break;
     default:
       break;
     }
+
+  /* Check to see if we should scan the name for possible namespace
+     info.  Only do this if this is C++, if we don't have namespace
+     debugging info in the file, if the psym is of an appropriate type
+     (otherwise we'll have psym == NULL), and if we actually had a
+     mangled name to begin with.  */
+
+  /* FIXME drow/2004-02-22: Why don't we do this for classes, i.e. the
+     cases which do not set PSYM above?  */
+
+  if (cu->language == language_cplus
+      && cu->has_namespace_info == 0
+      && psym != NULL
+      && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL)
+    cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym),
+                                        objfile);
+
+  if (built_actual_name)
+    xfree (actual_name);
+}
+
+/* Determine whether a die of type TAG living in a C++ class or
+   namespace needs to have the name of the scope prepended to the
+   name listed in the die.  */
+
+static int
+pdi_needs_namespace (enum dwarf_tag tag)
+{
+  switch (tag)
+    {
+    case DW_TAG_namespace:
+    case DW_TAG_typedef:
+    case DW_TAG_class_type:
+    case DW_TAG_structure_type:
+    case DW_TAG_union_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_enumerator:
+      return 1;
+    default:
+      return 0;
+    }
+}
+
+/* Read a partial die corresponding to a namespace; also, add a symbol
+   corresponding to that namespace to the symbol table.  NAMESPACE is
+   the name of the enclosing namespace.  */
+
+static void
+add_partial_namespace (struct partial_die_info *pdi,
+                      CORE_ADDR *lowpc, CORE_ADDR *highpc,
+                      struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+
+  /* Add a symbol for the namespace.  */
+
+  add_partial_symbol (pdi, cu);
+
+  /* Now scan partial symbols in that namespace.  */
+
+  if (pdi->has_children)
+    scan_partial_symbols (pdi->die_child, lowpc, highpc, cu);
+}
+
+/* See if we can figure out if the class lives in a namespace.  We do
+   this by looking for a member function; its demangled name will
+   contain namespace info, if there is any.  */
+
+static void
+guess_structure_name (struct partial_die_info *struct_pdi,
+                     struct dwarf2_cu *cu)
+{
+  if (cu->language == language_cplus
+      && cu->has_namespace_info == 0
+      && struct_pdi->has_children)
+    {
+      /* NOTE: carlton/2003-10-07: Getting the info this way changes
+        what template types look like, because the demangler
+        frequently doesn't give the same name as the debug info.  We
+        could fix this by only using the demangled name to get the
+        prefix (but see comment in read_structure_type).  */
+
+      struct partial_die_info *child_pdi = struct_pdi->die_child;
+      struct partial_die_info *real_pdi;
+      struct dwarf2_cu *spec_cu;
+
+      /* If this DIE (this DIE's specification, if any) has a parent, then
+        we should not do this.  We'll prepend the parent's fully qualified
+         name when we create the partial symbol.  */
+
+      real_pdi = struct_pdi;
+      spec_cu = cu;
+      while (real_pdi->has_specification)
+       real_pdi = find_partial_die (real_pdi->spec_offset, spec_cu, &spec_cu);
+
+      if (real_pdi->die_parent != NULL)
+       return;
+
+      while (child_pdi != NULL)
+       {
+         if (child_pdi->tag == DW_TAG_subprogram)
+           {
+             char *actual_class_name
+               = language_class_name_from_physname (cu->language_defn,
+                                                    child_pdi->name);
+             if (actual_class_name != NULL)
+               {
+                 struct_pdi->name
+                   = obsavestring (actual_class_name,
+                                   strlen (actual_class_name),
+                                   &cu->comp_unit_obstack);
+                 xfree (actual_class_name);
+               }
+             break;
+           }
+
+         child_pdi = child_pdi->die_sibling;
+       }
+    }
+}
+
+/* Read a partial die corresponding to an enumeration type.  */
+
+static void
+add_partial_enumeration (struct partial_die_info *enum_pdi,
+                        struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  bfd *abfd = objfile->obfd;
+  struct partial_die_info *pdi;
+
+  if (enum_pdi->name != NULL)
+    add_partial_symbol (enum_pdi, cu);
+
+  pdi = enum_pdi->die_child;
+  while (pdi)
+    {
+      if (pdi->tag != DW_TAG_enumerator || pdi->name == NULL)
+       complaint (&symfile_complaints, "malformed enumerator DIE ignored");
+      else
+       add_partial_symbol (pdi, cu);
+      pdi = pdi->die_sibling;
+    }
+}
+
+/* Read the initial uleb128 in the die at INFO_PTR in compilation unit CU.
+   Return the corresponding abbrev, or NULL if the number is zero (indicating
+   an empty DIE).  In either case *BYTES_READ will be set to the length of
+   the initial number.  */
+
+static struct abbrev_info *
+peek_die_abbrev (char *info_ptr, int *bytes_read, struct dwarf2_cu *cu)
+{
+  bfd *abfd = cu->objfile->obfd;
+  unsigned int abbrev_number;
+  struct abbrev_info *abbrev;
+
+  abbrev_number = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
+
+  if (abbrev_number == 0)
+    return NULL;
+
+  abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
+  if (!abbrev)
+    {
+      error ("Dwarf Error: Could not find abbrev number %d [in module %s]", abbrev_number,
+                     bfd_get_filename (abfd));
+    }
+
+  return abbrev;
+}
+
+/* Scan the debug information for CU starting at INFO_PTR.  Returns a
+   pointer to the end of a series of DIEs, terminated by an empty
+   DIE.  Any children of the skipped DIEs will also be skipped.  */
+
+static char *
+skip_children (char *info_ptr, struct dwarf2_cu *cu)
+{
+  struct abbrev_info *abbrev;
+  unsigned int bytes_read;
+
+  while (1)
+    {
+      abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu);
+      if (abbrev == NULL)
+       return info_ptr + bytes_read;
+      else
+       info_ptr = skip_one_die (info_ptr + bytes_read, abbrev, cu);
+    }
+}
+
+/* Scan the debug information for CU starting at INFO_PTR.  INFO_PTR
+   should point just after the initial uleb128 of a DIE, and the
+   abbrev corresponding to that skipped uleb128 should be passed in
+   ABBREV.  Returns a pointer to this DIE's sibling, skipping any
+   children.  */
+
+static char *
+skip_one_die (char *info_ptr, struct abbrev_info *abbrev,
+             struct dwarf2_cu *cu)
+{
+  unsigned int bytes_read;
+  struct attribute attr;
+  bfd *abfd = cu->objfile->obfd;
+  unsigned int form, i;
+
+  for (i = 0; i < abbrev->num_attrs; i++)
+    {
+      /* The only abbrev we care about is DW_AT_sibling.  */
+      if (abbrev->attrs[i].name == DW_AT_sibling)
+       {
+         read_attribute (&attr, &abbrev->attrs[i],
+                         abfd, info_ptr, cu);
+         if (attr.form == DW_FORM_ref_addr)
+           complaint (&symfile_complaints, "ignoring absolute DW_AT_sibling");
+         else
+           return dwarf2_per_objfile->info_buffer
+             + dwarf2_get_ref_die_offset (&attr, cu);
+       }
+
+      /* If it isn't DW_AT_sibling, skip this attribute.  */
+      form = abbrev->attrs[i].form;
+    skip_attribute:
+      switch (form)
+       {
+       case DW_FORM_addr:
+       case DW_FORM_ref_addr:
+         info_ptr += cu->header.addr_size;
+         break;
+       case DW_FORM_data1:
+       case DW_FORM_ref1:
+       case DW_FORM_flag:
+         info_ptr += 1;
+         break;
+       case DW_FORM_data2:
+       case DW_FORM_ref2:
+         info_ptr += 2;
+         break;
+       case DW_FORM_data4:
+       case DW_FORM_ref4:
+         info_ptr += 4;
+         break;
+       case DW_FORM_data8:
+       case DW_FORM_ref8:
+         info_ptr += 8;
+         break;
+       case DW_FORM_string:
+         read_string (abfd, info_ptr, &bytes_read);
+         info_ptr += bytes_read;
+         break;
+       case DW_FORM_strp:
+         info_ptr += cu->header.offset_size;
+         break;
+       case DW_FORM_block:
+         info_ptr += read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+         info_ptr += bytes_read;
+         break;
+       case DW_FORM_block1:
+         info_ptr += 1 + read_1_byte (abfd, info_ptr);
+         break;
+       case DW_FORM_block2:
+         info_ptr += 2 + read_2_bytes (abfd, info_ptr);
+         break;
+       case DW_FORM_block4:
+         info_ptr += 4 + read_4_bytes (abfd, info_ptr);
+         break;
+       case DW_FORM_sdata:
+       case DW_FORM_udata:
+       case DW_FORM_ref_udata:
+         info_ptr = skip_leb128 (abfd, info_ptr);
+         break;
+       case DW_FORM_indirect:
+         form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+         info_ptr += bytes_read;
+         /* We need to continue parsing from here, so just go back to
+            the top.  */
+         goto skip_attribute;
+
+       default:
+         error ("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]",
+                dwarf_form_name (form),
+                bfd_get_filename (abfd));
+       }
+    }
+
+  if (abbrev->has_children)
+    return skip_children (info_ptr, cu);
+  else
+    return info_ptr;
+}
+
+/* Locate ORIG_PDI's sibling; INFO_PTR should point to the start of
+   the next DIE after ORIG_PDI.  */
+
+static char *
+locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr,
+                   bfd *abfd, struct dwarf2_cu *cu)
+{
+  /* Do we know the sibling already?  */
+
+  if (orig_pdi->sibling)
+    return orig_pdi->sibling;
+
+  /* Are there any children to deal with?  */
+
+  if (!orig_pdi->has_children)
+    return info_ptr;
+
+  /* Skip the children the long way.  */
+
+  return skip_children (info_ptr, cu);
 }
 
 /* Expand this partial symbol table into a full symbol table.  */
@@ -1526,7 +2090,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
 {
   struct objfile *objfile = pst->objfile;
   bfd *abfd = objfile->obfd;
-  struct comp_unit_head cu_header;
+  struct dwarf2_cu cu;
   struct die_info *dies;
   unsigned long offset;
   CORE_ADDR lowpc, highpc;
@@ -1534,79 +2098,114 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
   char *info_ptr;
   struct symtab *symtab;
   struct cleanup *back_to;
+  struct attribute *attr;
+  CORE_ADDR baseaddr;
+  int i;
+
+  for (i = 0; i < pst->number_of_dependencies; i++)
+    if (!pst->dependencies[i]->readin)
+      {
+        /* Inform about additional files that need to be read in.  */
+        if (info_verbose)
+          {
+            fputs_filtered (" ", gdb_stdout);
+            wrap_here ("");
+            fputs_filtered ("and ", gdb_stdout);
+            wrap_here ("");
+            printf_filtered ("%s...", pst->dependencies[i]->filename);
+            wrap_here ("");     /* Flush output */
+            gdb_flush (gdb_stdout);
+          }
+        psymtab_to_symtab_1 (pst->dependencies[i]);
+      }
+
+  if (pst->read_symtab_private == NULL)
+    {
+      /* It's an include file, no symbols to read for it.
+         Everything is in the parent symtab.  */
+      pst->readin = 1;
+      return;
+    }
+
+  dwarf2_per_objfile = objfile_data (pst->objfile, dwarf2_objfile_data_key);
 
   /* 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);
-  dwarf_line_size = DWARF_LINE_SIZE (pst);
-  dwarf_str_buffer = DWARF_STR_BUFFER (pst);
-  dwarf_str_size = DWARF_STR_SIZE (pst);
-  dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (pst);
-  dwarf_macinfo_size = DWARF_MACINFO_SIZE (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);
+
+  info_ptr = dwarf2_per_objfile->info_buffer + offset;
+  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+  /* We're in the global namespace.  */
+  processing_current_prefix = "";
+
+  obstack_init (&cu.comp_unit_obstack);
+  back_to = make_cleanup (free_stack_comp_unit, &cu);
 
   buildsym_init ();
   make_cleanup (really_free_pendings, NULL);
 
+  cu.objfile = objfile;
+
   /* read in the comp_unit header  */
-  info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd);
+  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);
-  make_cleanup (dwarf2_empty_abbrev_table, NULL);
+  dwarf2_read_abbrevs (abfd, &cu);
+  make_cleanup (dwarf2_free_abbrev_table, &cu);
 
-  dies = read_comp_unit (info_ptr, abfd, &cu_header);
+  cu.header.offset = offset;
+
+  cu.list_in_scope = &file_symbols;
+
+  dies = read_comp_unit (info_ptr, abfd, &cu);
 
   make_cleanup_free_die_list (dies);
 
-  /* Do line number decoding in read_file_scope () */
-  process_die (dies, objfile, &cu_header);
+  /* Find the base address of the compilation unit for range lists and
+     location lists.  It will normally be specified by DW_AT_low_pc.
+     In DWARF-3 draft 4, the base address could be overridden by
+     DW_AT_entry_pc.  It's been removed, but GCC still uses this for
+     compilation units with discontinuous ranges.  */
 
-  if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
+  cu.header.base_known = 0;
+  cu.header.base_address = 0;
+
+  attr = dwarf2_attr (dies, DW_AT_entry_pc, &cu);
+  if (attr)
     {
-      /* 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.  */
-      highpc = 0;
-      if (dies->has_children)
+      cu.header.base_address = DW_ADDR (attr);
+      cu.header.base_known = 1;
+    }
+  else
+    {
+      attr = dwarf2_attr (dies, DW_AT_low_pc, &cu);
+      if (attr)
        {
-         child_die = dies->next;
-         while (child_die && child_die->tag)
-           {
-             if (child_die->tag == DW_TAG_subprogram)
-               {
-                 CORE_ADDR low, high;
-
-                 if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
-                   {
-                     highpc = max (highpc, high);
-                   }
-               }
-             child_die = sibling_die (child_die);
-           }
+         cu.header.base_address = DW_ADDR (attr);
+         cu.header.base_known = 1;
        }
     }
+
+  /* Do line number decoding in read_file_scope () */
+  process_die (dies, &cu);
+
+  /* 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.  */
+  get_scope_pc_bounds (dies, &lowpc, &highpc, &cu);
+
   symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
 
   /* 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))
+      && !(cu.language == language_c && symtab->language != language_c))
     {
-      symtab->language = cu_language;
+      symtab->language = cu.language;
     }
   pst->symtab = symtab;
   pst->readin = 1;
-  sort_symtab_syms (pst->symtab);
 
   do_cleanups (back_to);
 }
@@ -1614,19 +2213,18 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
 /* Process a die and its children.  */
 
 static void
-process_die (struct die_info *die, struct objfile *objfile,
-            const struct comp_unit_head *cu_header)
+process_die (struct die_info *die, struct dwarf2_cu *cu)
 {
   switch (die->tag)
     {
     case DW_TAG_padding:
       break;
     case DW_TAG_compile_unit:
-      read_file_scope (die, objfile, cu_header);
+      read_file_scope (die, cu);
       break;
     case DW_TAG_subprogram:
-      read_subroutine_type (die, objfile, cu_header);
-      read_func_scope (die, objfile, cu_header);
+      read_subroutine_type (die, cu);
+      read_func_scope (die, cu);
       break;
     case DW_TAG_inlined_subroutine:
       /* FIXME:  These are ignored for now.
@@ -1634,63 +2232,93 @@ process_die (struct die_info *die, struct objfile *objfile,
          of a function and make GDB `next' properly over inlined functions.  */
       break;
     case DW_TAG_lexical_block:
-      read_lexical_block_scope (die, objfile, cu_header);
+    case DW_TAG_try_block:
+    case DW_TAG_catch_block:
+      read_lexical_block_scope (die, cu);
       break;
     case DW_TAG_class_type:
     case DW_TAG_structure_type:
     case DW_TAG_union_type:
-      read_structure_scope (die, objfile, cu_header);
+      read_structure_type (die, cu);
+      process_structure_scope (die, cu);
       break;
     case DW_TAG_enumeration_type:
-      read_enumeration (die, objfile, cu_header);
+      read_enumeration_type (die, cu);
+      process_enumeration_scope (die, cu);
       break;
+
+    /* FIXME drow/2004-03-14: These initialize die->type, but do not create
+       a symbol or process any children.  Therefore it doesn't do anything
+       that won't be done on-demand by read_type_die.  */
     case DW_TAG_subroutine_type:
-      read_subroutine_type (die, objfile, cu_header);
+      read_subroutine_type (die, cu);
       break;
     case DW_TAG_array_type:
-      read_array_type (die, objfile, cu_header);
+      read_array_type (die, cu);
       break;
     case DW_TAG_pointer_type:
-      read_tag_pointer_type (die, objfile, cu_header);
+      read_tag_pointer_type (die, cu);
       break;
     case DW_TAG_ptr_to_member_type:
-      read_tag_ptr_to_member_type (die, objfile, cu_header);
+      read_tag_ptr_to_member_type (die, cu);
       break;
     case DW_TAG_reference_type:
-      read_tag_reference_type (die, objfile, cu_header);
+      read_tag_reference_type (die, cu);
       break;
     case DW_TAG_string_type:
-      read_tag_string_type (die, objfile);
+      read_tag_string_type (die, cu);
       break;
+    /* END FIXME */
+
     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);
-       }
+      read_base_type (die, cu);
+      /* Add a typedef symbol for the type definition, if it has a
+        DW_AT_name.  */
+      new_symbol (die, die->type, cu);
+      break;
+    case DW_TAG_subrange_type:
+      read_subrange_type (die, cu);
+      /* Add a typedef symbol for the type definition, if it has a
+         DW_AT_name.  */
+      new_symbol (die, die->type, cu);
       break;
     case DW_TAG_common_block:
-      read_common_block (die, objfile, cu_header);
+      read_common_block (die, cu);
       break;
     case DW_TAG_common_inclusion:
       break;
+    case DW_TAG_namespace:
+      processing_has_namespace_info = 1;
+      read_namespace (die, cu);
+      break;
+    case DW_TAG_imported_declaration:
+    case DW_TAG_imported_module:
+      /* FIXME: carlton/2002-10-16: Eventually, we should use the
+        information contained in these.  DW_TAG_imported_declaration
+        dies shouldn't have children; DW_TAG_imported_module dies
+        shouldn't in the C++ case, but conceivably could in the
+        Fortran case, so we'll have to replace this gdb_assert if
+        Fortran compilers start generating that info.  */
+      processing_has_namespace_info = 1;
+      gdb_assert (die->child == NULL);
+      break;
     default:
-      new_symbol (die, NULL, objfile, cu_header);
+      new_symbol (die, NULL, cu);
       break;
     }
 }
 
 static void
-initialize_cu_func_list (void)
+initialize_cu_func_list (struct dwarf2_cu *cu)
 {
-  cu_first_fn = cu_last_fn = cu_cached_fn = NULL;
+  cu->first_fn = cu->last_fn = cu->cached_fn = NULL;
 }
 
 static void
-read_file_scope (struct die_info *die, struct objfile *objfile,
-                const struct comp_unit_head *cu_header)
+read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
+  struct comp_unit_head *cu_header = &cu->header;
   struct cleanup *back_to = make_cleanup (null_cleanup, 0);
   CORE_ADDR lowpc = ((CORE_ADDR) -1);
   CORE_ADDR highpc = ((CORE_ADDR) 0);
@@ -1700,28 +2328,11 @@ read_file_scope (struct die_info *die, struct objfile *objfile,
   struct die_info *child_die;
   bfd *abfd = objfile->obfd;
   struct line_header *line_header = 0;
+  CORE_ADDR baseaddr;
+  
+  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
-    {
-      if (die->has_children)
-       {
-         child_die = die->next;
-         while (child_die && child_die->tag)
-           {
-             if (child_die->tag == DW_TAG_subprogram)
-               {
-                 CORE_ADDR low, high;
-
-                 if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
-                   {
-                     lowpc = min (lowpc, low);
-                     highpc = max (highpc, high);
-                   }
-               }
-             child_die = sibling_die (child_die);
-           }
-       }
-    }
+  get_scope_pc_bounds (die, &lowpc, &highpc, cu);
 
   /* If we didn't find a lowpc, set it to highpc to avoid complaints
      from finish_block.  */
@@ -1730,12 +2341,12 @@ read_file_scope (struct die_info *die, struct objfile *objfile,
   lowpc += baseaddr;
   highpc += baseaddr;
 
-  attr = dwarf_attr (die, DW_AT_name);
+  attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr)
     {
       name = DW_STRING (attr);
     }
-  attr = dwarf_attr (die, DW_AT_comp_dir);
+  attr = dwarf2_attr (die, DW_AT_comp_dir, cu);
   if (attr)
     {
       comp_dir = DW_STRING (attr);
@@ -1750,19 +2361,16 @@ read_file_scope (struct die_info *die, struct objfile *objfile,
        }
     }
 
-  if (objfile->ei.entry_point >= lowpc &&
-      objfile->ei.entry_point < highpc)
-    {
-      objfile->ei.entry_file_lowpc = lowpc;
-      objfile->ei.entry_file_highpc = highpc;
-    }
-
-  attr = dwarf_attr (die, DW_AT_language);
+  attr = dwarf2_attr (die, DW_AT_language, cu);
   if (attr)
     {
-      set_cu_language (DW_UNSND (attr));
+      set_cu_language (DW_UNSND (attr), cu);
     }
 
+  attr = dwarf2_attr (die, DW_AT_producer, cu);
+  if (attr) 
+    cu->producer = DW_STRING (attr);
+  
   /* We assume that we're processing GCC output. */
   processing_gcc_compilation = 2;
 #if 0
@@ -1775,36 +2383,35 @@ read_file_scope (struct die_info *die, struct objfile *objfile,
 
   /* 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 *));
+  memset (cu->ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
 
   start_symtab (name, comp_dir, lowpc);
   record_debugformat ("DWARF 2");
 
-  initialize_cu_func_list ();
+  initialize_cu_func_list (cu);
 
   /* Process all dies in compilation unit.  */
-  if (die->has_children)
+  if (die->child != NULL)
     {
-      child_die = die->next;
+      child_die = die->child;
       while (child_die && child_die->tag)
        {
-         process_die (child_die, objfile, cu_header);
+         process_die (child_die, cu);
          child_die = sibling_die (child_die);
        }
     }
 
   /* Decode line number information if present.  */
-  attr = dwarf_attr (die, DW_AT_stmt_list);
+  attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
   if (attr)
     {
       unsigned int line_offset = DW_UNSND (attr);
-      line_header = dwarf_decode_line_header (line_offset,
-                                              abfd, cu_header);
+      line_header = dwarf_decode_line_header (line_offset, abfd, cu);
       if (line_header)
         {
           make_cleanup ((make_cleanup_ftype *) free_line_header,
                         (void *) line_header);
-          dwarf_decode_lines (line_header, comp_dir, abfd, cu_header);
+          dwarf_decode_lines (line_header, comp_dir, abfd, cu, NULL);
         }
     }
 
@@ -1812,116 +2419,127 @@ read_file_scope (struct die_info *die, struct objfile *objfile,
      refers to information in the line number info statement program
      header, so we can only read it if we've read the header
      successfully.  */
-  attr = dwarf_attr (die, DW_AT_macro_info);
+  attr = dwarf2_attr (die, DW_AT_macro_info, cu);
   if (attr && line_header)
     {
       unsigned int macro_offset = DW_UNSND (attr);
       dwarf_decode_macros (line_header, macro_offset,
-                           comp_dir, abfd, cu_header, objfile);
+                           comp_dir, abfd, cu);
     }
   do_cleanups (back_to);
 }
 
 static void
-add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc)
+add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc,
+                    struct dwarf2_cu *cu)
 {
   struct function_range *thisfn;
 
   thisfn = (struct function_range *)
-    obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct function_range));
+    obstack_alloc (&cu->comp_unit_obstack, sizeof (struct function_range));
   thisfn->name = name;
   thisfn->lowpc = lowpc;
   thisfn->highpc = highpc;
   thisfn->seen_line = 0;
   thisfn->next = NULL;
 
-  if (cu_last_fn == NULL)
-      cu_first_fn = thisfn;
+  if (cu->last_fn == NULL)
+      cu->first_fn = thisfn;
   else
-      cu_last_fn->next = thisfn;
+      cu->last_fn->next = thisfn;
 
-  cu_last_fn = thisfn;
+  cu->last_fn = thisfn;
 }
 
 static void
-read_func_scope (struct die_info *die, struct objfile *objfile,
-                const struct comp_unit_head *cu_header)
+read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
 {
-  register struct context_stack *new;
+  struct objfile *objfile = cu->objfile;
+  struct context_stack *new;
   CORE_ADDR lowpc;
   CORE_ADDR highpc;
   struct die_info *child_die;
   struct attribute *attr;
   char *name;
+  const char *previous_prefix = processing_current_prefix;
+  struct cleanup *back_to = NULL;
+  CORE_ADDR baseaddr;
+
+  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-  name = dwarf2_linkage_name (die);
+  name = dwarf2_linkage_name (die, cu);
 
   /* 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))
+  if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu))
     return;
 
-  lowpc += baseaddr;
-  highpc += baseaddr;
+  if (cu->language == language_cplus)
+    {
+      struct die_info *spec_die = die_specification (die, cu);
 
-  /* Record the function range for dwarf_decode_lines.  */
-  add_to_cu_func_list (name, lowpc, highpc);
+      /* NOTE: carlton/2004-01-23: We have to be careful in the
+         presence of DW_AT_specification.  For example, with GCC 3.4,
+         given the code
 
-  if (objfile->ei.entry_point >= lowpc &&
-      objfile->ei.entry_point < highpc)
-    {
-      objfile->ei.entry_func_lowpc = lowpc;
-      objfile->ei.entry_func_highpc = highpc;
-    }
+           namespace N {
+             void foo() {
+               // Definition of N::foo.
+             }
+           }
 
-  /* 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)
-    {
-      CORE_ADDR addr;
+         then we'll have a tree of DIEs like this:
 
-      /* Support the .debug_loc offsets */
-      if (attr_form_is_block (attr))
-        {
-          addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
-        }
-      else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
-        {
-          complain (&dwarf2_complex_location_expr);
-          addr = 0;
-        }
-      else
-        {
-          complain (&dwarf2_invalid_attrib_class, "DW_AT_frame_base", name);
-          addr = 0;
-        }
-    
-      if (isderef)
-       complain (&dwarf2_unsupported_at_frame_base, name);
-      else if (isreg)
-       frame_base_reg = addr;
-      else if (offreg)
+         1: DW_TAG_compile_unit
+           2: DW_TAG_namespace        // N
+             3: DW_TAG_subprogram     // declaration of N::foo
+           4: DW_TAG_subprogram       // definition of N::foo
+                DW_AT_specification   // refers to die #3
+
+         Thus, when processing die #4, we have to pretend that we're
+         in the context of its DW_AT_specification, namely the contex
+         of die #3.  */
+       
+      if (spec_die != NULL)
        {
-         frame_base_reg = basereg;
-         frame_base_offset = addr;
+         char *specification_prefix = determine_prefix (spec_die, cu);
+         processing_current_prefix = specification_prefix;
+         back_to = make_cleanup (xfree, specification_prefix);
        }
-      else
-       complain (&dwarf2_unsupported_at_frame_base, name);
     }
 
+  lowpc += baseaddr;
+  highpc += baseaddr;
+
+  /* Record the function range for dwarf_decode_lines.  */
+  add_to_cu_func_list (name, lowpc, highpc, cu);
+
   new = push_context (0, lowpc);
-  new->name = new_symbol (die, die->type, objfile, cu_header);
-  list_in_scope = &local_symbols;
+  new->name = new_symbol (die, die->type, cu);
 
-  if (die->has_children)
-    {
-      child_die = die->next;
+  /* If there is a location expression for DW_AT_frame_base, record
+     it.  */
+  attr = dwarf2_attr (die, DW_AT_frame_base, cu);
+  if (attr)
+    /* FIXME: cagney/2004-01-26: The DW_AT_frame_base's location
+       expression is being recorded directly in the function's symbol
+       and not in a separate frame-base object.  I guess this hack is
+       to avoid adding some sort of frame-base adjunct/annex to the
+       function's symbol :-(.  The problem with doing this is that it
+       results in a function symbol with a location expression that
+       has nothing to do with the location of the function, ouch!  The
+       relationship should be: a function's symbol has-a frame base; a
+       frame-base has-a location expression.  */
+    dwarf2_symbol_mark_computed (attr, new->name, cu);
+
+  cu->list_in_scope = &local_symbols;
+
+  if (die->child != NULL)
+    {
+      child_die = die->child;
       while (child_die && child_die->tag)
        {
-         process_die (child_die, objfile, cu_header);
+         process_die (child_die, cu);
          child_die = sibling_die (child_die);
        }
     }
@@ -1930,33 +2548,55 @@ read_func_scope (struct die_info *die, struct objfile *objfile,
   /* Make a block for the local symbols within.  */
   finish_block (new->name, &local_symbols, new->old_blocks,
                lowpc, highpc, objfile);
-  list_in_scope = &file_symbols;
+  
+  /* In C++, we can have functions nested inside functions (e.g., when
+     a function declares a class that has methods).  This means that
+     when we finish processing a function scope, we may need to go
+     back to building a containing block's symbol lists.  */
+  local_symbols = new->locals;
+  param_symbols = new->params;
+
+  /* If we've finished processing a top-level function, subsequent
+     symbols go in the file symbol list.  */
+  if (outermost_context_p ())
+    cu->list_in_scope = &file_symbols;
+
+  processing_current_prefix = previous_prefix;
+  if (back_to != NULL)
+    do_cleanups (back_to);
 }
 
 /* Process all the DIES contained within a lexical block scope.  Start
    a new scope, process the dies, and then close the scope.  */
 
 static void
-read_lexical_block_scope (struct die_info *die, struct objfile *objfile,
-                         const struct comp_unit_head *cu_header)
+read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
 {
-  register struct context_stack *new;
+  struct objfile *objfile = cu->objfile;
+  struct context_stack *new;
   CORE_ADDR lowpc, highpc;
   struct die_info *child_die;
+  CORE_ADDR baseaddr;
+
+  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
   /* Ignore blocks with missing or invalid low and high pc attributes.  */
-  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+  /* ??? Perhaps consider discontiguous blocks defined by DW_AT_ranges
+     as multiple lexical blocks?  Handling children in a sane way would
+     be nasty.  Might be easier to properly extend generic blocks to 
+     describe ranges.  */
+  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu))
     return;
   lowpc += baseaddr;
   highpc += baseaddr;
 
   push_context (0, lowpc);
-  if (die->has_children)
+  if (die->child != NULL)
     {
-      child_die = die->next;
+      child_die = die->child;
       while (child_die && child_die->tag)
        {
-         process_die (child_die, objfile, cu_header);
+         process_die (child_die, cu);
          child_die = sibling_die (child_die);
        }
     }
@@ -1970,27 +2610,145 @@ read_lexical_block_scope (struct die_info *die, struct objfile *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.  */
+/* Get low and high pc attributes from a die.  Return 1 if the attributes
+   are present and valid, otherwise, return 0.  Return -1 if the range is
+   discontinuous, i.e. derived from DW_AT_ranges information.  */
+static int
+dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
+                     CORE_ADDR *highpc, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  struct comp_unit_head *cu_header = &cu->header;
+  struct attribute *attr;
+  bfd *obfd = objfile->obfd;
+  CORE_ADDR low = 0;
+  CORE_ADDR high = 0;
+  int ret = 0;
+
+  attr = dwarf2_attr (die, DW_AT_high_pc, cu);
+  if (attr)
+    {
+      high = DW_ADDR (attr);
+      attr = dwarf2_attr (die, DW_AT_low_pc, cu);
+      if (attr)
+       low = DW_ADDR (attr);
+      else
+       /* Found high w/o low attribute.  */
+       return 0;
+
+      /* Found consecutive range of addresses.  */
+      ret = 1;
+    }
+  else
+    {
+      attr = dwarf2_attr (die, DW_AT_ranges, cu);
+      if (attr != NULL)
+       {
+         unsigned int addr_size = cu_header->addr_size;
+         CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
+         /* Value of the DW_AT_ranges attribute is the offset in the
+            .debug_ranges section.  */
+         unsigned int offset = DW_UNSND (attr);
+         /* Base address selection entry.  */
+         CORE_ADDR base;
+         int found_base;
+         int dummy;
+         char *buffer;
+         CORE_ADDR marker;
+         int low_set;
+         found_base = cu_header->base_known;
+         base = cu_header->base_address;
+
+         if (offset >= dwarf2_per_objfile->ranges_size)
+           {
+             complaint (&symfile_complaints,
+                        "Offset %d out of bounds for DW_AT_ranges attribute",
+                        offset);
+             return 0;
+           }
+         buffer = dwarf2_per_objfile->ranges_buffer + offset;
+
+         /* Read in the largest possible address.  */
+         marker = read_address (obfd, buffer, cu, &dummy);
+         if ((marker & mask) == mask)
+           {
+             /* If we found the largest possible address, then
+                read the base address.  */
+             base = read_address (obfd, buffer + addr_size, cu, &dummy);
+             buffer += 2 * addr_size;
+             offset += 2 * addr_size;
+             found_base = 1;
+           }
+
+         low_set = 0;
+
+         while (1)
+           {
+             CORE_ADDR range_beginning, range_end;
+
+             range_beginning = read_address (obfd, buffer, cu, &dummy);
+             buffer += addr_size;
+             range_end = read_address (obfd, buffer, cu, &dummy);
+             buffer += addr_size;
+             offset += 2 * addr_size;
+
+             /* An end of list marker is a pair of zero addresses.  */
+             if (range_beginning == 0 && range_end == 0)
+               /* Found the end of list entry.  */
+               break;
+
+             /* Each base address selection entry is a pair of 2 values.
+                The first is the largest possible address, the second is
+                the base address.  Check for a base address here.  */
+             if ((range_beginning & mask) == mask)
+               {
+                 /* If we found the largest possible address, then
+                    read the base address.  */
+                 base = read_address (obfd, buffer + addr_size, cu, &dummy);
+                 found_base = 1;
+                 continue;
+               }
+
+             if (!found_base)
+               {
+                 /* We have no valid base address for the ranges
+                    data.  */
+                 complaint (&symfile_complaints,
+                            "Invalid .debug_ranges data (no base address)");
+                 return 0;
+               }
+
+             range_beginning += base;
+             range_end += base;
+
+             /* FIXME: This is recording everything as a low-high
+                segment of consecutive addresses.  We should have a
+                data structure for discontiguous block ranges
+                instead.  */
+             if (! low_set)
+               {
+                 low = range_beginning;
+                 high = range_end;
+                 low_set = 1;
+               }
+             else
+               {
+                 if (range_beginning < low)
+                   low = range_beginning;
+                 if (range_end > high)
+                   high = range_end;
+               }
+           }
 
-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;
+         if (! low_set)
+           /* If the first entry is an end-of-list marker, the range
+              describes an empty scope, i.e. no instructions.  */
+           return 0;
 
-  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;
+         ret = -1;
+       }
+    }
 
   if (high < low)
     return 0;
@@ -2003,21 +2761,83 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc,
      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)
+  if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0)
     return 0;
 
   *lowpc = low;
   *highpc = high;
-  return 1;
+  return ret;
+}
+
+/* Get the low and high pc's represented by the scope DIE, and store
+   them in *LOWPC and *HIGHPC.  If the correct values can't be
+   determined, set *LOWPC to -1 and *HIGHPC to 0.  */
+
+static void
+get_scope_pc_bounds (struct die_info *die,
+                    CORE_ADDR *lowpc, CORE_ADDR *highpc,
+                    struct dwarf2_cu *cu)
+{
+  CORE_ADDR best_low = (CORE_ADDR) -1;
+  CORE_ADDR best_high = (CORE_ADDR) 0;
+  CORE_ADDR current_low, current_high;
+
+  if (dwarf2_get_pc_bounds (die, &current_low, &current_high, cu))
+    {
+      best_low = current_low;
+      best_high = current_high;
+    }
+  else
+    {
+      struct die_info *child = die->child;
+
+      while (child && child->tag)
+       {
+         switch (child->tag) {
+         case DW_TAG_subprogram:
+           if (dwarf2_get_pc_bounds (child, &current_low, &current_high, cu))
+             {
+               best_low = min (best_low, current_low);
+               best_high = max (best_high, current_high);
+             }
+           break;
+         case DW_TAG_namespace:
+           /* FIXME: carlton/2004-01-16: Should we do this for
+              DW_TAG_class_type/DW_TAG_structure_type, too?  I think
+              that current GCC's always emit the DIEs corresponding
+              to definitions of methods of classes as children of a
+              DW_TAG_compile_unit or DW_TAG_namespace (as opposed to
+              the DIEs giving the declarations, which could be
+              anywhere).  But I don't see any reason why the
+              standards says that they have to be there.  */
+           get_scope_pc_bounds (child, &current_low, &current_high, cu);
+
+           if (current_low != ((CORE_ADDR) -1))
+             {
+               best_low = min (best_low, current_low);
+               best_high = max (best_high, current_high);
+             }
+           break;
+         default:
+           /* Ignore. */
+           break;
+         }
+
+         child = sibling_die (child);
+       }
+    }
+
+  *lowpc = best_low;
+  *highpc = best_high;
 }
 
 /* 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 dwarf2_cu *cu)
+{ 
+  struct objfile *objfile = cu->objfile;
   struct nextfield *new_field;
   struct attribute *attr;
   struct field *fp;
@@ -2040,23 +2860,28 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
     new_field->accessibility = DW_ACCESS_private;
   new_field->virtuality = DW_VIRTUALITY_none;
 
-  attr = dwarf_attr (die, DW_AT_accessibility);
+  attr = dwarf2_attr (die, DW_AT_accessibility, cu);
   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);
+  attr = dwarf2_attr (die, DW_AT_virtuality, cu);
   if (attr)
     new_field->virtuality = DW_UNSND (attr);
 
   fp = &new_field->field;
-  if (die->tag == DW_TAG_member)
+
+  if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu))
     {
+      /* Data member other than a C++ static data member.  */
+      
       /* Get type of field.  */
-      fp->type = die_type (die, objfile, cu_header);
+      fp->type = die_type (die, cu);
+
+      FIELD_STATIC_KIND (*fp) = 0;
 
       /* Get bit size of field (zero if none).  */
-      attr = dwarf_attr (die, DW_AT_bit_size);
+      attr = dwarf2_attr (die, DW_AT_bit_size, cu);
       if (attr)
        {
          FIELD_BITSIZE (*fp) = DW_UNSND (attr);
@@ -2067,15 +2892,15 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
        }
 
       /* Get bit offset of field.  */
-      attr = dwarf_attr (die, DW_AT_data_member_location);
+      attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
       if (attr)
        {
          FIELD_BITPOS (*fp) =
-           decode_locdesc (DW_BLOCK (attr), objfile, cu_header) * bits_per_byte;
+           decode_locdesc (DW_BLOCK (attr), cu) * bits_per_byte;
        }
       else
        FIELD_BITPOS (*fp) = 0;
-      attr = dwarf_attr (die, DW_AT_bit_offset);
+      attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
       if (attr)
        {
          if (BITS_BIG_ENDIAN)
@@ -2098,7 +2923,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
              int anonymous_size;
              int bit_offset = DW_UNSND (attr);
 
-             attr = dwarf_attr (die, DW_AT_byte_size);
+             attr = dwarf2_attr (die, DW_AT_byte_size, cu);
              if (attr)
                {
                  /* The size of the anonymous object containing
@@ -2120,50 +2945,59 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
        }
 
       /* Get name of field.  */
-      attr = dwarf_attr (die, DW_AT_name);
+      attr = dwarf2_attr (die, DW_AT_name, cu);
       if (attr && DW_STRING (attr))
        fieldname = DW_STRING (attr);
-      fp->name = obsavestring (fieldname, strlen (fieldname),
-                              &objfile->type_obstack);
+
+      /* The name is already allocated along with this objfile, so we don't
+        need to duplicate it for the type.  */
+      fp->name = fieldname;
 
       /* Change accessibility for artificial fields (e.g. virtual table
          pointer or virtual base class pointer) to private.  */
-      if (dwarf_attr (die, DW_AT_artificial))
+      if (dwarf2_attr (die, DW_AT_artificial, cu))
        {
          new_field->accessibility = DW_ACCESS_private;
          fip->non_public_fields = 1;
        }
     }
-  else if (die->tag == DW_TAG_variable)
+  else if (die->tag == DW_TAG_member || die->tag == DW_TAG_variable)
     {
+      /* C++ static member.  */
+
+      /* NOTE: carlton/2002-11-05: It should be a DW_TAG_member that
+        is a declaration, but all versions of G++ as of this writing
+        (so through at least 3.2.1) incorrectly generate
+        DW_TAG_variable tags.  */
+      
       char *physname;
 
-      /* C++ static member.
-        Get name of field.  */
-      attr = dwarf_attr (die, DW_AT_name);
+      /* Get name of field.  */
+      attr = dwarf2_attr (die, DW_AT_name, cu);
       if (attr && DW_STRING (attr))
        fieldname = DW_STRING (attr);
       else
        return;
 
       /* Get physical name.  */
-      physname = dwarf2_linkage_name (die);
+      physname = dwarf2_linkage_name (die, cu);
 
-      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);
+      /* The name is already allocated along with this objfile, so we don't
+        need to duplicate it for the type.  */
+      SET_FIELD_PHYSNAME (*fp, physname ? physname : "");
+      FIELD_TYPE (*fp) = die_type (die, cu);
+      FIELD_NAME (*fp) = fieldname;
     }
   else if (die->tag == DW_TAG_inheritance)
     {
       /* C++ base class field.  */
-      attr = dwarf_attr (die, DW_AT_data_member_location);
+      attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
       if (attr)
-       FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), objfile, cu_header)
+       FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), cu)
                              * bits_per_byte);
       FIELD_BITSIZE (*fp) = 0;
-      FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
+      FIELD_STATIC_KIND (*fp) = 0;
+      FIELD_TYPE (*fp) = die_type (die, cu);
       FIELD_NAME (*fp) = type_name_no_tag (fp->type);
       fip->nbaseclasses++;
     }
@@ -2173,7 +3007,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 
 static void
 dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
-                             struct objfile *objfile)
+                             struct dwarf2_cu *cu)
 {
   int nfields = fip->nfields;
 
@@ -2237,8 +3071,8 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
        default:
          /* Unknown accessibility.  Complain and treat it as public.  */
          {
-           complain (&dwarf2_unsupported_accessibility,
-                     fip->fields->accessibility);
+           complaint (&symfile_complaints, "unsupported accessibility %d",
+                      fip->fields->accessibility);
          }
          break;
        }
@@ -2260,9 +3094,9 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
 
 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 type *type, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
   struct attribute *attr;
   struct fnfieldlist *flp;
   int i;
@@ -2272,19 +3106,19 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
   struct nextfnfield *new_fnfield;
 
   /* Get name of member function.  */
-  attr = dwarf_attr (die, DW_AT_name);
+  attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr && DW_STRING (attr))
     fieldname = DW_STRING (attr);
   else
     return;
 
   /* Get the mangled name.  */
-  physname = dwarf2_linkage_name (die);
+  physname = dwarf2_linkage_name (die, cu);
 
   /* Look up member function name in fieldlist.  */
   for (i = 0; i < fip->nfnfields; i++)
     {
-      if (STREQ (fip->fnfieldlists[i].name, fieldname))
+      if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0)
        break;
     }
 
@@ -2320,12 +3154,12 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
 
   /* Fill in the member function field info.  */
   fnp = &new_fnfield->fnfield;
-  fnp->physname = obsavestring (physname, strlen (physname),
-                               &objfile->type_obstack);
+  /* The name is already allocated along with this objfile, so we don't
+     need to duplicate it for the type.  */
+  fnp->physname = physname ? physname : "";
   fnp->type = alloc_type (objfile);
   if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
     {
-      struct type *return_type = TYPE_TARGET_TYPE (die->type);
       int nparams = TYPE_NFIELDS (die->type);
 
       /* TYPE is the domain of this method, and DIE->TYPE is the type
@@ -2346,17 +3180,18 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
        fnp->voffset = VOFFSET_STATIC;
     }
   else
-    complain (&dwarf2_missing_member_fn_type_complaint, physname);
+    complaint (&symfile_complaints, "member function type missing for '%s'",
+              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);
+  if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL)
+    fnp->fcontext = die_containing_type (die, cu);
 
   /* 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);
+  attr = dwarf2_attr (die, DW_AT_accessibility, cu);
   if (attr)
     {
       switch (DW_UNSND (attr))
@@ -2371,27 +3206,27 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
     }
 
   /* Check for artificial methods.  */
-  attr = dwarf_attr (die, DW_AT_artificial);
+  attr = dwarf2_attr (die, DW_AT_artificial, cu);
   if (attr && DW_UNSND (attr) != 0)
     fnp->is_artificial = 1;
 
   /* Get index in virtual function table if it is a virtual member function.  */
-  attr = dwarf_attr (die, DW_AT_vtable_elem_location);
+  attr = dwarf2_attr (die, DW_AT_vtable_elem_location, cu);
   if (attr)
     {
       /* Support the .debug_loc offsets */
       if (attr_form_is_block (attr))
         {
-          fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2;
+          fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu) + 2;
         }
       else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
         {
-          complain (&dwarf2_complex_location_expr);
+         dwarf2_complex_location_expr_complaint ();
         }
       else
         {
-          complain (&dwarf2_invalid_attrib_class, "DW_AT_vtable_elem_location",
-                    fieldname);
+         dwarf2_invalid_attrib_class_complaint ("DW_AT_vtable_elem_location",
+                                                fieldname);
         }
    }
 }
@@ -2400,7 +3235,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
 
 static void
 dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
-                                struct objfile *objfile)
+                                struct dwarf2_cu *cu)
 {
   struct fnfieldlist *flp;
   int total_length = 0;
@@ -2430,6 +3265,23 @@ dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
   TYPE_NFN_FIELDS_TOTAL (type) = total_length;
 }
 
+
+/* Returns non-zero if NAME is the name of a vtable member in CU's
+   language, zero otherwise.  */
+static int
+is_vtable_name (const char *name, struct dwarf2_cu *cu)
+{
+  static const char vptr[] = "_vptr";
+
+  /* C++ and some implementations of Java use this name.  */
+  if (strncmp (name, vptr, sizeof (vptr) - 1) == 0
+      && is_cplus_marker (name[sizeof (vptr) - 1]))
+    return 1;
+
+  return 0;
+}
+
+
 /* 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.
@@ -2447,21 +3299,38 @@ dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
    suppresses creating a symbol table entry itself).  */
 
 static void
-read_structure_scope (struct die_info *die, struct objfile *objfile,
-                     const struct comp_unit_head *cu_header)
+read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
   struct type *type;
   struct attribute *attr;
+  const char *previous_prefix = processing_current_prefix;
+  struct cleanup *back_to = NULL;
+
+  if (die->type)
+    return;
 
   type = alloc_type (objfile);
 
   INIT_CPLUS_SPECIFIC (type);
-  attr = dwarf_attr (die, DW_AT_name);
+  attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr && DW_STRING (attr))
     {
-      TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
-                                          strlen (DW_STRING (attr)),
-                                          &objfile->type_obstack);
+      if (cu->language == language_cplus)
+       {
+         char *new_prefix = determine_class_name (die, cu);
+         TYPE_TAG_NAME (type) = obsavestring (new_prefix,
+                                              strlen (new_prefix),
+                                              &objfile->objfile_obstack);
+         back_to = make_cleanup (xfree, new_prefix);
+         processing_current_prefix = new_prefix;
+       }
+      else
+       {
+         /* The name is already allocated along with this objfile, so
+            we don't need to duplicate it for the type.  */
+         TYPE_TAG_NAME (type) = DW_STRING (attr);
+       }
     }
 
   if (die->tag == DW_TAG_structure_type)
@@ -2479,7 +3348,7 @@ read_structure_scope (struct die_info *die, struct objfile *objfile,
       TYPE_CODE (type) = TYPE_CODE_CLASS;
     }
 
-  attr = dwarf_attr (die, DW_AT_byte_size);
+  attr = dwarf2_attr (die, DW_AT_byte_size, cu);
   if (attr)
     {
       TYPE_LENGTH (type) = DW_UNSND (attr);
@@ -2489,12 +3358,15 @@ read_structure_scope (struct die_info *die, struct objfile *objfile,
       TYPE_LENGTH (type) = 0;
     }
 
+  if (die_is_declaration (die, cu))
+    TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+
   /* We need to add the type field to the die immediately so we don't
      infinitely recurse when dealing with pointers to the structure
      type within the structure itself. */
   die->type = type;
 
-  if (die->has_children && ! die_is_declaration (die))
+  if (die->child != NULL && ! die_is_declaration (die, cu))
     {
       struct field_info fi;
       struct die_info *child_die;
@@ -2502,57 +3374,52 @@ read_structure_scope (struct die_info *die, struct objfile *objfile,
 
       memset (&fi, 0, sizeof (struct field_info));
 
-      child_die = die->next;
+      child_die = die->child;
 
       while (child_die && child_die->tag)
        {
-         if (child_die->tag == DW_TAG_member)
-           {
-             dwarf2_add_field (&fi, child_die, objfile, cu_header);
-           }
-         else if (child_die->tag == DW_TAG_variable)
+         if (child_die->tag == DW_TAG_member
+             || child_die->tag == DW_TAG_variable)
            {
-             /* C++ static member.  */
-             dwarf2_add_field (&fi, child_die, objfile, cu_header);
+             /* NOTE: carlton/2002-11-05: A C++ static data member
+                should be a DW_TAG_member that is a declaration, but
+                all versions of G++ as of this writing (so through at
+                least 3.2.1) incorrectly generate DW_TAG_variable
+                tags for them instead.  */
+             dwarf2_add_field (&fi, child_die, cu);
            }
          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);
+             read_type_die (child_die, cu);
+             dwarf2_add_member_fn (&fi, child_die, type, cu);
            }
          else if (child_die->tag == DW_TAG_inheritance)
            {
              /* C++ base class field.  */
-             dwarf2_add_field (&fi, child_die, objfile, cu_header);
-           }
-         else
-           {
-             process_die (child_die, objfile, cu_header);
+             dwarf2_add_field (&fi, child_die, cu);
            }
          child_die = sibling_die (child_die);
        }
 
       /* Attach fields and member functions to the type.  */
       if (fi.nfields)
-       dwarf2_attach_fields_to_type (&fi, type, objfile);
+       dwarf2_attach_fields_to_type (&fi, type, cu);
       if (fi.nfnfields)
        {
-         dwarf2_attach_fn_fields_to_type (&fi, type, objfile);
+         dwarf2_attach_fn_fields_to_type (&fi, type, cu);
 
          /* 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)
+         if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL)
            {
-             struct type *t = die_containing_type (die, objfile, cu_header);
+             struct type *t = die_containing_type (die, cu);
 
              TYPE_VPTR_BASETYPE (type) = t;
              if (type == t)
                {
-                 static const char vptr_name[] =
-                 {'_', 'v', 'p', 't', 'r', '\0'};
                  int i;
 
                  /* Our own class provides vtbl ptr.  */
@@ -2562,8 +3429,7 @@ read_structure_scope (struct die_info *die, struct objfile *objfile,
                    {
                      char *fieldname = TYPE_FIELD_NAME (t, i);
 
-                     if (STREQN (fieldname, vptr_name, strlen (vptr_name) - 1)
-                         && is_cplus_marker (fieldname[strlen (vptr_name)]))
+                      if (is_vtable_name (fieldname, cu))
                        {
                          TYPE_VPTR_FIELDNO (type) = i;
                          break;
@@ -2572,8 +3438,10 @@ read_structure_scope (struct die_info *die, struct objfile *objfile,
 
                  /* 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) : "");
+                   complaint (&symfile_complaints,
+                              "virtual function table pointer not found when defining class '%s'",
+                              TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) :
+                              "");
                }
              else
                {
@@ -2582,50 +3450,89 @@ read_structure_scope (struct die_info *die, struct objfile *objfile,
            }
        }
 
-      new_symbol (die, type, objfile, cu_header);
-
       do_cleanups (back_to);
     }
-  else
+
+  processing_current_prefix = previous_prefix;
+  if (back_to != NULL)
+    do_cleanups (back_to);
+}
+
+static void
+process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  const char *previous_prefix = processing_current_prefix;
+  struct die_info *child_die = die->child;
+
+  if (TYPE_TAG_NAME (die->type) != NULL)
+    processing_current_prefix = TYPE_TAG_NAME (die->type);
+
+  /* NOTE: carlton/2004-03-16: GCC 3.4 (or at least one of its
+     snapshots) has been known to create a die giving a declaration
+     for a class that has, as a child, a die giving a definition for a
+     nested class.  So we have to process our children even if the
+     current die is a declaration.  Normally, of course, a declaration
+     won't have any children at all.  */
+
+  while (child_die != NULL && child_die->tag)
     {
-      /* No children, must be stub. */
-      TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+      if (child_die->tag == DW_TAG_member
+         || child_die->tag == DW_TAG_variable
+         || child_die->tag == DW_TAG_inheritance)
+       {
+         /* Do nothing.  */
+       }
+      else
+       process_die (child_die, cu);
+
+      child_die = sibling_die (child_die);
     }
-}
 
-/* Given a pointer to a die which begins an enumeration, process all
-   the dies that define the members of the enumeration.
+  if (die->child != NULL && ! die_is_declaration (die, cu))
+    new_symbol (die, die->type, cu);
 
-   This will be much nicer in draft 6 of the DWARF spec when our
-   members will be dies instead squished into the DW_AT_element_list
-   attribute.
+  processing_current_prefix = previous_prefix;
+}
 
-   NOTE: We reverse the order of the element list.  */
+/* Given a DW_AT_enumeration_type die, set its type.  We do not
+   complete the type's fields yet, or create any symbols.  */
 
 static void
-read_enumeration (struct die_info *die, struct objfile *objfile,
-                 const struct comp_unit_head *cu_header)
+read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
 {
-  struct die_info *child_die;
+  struct objfile *objfile = cu->objfile;
   struct type *type;
-  struct field *fields;
   struct attribute *attr;
-  struct symbol *sym;
-  int num_fields;
-  int unsigned_enum = 1;
+
+  if (die->type)
+    return;
 
   type = alloc_type (objfile);
 
   TYPE_CODE (type) = TYPE_CODE_ENUM;
-  attr = dwarf_attr (die, DW_AT_name);
+  attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr && DW_STRING (attr))
     {
-      TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
-                                          strlen (DW_STRING (attr)),
-                                          &objfile->type_obstack);
+      char *name = DW_STRING (attr);
+
+      if (processing_has_namespace_info)
+       {
+         TYPE_TAG_NAME (type) = obconcat (&objfile->objfile_obstack,
+                                          processing_current_prefix,
+                                          processing_current_prefix[0] == '\0'
+                                          ? "" : "::",
+                                          name);
+       }
+      else
+       {
+         /* The name is already allocated along with this objfile, so
+            we don't need to duplicate it for the type.  */
+         TYPE_TAG_NAME (type) = name;
+       }
     }
 
-  attr = dwarf_attr (die, DW_AT_byte_size);
+  attr = dwarf2_attr (die, DW_AT_byte_size, cu);
   if (attr)
     {
       TYPE_LENGTH (type) = DW_UNSND (attr);
@@ -2635,23 +3542,101 @@ read_enumeration (struct die_info *die, struct objfile *objfile,
       TYPE_LENGTH (type) = 0;
     }
 
+  die->type = type;
+}
+
+/* Determine the name of the type represented by DIE, which should be
+   a named C++ compound type.  Return the name in question; the caller
+   is responsible for xfree()'ing it.  */
+
+static char *
+determine_class_name (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct cleanup *back_to = NULL;
+  struct die_info *spec_die = die_specification (die, cu);
+  char *new_prefix = NULL;
+
+  /* If this is the definition of a class that is declared by another
+     die, then processing_current_prefix may not be accurate; see
+     read_func_scope for a similar example.  */
+  if (spec_die != NULL)
+    {
+      char *specification_prefix = determine_prefix (spec_die, cu);
+      processing_current_prefix = specification_prefix;
+      back_to = make_cleanup (xfree, specification_prefix);
+    }
+
+  /* If we don't have namespace debug info, guess the name by trying
+     to demangle the names of members, just like we did in
+     guess_structure_name.  */
+  if (!processing_has_namespace_info)
+    {
+      struct die_info *child;
+
+      for (child = die->child;
+          child != NULL && child->tag != 0;
+          child = sibling_die (child))
+       {
+         if (child->tag == DW_TAG_subprogram)
+           {
+             new_prefix 
+               = language_class_name_from_physname (cu->language_defn,
+                                                    dwarf2_linkage_name
+                                                    (child, cu));
+
+             if (new_prefix != NULL)
+               break;
+           }
+       }
+    }
+
+  if (new_prefix == NULL)
+    {
+      const char *name = dwarf2_name (die, cu);
+      new_prefix = typename_concat (processing_current_prefix,
+                                   name ? name : "<<anonymous>>");
+    }
+
+  if (back_to != NULL)
+    do_cleanups (back_to);
+
+  return new_prefix;
+}
+
+/* Given a pointer to a die which begins an enumeration, process all
+   the dies that define the members of the enumeration, and create the
+   symbol for the enumeration type.
+
+   NOTE: We reverse the order of the element list.  */
+
+static void
+process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  struct die_info *child_die;
+  struct field *fields;
+  struct attribute *attr;
+  struct symbol *sym;
+  int num_fields;
+  int unsigned_enum = 1;
+
   num_fields = 0;
   fields = NULL;
-  if (die->has_children)
+  if (die->child != NULL)
     {
-      child_die = die->next;
+      child_die = die->child;
       while (child_die && child_die->tag)
        {
          if (child_die->tag != DW_TAG_enumerator)
            {
-             process_die (child_die, objfile, cu_header);
+             process_die (child_die, cu);
            }
          else
            {
-             attr = dwarf_attr (child_die, DW_AT_name);
+             attr = dwarf2_attr (child_die, DW_AT_name, cu);
              if (attr)
                {
-                 sym = new_symbol (child_die, type, objfile, cu_header);
+                 sym = new_symbol (child_die, die->type, cu);
                  if (SYMBOL_VALUE (sym) < 0)
                    unsigned_enum = 0;
 
@@ -2663,10 +3648,11 @@ read_enumeration (struct die_info *die, struct objfile *objfile,
                                  * sizeof (struct field));
                    }
 
-                 FIELD_NAME (fields[num_fields]) = SYMBOL_NAME (sym);
+                 FIELD_NAME (fields[num_fields]) = DEPRECATED_SYMBOL_NAME (sym);
                  FIELD_TYPE (fields[num_fields]) = NULL;
                  FIELD_BITPOS (fields[num_fields]) = SYMBOL_VALUE (sym);
                  FIELD_BITSIZE (fields[num_fields]) = 0;
+                 FIELD_STATIC_KIND (fields[num_fields]) = 0;
 
                  num_fields++;
                }
@@ -2677,18 +3663,18 @@ read_enumeration (struct die_info *die, struct objfile *objfile,
 
       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,
+         TYPE_NFIELDS (die->type) = num_fields;
+         TYPE_FIELDS (die->type) = (struct field *)
+           TYPE_ALLOC (die->type, sizeof (struct field) * num_fields);
+         memcpy (TYPE_FIELDS (die->type), fields,
                  sizeof (struct field) * num_fields);
          xfree (fields);
        }
       if (unsigned_enum)
-       TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+       TYPE_FLAGS (die->type) |= TYPE_FLAG_UNSIGNED;
     }
-  die->type = type;
-  new_symbol (die, type, objfile, cu_header);
+
+  new_symbol (die, die->type, cu);
 }
 
 /* Extract all information from a DW_TAG_array_type DIE and put it in
@@ -2696,9 +3682,9 @@ read_enumeration (struct die_info *die, struct objfile *objfile,
    arrays.  */
 
 static void
-read_array_type (struct die_info *die, struct objfile *objfile,
-                const struct comp_unit_head *cu_header)
+read_array_type (struct die_info *die, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
   struct die_info *child_die;
   struct type *type = NULL;
   struct type *element_type, *range_type, *index_type;
@@ -2713,119 +3699,60 @@ read_array_type (struct die_info *die, struct objfile *objfile,
       return;
     }
 
-  element_type = die_type (die, objfile, cu_header);
+  element_type = die_type (die, cu);
 
   /* Irix 6.2 native cc creates array types without children for
      arrays with unspecified length.  */
-  if (die->has_children == 0)
+  if (die->child == NULL)
     {
-      index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
+      index_type = dwarf2_fundamental_type (objfile, FT_INTEGER, cu);
       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;
+  child_die = die->child;
   while (child_die && child_die->tag)
     {
       if (child_die->tag == DW_TAG_subrange_type)
        {
-         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)
-           {
-             if (attr->form == DW_FORM_sdata)
-               {
-                 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_data8)
-               {
-                 low = DW_UNSND (attr);
-               }
-             else
-               {
-                 complain (&dwarf2_non_const_array_bound_ignored,
-                           dwarf_form_name (attr->form));
-#ifdef FORTRAN_HACK
-                 die->type = lookup_pointer_type (element_type);
-                 return;
-#else
-                 low = 0;
-#endif
-               }
-           }
-         attr = dwarf_attr (child_die, DW_AT_upper_bound);
-         if (attr)
-           {
-             if (attr->form == DW_FORM_sdata)
-               {
-                 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_data8)
-               {
-                 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
-               {
-                 complain (&dwarf2_non_const_array_bound_ignored,
-                           dwarf_form_name (attr->form));
-#ifdef FORTRAN_HACK
-                 die->type = lookup_pointer_type (element_type);
-                 return;
-#else
-                 high = 1;
-#endif
-               }
-           }
+          read_subrange_type (child_die, cu);
 
-         /* 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);
+          if (child_die->type != NULL)
+            {
+             /* The range type was succesfully read. Save it for
+                 the 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++] = child_die->type;
+            }
        }
       child_die = sibling_die (child_die);
     }
 
   /* 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]);
+
+  if (read_array_order (die, cu) == DW_ORD_col_major)
+    {
+      int i = 0;
+      while (i < ndim)
+       type = create_array_type (NULL, type, range_types[i++]);
+    }
+  else
+    {
+      while (ndim-- > 0)
+       type = create_array_type (NULL, type, range_types[ndim]);
+    }
 
   /* Understand Dwarf2 support for vector types (like they occur on
      the PowerPC w/ AltiVec).  Gcc just adds another attribute to the
@@ -2833,7 +3760,7 @@ read_array_type (struct die_info *die, struct objfile *objfile,
      custom vendor extension.  The main difference between a regular
      array and the vector variant is that vectors are passed by value
      to functions.  */
-  attr = dwarf_attr (die, DW_AT_GNU_vector);
+  attr = dwarf2_attr (die, DW_AT_GNU_vector, cu);
   if (attr)
     TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
 
@@ -2843,46 +3770,80 @@ read_array_type (struct die_info *die, struct objfile *objfile,
   die->type = type;
 }
 
+static enum dwarf_array_dim_ordering
+read_array_order (struct die_info *die, struct dwarf2_cu *cu) 
+{
+  struct attribute *attr;
+
+  attr = dwarf2_attr (die, DW_AT_ordering, cu);
+
+  if (attr) return DW_SND (attr);
+
+  /*
+    GNU F77 is a special case, as at 08/2004 array type info is the
+    opposite order to the dwarf2 specification, but data is still 
+    laid out as per normal fortran.
+
+    FIXME: dsl/2004-8-20: If G77 is ever fixed, this will also need 
+    version checking.
+  */
+
+  if (cu->language == language_fortran &&
+      cu->producer && strstr (cu->producer, "GNU F77"))
+    {
+      return DW_ORD_row_major;
+    }
+
+  switch (cu->language_defn->la_array_ordering) 
+    {
+    case array_column_major:
+      return DW_ORD_col_major;
+    case array_row_major:
+    default:
+      return DW_ORD_row_major;
+    };
+}
+
+
 /* First cut: install each common block member as a global variable.  */
 
 static void
-read_common_block (struct die_info *die, struct objfile *objfile,
-                  const struct comp_unit_head *cu_header)
+read_common_block (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct die_info *child_die;
   struct attribute *attr;
   struct symbol *sym;
   CORE_ADDR base = (CORE_ADDR) 0;
 
-  attr = dwarf_attr (die, DW_AT_location);
+  attr = dwarf2_attr (die, DW_AT_location, cu);
   if (attr)
     {
       /* Support the .debug_loc offsets */
       if (attr_form_is_block (attr))
         {
-          base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+          base = decode_locdesc (DW_BLOCK (attr), cu);
         }
       else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
         {
-          complain (&dwarf2_complex_location_expr);
+         dwarf2_complex_location_expr_complaint ();
         }
       else
         {
-          complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
-                    "common block member");
+         dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+                                                "common block member");
         }
     }
-  if (die->has_children)
+  if (die->child != NULL)
     {
-      child_die = die->next;
+      child_die = die->child;
       while (child_die && child_die->tag)
        {
-         sym = new_symbol (child_die, NULL, objfile, cu_header);
-         attr = dwarf_attr (child_die, DW_AT_data_member_location);
+         sym = new_symbol (child_die, NULL, cu);
+         attr = dwarf2_attr (child_die, DW_AT_data_member_location, cu);
          if (attr)
            {
              SYMBOL_VALUE_ADDRESS (sym) =
-               base + decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+               base + decode_locdesc (DW_BLOCK (attr), cu);
              add_symbol_to_list (sym, &global_symbols);
            }
          child_die = sibling_die (child_die);
@@ -2890,31 +3851,160 @@ read_common_block (struct die_info *die, struct objfile *objfile,
     }
 }
 
+/* Read a C++ namespace.  */
+
+static void
+read_namespace (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  const char *previous_prefix = processing_current_prefix;
+  const char *name;
+  int is_anonymous;
+  struct die_info *current_die;
+
+  name = namespace_name (die, &is_anonymous, cu);
+
+  /* Now build the name of the current namespace.  */
+
+  if (previous_prefix[0] == '\0')
+    {
+      processing_current_prefix = name;
+    }
+  else
+    {
+      /* We need temp_name around because processing_current_prefix
+        is a const char *.  */
+      char *temp_name = alloca (strlen (previous_prefix)
+                               + 2 + strlen(name) + 1);
+      strcpy (temp_name, previous_prefix);
+      strcat (temp_name, "::");
+      strcat (temp_name, name);
+
+      processing_current_prefix = temp_name;
+    }
+
+  /* Add a symbol associated to this if we haven't seen the namespace
+     before.  Also, add a using directive if it's an anonymous
+     namespace.  */
+
+  if (dwarf2_extension (die, cu) == NULL)
+    {
+      struct type *type;
+
+      /* FIXME: carlton/2003-06-27: Once GDB is more const-correct,
+        this cast will hopefully become unnecessary.  */
+      type = init_type (TYPE_CODE_NAMESPACE, 0, 0,
+                       (char *) processing_current_prefix,
+                       objfile);
+      TYPE_TAG_NAME (type) = TYPE_NAME (type);
+
+      new_symbol (die, type, cu);
+      die->type = type;
+
+      if (is_anonymous)
+       cp_add_using_directive (processing_current_prefix,
+                               strlen (previous_prefix),
+                               strlen (processing_current_prefix));
+    }
+
+  if (die->child != NULL)
+    {
+      struct die_info *child_die = die->child;
+      
+      while (child_die && child_die->tag)
+       {
+         process_die (child_die, cu);
+         child_die = sibling_die (child_die);
+       }
+    }
+
+  processing_current_prefix = previous_prefix;
+}
+
+/* Return the name of the namespace represented by DIE.  Set
+   *IS_ANONYMOUS to tell whether or not the namespace is an anonymous
+   namespace.  */
+
+static const char *
+namespace_name (struct die_info *die, int *is_anonymous, struct dwarf2_cu *cu)
+{
+  struct die_info *current_die;
+  const char *name = NULL;
+
+  /* Loop through the extensions until we find a name.  */
+
+  for (current_die = die;
+       current_die != NULL;
+       current_die = dwarf2_extension (die, cu))
+    {
+      name = dwarf2_name (current_die, cu);
+      if (name != NULL)
+       break;
+    }
+
+  /* Is it an anonymous namespace?  */
+
+  *is_anonymous = (name == NULL);
+  if (*is_anonymous)
+    name = "(anonymous namespace)";
+
+  return name;
+}
+
 /* Extract all information from a DW_TAG_pointer_type DIE and add to
    the user defined type vector.  */
 
 static void
-read_tag_pointer_type (struct die_info *die, struct objfile *objfile,
-                      const struct comp_unit_head *cu_header)
+read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
 {
+  struct comp_unit_head *cu_header = &cu->header;
   struct type *type;
-  struct attribute *attr;
+  struct attribute *attr_byte_size;
+  struct attribute *attr_address_class;
+  int byte_size, addr_class;
 
   if (die->type)
     {
       return;
     }
 
-  type = lookup_pointer_type (die_type (die, objfile, cu_header));
-  attr = dwarf_attr (die, DW_AT_byte_size);
-  if (attr)
-    {
-      TYPE_LENGTH (type) = DW_UNSND (attr);
-    }
+  type = lookup_pointer_type (die_type (die, cu));
+
+  attr_byte_size = dwarf2_attr (die, DW_AT_byte_size, cu);
+  if (attr_byte_size)
+    byte_size = DW_UNSND (attr_byte_size);
   else
+    byte_size = cu_header->addr_size;
+
+  attr_address_class = dwarf2_attr (die, DW_AT_address_class, cu);
+  if (attr_address_class)
+    addr_class = DW_UNSND (attr_address_class);
+  else
+    addr_class = DW_ADDR_none;
+
+  /* If the pointer size or address class is different than the
+     default, create a type variant marked as such and set the
+     length accordingly.  */
+  if (TYPE_LENGTH (type) != byte_size || addr_class != DW_ADDR_none)
     {
-      TYPE_LENGTH (type) = cu_header->addr_size;
+      if (ADDRESS_CLASS_TYPE_FLAGS_P ())
+       {
+         int type_flags;
+
+         type_flags = ADDRESS_CLASS_TYPE_FLAGS (byte_size, addr_class);
+         gdb_assert ((type_flags & ~TYPE_FLAG_ADDRESS_CLASS_ALL) == 0);
+         type = make_type_with_address_space (type, type_flags);
+       }
+      else if (TYPE_LENGTH (type) != byte_size)
+       {
+         complaint (&symfile_complaints, "invalid pointer size %d", byte_size);
+       }
+      else {
+       /* Should we also complain about unhandled address classes?  */
+      }
     }
+
+  TYPE_LENGTH (type) = byte_size;
   die->type = type;
 }
 
@@ -2922,9 +4012,9 @@ read_tag_pointer_type (struct die_info *die, struct objfile *objfile,
    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)
+read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
   struct type *type;
   struct type *to_type;
   struct type *domain;
@@ -2935,8 +4025,8 @@ read_tag_ptr_to_member_type (struct die_info *die, struct objfile *objfile,
     }
 
   type = alloc_type (objfile);
-  to_type = die_type (die, objfile, cu_header);
-  domain = die_containing_type (die, objfile, cu_header);
+  to_type = die_type (die, cu);
+  domain = die_containing_type (die, cu);
   smash_to_member_type (type, domain, to_type);
 
   die->type = type;
@@ -2946,9 +4036,9 @@ read_tag_ptr_to_member_type (struct die_info *die, struct objfile *objfile,
    the user defined type vector.  */
 
 static void
-read_tag_reference_type (struct die_info *die, struct objfile *objfile,
-                        const struct comp_unit_head *cu_header)
+read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu)
 {
+  struct comp_unit_head *cu_header = &cu->header;
   struct type *type;
   struct attribute *attr;
 
@@ -2957,8 +4047,8 @@ read_tag_reference_type (struct die_info *die, struct objfile *objfile,
       return;
     }
 
-  type = lookup_reference_type (die_type (die, objfile, cu_header));
-  attr = dwarf_attr (die, DW_AT_byte_size);
+  type = lookup_reference_type (die_type (die, cu));
+  attr = dwarf2_attr (die, DW_AT_byte_size, cu);
   if (attr)
     {
       TYPE_LENGTH (type) = DW_UNSND (attr);
@@ -2971,8 +4061,7 @@ read_tag_reference_type (struct die_info *die, struct objfile *objfile,
 }
 
 static void
-read_tag_const_type (struct die_info *die, struct objfile *objfile,
-                    const struct comp_unit_head *cu_header)
+read_tag_const_type (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct type *base_type;
 
@@ -2981,13 +4070,12 @@ read_tag_const_type (struct die_info *die, struct objfile *objfile,
       return;
     }
 
-  base_type = die_type (die, objfile, cu_header);
+  base_type = die_type (die, cu);
   die->type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
 }
 
 static void
-read_tag_volatile_type (struct die_info *die, struct objfile *objfile,
-                       const struct comp_unit_head *cu_header)
+read_tag_volatile_type (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct type *base_type;
 
@@ -2996,7 +4084,7 @@ read_tag_volatile_type (struct die_info *die, struct objfile *objfile,
       return;
     }
 
-  base_type = die_type (die, objfile, cu_header);
+  base_type = die_type (die, cu);
   die->type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
 }
 
@@ -3006,8 +4094,9 @@ read_tag_volatile_type (struct die_info *die, struct objfile *objfile,
    attribute to reference it.  */
 
 static void
-read_tag_string_type (struct die_info *die, struct objfile *objfile)
+read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
   struct type *type, *range_type, *index_type, *char_type;
   struct attribute *attr;
   unsigned int length;
@@ -3017,7 +4106,7 @@ read_tag_string_type (struct die_info *die, struct objfile *objfile)
       return;
     }
 
-  attr = dwarf_attr (die, DW_AT_string_length);
+  attr = dwarf2_attr (die, DW_AT_string_length, cu);
   if (attr)
     {
       length = DW_UNSND (attr);
@@ -3025,7 +4114,7 @@ read_tag_string_type (struct die_info *die, struct objfile *objfile)
   else
     {
       /* check for the DW_AT_byte_size attribute */
-      attr = dwarf_attr (die, DW_AT_byte_size);
+      attr = dwarf2_attr (die, DW_AT_byte_size, cu);
       if (attr)
         {
           length = DW_UNSND (attr);
@@ -3035,9 +4124,9 @@ read_tag_string_type (struct die_info *die, struct objfile *objfile)
           length = 1;
         }
     }
-  index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
+  index_type = dwarf2_fundamental_type (objfile, FT_INTEGER, cu);
   range_type = create_range_type (NULL, index_type, 1, length);
-  if (cu_language == language_fortran)
+  if (cu->language == language_fortran)
     {
       /* Need to create a unique string type for bounds
          information */
@@ -3045,7 +4134,7 @@ read_tag_string_type (struct die_info *die, struct objfile *objfile)
     }
   else
     {
-      char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
+      char_type = dwarf2_fundamental_type (objfile, FT_CHAR, cu);
       type = create_string_type (char_type, range_type);
     }
   die->type = type;
@@ -3063,8 +4152,7 @@ read_tag_string_type (struct die_info *die, struct objfile *objfile)
  */
 
 static void
-read_subroutine_type (struct die_info *die, struct objfile *objfile,
-                     const struct comp_unit_head *cu_header)
+read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct type *type;           /* Type that this function returns */
   struct type *ftype;          /* Function that returns above type */
@@ -3075,16 +4163,16 @@ read_subroutine_type (struct die_info *die, struct objfile *objfile,
     {
       return;
     }
-  type = die_type (die, objfile, cu_header);
+  type = die_type (die, cu);
   ftype = lookup_function_type (type);
 
   /* All functions in C++ have prototypes.  */
-  attr = dwarf_attr (die, DW_AT_prototyped);
+  attr = dwarf2_attr (die, DW_AT_prototyped, cu);
   if ((attr && (DW_UNSND (attr) != 0))
-      || cu_language == language_cplus)
+      || cu->language == language_cplus)
     TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
 
-  if (die->has_children)
+  if (die->child != NULL)
     {
       struct die_info *child_die;
       int nparams = 0;
@@ -3093,7 +4181,7 @@ read_subroutine_type (struct die_info *die, struct objfile *objfile,
       /* Count the number of parameters.
          FIXME: GDB currently ignores vararg functions, but knows about
          vararg member functions.  */
-      child_die = die->next;
+      child_die = die->child;
       while (child_die && child_die->tag)
        {
          if (child_die->tag == DW_TAG_formal_parameter)
@@ -3108,7 +4196,7 @@ read_subroutine_type (struct die_info *die, struct objfile *objfile,
       TYPE_FIELDS (ftype) = (struct field *)
        TYPE_ALLOC (ftype, nparams * sizeof (struct field));
 
-      child_die = die->next;
+      child_die = die->child;
       while (child_die && child_die->tag)
        {
          if (child_die->tag == DW_TAG_formal_parameter)
@@ -3118,13 +4206,12 @@ read_subroutine_type (struct die_info *die, struct objfile *objfile,
                 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);
+             attr = dwarf2_attr (child_die, DW_AT_artificial, cu);
              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);
+             TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, cu);
              iparams++;
            }
          child_die = sibling_die (child_die);
@@ -3135,21 +4222,21 @@ read_subroutine_type (struct die_info *die, struct objfile *objfile,
 }
 
 static void
-read_typedef (struct die_info *die, struct objfile *objfile,
-             const struct comp_unit_head *cu_header)
+read_typedef (struct die_info *die, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
   struct attribute *attr;
   char *name = NULL;
 
   if (!die->type)
     {
-      attr = dwarf_attr (die, DW_AT_name);
+      attr = dwarf2_attr (die, DW_AT_name, cu);
       if (attr && DW_STRING (attr))
        {
          name = DW_STRING (attr);
        }
       die->type = init_type (TYPE_CODE_TYPEDEF, 0, TYPE_FLAG_TARGET_STUB, name, objfile);
-      TYPE_TARGET_TYPE (die->type) = die_type (die, objfile, cu_header);
+      TYPE_TARGET_TYPE (die->type) = die_type (die, cu);
     }
 }
 
@@ -3157,8 +4244,9 @@ read_typedef (struct die_info *die, struct objfile *objfile,
    it in the TYPE field of the die.  */
 
 static void
-read_base_type (struct die_info *die, struct objfile *objfile)
+read_base_type (struct die_info *die, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
   struct type *type;
   struct attribute *attr;
   int encoding = 0, size = 0;
@@ -3169,17 +4257,17 @@ read_base_type (struct die_info *die, struct objfile *objfile)
       return;
     }
 
-  attr = dwarf_attr (die, DW_AT_encoding);
+  attr = dwarf2_attr (die, DW_AT_encoding, cu);
   if (attr)
     {
       encoding = DW_UNSND (attr);
     }
-  attr = dwarf_attr (die, DW_AT_byte_size);
+  attr = dwarf2_attr (die, DW_AT_byte_size, cu);
   if (attr)
     {
       size = DW_UNSND (attr);
     }
-  attr = dwarf_attr (die, DW_AT_name);
+  attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr && DW_STRING (attr))
     {
       enum type_code code = TYPE_CODE_INT;
@@ -3210,79 +4298,193 @@ read_base_type (struct die_info *die, struct objfile *objfile)
          type_flags |= TYPE_FLAG_UNSIGNED;
          break;
        default:
-         complain (&dwarf2_unsupported_at_encoding,
-                   dwarf_type_encoding_name (encoding));
+         complaint (&symfile_complaints, "unsupported DW_AT_encoding: '%s'",
+                    dwarf_type_encoding_name (encoding));
          break;
        }
       type = init_type (code, size, type_flags, DW_STRING (attr), objfile);
       if (encoding == DW_ATE_address)
-       TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID);
+       TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID,
+                                                          cu);
       else if (encoding == DW_ATE_complex_float)
        {
          if (size == 32)
            TYPE_TARGET_TYPE (type)
-             = dwarf2_fundamental_type (objfile, FT_EXT_PREC_FLOAT);
+             = dwarf2_fundamental_type (objfile, FT_EXT_PREC_FLOAT, cu);
          else if (size == 16)
            TYPE_TARGET_TYPE (type)
-             = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
+             = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT, cu);
          else if (size == 8)
            TYPE_TARGET_TYPE (type)
-             = dwarf2_fundamental_type (objfile, FT_FLOAT);
+             = dwarf2_fundamental_type (objfile, FT_FLOAT, cu);
        }
     }
   else
     {
-      type = dwarf_base_type (encoding, size, objfile);
+      type = dwarf_base_type (encoding, size, cu);
+    }
+  die->type = type;
+}
+
+/* Read the given DW_AT_subrange DIE.  */
+
+static void
+read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct type *base_type;
+  struct type *range_type;
+  struct attribute *attr;
+  int low = 0;
+  int high = -1;
+  
+  /* If we have already decoded this die, then nothing more to do.  */
+  if (die->type)
+    return;
+
+  base_type = die_type (die, cu);
+  if (base_type == NULL)
+    {
+      complaint (&symfile_complaints,
+                "DW_AT_type missing from DW_TAG_subrange_type");
+      return;
     }
-  die->type = type;
+
+  if (TYPE_CODE (base_type) == TYPE_CODE_VOID)
+    base_type = alloc_type (NULL);
+
+  if (cu->language == language_fortran)
+    { 
+      /* FORTRAN implies a lower bound of 1, if not given.  */
+      low = 1;
+    }
+
+  attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
+  if (attr)
+    low = dwarf2_get_attr_constant_value (attr, 0);
+
+  attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
+  if (attr)
+    {       
+      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.
+
+             FIXME: jimb/2003-09-22: GDB does not really know
+             how to handle arrays of unspecified length
+             either; we just represent them as zero-length
+             arrays.  Choose an appropriate upper bound given
+             the lower bound we've computed above.  */
+          high = low - 1;
+        }
+      else
+        high = dwarf2_get_attr_constant_value (attr, 1);
+    }
+
+  range_type = create_range_type (NULL, base_type, low, high);
+
+  attr = dwarf2_attr (die, DW_AT_name, cu);
+  if (attr && DW_STRING (attr))
+    TYPE_NAME (range_type) = DW_STRING (attr);
+  
+  attr = dwarf2_attr (die, DW_AT_byte_size, cu);
+  if (attr)
+    TYPE_LENGTH (range_type) = DW_UNSND (attr);
+
+  die->type = range_type;
 }
+  
 
 /* Read a whole compilation unit into a linked list of dies.  */
 
 static struct die_info *
-read_comp_unit (char *info_ptr, bfd *abfd,
-               const struct comp_unit_head *cu_header)
+read_comp_unit (char *info_ptr, bfd *abfd, struct dwarf2_cu *cu)
 {
-  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 ();
 
+  return read_die_and_children (info_ptr, abfd, cu, &info_ptr, NULL);
+}
+
+/* Read a single die and all its descendents.  Set the die's sibling
+   field to NULL; set other fields in the die correctly, and set all
+   of the descendents' fields correctly.  Set *NEW_INFO_PTR to the
+   location of the info_ptr after reading all of those dies.  PARENT
+   is the parent of the die in question.  */
+
+static struct die_info *
+read_die_and_children (char *info_ptr, bfd *abfd,
+                      struct dwarf2_cu *cu,
+                      char **new_info_ptr,
+                      struct die_info *parent)
+{
+  struct die_info *die;
+  char *cur_ptr;
+  int has_children;
+
+  cur_ptr = read_full_die (&die, abfd, info_ptr, cu, &has_children);
+  store_in_ref_table (die->offset, die);
+
+  if (has_children)
+    {
+      die->child = read_die_and_siblings (cur_ptr, abfd, cu,
+                                         new_info_ptr, die);
+    }
+  else
+    {
+      die->child = NULL;
+      *new_info_ptr = cur_ptr;
+    }
+
+  die->sibling = NULL;
+  die->parent = parent;
+  return die;
+}
+
+/* Read a die, all of its descendents, and all of its siblings; set
+   all of the fields of all of the dies correctly.  Arguments are as
+   in read_die_and_children.  */
+
+static struct die_info *
+read_die_and_siblings (char *info_ptr, bfd *abfd,
+                      struct dwarf2_cu *cu,
+                      char **new_info_ptr,
+                      struct die_info *parent)
+{
+  struct die_info *first_die, *last_sibling;
+  char *cur_ptr;
+
   cur_ptr = info_ptr;
-  nesting_level = 0;
-  first_die = last_die = NULL;
-  do
+  first_die = last_sibling = NULL;
+
+  while (1)
     {
-      cur_ptr = read_full_die (&die, abfd, cur_ptr, cu_header);
-      if (die->has_children)
+      struct die_info *die
+       = read_die_and_children (cur_ptr, abfd, cu, &cur_ptr, parent);
+
+      if (!first_die)
        {
-         nesting_level++;
+         first_die = die;
        }
-      if (die->tag == 0)
+      else
        {
-         nesting_level--;
+         last_sibling->sibling = die;
        }
 
-      die->next = NULL;
-
-      /* Enter die in reference hash table */
-      store_in_ref_table (die->offset, die);
-
-      if (!first_die)
+      if (die->tag == 0)
        {
-         first_die = last_die = die;
+         *new_info_ptr = cur_ptr;
+         return first_die;
        }
       else
        {
-         last_die->next = die;
-         last_die = die;
+         last_sibling = die;
        }
     }
-  while (nesting_level > 0);
-  return first_die;
 }
 
 /* Free a linked list of dies.  */
@@ -3295,7 +4497,9 @@ free_die_list (struct die_info *dies)
   die = dies;
   while (die)
     {
-      next = die->next;
+      if (die->child != NULL)
+       free_die_list (die->child);
+      next = die->sibling;
       xfree (die->attrs);
       xfree (die);
       die = next;
@@ -3316,53 +4520,68 @@ make_cleanup_free_die_list (struct die_info *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.  */
+   object file specified by OBJFILE into the objfile_obstack and return it.  */
 
 char *
-dwarf2_read_section (struct objfile *objfile, file_ptr offset,
-                    unsigned int size)
+dwarf2_read_section (struct objfile *objfile, asection *sectp)
 {
   bfd *abfd = objfile->obfd;
-  char *buf;
+  char *buf, *retbuf;
+  bfd_size_type size = bfd_get_section_size (sectp);
 
   if (size == 0)
     return NULL;
 
-  buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
-  if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
-      (bfd_bread (buf, size, abfd) != size))
-    {
-      buf = NULL;
-      error ("Dwarf Error: Can't read DWARF data from '%s'",
-            bfd_get_filename (abfd));
-    }
+  buf = (char *) obstack_alloc (&objfile->objfile_obstack, size);
+  retbuf
+    = (char *) symfile_relocate_debug_section (abfd, sectp, (bfd_byte *) buf);
+  if (retbuf != NULL)
+    return retbuf;
+
+  if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
+      || bfd_bread (buf, size, abfd) != size)
+    error ("Dwarf Error: Can't read DWARF data from '%s'",
+          bfd_get_filename (abfd));
+
   return buf;
 }
 
 /* In DWARF version 2, the description of the debugging information is
    stored in a separate .debug_abbrev section.  Before we read any
    dies from a section we read in all abbreviations and install them
-   in a hash table.  */
+   in a hash table.  This function also sets flags in CU describing
+   the data found in the abbrev table.  */
 
 static void
-dwarf2_read_abbrevs (bfd *abfd, unsigned int offset)
+dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu)
 {
+  struct comp_unit_head *cu_header = &cu->header;
   char *abbrev_ptr;
   struct abbrev_info *cur_abbrev;
   unsigned int abbrev_number, bytes_read, abbrev_name;
   unsigned int abbrev_form, hash_number;
-
-  /* empty the table */
-  dwarf2_empty_abbrev_table (NULL);
-
-  abbrev_ptr = dwarf_abbrev_buffer + offset;
+  struct attr_abbrev *cur_attrs;
+  unsigned int allocated_attrs;
+
+  /* Initialize dwarf2 abbrevs */
+  obstack_init (&cu->abbrev_obstack);
+  cu->dwarf2_abbrevs = obstack_alloc (&cu->abbrev_obstack,
+                                     (ABBREV_HASH_SIZE
+                                      * sizeof (struct abbrev_info *)));
+  memset (cu->dwarf2_abbrevs, 0,
+          ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
+
+  abbrev_ptr = dwarf2_per_objfile->abbrev_buffer + cu_header->abbrev_offset;
   abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
   abbrev_ptr += bytes_read;
 
+  allocated_attrs = ATTR_ALLOC_CHUNK;
+  cur_attrs = xmalloc (allocated_attrs * sizeof (struct attr_abbrev));
+  
   /* loop until we reach an abbrev number of 0 */
   while (abbrev_number)
     {
-      cur_abbrev = dwarf_alloc_abbrev ();
+      cur_abbrev = dwarf_alloc_abbrev (cu);
 
       /* read in abbrev header */
       cur_abbrev->number = abbrev_number;
@@ -3371,6 +4590,9 @@ dwarf2_read_abbrevs (bfd *abfd, unsigned int offset)
       cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
       abbrev_ptr += 1;
 
+      if (cur_abbrev->tag == DW_TAG_namespace)
+       cu->has_namespace_info = 1;
+
       /* now read in declarations */
       abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
       abbrev_ptr += bytes_read;
@@ -3378,24 +4600,30 @@ dwarf2_read_abbrevs (bfd *abfd, unsigned int offset)
       abbrev_ptr += bytes_read;
       while (abbrev_name)
        {
-         if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0)
+         if (cur_abbrev->num_attrs == allocated_attrs)
            {
-             cur_abbrev->attrs = (struct attr_abbrev *)
-               xrealloc (cur_abbrev->attrs,
-                         (cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK)
-                         * sizeof (struct attr_abbrev));
+             allocated_attrs += ATTR_ALLOC_CHUNK;
+             cur_attrs
+               = xrealloc (cur_attrs, (allocated_attrs
+                                       * sizeof (struct attr_abbrev)));
            }
-         cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name;
-         cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form;
+         cur_attrs[cur_abbrev->num_attrs].name = abbrev_name;
+         cur_attrs[cur_abbrev->num_attrs++].form = abbrev_form;
          abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
          abbrev_ptr += bytes_read;
          abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
          abbrev_ptr += bytes_read;
        }
 
+      cur_abbrev->attrs = obstack_alloc (&cu->abbrev_obstack,
+                                        (cur_abbrev->num_attrs
+                                         * sizeof (struct attr_abbrev)));
+      memcpy (cur_abbrev->attrs, cur_attrs,
+             cur_abbrev->num_attrs * sizeof (struct attr_abbrev));
+
       hash_number = abbrev_number % ABBREV_HASH_SIZE;
-      cur_abbrev->next = dwarf2_abbrevs[hash_number];
-      dwarf2_abbrevs[hash_number] = cur_abbrev;
+      cur_abbrev->next = cu->dwarf2_abbrevs[hash_number];
+      cu->dwarf2_abbrevs[hash_number] = cur_abbrev;
 
       /* Get next abbreviation.
          Under Irix6 the abbreviations for a compilation unit are not
@@ -3404,50 +4632,39 @@ dwarf2_read_abbrevs (bfd *abfd, unsigned int offset)
          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)
+      if ((unsigned int) (abbrev_ptr - dwarf2_per_objfile->abbrev_buffer)
+         >= dwarf2_per_objfile->abbrev_size)
        break;
       abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
       abbrev_ptr += bytes_read;
-      if (dwarf2_lookup_abbrev (abbrev_number) != NULL)
+      if (dwarf2_lookup_abbrev (abbrev_number, cu) != NULL)
        break;
     }
+
+  xfree (cur_attrs);
 }
 
-/* Empty the abbrev table for a new compilation unit.  */
+/* Release the memory used by the abbrev table for a compilation unit.  */
 
-/* ARGSUSED */
 static void
-dwarf2_empty_abbrev_table (PTR ignore)
+dwarf2_free_abbrev_table (void *ptr_to_cu)
 {
-  int i;
-  struct abbrev_info *abbrev, *next;
+  struct dwarf2_cu *cu = ptr_to_cu;
 
-  for (i = 0; i < ABBREV_HASH_SIZE; ++i)
-    {
-      next = NULL;
-      abbrev = dwarf2_abbrevs[i];
-      while (abbrev)
-       {
-         next = abbrev->next;
-         xfree (abbrev->attrs);
-         xfree (abbrev);
-         abbrev = next;
-       }
-      dwarf2_abbrevs[i] = NULL;
-    }
+  obstack_free (&cu->abbrev_obstack, NULL);
+  cu->dwarf2_abbrevs = NULL;
 }
 
 /* Lookup an abbrev_info structure in the abbrev hash table.  */
 
 static struct abbrev_info *
-dwarf2_lookup_abbrev (unsigned int number)
+dwarf2_lookup_abbrev (unsigned int number, struct dwarf2_cu *cu)
 {
   unsigned int hash_number;
   struct abbrev_info *abbrev;
 
   hash_number = number % ABBREV_HASH_SIZE;
-  abbrev = dwarf2_abbrevs[hash_number];
+  abbrev = cu->dwarf2_abbrevs[hash_number];
 
   while (abbrev)
     {
@@ -3459,40 +4676,261 @@ dwarf2_lookup_abbrev (unsigned int number)
   return NULL;
 }
 
+/* Returns nonzero if TAG represents a type that we might generate a partial
+   symbol for.  */
+
+static int
+is_type_tag_for_partial (int tag)
+{
+  switch (tag)
+    {
+#if 0
+    /* Some types that would be reasonable to generate partial symbols for,
+       that we don't at present.  */
+    case DW_TAG_array_type:
+    case DW_TAG_file_type:
+    case DW_TAG_ptr_to_member_type:
+    case DW_TAG_set_type:
+    case DW_TAG_string_type:
+    case DW_TAG_subroutine_type:
+#endif
+    case DW_TAG_base_type:
+    case DW_TAG_class_type:
+    case DW_TAG_enumeration_type:
+    case DW_TAG_structure_type:
+    case DW_TAG_subrange_type:
+    case DW_TAG_typedef:
+    case DW_TAG_union_type:
+      return 1;
+    default:
+      return 0;
+    }
+}
+
+/* Load all DIEs that are interesting for partial symbols into memory.  */
+
+static struct partial_die_info *
+load_partial_dies (bfd *abfd, char *info_ptr, int building_psymtab,
+                  struct dwarf2_cu *cu)
+{
+  struct partial_die_info *part_die;
+  struct partial_die_info *parent_die, *last_die, *first_die = NULL;
+  struct abbrev_info *abbrev;
+  unsigned int bytes_read;
+
+  int nesting_level = 1;
+
+  parent_die = NULL;
+  last_die = NULL;
+
+  cu->partial_dies
+    = htab_create_alloc_ex (cu->header.length / 12,
+                           partial_die_hash,
+                           partial_die_eq,
+                           NULL,
+                           &cu->comp_unit_obstack,
+                           hashtab_obstack_allocate,
+                           dummy_obstack_deallocate);
+
+  part_die = obstack_alloc (&cu->comp_unit_obstack,
+                           sizeof (struct partial_die_info));
+
+  while (1)
+    {
+      abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu);
+
+      /* A NULL abbrev means the end of a series of children.  */
+      if (abbrev == NULL)
+       {
+         if (--nesting_level == 0)
+           {
+             /* PART_DIE was probably the last thing allocated on the
+                comp_unit_obstack, so we could call obstack_free
+                here.  We don't do that because the waste is small,
+                and will be cleaned up when we're done with this
+                compilation unit.  This way, we're also more robust
+                against other users of the comp_unit_obstack.  */
+             return first_die;
+           }
+         info_ptr += bytes_read;
+         last_die = parent_die;
+         parent_die = parent_die->die_parent;
+         continue;
+       }
+
+      /* Check whether this DIE is interesting enough to save.  */
+      if (!is_type_tag_for_partial (abbrev->tag)
+         && abbrev->tag != DW_TAG_enumerator
+         && abbrev->tag != DW_TAG_subprogram
+         && abbrev->tag != DW_TAG_variable
+         && abbrev->tag != DW_TAG_namespace)
+       {
+         /* Otherwise we skip to the next sibling, if any.  */
+         info_ptr = skip_one_die (info_ptr + bytes_read, abbrev, cu);
+         continue;
+       }
+
+      info_ptr = read_partial_die (part_die, abbrev, bytes_read,
+                                  abfd, info_ptr, cu);
+
+      /* This two-pass algorithm for processing partial symbols has a
+        high cost in cache pressure.  Thus, handle some simple cases
+        here which cover the majority of C partial symbols.  DIEs
+        which neither have specification tags in them, nor could have
+        specification tags elsewhere pointing at them, can simply be
+        processed and discarded.
+
+        This segment is also optional; scan_partial_symbols and
+        add_partial_symbol will handle these DIEs if we chain
+        them in normally.  When compilers which do not emit large
+        quantities of duplicate debug information are more common,
+        this code can probably be removed.  */
+
+      /* Any complete simple types at the top level (pretty much all
+        of them, for a language without namespaces), can be processed
+        directly.  */
+      if (parent_die == NULL
+         && part_die->has_specification == 0
+         && part_die->is_declaration == 0
+         && (part_die->tag == DW_TAG_typedef
+             || part_die->tag == DW_TAG_base_type
+             || part_die->tag == DW_TAG_subrange_type))
+       {
+         if (building_psymtab && part_die->name != NULL)
+           add_psymbol_to_list (part_die->name, strlen (part_die->name),
+                                VAR_DOMAIN, LOC_TYPEDEF,
+                                &cu->objfile->static_psymbols,
+                                0, (CORE_ADDR) 0, cu->language, cu->objfile);
+         info_ptr = locate_pdi_sibling (part_die, info_ptr, abfd, cu);
+         continue;
+       }
+
+      /* If we're at the second level, and we're an enumerator, and
+        our parent has no specification (meaning possibly lives in a
+        namespace elsewhere), then we can add the partial symbol now
+        instead of queueing it.  */
+      if (part_die->tag == DW_TAG_enumerator
+         && parent_die != NULL
+         && parent_die->die_parent == NULL
+         && parent_die->tag == DW_TAG_enumeration_type
+         && parent_die->has_specification == 0)
+       {
+         if (part_die->name == NULL)
+           complaint (&symfile_complaints, "malformed enumerator DIE ignored");
+         else if (building_psymtab)
+           add_psymbol_to_list (part_die->name, strlen (part_die->name),
+                                VAR_DOMAIN, LOC_CONST,
+                                cu->language == language_cplus
+                                ? &cu->objfile->global_psymbols
+                                : &cu->objfile->static_psymbols,
+                                0, (CORE_ADDR) 0, cu->language, cu->objfile);
+
+         info_ptr = locate_pdi_sibling (part_die, info_ptr, abfd, cu);
+         continue;
+       }
+
+      /* We'll save this DIE so link it in.  */
+      part_die->die_parent = parent_die;
+      part_die->die_sibling = NULL;
+      part_die->die_child = NULL;
+
+      if (last_die && last_die == parent_die)
+       last_die->die_child = part_die;
+      else if (last_die)
+       last_die->die_sibling = part_die;
+
+      last_die = part_die;
+
+      if (first_die == NULL)
+       first_die = part_die;
+
+      /* Maybe add the DIE to the hash table.  Not all DIEs that we
+        find interesting need to be in the hash table, because we
+        also have the parent/sibling/child chains; only those that we
+        might refer to by offset later during partial symbol reading.
+
+        For now this means things that might have be the target of a
+        DW_AT_specification, DW_AT_abstract_origin, or
+        DW_AT_extension.  DW_AT_extension will refer only to
+        namespaces; DW_AT_abstract_origin refers to functions (and
+        many things under the function DIE, but we do not recurse
+        into function DIEs during partial symbol reading) and
+        possibly variables as well; DW_AT_specification refers to
+        declarations.  Declarations ought to have the DW_AT_declaration
+        flag.  It happens that GCC forgets to put it in sometimes, but
+        only for functions, not for types.
+
+        Adding more things than necessary to the hash table is harmless
+        except for the performance cost.  Adding too few will result in
+        internal errors in find_partial_die.  */
+
+      if (abbrev->tag == DW_TAG_subprogram
+         || abbrev->tag == DW_TAG_variable
+         || abbrev->tag == DW_TAG_namespace
+         || part_die->is_declaration)
+       {
+         void **slot;
+
+         slot = htab_find_slot_with_hash (cu->partial_dies, part_die,
+                                          part_die->offset, INSERT);
+         *slot = part_die;
+       }
+
+      part_die = obstack_alloc (&cu->comp_unit_obstack,
+                               sizeof (struct partial_die_info));
+
+      /* For some DIEs we want to follow their children (if any).  For C
+         we have no reason to follow the children of structures; for other
+        languages we have to, both so that we can get at method physnames
+        to infer fully qualified class names, and for DW_AT_specification.  */
+      if (last_die->has_children
+         && (last_die->tag == DW_TAG_namespace
+             || last_die->tag == DW_TAG_enumeration_type
+             || (cu->language != language_c
+                 && (last_die->tag == DW_TAG_class_type
+                     || last_die->tag == DW_TAG_structure_type
+                     || last_die->tag == DW_TAG_union_type))))
+       {
+         nesting_level++;
+         parent_die = last_die;
+         continue;
+       }
+
+      /* Otherwise we skip to the next sibling, if any.  */
+      info_ptr = locate_pdi_sibling (last_die, info_ptr, abfd, cu);
+
+      /* Back to the top, do it again.  */
+    }
+}
+
 /* Read a minimal amount of information into the minimal die structure.  */
 
 static char *
-read_partial_die (struct partial_die_info *part_die, bfd *abfd,
-                 char *info_ptr, const struct comp_unit_head *cu_header)
+read_partial_die (struct partial_die_info *part_die,
+                 struct abbrev_info *abbrev,
+                 unsigned int abbrev_len, bfd *abfd,
+                 char *info_ptr, struct dwarf2_cu *cu)
 {
-  unsigned int abbrev_number, bytes_read, i;
-  struct abbrev_info *abbrev;
+  unsigned int bytes_read, i;
   struct attribute attr;
-  struct attribute spec_attr;
-  int found_spec_attr = 0;
   int has_low_pc_attr = 0;
   int has_high_pc_attr = 0;
 
-  *part_die = zeroed_partial_die;
-  abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
-  info_ptr += bytes_read;
-  if (!abbrev_number)
+  memset (part_die, 0, sizeof (struct partial_die_info));
+
+  part_die->offset = info_ptr - dwarf2_per_objfile->info_buffer;
+
+  info_ptr += abbrev_len;
+
+  if (abbrev == NULL)
     return info_ptr;
 
-  abbrev = dwarf2_lookup_abbrev (abbrev_number);
-  if (!abbrev)
-    {
-      error ("Dwarf Error: Could not find abbrev number %d.", abbrev_number);
-    }
-  part_die->offset = info_ptr - dwarf_info_buffer;
   part_die->tag = abbrev->tag;
   part_die->has_children = abbrev->has_children;
-  part_die->abbrev = abbrev_number;
 
   for (i = 0; i < abbrev->num_attrs; ++i)
     {
-      info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd,
-                                info_ptr, cu_header);
+      info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, info_ptr, cu);
 
       /* Store the data if it is of an attribute we want to keep in a
          partial symbol table.  */
@@ -3504,6 +4942,10 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd,
          if (part_die->name == NULL)
            part_die->name = DW_STRING (&attr);
          break;
+       case DW_AT_comp_dir:
+         if (part_die->dirname == NULL)
+           part_die->dirname = DW_STRING (&attr);
+         break;
        case DW_AT_MIPS_linkage_name:
          part_die->name = DW_STRING (&attr);
          break;
@@ -3523,12 +4965,12 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd,
             }
           else if (attr.form == DW_FORM_data4 || attr.form == DW_FORM_data8)
             {
-              complain (&dwarf2_complex_location_expr);
+             dwarf2_complex_location_expr_complaint ();
             }
           else
             {
-              complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
-                        "partial symbol information");
+             dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+                                                    "partial symbol information");
             }
          break;
        case DW_AT_language:
@@ -3545,44 +4987,28 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd,
          break;
        case DW_AT_abstract_origin:
        case DW_AT_specification:
-         found_spec_attr = 1;
-         spec_attr = attr;
+       case DW_AT_extension:
+         part_die->has_specification = 1;
+         part_die->spec_offset = dwarf2_get_ref_die_offset (&attr, cu);
          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);
+           complaint (&symfile_complaints, "ignoring absolute DW_AT_sibling");
          else
-           part_die->sibling =
-             dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr);
+           part_die->sibling = dwarf2_per_objfile->info_buffer
+             + dwarf2_get_ref_die_offset (&attr, cu);
          break;
+        case DW_AT_stmt_list:
+          part_die->has_stmt_list = 1;
+          part_die->line_offset = DW_UNSND (&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.
@@ -3599,18 +5025,100 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd,
   return info_ptr;
 }
 
-/* Read the die from the .debug_info section buffer.  And set diep to
-   point to a newly allocated die with its information.  */
+/* Find a cached partial DIE at OFFSET in CU.  */
+
+static struct partial_die_info *
+find_partial_die_in_comp_unit (unsigned long offset, struct dwarf2_cu *cu)
+{
+  struct partial_die_info *lookup_die = NULL;
+  struct partial_die_info part_die;
+
+  part_die.offset = offset;
+  lookup_die = htab_find_with_hash (cu->partial_dies, &part_die, offset);
+
+  if (lookup_die == NULL)
+    internal_error (__FILE__, __LINE__,
+                   "could not find partial DIE in cache\n");
+
+  return lookup_die;
+}
+
+/* Find a partial DIE at OFFSET, which may or may not be in CU.  */
+
+static struct partial_die_info *
+find_partial_die (unsigned long offset, struct dwarf2_cu *cu,
+                 struct dwarf2_cu **target_cu)
+{
+  struct dwarf2_per_cu_data *per_cu;
+
+  if (offset >= cu->header.offset
+      && offset < cu->header.offset + cu->header.length)
+    {
+      *target_cu = cu;
+      return find_partial_die_in_comp_unit (offset, cu);
+    }
+
+  internal_error (__FILE__, __LINE__,
+                 "unsupported inter-compilation-unit reference");
+}
+
+/* Adjust PART_DIE before generating a symbol for it.  This function
+   may set the is_external flag or change the DIE's name.  */
+
+static void
+fixup_partial_die (struct partial_die_info *part_die,
+                  struct dwarf2_cu *cu)
+{
+  /* If we found a reference attribute and the DIE has no name, try
+     to find a name in the referred to DIE.  */
+
+  if (part_die->name == NULL && part_die->has_specification)
+    {
+      struct partial_die_info *spec_die;
+      struct dwarf2_cu *spec_cu;
+
+      spec_die = find_partial_die (part_die->spec_offset, cu, &spec_cu);
+
+      fixup_partial_die (spec_die, spec_cu);
+
+      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;
+       }
+    }
+
+  /* Set default names for some unnamed DIEs.  */
+  if (part_die->name == NULL && (part_die->tag == DW_TAG_structure_type
+                                || part_die->tag == DW_TAG_class_type))
+    part_die->name = "(anonymous class)";
+
+  if (part_die->name == NULL && part_die->tag == DW_TAG_namespace)
+    part_die->name = "(anonymous namespace)";
+
+  if (part_die->tag == DW_TAG_structure_type
+      || part_die->tag == DW_TAG_class_type
+      || part_die->tag == DW_TAG_union_type)
+    guess_structure_name (part_die, cu);
+}
+
+/* Read the die from the .debug_info section buffer.  Set DIEP to
+   point to a newly allocated die with its information, except for its
+   child, sibling, and parent fields.  Set HAS_CHILDREN to tell
+   whether the die has children or not.  */
 
 static char *
 read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
-              const struct comp_unit_head *cu_header)
+              struct dwarf2_cu *cu, int *has_children)
 {
   unsigned int abbrev_number, bytes_read, i, offset;
   struct abbrev_info *abbrev;
   struct die_info *die;
 
-  offset = info_ptr - dwarf_info_buffer;
+  offset = info_ptr - dwarf2_per_objfile->info_buffer;
   abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
   info_ptr += bytes_read;
   if (!abbrev_number)
@@ -3620,18 +5128,20 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
       die->abbrev = abbrev_number;
       die->type = NULL;
       *diep = die;
+      *has_children = 0;
       return info_ptr;
     }
 
-  abbrev = dwarf2_lookup_abbrev (abbrev_number);
+  abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
   if (!abbrev)
     {
-      error ("Dwarf Error: could not find abbrev number %d.", abbrev_number);
+      error ("Dwarf Error: could not find abbrev number %d [in module %s]",
+            abbrev_number,
+            bfd_get_filename (abfd));
     }
   die = dwarf_alloc_die ();
   die->offset = offset;
   die->tag = abbrev->tag;
-  die->has_children = abbrev->has_children;
   die->abbrev = abbrev_number;
   die->type = NULL;
 
@@ -3642,10 +5152,11 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
   for (i = 0; i < abbrev->num_attrs; ++i)
     {
       info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
-                                abfd, info_ptr, cu_header);
+                                abfd, info_ptr, cu);
     }
 
   *diep = die;
+  *has_children = abbrev->has_children;
   return info_ptr;
 }
 
@@ -3653,9 +5164,10 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
 
 static char *
 read_attribute_value (struct attribute *attr, unsigned form,
-               bfd *abfd, char *info_ptr,
-               const struct comp_unit_head *cu_header)
+                     bfd *abfd, char *info_ptr,
+                     struct dwarf2_cu *cu)
 {
+  struct comp_unit_head *cu_header = &cu->header;
   unsigned int bytes_read;
   struct dwarf_block *blk;
 
@@ -3664,11 +5176,11 @@ read_attribute_value (struct attribute *attr, unsigned form,
     {
     case DW_FORM_addr:
     case DW_FORM_ref_addr:
-      DW_ADDR (attr) = read_address (abfd, info_ptr, cu_header, &bytes_read);
+      DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
       info_ptr += bytes_read;
       break;
     case DW_FORM_block2:
-      blk = dwarf_alloc_block ();
+      blk = dwarf_alloc_block (cu);
       blk->size = read_2_bytes (abfd, info_ptr);
       info_ptr += 2;
       blk->data = read_n_bytes (abfd, info_ptr, blk->size);
@@ -3676,7 +5188,7 @@ read_attribute_value (struct attribute *attr, unsigned form,
       DW_BLOCK (attr) = blk;
       break;
     case DW_FORM_block4:
-      blk = dwarf_alloc_block ();
+      blk = dwarf_alloc_block (cu);
       blk->size = read_4_bytes (abfd, info_ptr);
       info_ptr += 4;
       blk->data = read_n_bytes (abfd, info_ptr, blk->size);
@@ -3705,7 +5217,7 @@ read_attribute_value (struct attribute *attr, unsigned form,
       info_ptr += bytes_read;
       break;
     case DW_FORM_block:
-      blk = dwarf_alloc_block ();
+      blk = dwarf_alloc_block (cu);
       blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
       blk->data = read_n_bytes (abfd, info_ptr, blk->size);
@@ -3713,7 +5225,7 @@ read_attribute_value (struct attribute *attr, unsigned form,
       DW_BLOCK (attr) = blk;
       break;
     case DW_FORM_block1:
-      blk = dwarf_alloc_block ();
+      blk = dwarf_alloc_block (cu);
       blk->size = read_1_byte (abfd, info_ptr);
       info_ptr += 1;
       blk->data = read_n_bytes (abfd, info_ptr, blk->size);
@@ -3759,11 +5271,12 @@ read_attribute_value (struct attribute *attr, unsigned form,
     case DW_FORM_indirect:
       form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
-      info_ptr = read_attribute_value (attr, form, abfd, info_ptr, cu_header);
+      info_ptr = read_attribute_value (attr, form, abfd, info_ptr, cu);
       break;
     default:
-      error ("Dwarf Error: Cannot handle %s in DWARF reader.",
-            dwarf_form_name (form));
+      error ("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]",
+            dwarf_form_name (form),
+            bfd_get_filename (abfd));
     }
   return info_ptr;
 }
@@ -3772,11 +5285,10 @@ read_attribute_value (struct attribute *attr, unsigned form,
 
 static char *
 read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
-               bfd *abfd, char *info_ptr,
-               const struct comp_unit_head *cu_header)
+               bfd *abfd, char *info_ptr, struct dwarf2_cu *cu)
 {
   attr->name = abbrev->name;
-  return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu_header);
+  return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu);
 }
 
 /* read dwarf information from a buffer */
@@ -3824,9 +5336,9 @@ read_8_bytes (bfd *abfd, char *buf)
 }
 
 static CORE_ADDR
-read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
-             int *bytes_read)
+read_address (bfd *abfd, char *buf, struct dwarf2_cu *cu, int *bytes_read)
 {
+  struct comp_unit_head *cu_header = &cu->header;
   CORE_ADDR retval = 0;
 
   if (cu_header->signed_addr_p)
@@ -3844,7 +5356,8 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
          break;
        default:
          internal_error (__FILE__, __LINE__,
-                         "read_address: bad switch, signed");
+                         "read_address: bad switch, signed [in module %s]",
+                         bfd_get_filename (abfd));
        }
     }
   else
@@ -3862,7 +5375,8 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
          break;
        default:
          internal_error (__FILE__, __LINE__,
-                         "read_address: bad switch, unsigned");
+                         "read_address: bad switch, unsigned [in module %s]",
+                         bfd_get_filename (abfd));
        }
     }
 
@@ -3977,7 +5491,8 @@ read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
       break;
     default:
       internal_error (__FILE__, __LINE__,
-                     "read_offset: bad switch");
+                     "read_offset: bad switch [in module %s]",
+                     bfd_get_filename (abfd));
     }
 
  return retval;
@@ -4017,20 +5532,22 @@ read_indirect_string (bfd *abfd, char *buf,
   LONGEST str_offset = read_offset (abfd, buf, cu_header,
                                    (int *) bytes_read_ptr);
 
-  if (dwarf_str_buffer == NULL)
+  if (dwarf2_per_objfile->str_buffer == NULL)
     {
-      error ("DW_FORM_strp used without .debug_str section");
+      error ("DW_FORM_strp used without .debug_str section [in module %s]",
+                     bfd_get_filename (abfd));
       return NULL;
     }
-  if (str_offset >= dwarf_str_size)
+  if (str_offset >= dwarf2_per_objfile->str_size)
     {
-      error ("DW_FORM_strp pointing outside of .debug_str section");
+      error ("DW_FORM_strp pointing outside of .debug_str section [in module %s]",
+                     bfd_get_filename (abfd));
       return NULL;
     }
   gdb_assert (HOST_CHAR_BIT == 8);
-  if (dwarf_str_buffer[str_offset] == '\0')
+  if (dwarf2_per_objfile->str_buffer[str_offset] == '\0')
     return NULL;
-  return dwarf_str_buffer + str_offset;
+  return dwarf2_per_objfile->str_buffer + str_offset;
 }
 
 static unsigned long
@@ -4093,28 +5610,44 @@ read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
   return result;
 }
 
+/* Return a pointer to just past the end of an LEB128 number in BUF.  */
+
+static char *
+skip_leb128 (bfd *abfd, char *buf)
+{
+  int byte;
+
+  while (1)
+    {
+      byte = bfd_get_8 (abfd, (bfd_byte *) buf);
+      buf++;
+      if ((byte & 128) == 0)
+       return buf;
+    }
+}
+
 static void
-set_cu_language (unsigned int lang)
+set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
 {
   switch (lang)
     {
     case DW_LANG_C89:
     case DW_LANG_C:
-      cu_language = language_c;
+      cu->language = language_c;
       break;
     case DW_LANG_C_plus_plus:
-      cu_language = language_cplus;
+      cu->language = language_cplus;
       break;
     case DW_LANG_Fortran77:
     case DW_LANG_Fortran90:
     case DW_LANG_Fortran95:
-      cu_language = language_fortran;
+      cu->language = language_fortran;
       break;
     case DW_LANG_Mips_Assembler:
-      cu_language = language_asm;
+      cu->language = language_asm;
       break;
     case DW_LANG_Java:
-      cu_language = language_java;
+      cu->language = language_java;
       break;
     case DW_LANG_Ada83:
     case DW_LANG_Ada95:
@@ -4123,16 +5656,16 @@ set_cu_language (unsigned int lang)
     case DW_LANG_Pascal83:
     case DW_LANG_Modula2:
     default:
-      cu_language = language_unknown;
+      cu->language = language_minimal;
       break;
     }
-  cu_language_defn = language_def (cu_language);
+  cu->language_defn = language_def (cu->language);
 }
 
 /* Return the named attribute or NULL if not there.  */
 
 static struct attribute *
-dwarf_attr (struct die_info *die, unsigned int name)
+dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu)
 {
   unsigned int i;
   struct attribute *spec = NULL;
@@ -4150,22 +5683,54 @@ dwarf_attr (struct die_info *die, unsigned int name)
   if (spec)
     {
       struct die_info *ref_die =
-      follow_die_ref (dwarf2_get_ref_die_offset (spec));
+      follow_die_ref (dwarf2_get_ref_die_offset (spec, cu));
 
       if (ref_die)
-       return dwarf_attr (ref_die, name);
+       return dwarf2_attr (ref_die, name, cu);
     }
 
   return NULL;
 }
 
+/* Return non-zero iff the attribute NAME is defined for the given DIE,
+   and holds a non-zero value.  This function should only be used for
+   DW_FORM_flag attributes.  */
+
 static int
-die_is_declaration (struct die_info *die)
+dwarf2_flag_true_p (struct die_info *die, unsigned name, struct dwarf2_cu *cu)
 {
-  return (dwarf_attr (die, DW_AT_declaration)
-         && ! dwarf_attr (die, DW_AT_specification));
+  struct attribute *attr = dwarf2_attr (die, name, cu);
+
+  return (attr && DW_UNSND (attr));
+}
+
+static int
+die_is_declaration (struct die_info *die, struct dwarf2_cu *cu)
+{
+  /* A DIE is a declaration if it has a DW_AT_declaration attribute
+     which value is non-zero.  However, we have to be careful with
+     DIEs having a DW_AT_specification attribute, because dwarf2_attr()
+     (via dwarf2_flag_true_p) follows this attribute.  So we may
+     end up accidently finding a declaration attribute that belongs
+     to a different DIE referenced by the specification attribute,
+     even though the given DIE does not have a declaration attribute.  */
+  return (dwarf2_flag_true_p (die, DW_AT_declaration, cu)
+         && dwarf2_attr (die, DW_AT_specification, cu) == NULL);
 }
 
+/* Return the die giving the specification for DIE, if there is
+   one.  */
+
+static struct die_info *
+die_specification (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *spec_attr = dwarf2_attr (die, DW_AT_specification, cu);
+
+  if (spec_attr == NULL)
+    return NULL;
+  else
+    return follow_die_ref (dwarf2_get_ref_die_offset (spec_attr, cu));
+}
 
 /* Free the line_header structure *LH, and any arrays and strings it
    refers to.  */
@@ -4241,19 +5806,20 @@ add_file_name (struct line_header *lh,
   fe->dir_index = dir_index;
   fe->mod_time = mod_time;
   fe->length = length;
+  fe->included_p = 0;
 }
  
 
 /* Read the statement program header starting at OFFSET in
-   dwarf_line_buffer, according to the endianness of ABFD.  Return a
-   pointer to a struct line_header, allocated using xmalloc.
+   .debug_line, according to the endianness of ABFD.  Return a pointer
+   to a struct line_header, allocated using xmalloc.
 
    NOTE: the strings in the include directory and file name tables of
    the returned object point into debug_line_buffer, and must not be
    freed.  */
 static struct line_header *
 dwarf_decode_line_header (unsigned int offset, bfd *abfd,
-                          const struct comp_unit_head *cu_header)
+                         struct dwarf2_cu *cu)
 {
   struct cleanup *back_to;
   struct line_header *lh;
@@ -4262,17 +5828,17 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
   int i;
   char *cur_dir, *cur_file;
 
-  if (dwarf_line_buffer == NULL)
+  if (dwarf2_per_objfile->line_buffer == NULL)
     {
-      complain (&dwarf2_missing_line_number_section);
+      complaint (&symfile_complaints, "missing .debug_line section");
       return 0;
     }
 
   /* Make sure that at least there's room for the total_length field.  That
      could be 12 bytes long, but we're just going to fudge that.  */
-  if (offset + 4 >= dwarf_line_size)
+  if (offset + 4 >= dwarf2_per_objfile->line_size)
     {
-      complain (&dwarf2_statement_list_fits_in_line_number_section);
+      dwarf2_statement_list_fits_in_line_number_section_complaint ();
       return 0;
     }
 
@@ -4281,20 +5847,21 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
   back_to = make_cleanup ((make_cleanup_ftype *) free_line_header,
                           (void *) lh);
 
-  line_ptr = dwarf_line_buffer + offset;
+  line_ptr = dwarf2_per_objfile->line_buffer + offset;
 
   /* read in the header */
   lh->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
   line_ptr += bytes_read;
-  if (line_ptr + lh->total_length > dwarf_line_buffer + dwarf_line_size)
+  if (line_ptr + lh->total_length > (dwarf2_per_objfile->line_buffer
+                                    + dwarf2_per_objfile->line_size))
     {
-      complain (&dwarf2_statement_list_fits_in_line_number_section);
+      dwarf2_statement_list_fits_in_line_number_section_complaint ();
       return 0;
     }
   lh->statement_program_end = line_ptr + lh->total_length;
   lh->version = read_2_bytes (abfd, line_ptr);
   line_ptr += 2;
-  lh->header_length = read_offset (abfd, line_ptr, cu_header, &bytes_read);
+  lh->header_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;
@@ -4342,8 +5909,10 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
   line_ptr += bytes_read;
   lh->statement_program_start = line_ptr; 
 
-  if (line_ptr > dwarf_line_buffer + dwarf_line_size)
-    complain (&dwarf2_line_header_too_long);
+  if (line_ptr > (dwarf2_per_objfile->line_buffer
+                 + dwarf2_per_objfile->line_size))
+    complaint (&symfile_complaints,
+              "line number info header doesn't fit in `.debug_line' section");
 
   discard_cleanups (back_to);
   return lh;
@@ -4357,26 +5926,26 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
    addresses passed to record_line.  */
 
 static CORE_ADDR
-check_cu_functions (CORE_ADDR address)
+check_cu_functions (CORE_ADDR address, struct dwarf2_cu *cu)
 {
   struct function_range *fn;
 
   /* Find the function_range containing address.  */
-  if (!cu_first_fn)
+  if (!cu->first_fn)
     return address;
 
-  if (!cu_cached_fn)
-    cu_cached_fn = cu_first_fn;
+  if (!cu->cached_fn)
+    cu->cached_fn = cu->first_fn;
 
-  fn = cu_cached_fn;
+  fn = cu->cached_fn;
   while (fn)
     if (fn->lowpc <= address && fn->highpc > address)
       goto found;
     else
       fn = fn->next;
 
-  fn = cu_first_fn;
-  while (fn && fn != cu_cached_fn)
+  fn = cu->first_fn;
+  while (fn && fn != cu->cached_fn)
     if (fn->lowpc <= address && fn->highpc > address)
       goto found;
     else
@@ -4388,25 +5957,44 @@ check_cu_functions (CORE_ADDR address)
   if (fn->seen_line)
     return address;
   if (address != fn->lowpc)
-    complain (&dwarf2_misplaced_line_number,
-             (unsigned long) address, fn->name);
+    complaint (&symfile_complaints,
+              "misplaced first line number at 0x%lx for '%s'",
+              (unsigned long) address, fn->name);
   fn->seen_line = 1;
   return fn->lowpc;
 }
 
-/* Decode the line number information for the compilation unit whose
-   line number info is at OFFSET in the .debug_line section.
-   The compilation directory of the file is passed in COMP_DIR.  */
+/* Decode the Line Number Program (LNP) for the given line_header
+   structure and CU.  The actual information extracted and the type
+   of structures created from the LNP depends on the value of PST.
+
+   1. If PST is NULL, then this procedure uses the data from the program
+      to create all necessary symbol tables, and their linetables.
+      The compilation directory of the file is passed in COMP_DIR,
+      and must not be NULL.
+   
+   2. If PST is not NULL, this procedure reads the program to determine
+      the list of files included by the unit represented by PST, and
+      builds all the associated partial symbol tables.  In this case,
+      the value of COMP_DIR is ignored, and can thus be NULL (the COMP_DIR
+      is not used to compute the full name of the symtab, and therefore
+      omitting it when building the partial symtab does not introduce
+      the potential for inconsistency - a partial symtab and its associated
+      symbtab having a different fullname -).  */
 
 static void
 dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
-                   const struct comp_unit_head *cu_header)
+                   struct dwarf2_cu *cu, struct partial_symtab *pst)
 {
   char *line_ptr;
   char *line_end;
-  unsigned int i, bytes_read;
-  char *cur_dir;
+  unsigned int bytes_read;
   unsigned char op_code, extended_op, adj_opcode;
+  CORE_ADDR baseaddr;
+  struct objfile *objfile = cu->objfile;
+  const int decode_for_pst_p = (pst != NULL);
+
+  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
   line_ptr = lh->statement_program_start;
   line_end = lh->statement_program_end;
@@ -4423,9 +6011,9 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
       int basic_block = 0;
       int end_sequence = 0;
 
-      /* Start a subfile for the current file of the state machine.  */
-      if (lh->num_file_names >= file)
+      if (!decode_for_pst_p && lh->num_file_names >= file)
        {
+          /* Start a subfile for the current file of the state machine.  */
          /* lh->include_dirs and lh->file_names are 0-based, but the
             directory and file name numbers in the statement program
             are 1-based.  */
@@ -4450,25 +6038,32 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
              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 */
-             address = check_cu_functions (address);
-             record_line (current_subfile, line, address);
+              lh->file_names[file - 1].included_p = 1;
+              if (!decode_for_pst_p)
+                {
+                 /* append row to matrix using current values */
+                 record_line (current_subfile, line, 
+                              check_cu_functions (address, cu));
+                }
              basic_block = 1;
            }
          else switch (op_code)
            {
            case DW_LNS_extended_op:
-             line_ptr += 1;    /* ignore length */
+             read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+             line_ptr += bytes_read;
              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, 0, address);
+                  lh->file_names[file - 1].included_p = 1;
+                  if (!decode_for_pst_p)
+                   record_line (current_subfile, 0, address);
                  break;
                case DW_LNE_set_address:
-                 address = read_address (abfd, line_ptr, cu_header, &bytes_read);
+                 address = read_address (abfd, line_ptr, cu, &bytes_read);
                  line_ptr += bytes_read;
                  address += baseaddr;
                  break;
@@ -4492,13 +6087,16 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
                   }
                  break;
                default:
-                 complain (&dwarf2_mangled_line_number_section);
+                 complaint (&symfile_complaints,
+                            "mangled .debug_line section");
                  return;
                }
              break;
            case DW_LNS_copy:
-             address = check_cu_functions (address);
-             record_line (current_subfile, line, address);
+              lh->file_names[file - 1].included_p = 1;
+              if (!decode_for_pst_p)
+               record_line (current_subfile, line, 
+                            check_cu_functions (address, cu));
              basic_block = 0;
              break;
            case DW_LNS_advance_pc:
@@ -4524,7 +6122,8 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
                   dir = lh->include_dirs[fe->dir_index - 1];
                 else
                   dir = comp_dir;
-                dwarf2_start_subfile (fe->name, dir);
+                if (!decode_for_pst_p)
+                  dwarf2_start_subfile (fe->name, dir);
               }
              break;
            case DW_LNS_set_column:
@@ -4562,6 +6161,22 @@ dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
            }
        }
     }
+
+  if (decode_for_pst_p)
+    {
+      int file_index;
+
+      /* Now that we're done scanning the Line Header Program, we can
+         create the psymtab of each included file.  */
+      for (file_index = 0; file_index < lh->num_file_names; file_index++)
+        if (lh->file_names[file_index].included_p == 1)
+          {
+            char *include_name = lh->file_names [file_index].name;
+    
+            if (strcmp (include_name, pst->filename) != 0)
+              dwarf2_create_include_psymtab (include_name, pst, objfile);
+          }
+    }
 }
 
 /* Start a subfile for DWARF.  FILENAME is the name of the file and
@@ -4609,6 +6224,62 @@ dwarf2_start_subfile (char *filename, char *dirname)
   start_subfile (filename, dirname);
 }
 
+static void
+var_decode_location (struct attribute *attr, struct symbol *sym,
+                    struct dwarf2_cu *cu)
+{
+  struct objfile *objfile = cu->objfile;
+  struct comp_unit_head *cu_header = &cu->header;
+
+  /* NOTE drow/2003-01-30: There used to be a comment and some special
+     code here to turn a symbol with DW_AT_external and a
+     SYMBOL_VALUE_ADDRESS of 0 into a LOC_UNRESOLVED symbol.  This was
+     necessary for platforms (maybe Alpha, certainly PowerPC GNU/Linux
+     with some versions of binutils) where shared libraries could have
+     relocations against symbols in their debug information - the
+     minimal symbol would have the right address, but the debug info
+     would not.  It's no longer necessary, because we will explicitly
+     apply relocations when we read in the debug information now.  */
+
+  /* A DW_AT_location attribute with no contents indicates that a
+     variable has been optimized away.  */
+  if (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0)
+    {
+      SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+      return;
+    }
+
+  /* Handle one degenerate form of location expression specially, to
+     preserve GDB's previous behavior when section offsets are
+     specified.  If this is just a DW_OP_addr then mark this symbol
+     as LOC_STATIC.  */
+
+  if (attr_form_is_block (attr)
+      && DW_BLOCK (attr)->size == 1 + cu_header->addr_size
+      && DW_BLOCK (attr)->data[0] == DW_OP_addr)
+    {
+      int dummy;
+
+      SYMBOL_VALUE_ADDRESS (sym) =
+       read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu, &dummy);
+      fixup_symbol_section (sym, objfile);
+      SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets,
+                                             SYMBOL_SECTION (sym));
+      SYMBOL_CLASS (sym) = LOC_STATIC;
+      return;
+    }
+
+  /* NOTE drow/2002-01-30: It might be worthwhile to have a static
+     expression evaluator, and use LOC_COMPUTED only when necessary
+     (i.e. when the value of a register or memory location is
+     referenced, or a thread-local block, etc.).  Then again, it might
+     not be worthwhile.  I'm assuming that it isn't unless performance
+     or memory numbers show me otherwise.  */
+
+  dwarf2_symbol_mark_computed (attr, sym, cu);
+  SYMBOL_CLASS (sym) = LOC_COMPUTED;
+}
+
 /* 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.
@@ -4616,51 +6287,50 @@ dwarf2_start_subfile (char *filename, char *dirname)
    used the passed type.  */
 
 static struct symbol *
-new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
-           const struct comp_unit_head *cu_header)
+new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
   struct symbol *sym = NULL;
   char *name;
   struct attribute *attr = NULL;
   struct attribute *attr2 = NULL;
-  CORE_ADDR addr = 0;
+  CORE_ADDR baseaddr;
+
+  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+  if (die->tag != DW_TAG_namespace)
+    name = dwarf2_linkage_name (die, cu);
+  else
+    name = TYPE_NAME (type);
 
-  name = dwarf2_linkage_name (die);
   if (name)
     {
-      sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+      sym = (struct symbol *) obstack_alloc (&objfile->objfile_obstack,
                                             sizeof (struct symbol));
       OBJSTAT (objfile, n_syms++);
       memset (sym, 0, sizeof (struct symbol));
-      SYMBOL_NAME (sym) = obsavestring (name, strlen (name),
-                                       &objfile->symbol_obstack);
+
+      /* Cache this symbol's name and the name's demangled form (if any).  */
+      SYMBOL_LANGUAGE (sym) = cu->language;
+      SYMBOL_SET_NAMES (sym, name, strlen (name), objfile);
 
       /* Default assumptions.
          Use the passed type or decode it from the die.  */
-      SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+      SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
       SYMBOL_CLASS (sym) = LOC_STATIC;
       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);
+       SYMBOL_TYPE (sym) = die_type (die, cu);
+      attr = dwarf2_attr (die, DW_AT_decl_line, cu);
       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
-         typical time versus space tradeoff, that was decided in favor
-         of time because it sped up C++ symbol lookups by a factor of
-         about 20. */
-
-      SYMBOL_LANGUAGE (sym) = cu_language;
-      SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
       switch (die->tag)
        {
        case DW_TAG_label:
-         attr = dwarf_attr (die, DW_AT_low_pc);
+         attr = dwarf2_attr (die, DW_AT_low_pc, cu);
          if (attr)
            {
              SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr;
@@ -4671,14 +6341,14 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
          /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
             finish_block.  */
          SYMBOL_CLASS (sym) = LOC_BLOCK;
-         attr2 = dwarf_attr (die, DW_AT_external);
+         attr2 = dwarf2_attr (die, DW_AT_external, cu);
          if (attr2 && (DW_UNSND (attr2) != 0))
            {
              add_symbol_to_list (sym, &global_symbols);
            }
          else
            {
-             add_symbol_to_list (sym, list_in_scope);
+             add_symbol_to_list (sym, cu->list_in_scope);
            }
          break;
        case DW_TAG_variable:
@@ -4690,107 +6360,26 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
                                           TARGET_INT_BIT / HOST_CHAR_BIT, 0,
                                           "<variable, no debug info>",
                                           objfile);
-         attr = dwarf_attr (die, DW_AT_const_value);
+         attr = dwarf2_attr (die, DW_AT_const_value, cu);
          if (attr)
            {
-             dwarf2_const_value (attr, sym, objfile, cu_header);
-             attr2 = dwarf_attr (die, DW_AT_external);
+             dwarf2_const_value (attr, sym, cu);
+             attr2 = dwarf2_attr (die, DW_AT_external, cu);
              if (attr2 && (DW_UNSND (attr2) != 0))
                add_symbol_to_list (sym, &global_symbols);
              else
-               add_symbol_to_list (sym, list_in_scope);
+               add_symbol_to_list (sym, cu->list_in_scope);
              break;
            }
-         attr = dwarf_attr (die, DW_AT_location);
+         attr = dwarf2_attr (die, DW_AT_location, cu);
          if (attr)
            {
-             attr2 = dwarf_attr (die, DW_AT_external);
+             var_decode_location (attr, sym, cu);
+             attr2 = dwarf2_attr (die, DW_AT_external, cu);
              if (attr2 && (DW_UNSND (attr2) != 0))
-               {
-                  /* Support the .debug_loc offsets */
-                  if (attr_form_is_block (attr))
-                    {
-                     SYMBOL_VALUE_ADDRESS (sym) =
-                       decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
-                    }
-                  else if (attr->form == DW_FORM_data4
-                           || attr->form == DW_FORM_data8)
-                    {
-                      complain (&dwarf2_complex_location_expr);
-                    }
-                  else
-                    {
-                      complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
-                                "external variable");
-                    }
-                 add_symbol_to_list (sym, &global_symbols);
-
-                 /* 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;
-               }
+               add_symbol_to_list (sym, &global_symbols);
              else
-               {
-                  /* Support the .debug_loc offsets */
-                  if (attr_form_is_block (attr))
-                    {
-                     SYMBOL_VALUE (sym) = addr =
-                       decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
-                    }
-                  else if (attr->form == DW_FORM_data4
-                           || attr->form == DW_FORM_data8)
-                    {
-                      complain (&dwarf2_complex_location_expr);
-                    }
-                  else
-                    {
-                      complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
-                                "external variable");
-                      addr = 0;
-                    }
-                 add_symbol_to_list (sym, list_in_scope);
-                 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_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;
-                   }
-               }
+               add_symbol_to_list (sym, cu->list_in_scope);
            }
          else
            {
@@ -4800,9 +6389,9 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
                 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);
+             attr2 = dwarf2_attr (die, DW_AT_external, cu);
              if (attr2 && (DW_UNSND (attr2) != 0)
-                 && dwarf_attr (die, DW_AT_type) != NULL)
+                 && dwarf2_attr (die, DW_AT_type, cu) != NULL)
                {
                  SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
                  add_symbol_to_list (sym, &global_symbols);
@@ -4810,42 +6399,20 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
            }
          break;
        case DW_TAG_formal_parameter:
-         attr = dwarf_attr (die, DW_AT_location);
+         attr = dwarf2_attr (die, DW_AT_location, cu);
          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_BASEREG_ARG;
-                     SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
-                   }
-               }
-             else
-               {
-                 SYMBOL_CLASS (sym) = LOC_ARG;
-               }
+             var_decode_location (attr, sym, cu);
+             /* FIXME drow/2003-07-31: Is LOC_COMPUTED_ARG necessary?  */
+             if (SYMBOL_CLASS (sym) == LOC_COMPUTED)
+               SYMBOL_CLASS (sym) = LOC_COMPUTED_ARG;
            }
-         attr = dwarf_attr (die, DW_AT_const_value);
+         attr = dwarf2_attr (die, DW_AT_const_value, cu);
          if (attr)
            {
-             dwarf2_const_value (attr, sym, objfile, cu_header);
+             dwarf2_const_value (attr, sym, cu);
            }
-         add_symbol_to_list (sym, list_in_scope);
+         add_symbol_to_list (sym, cu->list_in_scope);
          break;
        case DW_TAG_unspecified_parameters:
          /* From varargs functions; gdb doesn't seem to have any
@@ -4857,47 +6424,122 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
        case DW_TAG_union_type:
        case DW_TAG_enumeration_type:
          SYMBOL_CLASS (sym) = LOC_TYPEDEF;
-         SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
-         add_symbol_to_list (sym, list_in_scope);
+         SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
 
-         /* 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)
+         /* Make sure that the symbol includes appropriate enclosing
+            classes/namespaces in its name.  These are calculated in
+            read_structure_type, and the correct name is saved in
+            the type.  */
+
+         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);
+             struct type *type = SYMBOL_TYPE (sym);
+             
+             if (TYPE_TAG_NAME (type) != NULL)
+               {
+                 /* FIXME: carlton/2003-11-10: Should this use
+                    SYMBOL_SET_NAMES instead?  (The same problem also
+                    arises further down in this function.)  */
+                 /* The type's name is already allocated along with
+                    this objfile, so we don't need to duplicate it
+                    for the symbol.  */
+                 SYMBOL_LINKAGE_NAME (sym) = TYPE_TAG_NAME (type);
+               }
            }
+
+         {
+           /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't
+              really ever be static objects: otherwise, if you try
+              to, say, break of a class's method and you're in a file
+              which doesn't mention that class, it won't work unless
+              the check for all static symbols in lookup_symbol_aux
+              saves you.  See the OtherFileClass tests in
+              gdb.c++/namespace.exp.  */
+
+           struct pending **list_to_add;
+
+           list_to_add = (cu->list_in_scope == &file_symbols
+                          && cu->language == language_cplus
+                          ? &global_symbols : cu->list_in_scope);
+         
+           add_symbol_to_list (sym, list_to_add);
+
+           /* 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->objfile_obstack,
+                                sizeof (struct symbol));
+               *typedef_sym = *sym;
+               SYMBOL_DOMAIN (typedef_sym) = VAR_DOMAIN;
+               /* The symbol's name is already allocated along with
+                  this objfile, so we don't need to duplicate it for
+                  the type.  */
+               if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
+                 TYPE_NAME (SYMBOL_TYPE (sym)) = SYMBOL_NATURAL_NAME (sym);
+               add_symbol_to_list (typedef_sym, list_to_add);
+             }
+         }
          break;
        case DW_TAG_typedef:
+         if (processing_has_namespace_info
+             && processing_current_prefix[0] != '\0')
+           {
+             SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->objfile_obstack,
+                                                   processing_current_prefix,
+                                                   "::",
+                                                   name);
+           }
+         SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+         SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+         add_symbol_to_list (sym, cu->list_in_scope);
+         break;
        case DW_TAG_base_type:
+        case DW_TAG_subrange_type:
          SYMBOL_CLASS (sym) = LOC_TYPEDEF;
-         SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
-         add_symbol_to_list (sym, list_in_scope);
+         SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+         add_symbol_to_list (sym, cu->list_in_scope);
          break;
        case DW_TAG_enumerator:
-         attr = dwarf_attr (die, DW_AT_const_value);
+         if (processing_has_namespace_info
+             && processing_current_prefix[0] != '\0')
+           {
+             SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->objfile_obstack,
+                                                   processing_current_prefix,
+                                                   "::",
+                                                   name);
+           }
+         attr = dwarf2_attr (die, DW_AT_const_value, cu);
          if (attr)
            {
-             dwarf2_const_value (attr, sym, objfile, cu_header);
+             dwarf2_const_value (attr, sym, cu);
            }
-         add_symbol_to_list (sym, list_in_scope);
+         {
+           /* NOTE: carlton/2003-11-10: See comment above in the
+              DW_TAG_class_type, etc. block.  */
+
+           struct pending **list_to_add;
+
+           list_to_add = (cu->list_in_scope == &file_symbols
+                          && cu->language == language_cplus
+                          ? &global_symbols : cu->list_in_scope);
+         
+           add_symbol_to_list (sym, list_to_add);
+         }
+         break;
+       case DW_TAG_namespace:
+         SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+         add_symbol_to_list (sym, &global_symbols);
          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));
+         complaint (&symfile_complaints, "unsupported tag: '%s'",
+                    dwarf_tag_name (die->tag));
          break;
        }
     }
@@ -4908,21 +6550,26 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
 
 static void
 dwarf2_const_value (struct attribute *attr, struct symbol *sym,
-                   struct objfile *objfile,
-                   const struct comp_unit_head *cu_header)
+                   struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
+  struct comp_unit_head *cu_header = &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)));
+       dwarf2_const_value_length_mismatch_complaint (DEPRECATED_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));
+       obstack_alloc (&objfile->objfile_obstack, cu_header->addr_size);
+      /* NOTE: cagney/2003-05-09: In-lined store_address call with
+         it's body - store_unsigned_integer.  */
+      store_unsigned_integer (SYMBOL_VALUE_BYTES (sym), cu_header->addr_size,
+                             DW_ADDR (attr));
       SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
       break;
     case DW_FORM_block1:
@@ -4931,10 +6578,12 @@ dwarf2_const_value (struct attribute *attr, struct symbol *sym,
     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)));
+       dwarf2_const_value_length_mismatch_complaint (DEPRECATED_SYMBOL_NAME (sym),
+                                                     blk->size,
+                                                     TYPE_LENGTH (SYMBOL_TYPE
+                                                                  (sym)));
       SYMBOL_VALUE_BYTES (sym) = (char *)
-       obstack_alloc (&objfile->symbol_obstack, blk->size);
+       obstack_alloc (&objfile->objfile_obstack, blk->size);
       memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size);
       SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
       break;
@@ -4968,8 +6617,9 @@ dwarf2_const_value (struct attribute *attr, struct symbol *sym,
       break;
 
     default:
-      complain (&dwarf2_unsupported_const_value_attr,
-               dwarf_form_name (attr->form));
+      complaint (&symfile_complaints,
+                "unsupported const value attribute form: '%s'",
+                dwarf_form_name (attr->form));
       SYMBOL_VALUE (sym) = 0;
       SYMBOL_CLASS (sym) = LOC_CONST;
       break;
@@ -5002,35 +6652,36 @@ dwarf2_const_value_data (struct attribute *attr,
 /* Return the type of the die in question using its DW_AT_type attribute.  */
 
 static struct type *
-die_type (struct die_info *die, struct objfile *objfile,
-         const struct comp_unit_head *cu_header)
+die_type (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct type *type;
   struct attribute *type_attr;
   struct die_info *type_die;
   unsigned int ref;
 
-  type_attr = dwarf_attr (die, DW_AT_type);
+  type_attr = dwarf2_attr (die, DW_AT_type, cu);
   if (!type_attr)
     {
       /* A missing DW_AT_type represents a void type.  */
-      return dwarf2_fundamental_type (objfile, FT_VOID);
+      return dwarf2_fundamental_type (cu->objfile, FT_VOID, cu);
     }
   else
     {
-      ref = dwarf2_get_ref_die_offset (type_attr);
+      ref = dwarf2_get_ref_die_offset (type_attr, cu);
       type_die = follow_die_ref (ref);
       if (!type_die)
        {
-         error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+         error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", 
+                         ref, cu->objfile->name);
          return NULL;
        }
     }
-  type = tag_type_to_type (type_die, objfile, cu_header);
+  type = tag_type_to_type (type_die, cu);
   if (!type)
     {
       dump_die (type_die);
-      error ("Dwarf Error: Problem turning type die at offset into gdb type.");
+      error ("Dwarf Error: Problem turning type die at offset into gdb type [in module %s]",
+                     cu->objfile->name);
     }
   return type;
 }
@@ -5039,38 +6690,39 @@ die_type (struct die_info *die, struct objfile *objfile,
    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)
+die_containing_type (struct die_info *die, struct dwarf2_cu *cu)
 {
   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);
+  type_attr = dwarf2_attr (die, DW_AT_containing_type, cu);
   if (type_attr)
     {
-      ref = dwarf2_get_ref_die_offset (type_attr);
+      ref = dwarf2_get_ref_die_offset (type_attr, cu);
       type_die = follow_die_ref (ref);
       if (!type_die)
        {
-         error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+         error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", ref, 
+                         cu->objfile->name);
          return NULL;
        }
-      type = tag_type_to_type (type_die, objfile, cu_header);
+      type = tag_type_to_type (type_die, cu);
     }
   if (!type)
     {
       if (type_die)
        dump_die (type_die);
-      error ("Dwarf Error: Problem turning containing type into gdb type.");
+      error ("Dwarf Error: Problem turning containing type into gdb type [in module %s]", 
+                     cu->objfile->name);
     }
   return type;
 }
 
 #if 0
 static struct type *
-type_at_offset (unsigned int offset, struct objfile *objfile)
+type_at_offset (unsigned int offset, struct dwarf2_cu *cu)
 {
   struct die_info *die;
   struct type *type;
@@ -5081,14 +6733,13 @@ type_at_offset (unsigned int offset, struct objfile *objfile)
       error ("Dwarf Error: Cannot find type referent at offset %d.", offset);
       return NULL;
     }
-  type = tag_type_to_type (die, objfile);
+  type = tag_type_to_type (die, cu);
   return type;
 }
 #endif
 
 static struct type *
-tag_type_to_type (struct die_info *die, struct objfile *objfile,
-                 const struct comp_unit_head *cu_header)
+tag_type_to_type (struct die_info *die, struct dwarf2_cu *cu)
 {
   if (die->type)
     {
@@ -5096,139 +6747,245 @@ tag_type_to_type (struct die_info *die, struct objfile *objfile,
     }
   else
     {
-      read_type_die (die, objfile, cu_header);
+      read_type_die (die, cu);
       if (!die->type)
        {
          dump_die (die);
-         error ("Dwarf Error: Cannot find type of die.");
+         error ("Dwarf Error: Cannot find type of die [in module %s]", 
+                         cu->objfile->name);
        }
       return die->type;
     }
 }
 
 static void
-read_type_die (struct die_info *die, struct objfile *objfile,
-              const struct comp_unit_head *cu_header)
+read_type_die (struct die_info *die, struct dwarf2_cu *cu)
 {
+  char *prefix = determine_prefix (die, cu);
+  const char *old_prefix = processing_current_prefix;
+  struct cleanup *back_to = make_cleanup (xfree, prefix);
+  processing_current_prefix = prefix;
+  
   switch (die->tag)
     {
     case DW_TAG_class_type:
     case DW_TAG_structure_type:
     case DW_TAG_union_type:
-      read_structure_scope (die, objfile, cu_header);
+      read_structure_type (die, cu);
       break;
     case DW_TAG_enumeration_type:
-      read_enumeration (die, objfile, cu_header);
+      read_enumeration_type (die, cu);
       break;
     case DW_TAG_subprogram:
     case DW_TAG_subroutine_type:
-      read_subroutine_type (die, objfile, cu_header);
+      read_subroutine_type (die, cu);
       break;
     case DW_TAG_array_type:
-      read_array_type (die, objfile, cu_header);
+      read_array_type (die, cu);
       break;
     case DW_TAG_pointer_type:
-      read_tag_pointer_type (die, objfile, cu_header);
+      read_tag_pointer_type (die, cu);
       break;
     case DW_TAG_ptr_to_member_type:
-      read_tag_ptr_to_member_type (die, objfile, cu_header);
+      read_tag_ptr_to_member_type (die, cu);
       break;
     case DW_TAG_reference_type:
-      read_tag_reference_type (die, objfile, cu_header);
+      read_tag_reference_type (die, cu);
       break;
     case DW_TAG_const_type:
-      read_tag_const_type (die, objfile, cu_header);
+      read_tag_const_type (die, cu);
       break;
     case DW_TAG_volatile_type:
-      read_tag_volatile_type (die, objfile, cu_header);
+      read_tag_volatile_type (die, cu);
       break;
     case DW_TAG_string_type:
-      read_tag_string_type (die, objfile);
+      read_tag_string_type (die, cu);
       break;
     case DW_TAG_typedef:
-      read_typedef (die, objfile, cu_header);
+      read_typedef (die, cu);
+      break;
+    case DW_TAG_subrange_type:
+      read_subrange_type (die, cu);
       break;
     case DW_TAG_base_type:
-      read_base_type (die, objfile);
+      read_base_type (die, cu);
       break;
     default:
-      complain (&dwarf2_unexpected_tag, dwarf_tag_name (die->tag));
+      complaint (&symfile_complaints, "unexepected tag in read_type_die: '%s'",
+                dwarf_tag_name (die->tag));
       break;
     }
+
+  processing_current_prefix = old_prefix;
+  do_cleanups (back_to);
+}
+
+/* Return the name of the namespace/class that DIE is defined within,
+   or "" if we can't tell.  The caller should xfree the result.  */
+
+/* NOTE: carlton/2004-01-23: See read_func_scope (and the comment
+   therein) for an example of how to use this function to deal with
+   DW_AT_specification.  */
+
+static char *
+determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct die_info *parent;
+
+  if (cu->language != language_cplus)
+    return NULL;
+
+  parent = die->parent;
+
+  if (parent == NULL)
+    {
+      return xstrdup ("");
+    }
+  else
+    {
+      switch (parent->tag) {
+      case DW_TAG_namespace:
+       {
+         /* FIXME: carlton/2004-03-05: Should I follow extension dies
+            before doing this check?  */
+         if (parent->type != NULL && TYPE_TAG_NAME (parent->type) != NULL)
+           {
+             return xstrdup (TYPE_TAG_NAME (parent->type));
+           }
+         else
+           {
+             int dummy;
+             char *parent_prefix = determine_prefix (parent, cu);
+             char *retval = typename_concat (parent_prefix,
+                                             namespace_name (parent, &dummy,
+                                                             cu));
+             xfree (parent_prefix);
+             return retval;
+           }
+       }
+       break;
+      case DW_TAG_class_type:
+      case DW_TAG_structure_type:
+       {
+         if (parent->type != NULL && TYPE_TAG_NAME (parent->type) != NULL)
+           {
+             return xstrdup (TYPE_TAG_NAME (parent->type));
+           }
+         else
+           {
+             const char *old_prefix = processing_current_prefix;
+             char *new_prefix = determine_prefix (parent, cu);
+             char *retval;
+
+             processing_current_prefix = new_prefix;
+             retval = determine_class_name (parent, cu);
+             processing_current_prefix = old_prefix;
+
+             xfree (new_prefix);
+             return retval;
+           }
+       }
+      default:
+       return determine_prefix (parent, cu);
+      }
+    }
+}
+
+/* Return a newly-allocated string formed by concatenating PREFIX,
+   "::", and SUFFIX, except that if PREFIX is NULL or the empty
+   string, just return a copy of SUFFIX.  */
+
+static char *
+typename_concat (const char *prefix, const char *suffix)
+{
+  if (prefix == NULL || prefix[0] == '\0')
+    return xstrdup (suffix);
+  else
+    {
+      char *retval = xmalloc (strlen (prefix) + 2 + strlen (suffix) + 1);
+
+      strcpy (retval, prefix);
+      strcat (retval, "::");
+      strcat (retval, suffix);
+
+      return retval;
+    }
 }
 
 static struct type *
-dwarf_base_type (int encoding, int size, struct objfile *objfile)
+dwarf_base_type (int encoding, int size, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
+
   /* FIXME - this should not produce a new (struct type *)
      every time.  It should cache base types.  */
   struct type *type;
   switch (encoding)
     {
     case DW_ATE_address:
-      type = dwarf2_fundamental_type (objfile, FT_VOID);
+      type = dwarf2_fundamental_type (objfile, FT_VOID, cu);
       return type;
     case DW_ATE_boolean:
-      type = dwarf2_fundamental_type (objfile, FT_BOOLEAN);
+      type = dwarf2_fundamental_type (objfile, FT_BOOLEAN, cu);
       return type;
     case DW_ATE_complex_float:
       if (size == 16)
        {
-         type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX);
+         type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX, cu);
        }
       else
        {
-         type = dwarf2_fundamental_type (objfile, FT_COMPLEX);
+         type = dwarf2_fundamental_type (objfile, FT_COMPLEX, cu);
        }
       return type;
     case DW_ATE_float:
       if (size == 8)
        {
-         type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
+         type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT, cu);
        }
       else
        {
-         type = dwarf2_fundamental_type (objfile, FT_FLOAT);
+         type = dwarf2_fundamental_type (objfile, FT_FLOAT, cu);
        }
       return type;
     case DW_ATE_signed:
       switch (size)
        {
        case 1:
-         type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
+         type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR, cu);
          break;
        case 2:
-         type = dwarf2_fundamental_type (objfile, FT_SIGNED_SHORT);
+         type = dwarf2_fundamental_type (objfile, FT_SIGNED_SHORT, cu);
          break;
        default:
        case 4:
-         type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
+         type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER, cu);
          break;
        }
       return type;
     case DW_ATE_signed_char:
-      type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
+      type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR, cu);
       return type;
     case DW_ATE_unsigned:
       switch (size)
        {
        case 1:
-         type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
+         type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR, cu);
          break;
        case 2:
-         type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_SHORT);
+         type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_SHORT, cu);
          break;
        default:
        case 4:
-         type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_INTEGER);
+         type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_INTEGER, cu);
          break;
        }
       return type;
     case DW_ATE_unsigned_char:
-      type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
+      type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR, cu);
       return type;
     default:
-      type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
+      type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER, cu);
       return type;
     }
 }
@@ -5271,65 +7028,66 @@ copy_die (struct die_info *old_die)
 static struct die_info *
 sibling_die (struct die_info *die)
 {
-  int nesting_level = 0;
-
-  if (!die->has_children)
-    {
-      if (die->next && (die->next->tag == 0))
-       {
-         return NULL;
-       }
-      else
-       {
-         return die->next;
-       }
-    }
-  else
-    {
-      do
-       {
-         if (die->has_children)
-           {
-             nesting_level++;
-           }
-         if (die->tag == 0)
-           {
-             nesting_level--;
-           }
-         die = die->next;
-       }
-      while (nesting_level);
-      if (die && (die->tag == 0))
-       {
-         return NULL;
-       }
-      else
-       {
-         return die;
-       }
-    }
+  return die->sibling;
 }
 
 /* Get linkage name of a die, return NULL if not found.  */
 
 static char *
-dwarf2_linkage_name (struct die_info *die)
+dwarf2_linkage_name (struct die_info *die, struct dwarf2_cu *cu)
 {
   struct attribute *attr;
 
-  attr = dwarf_attr (die, DW_AT_MIPS_linkage_name);
+  attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
+  if (attr && DW_STRING (attr))
+    return DW_STRING (attr);
+  attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr && DW_STRING (attr))
     return DW_STRING (attr);
-  attr = dwarf_attr (die, DW_AT_name);
+  return NULL;
+}
+
+/* Get name of a die, return NULL if not found.  */
+
+static char *
+dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *attr;
+
+  attr = dwarf2_attr (die, DW_AT_name, cu);
   if (attr && DW_STRING (attr))
     return DW_STRING (attr);
   return NULL;
 }
 
+/* Return the die that this die in an extension of, or NULL if there
+   is none.  */
+
+static struct die_info *
+dwarf2_extension (struct die_info *die, struct dwarf2_cu *cu)
+{
+  struct attribute *attr;
+  struct die_info *extension_die;
+  unsigned int ref;
+
+  attr = dwarf2_attr (die, DW_AT_extension, cu);
+  if (attr == NULL)
+    return NULL;
+
+  ref = dwarf2_get_ref_die_offset (attr, cu);
+  extension_die = follow_die_ref (ref);
+  if (!extension_die)
+    {
+      error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+    }
+
+  return extension_die;
+}
+
 /* Convert a DIE tag into its string name.  */
 
 static char *
-dwarf_tag_name (register unsigned tag)
+dwarf_tag_name (unsigned tag)
 {
   switch (tag)
     {
@@ -5429,6 +7187,22 @@ dwarf_tag_name (register unsigned tag)
       return "DW_TAG_variable";
     case DW_TAG_volatile_type:
       return "DW_TAG_volatile_type";
+    case DW_TAG_dwarf_procedure:
+      return "DW_TAG_dwarf_procedure";
+    case DW_TAG_restrict_type:
+      return "DW_TAG_restrict_type";
+    case DW_TAG_interface_type:
+      return "DW_TAG_interface_type";
+    case DW_TAG_namespace:
+      return "DW_TAG_namespace";
+    case DW_TAG_imported_module:
+      return "DW_TAG_imported_module";
+    case DW_TAG_unspecified_type:
+      return "DW_TAG_unspecified_type";
+    case DW_TAG_partial_unit:
+      return "DW_TAG_partial_unit";
+    case DW_TAG_imported_unit:
+      return "DW_TAG_imported_unit";
     case DW_TAG_MIPS_loop:
       return "DW_TAG_MIPS_loop";
     case DW_TAG_format_label:
@@ -5445,7 +7219,7 @@ dwarf_tag_name (register unsigned tag)
 /* Convert a DWARF attribute code into its string name.  */
 
 static char *
-dwarf_attr_name (register unsigned attr)
+dwarf_attr_name (unsigned attr)
 {
   switch (attr)
     {
@@ -5573,7 +7347,30 @@ dwarf_attr_name (register unsigned attr)
       return "DW_AT_virtuality";
     case DW_AT_vtable_elem_location:
       return "DW_AT_vtable_elem_location";
-
+    case DW_AT_allocated:
+      return "DW_AT_allocated";
+    case DW_AT_associated:
+      return "DW_AT_associated";
+    case DW_AT_data_location:
+      return "DW_AT_data_location";
+    case DW_AT_stride:
+      return "DW_AT_stride";
+    case DW_AT_entry_pc:
+      return "DW_AT_entry_pc";
+    case DW_AT_use_UTF8:
+      return "DW_AT_use_UTF8";
+    case DW_AT_extension:
+      return "DW_AT_extension";
+    case DW_AT_ranges:
+      return "DW_AT_ranges";
+    case DW_AT_trampoline:
+      return "DW_AT_trampoline";
+    case DW_AT_call_column:
+      return "DW_AT_call_column";
+    case DW_AT_call_file:
+      return "DW_AT_call_file";
+    case DW_AT_call_line:
+      return "DW_AT_call_line";
 #ifdef MIPS
     case DW_AT_MIPS_fde:
       return "DW_AT_MIPS_fde";
@@ -5587,9 +7384,9 @@ dwarf_attr_name (register unsigned attr)
       return "DW_AT_MIPS_loop_unroll_factor";
     case DW_AT_MIPS_software_pipeline_depth:
       return "DW_AT_MIPS_software_pipeline_depth";
+#endif
     case DW_AT_MIPS_linkage_name:
       return "DW_AT_MIPS_linkage_name";
-#endif
 
     case DW_AT_sf_names:
       return "DW_AT_sf_names";
@@ -5613,7 +7410,7 @@ dwarf_attr_name (register unsigned attr)
 /* Convert a DWARF value form code into its string name.  */
 
 static char *
-dwarf_form_name (register unsigned form)
+dwarf_form_name (unsigned form)
 {
   switch (form)
     {
@@ -5667,7 +7464,7 @@ dwarf_form_name (register unsigned form)
 /* Convert a DWARF stack opcode into its string name.  */
 
 static char *
-dwarf_stack_op_name (register unsigned op)
+dwarf_stack_op_name (unsigned op)
 {
   switch (op)
     {
@@ -5990,7 +7787,7 @@ dwarf_bool_name (unsigned mybool)
 /* Convert a DWARF type code into its string name.  */
 
 static char *
-dwarf_type_encoding_name (register unsigned enc)
+dwarf_type_encoding_name (unsigned enc)
 {
   switch (enc)
     {
@@ -6010,6 +7807,8 @@ dwarf_type_encoding_name (register unsigned enc)
       return "DW_ATE_unsigned";
     case DW_ATE_unsigned_char:
       return "DW_ATE_unsigned_char";
+    case DW_ATE_imaginary_float:
+      return "DW_ATE_imaginary_float";
     default:
       return "DW_ATE_<unknown>";
     }
@@ -6019,7 +7818,7 @@ dwarf_type_encoding_name (register unsigned enc)
 
 #if 0
 static char *
-dwarf_cfi_name (register unsigned cfi_opc)
+dwarf_cfi_name (unsigned cfi_opc)
 {
   switch (cfi_opc)
     {
@@ -6098,7 +7897,7 @@ dump_die (struct die_info *die)
   fprintf_unfiltered (gdb_stderr, "Die: %s (abbrev = %d, offset = %d)\n",
           dwarf_tag_name (die->tag), die->abbrev, die->offset);
   fprintf_unfiltered (gdb_stderr, "\thas children: %s\n",
-          dwarf_bool_name (die->has_children));
+          dwarf_bool_name (die->child != NULL));
 
   fprintf_unfiltered (gdb_stderr, "\tattributes:\n");
   for (i = 0; i < die->num_attrs; ++i)
@@ -6161,7 +7960,10 @@ dump_die_list (struct die_info *die)
   while (die)
     {
       dump_die (die);
-      die = die->next;
+      if (die->child != NULL)
+       dump_die_list (die->child);
+      if (die->sibling != NULL)
+       dump_die_list (die->sibling);
     }
 }
 
@@ -6185,7 +7987,7 @@ dwarf2_empty_hash_tables (void)
 }
 
 static unsigned int
-dwarf2_get_ref_die_offset (struct attribute *attr)
+dwarf2_get_ref_die_offset (struct attribute *attr, struct dwarf2_cu *cu)
 {
   unsigned int result = 0;
 
@@ -6199,14 +8001,38 @@ dwarf2_get_ref_die_offset (struct attribute *attr)
     case DW_FORM_ref4:
     case DW_FORM_ref8:
     case DW_FORM_ref_udata:
-      result = cu_header_offset + DW_UNSND (attr);
+      result = cu->header.offset + DW_UNSND (attr);
       break;
     default:
-      complain (&dwarf2_unsupported_die_ref_attr, dwarf_form_name (attr->form));
+      complaint (&symfile_complaints,
+                "unsupported die ref attribute form: '%s'",
+                dwarf_form_name (attr->form));
     }
   return result;
 }
 
+/* Return the constant value held by the given attribute.  Return -1
+   if the value held by the attribute is not constant.  */
+
+static int
+dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
+{
+  if (attr->form == DW_FORM_sdata)
+    return 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_data8)
+    return DW_UNSND (attr);
+  else
+    {
+      complaint (&symfile_complaints, "Attribute value is not a constant (%s)",
+                 dwarf_form_name (attr->form));
+      return default_value;
+    }
+}
+
 static struct die_info *
 follow_die_ref (unsigned int offset)
 {
@@ -6227,58 +8053,57 @@ follow_die_ref (unsigned int offset)
 }
 
 static struct type *
-dwarf2_fundamental_type (struct objfile *objfile, int typeid)
+dwarf2_fundamental_type (struct objfile *objfile, int typeid,
+                        struct dwarf2_cu *cu)
 {
   if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
     {
-      error ("Dwarf Error: internal error - invalid fundamental type id %d.",
-            typeid);
+      error ("Dwarf Error: internal error - invalid fundamental type id %d [in module %s]",
+            typeid, objfile->name);
     }
 
   /* Look for this particular type in the fundamental type vector.  If
      one is not found, create and install one appropriate for the
      current language and the current target machine. */
 
-  if (ftypes[typeid] == NULL)
+  if (cu->ftypes[typeid] == NULL)
     {
-      ftypes[typeid] = cu_language_defn->la_fund_type (objfile, typeid);
+      cu->ftypes[typeid] = cu->language_defn->la_fund_type (objfile, typeid);
     }
 
-  return (ftypes[typeid]);
+  return (cu->ftypes[typeid]);
 }
 
 /* Decode simple location descriptions.
    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.
+   NOTE drow/2003-11-18: This function is called in two situations
+   now: for the address of static or global variables (partial symbols
+   only) and for offsets into structures which are expected to be
+   (more or less) constant.  The partial symbol case should go away,
+   and only the constant case should remain.  That will let this
+   function complain more accurately.  A few special modes are allowed
+   without complaint for global variables (for instance, global
+   register values and thread-local values).
 
    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.
+   object is optimized out.  The return value is 0 for that case.
+   FIXME drow/2003-11-16: No callers check for this case any more; soon all
+   callers will only want a very basic result and this can become a
+   complaint.
 
    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 (struct dwarf_block *blk, struct objfile *objfile,
-               const struct comp_unit_head *cu_header)
+decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
 {
+  struct objfile *objfile = cu->objfile;
+  struct comp_unit_head *cu_header = &cu->header;
   int i;
   int size = blk->size;
   char *data = blk->data;
@@ -6291,14 +8116,9 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
   stacki = 0;
   stack[stacki] = 0;
   isreg = 0;
-  offreg = 0;
-  isderef = 0;
-  islocal = 0;
-  optimized_out = 1;
 
   while (i < size)
     {
-      optimized_out = 0;
       op = data[i++];
       switch (op)
        {
@@ -6371,6 +8191,8 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
        case DW_OP_reg31:
          isreg = 1;
          stack[++stacki] = op - DW_OP_reg0;
+         if (i < size)
+           dwarf2_complex_location_expr_complaint ();
          break;
 
        case DW_OP_regx:
@@ -6378,73 +8200,13 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
          unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
          i += bytes_read;
          stack[++stacki] = unsnd;
-         break;
-
-       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;
-         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;
-         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;
-           }
+         if (i < size)
+           dwarf2_complex_location_expr_complaint ();
          break;
 
        case DW_OP_addr:
          stack[++stacki] = read_address (objfile->obfd, &data[i],
-                                         cu_header, &bytes_read);
+                                         cu, &bytes_read);
          i += bytes_read;
          break;
 
@@ -6510,15 +8272,28 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
          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.  */
+            this using GDB's address_class enum.  This is valid for partial
+            global symbols, although the variable's address will be bogus
+            in the psymtab.  */
          if (i < size)
-           complain (&dwarf2_complex_location_expr);
+           dwarf2_complex_location_expr_complaint ();
          break;
 
+        case DW_OP_GNU_push_tls_address:
+         /* The top of the stack has the offset from the beginning
+            of the thread control block at which the variable is located.  */
+         /* Nothing should follow this operator, so the top of stack would
+            be returned.  */
+         /* This is valid for partial global symbols, but the variable's
+            address will be bogus in the psymtab.  */
+         if (i < size)
+           dwarf2_complex_location_expr_complaint ();
+          break;
+
        default:
-         complain (&dwarf2_unsupported_stack_op, dwarf_stack_op_name (op));
+         complaint (&symfile_complaints, "unsupported stack op: '%s'",
+                    dwarf_stack_op_name (op));
          return (stack[stacki]);
        }
     }
@@ -6527,29 +8302,23 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
 
 /* memory allocation interface */
 
-/* ARGSUSED */
-static void
-dwarf2_free_tmp_obstack (PTR ignore)
-{
-  obstack_free (&dwarf2_tmp_obstack, NULL);
-}
-
 static struct dwarf_block *
-dwarf_alloc_block (void)
+dwarf_alloc_block (struct dwarf2_cu *cu)
 {
   struct dwarf_block *blk;
 
   blk = (struct dwarf_block *)
-    obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct dwarf_block));
+    obstack_alloc (&cu->comp_unit_obstack, sizeof (struct dwarf_block));
   return (blk);
 }
 
 static struct abbrev_info *
-dwarf_alloc_abbrev (void)
+dwarf_alloc_abbrev (struct dwarf2_cu *cu)
 {
   struct abbrev_info *abbrev;
 
-  abbrev = (struct abbrev_info *) xmalloc (sizeof (struct abbrev_info));
+  abbrev = (struct abbrev_info *)
+    obstack_alloc (&cu->abbrev_obstack, sizeof (struct abbrev_info));
   memset (abbrev, 0, sizeof (struct abbrev_info));
   return (abbrev);
 }
@@ -6617,7 +8386,7 @@ macro_start_file (int file, int line,
   /* We don't create a macro table for this compilation unit
      at all until we actually get a filename.  */
   if (! pending_macros)
-    pending_macros = new_macro_table (&objfile->symbol_obstack,
+    pending_macros = new_macro_table (&objfile->objfile_obstack,
                                       objfile->macro_cache);
 
   if (! current_file)
@@ -6651,7 +8420,9 @@ consume_improper_spaces (const char *p, const char *body)
 {
   if (*p == ' ')
     {
-      complain (&dwarf2_macro_spaces_in_definition, body);
+      complaint (&symfile_complaints,
+                "macro definition contains spaces in formal argument list:\n`%s'",
+                body);
 
       while (*p == ' ')
         p++;
@@ -6709,7 +8480,7 @@ parse_macro_definition (struct macro_source_file *file, int line,
         replacement = body + name_len + 1;
       else
         {
-          complain (&dwarf2_macro_malformed_definition, body);
+         dwarf2_macro_malformed_definition_complaint (body);
           replacement = body + name_len;
         }
       
@@ -6739,8 +8510,7 @@ parse_macro_definition (struct macro_source_file *file, int line,
             p++;
 
           if (! *p || p == arg_start)
-            complain (&dwarf2_macro_malformed_definition,
-                      body);
+           dwarf2_macro_malformed_definition_complaint (body);
           else
             {
               /* Make sure argv has room for the new argument.  */
@@ -6776,18 +8546,18 @@ parse_macro_definition (struct macro_source_file *file, int line,
           else if (*p == '\0')
             {
               /* Complain, but do define it.  */
-              complain (&dwarf2_macro_malformed_definition, body);
+             dwarf2_macro_malformed_definition_complaint (body);
               macro_define_function (file, line, name,
                                      argc, (const char **) argv, 
                                      p);
             }
           else
             /* Just complain.  */
-            complain (&dwarf2_macro_malformed_definition, body);
+           dwarf2_macro_malformed_definition_complaint (body);
         }
       else
         /* Just complain.  */
-        complain (&dwarf2_macro_malformed_definition, body);
+       dwarf2_macro_malformed_definition_complaint (body);
 
       xfree (name);
       {
@@ -6799,27 +8569,27 @@ parse_macro_definition (struct macro_source_file *file, int line,
       xfree (argv);
     }
   else
-    complain (&dwarf2_macro_malformed_definition, body);
+    dwarf2_macro_malformed_definition_complaint (body);
 }
 
 
 static void
 dwarf_decode_macros (struct line_header *lh, unsigned int offset,
                      char *comp_dir, bfd *abfd,
-                     const struct comp_unit_head *cu_header,
-                     struct objfile *objfile)
+                     struct dwarf2_cu *cu)
 {
   char *mac_ptr, *mac_end;
   struct macro_source_file *current_file = 0;
 
-  if (dwarf_macinfo_buffer == NULL)
+  if (dwarf2_per_objfile->macinfo_buffer == NULL)
     {
-      complain (&dwarf2_missing_macinfo_section);
+      complaint (&symfile_complaints, "missing .debug_macinfo section");
       return;
     }
 
-  mac_ptr = dwarf_macinfo_buffer + offset;
-  mac_end = dwarf_macinfo_buffer + dwarf_macinfo_size;
+  mac_ptr = dwarf2_per_objfile->macinfo_buffer + offset;
+  mac_end = dwarf2_per_objfile->macinfo_buffer
+    + dwarf2_per_objfile->macinfo_size;
 
   for (;;)
     {
@@ -6828,7 +8598,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
       /* Do we at least have room for a macinfo type byte?  */
       if (mac_ptr >= mac_end)
         {
-          complain (&dwarf2_macros_too_long);
+         dwarf2_macros_too_long_complaint ();
           return;
         }
 
@@ -6855,11 +8625,12 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
             mac_ptr += bytes_read;
 
             if (! current_file)
-              complain (&dwarf2_macro_outside_file,
-                        macinfo_type == DW_MACINFO_define ? "definition" :
-                        macinfo_type == DW_MACINFO_undef ? "undefinition" :
-                        "something-or-other",
-                        body);
+             complaint (&symfile_complaints,
+                        "debug info gives macro %s outside of any file: %s",
+                        macinfo_type ==
+                        DW_MACINFO_define ? "definition" : macinfo_type ==
+                        DW_MACINFO_undef ? "undefinition" :
+                        "something-or-other", body);
             else
               {
                 if (macinfo_type == DW_MACINFO_define)
@@ -6882,13 +8653,14 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
 
             current_file = macro_start_file (file, line,
                                              current_file, comp_dir,
-                                             lh, objfile);
+                                             lh, cu->objfile);
           }
           break;
 
         case DW_MACINFO_end_file:
           if (! current_file)
-            complain (&dwarf2_macro_unmatched_end_file);
+           complaint (&symfile_complaints,
+                      "macro debug info has an unmatched `close_file' directive");
           else
             {
               current_file = current_file->included_by;
@@ -6904,7 +8676,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
                   /* Do we at least have room for a macinfo type byte?  */
                   if (mac_ptr >= mac_end)
                     {
-                      complain (&dwarf2_macros_too_long);
+                     dwarf2_macros_too_long_complaint ();
                       return;
                     }
 
@@ -6912,7 +8684,8 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
                      a look-ahead.  */
                   next_type = read_1_byte (abfd, mac_ptr);
                   if (next_type != 0)
-                    complain (&dwarf2_macros_not_terminated);
+                   complaint (&symfile_complaints,
+                              "no terminating 0-type entry for macros in `.debug_macinfo' section");
 
                   return;
                 }
@@ -6948,3 +8721,124 @@ attr_form_is_block (struct attribute *attr)
       || attr->form == DW_FORM_block4
       || attr->form == DW_FORM_block);
 }
+
+static void
+dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+                            struct dwarf2_cu *cu)
+{
+  if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+    {
+      struct dwarf2_loclist_baton *baton;
+
+      baton = obstack_alloc (&cu->objfile->objfile_obstack,
+                            sizeof (struct dwarf2_loclist_baton));
+      baton->objfile = cu->objfile;
+
+      /* We don't know how long the location list is, but make sure we
+        don't run off the edge of the section.  */
+      baton->size = dwarf2_per_objfile->loc_size - DW_UNSND (attr);
+      baton->data = dwarf2_per_objfile->loc_buffer + DW_UNSND (attr);
+      baton->base_address = cu->header.base_address;
+      if (cu->header.base_known == 0)
+       complaint (&symfile_complaints,
+                  "Location list used without specifying the CU base address.");
+
+      SYMBOL_OPS (sym) = &dwarf2_loclist_funcs;
+      SYMBOL_LOCATION_BATON (sym) = baton;
+    }
+  else
+    {
+      struct dwarf2_locexpr_baton *baton;
+
+      baton = obstack_alloc (&cu->objfile->objfile_obstack,
+                            sizeof (struct dwarf2_locexpr_baton));
+      baton->objfile = cu->objfile;
+
+      if (attr_form_is_block (attr))
+       {
+         /* Note that we're just copying the block's data pointer
+            here, not the actual data.  We're still pointing into the
+            info_buffer for SYM's objfile; right now we never release
+            that buffer, but when we do clean up properly this may
+            need to change.  */
+         baton->size = DW_BLOCK (attr)->size;
+         baton->data = DW_BLOCK (attr)->data;
+       }
+      else
+       {
+         dwarf2_invalid_attrib_class_complaint ("location description",
+                                                SYMBOL_NATURAL_NAME (sym));
+         baton->size = 0;
+         baton->data = NULL;
+       }
+      
+      SYMBOL_OPS (sym) = &dwarf2_locexpr_funcs;
+      SYMBOL_LOCATION_BATON (sym) = baton;
+    }
+}
+
+/* This cleanup function is passed the address of a dwarf2_cu on the stack
+   when we're finished with it.  We can't free the pointer itself, but
+   release any associated storage.
+
+   Only used during partial symbol parsing.  */
+
+static void
+free_stack_comp_unit (void *data)
+{
+  struct dwarf2_cu *cu = data;
+
+  obstack_free (&cu->comp_unit_obstack, NULL);
+  cu->partial_dies = NULL;
+}
+
+/* Allocation function for the libiberty hash table which uses an
+   obstack.  */
+
+static void *
+hashtab_obstack_allocate (void *data, size_t size, size_t count)
+{
+  unsigned int total = size * count;
+  void *ptr = obstack_alloc ((struct obstack *) data, total);
+  memset (ptr, 0, total);
+  return ptr;
+}
+
+/* Trivial deallocation function for the libiberty splay tree and hash
+   table - don't deallocate anything.  Rely on later deletion of the
+   obstack.  */
+
+static void
+dummy_obstack_deallocate (void *object, void *data)
+{
+  return;
+}
+
+/* Trivial hash function for partial_die_info: the hash value of a DIE
+   is its offset in .debug_info for this objfile.  */
+
+static hashval_t
+partial_die_hash (const void *item)
+{
+  const struct partial_die_info *part_die = item;
+  return part_die->offset;
+}
+
+/* Trivial comparison function for partial_die_info structures: two DIEs
+   are equal if they have the same offset.  */
+
+static int
+partial_die_eq (const void *item_lhs, const void *item_rhs)
+{
+  const struct partial_die_info *part_die_lhs = item_lhs;
+  const struct partial_die_info *part_die_rhs = item_rhs;
+  return part_die_lhs->offset == part_die_rhs->offset;
+}
+
+void _initialize_dwarf2_read (void);
+
+void
+_initialize_dwarf2_read (void)
+{
+  dwarf2_objfile_data_key = register_objfile_data ();
+}
This page took 0.137966 seconds and 4 git commands to generate.