2003-09-16 Andrew Cagney <cagney@redhat.com>
[deliverable/binutils-gdb.git] / gdb / dwarf2read.c
index cb123efb3da72177387c327e149471adf005cd13..945a387463d6c7375fe4c9b55ad0d2bdec5f0a39 100644 (file)
@@ -1,5 +1,6 @@
 /* DWARF 2 debugging format support for GDB.
-   Copyright 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+   Free Software Foundation, Inc.
 
    Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
    Inc.  with support from Florida State University (under contract
 #include "buildsym.h"
 #include "demangle.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 <fcntl.h>
 #include "gdb_string.h"
+#include "gdb_assert.h"
 #include <sys/types.h>
 
+#ifndef DWARF2_REG_TO_REGNUM
+#define DWARF2_REG_TO_REGNUM(REG) (REG)
+#endif
+
 #if 0
 /* .debug_info header for a compilation unit
    Because of alignment constraints, this structure has padding and cannot
@@ -125,6 +136,9 @@ static file_ptr dwarf_aranges_offset;
 static file_ptr dwarf_loc_offset;
 static file_ptr dwarf_macinfo_offset;
 static file_ptr dwarf_str_offset;
+static file_ptr dwarf_ranges_offset;
+file_ptr dwarf_frame_offset;
+file_ptr dwarf_eh_frame_offset;
 
 static unsigned int dwarf_info_size;
 static unsigned int dwarf_abbrev_size;
@@ -134,6 +148,21 @@ static unsigned int dwarf_aranges_size;
 static unsigned int dwarf_loc_size;
 static unsigned int dwarf_macinfo_size;
 static unsigned int dwarf_str_size;
+static unsigned int dwarf_ranges_size;
+unsigned int dwarf_frame_size;
+unsigned int dwarf_eh_frame_size;
+
+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 */
 
@@ -145,9 +174,17 @@ static unsigned int dwarf_str_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
@@ -160,21 +197,82 @@ 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;
+
+    /* DWARF abbreviation table associated with this compilation unit */
+
+    struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
+
+    /* Base address of this compilation unit.  */
+
+    CORE_ADDR base_address;
+
+    /* Non-zero if base_address has been set.  */
+
+    int base_known;
   };
 
-/* The data in the .debug_line statement prologue looks like this.  */
-struct line_head
+/* 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.  */
+struct line_header
+{
+  unsigned int total_length;
+  unsigned short version;
+  unsigned int header_length;
+  unsigned char minimum_instruction_length;
+  unsigned char default_is_stmt;
+  int line_base;
+  unsigned char line_range;
+  unsigned char opcode_base;
+
+  /* standard_opcode_lengths[i] is the number of operands for the
+     standard opcode whose value is i.  This means that
+     standard_opcode_lengths[0] is unused, and the last meaningful
+     element is standard_opcode_lengths[opcode_base - 1].  */
+  unsigned char *standard_opcode_lengths;
+
+  /* The include_directories table.  NOTE!  These strings are not
+     allocated with xmalloc; instead, they are pointers into
+     debug_line_buffer.  If you try to free them, `free' will get
+     indigestion.  */
+  unsigned int num_include_dirs, include_dirs_size;
+  char **include_dirs;
+
+  /* The file_names table.  NOTE!  These strings are not allocated
+     with xmalloc; instead, they are pointers into debug_line_buffer.
+     Don't try to free them directly.  */
+  unsigned int num_file_names, file_names_size;
+  struct file_entry
   {
-    unsigned int total_length;
-    unsigned short version;
-    unsigned int prologue_length;
-    unsigned char minimum_instruction_length;
-    unsigned char default_is_stmt;
-    int line_base;
-    unsigned char line_range;
-    unsigned char opcode_base;
-    unsigned char *standard_opcode_lengths;
-  };
+    char *name;
+    unsigned int dir_index;
+    unsigned int mod_time;
+    unsigned int length;
+  } *file_names;
+
+  /* The start and end of the statement program following this
+     header.  These point into dwarf_line_buffer.  */
+  char *statement_program_start, *statement_program_end;
+};
 
 /* When we construct a partial symbol table entry we only
    need this much information. */
@@ -188,6 +286,7 @@ struct partial_die_info
     unsigned int offset;
     unsigned int abbrev;
     char *name;
+    int has_pc_info;
     CORE_ADDR lowpc;
     CORE_ADDR highpc;
     struct dwarf_block *locdesc;
@@ -242,6 +341,16 @@ struct attribute
     u;
   };
 
+struct function_range
+{
+  const char *name;
+  CORE_ADDR lowpc, highpc;
+  int seen_line;
+  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)
@@ -257,17 +366,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
@@ -295,6 +397,10 @@ static const struct language_defn *cu_language_defn;
 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;
+static char *dwarf_ranges_buffer;
+static char *dwarf_loc_buffer;
 
 /* A zeroed version of a partial die for initialization purposes.  */
 static struct partial_die_info zeroed_partial_die;
@@ -376,6 +482,42 @@ struct dwarf2_pinfo
     /* 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;
+
+    /* Pointer to start of dwarf ranges buffer for the objfile.  */
+
+    char *dwarf_ranges_buffer;
+
+    /* Size of dwarf ranges buffer for the objfile.  */
+
+    unsigned int dwarf_ranges_size;
+
+    /* Pointer to start of dwarf locations buffer for the objfile.  */
+
+    char *dwarf_loc_buffer;
+
+    /* Size of dwarf locations buffer for the objfile.  */
+
+    unsigned int dwarf_loc_size;
   };
 
 #define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
@@ -384,6 +526,15 @@ struct dwarf2_pinfo
 #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)
+#define DWARF_RANGES_BUFFER(p)  (PST_PRIVATE(p)->dwarf_ranges_buffer)
+#define DWARF_RANGES_SIZE(p)    (PST_PRIVATE(p)->dwarf_ranges_size)
+#define DWARF_LOC_BUFFER(p)     (PST_PRIVATE(p)->dwarf_loc_buffer)
+#define DWARF_LOC_SIZE(p)       (PST_PRIVATE(p)->dwarf_loc_size)
 
 /* Maintain an array of referenced fundamental types for the current
    compilation unit being read.  For DWARF version 1, we have to construct
@@ -449,110 +600,69 @@ struct field_info
     int nfnfields;
   };
 
-/* FIXME: Kludge to mark a varargs function type for C++ member function
-   argument processing.  */
-#define TYPE_FLAG_VARARGS      (1 << 10)
-
-/* Dwarf2 has no clean way to discern C++ static and non-static member
-   functions. G++ helps GDB by marking the first parameter for non-static
-   member functions (which is the this pointer) as artificial.
-   We pass this information between dwarf2_add_member_fn and
-   read_subroutine_type via TYPE_FIELD_ARTIFICIAL.  */
-#define TYPE_FIELD_ARTIFICIAL  TYPE_FIELD_BITPOS
-
 /* 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_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 =
+static void
+dwarf2_non_const_array_bound_ignored_complaint (const char *arg1)
 {
-  "unsupported accessibility %d", 0, 0
-};
-static struct complaint dwarf2_bad_member_name_complaint =
+  complaint (&symfile_complaints, "non-constant array bounds form '%s' ignored",
+            arg1);
+}
+
+static void
+dwarf2_statement_list_fits_in_line_number_section_complaint (void)
 {
-  "cannot extract member name from '%s'", 0, 0
-};
-static struct complaint dwarf2_missing_member_fn_type_complaint =
+  complaint (&symfile_complaints,
+            "statement list doesn't fit in .debug_line section");
+}
+
+static void
+dwarf2_complex_location_expr_complaint (void)
 {
-  "member function type missing for '%s'", 0, 0
-};
-static struct complaint dwarf2_vtbl_not_found_complaint =
+  complaint (&symfile_complaints, "location expression too complex");
+}
+
+static void
+dwarf2_unsupported_at_frame_base_complaint (const char *arg1)
 {
-  "virtual function table pointer not found when defining class '%s'", 0, 0
-};
-static struct complaint dwarf2_absolute_sibling_complaint =
+  complaint (&symfile_complaints,
+            "unsupported DW_AT_frame_base for function '%s'", arg1);
+}
+
+static void
+dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2,
+                                             int arg3)
 {
-  "ignoring absolute DW_AT_sibling", 0, 0
-};
-static struct complaint dwarf2_const_value_length_mismatch =
+  complaint (&symfile_complaints,
+            "const value length mismatch for '%s', got %d, expected %d", arg1,
+            arg2, arg3);
+}
+
+static void
+dwarf2_macros_too_long_complaint (void)
 {
-  "const value length mismatch for '%s', got %d, expected %d", 0, 0
-};
-static struct complaint dwarf2_unsupported_const_value_attr =
+  complaint (&symfile_complaints,
+            "macro info runs off end of `.debug_macinfo' section");
+}
+
+static void
+dwarf2_macro_malformed_definition_complaint (const char *arg1)
 {
-  "unsupported const value attribute form: '%s'", 0, 0
-};
+  complaint (&symfile_complaints,
+            "macro debug info contains a malformed macro definition:\n`%s'",
+            arg1);
+}
 
-/* Externals references.  */
-extern int info_verbose;       /* From main.c; nonzero => verbose */
+static void
+dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
+{
+  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);
@@ -562,25 +672,47 @@ 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 *);
+                                  const struct comp_unit_head *,
+                                  const char *namespace);
 
 static void add_partial_symbol (struct partial_die_info *, struct objfile *,
-                               const struct comp_unit_head *);
+                               const struct comp_unit_head *,
+                               const char *namespace);
+
+static char *add_partial_namespace (struct partial_die_info *pdi,
+                                   char *info_ptr,
+                                   struct objfile *objfile,
+                                   CORE_ADDR *lowpc, CORE_ADDR *highpc,
+                                   const struct comp_unit_head *cu_header,
+                                   const char *namespace);
+
+static char *add_partial_enumeration (struct partial_die_info *enum_pdi,
+                                     char *info_ptr,
+                                     struct objfile *objfile,
+                                     const struct comp_unit_head *cu_header,
+                                     const char *namespace);
+
+static char *locate_pdi_sibling (struct partial_die_info *orig_pdi,
+                                char *info_ptr,
+                                bfd *abfd,
+                                const struct comp_unit_head *cu_header);
 
 static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
 
 static void psymtab_to_symtab_1 (struct partial_symtab *);
 
-static char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int);
+char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int,
+                          asection *);
 
-static void dwarf2_read_abbrevs (bfd *, unsigned int);
+static void dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header);
 
-static void dwarf2_empty_abbrev_table (PTR);
+static void dwarf2_empty_abbrev_table (void *);
 
-static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int);
+static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int,
+                                         const struct comp_unit_head *cu_header);
 
 static char *read_partial_die (struct partial_die_info *,
-                              bfd *, char *, int *,
+                              bfd *, char *,
                               const struct comp_unit_head *);
 
 static char *read_full_die (struct die_info **, bfd *, char *,
@@ -589,6 +721,9 @@ static char *read_full_die (struct die_info **, bfd *, char *,
 static char *read_attribute (struct attribute *, struct attr_abbrev *,
                             bfd *, char *, const struct comp_unit_head *);
 
+static char *read_attribute_value (struct attribute *, unsigned,
+                            bfd *, char *, const struct comp_unit_head *);
+
 static unsigned int read_1_byte (bfd *, char *);
 
 static int read_1_signed_byte (bfd *, char *);
@@ -612,6 +747,9 @@ static char *read_n_bytes (bfd *, char *, unsigned int);
 
 static char *read_string (bfd *, char *, unsigned int *);
 
+static char *read_indirect_string (bfd *, char *, const struct comp_unit_head *,
+                                  unsigned int *);
+
 static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *);
 
 static long read_signed_leb128 (bfd *, char *, unsigned int *);
@@ -622,7 +760,14 @@ static struct attribute *dwarf_attr (struct die_info *, unsigned int);
 
 static int die_is_declaration (struct die_info *);
 
-static void dwarf_decode_lines (unsigned int, char *, bfd *,
+static void free_line_header (struct line_header *lh);
+
+static struct line_header *(dwarf_decode_line_header
+                            (unsigned int offset,
+                             bfd *abfd,
+                             const struct comp_unit_head *cu_header));
+
+static void dwarf_decode_lines (struct line_header *, char *, bfd *,
                                const struct comp_unit_head *);
 
 static void dwarf2_start_subfile (char *, char *);
@@ -668,7 +813,8 @@ static void read_lexical_block_scope (struct die_info *, struct objfile *,
                                      const struct comp_unit_head *);
 
 static int dwarf2_get_pc_bounds (struct die_info *,
-                                CORE_ADDR *, CORE_ADDR *, struct objfile *);
+                                CORE_ADDR *, CORE_ADDR *, struct objfile *,
+                                const struct comp_unit_head *);
 
 static void dwarf2_add_field (struct field_info *, struct die_info *,
                              struct objfile *, const struct comp_unit_head *);
@@ -690,6 +836,9 @@ static void read_structure_scope (struct die_info *, struct objfile *,
 static void read_common_block (struct die_info *, struct objfile *,
                               const struct comp_unit_head *);
 
+static void read_namespace (struct die_info *die, struct objfile *objfile,
+                           const struct comp_unit_head *cu_header);
+
 static void read_enumeration (struct die_info *, struct objfile *,
                              const struct comp_unit_head *);
 
@@ -721,7 +870,8 @@ static void read_tag_string_type (struct die_info *, struct objfile *);
 static void read_subroutine_type (struct die_info *, struct objfile *,
                                  const struct comp_unit_head *);
 
-struct die_info *read_comp_unit (char *, bfd *, const struct comp_unit_head *);
+static struct die_info *read_comp_unit (char *, bfd *,
+                                        const struct comp_unit_head *);
 
 static void free_die_list (struct die_info *);
 
@@ -732,6 +882,10 @@ static void process_die (struct die_info *, struct objfile *,
 
 static char *dwarf2_linkage_name (struct die_info *);
 
+static char *dwarf2_name (struct die_info *die);
+
+static struct die_info *dwarf2_extension (struct die_info *die);
+
 static char *dwarf_tag_name (unsigned int);
 
 static char *dwarf_attr_name (unsigned int);
@@ -750,25 +904,25 @@ static char *dwarf_cfi_name (unsigned int);
 struct die_info *copy_die (struct die_info *);
 #endif
 
-struct die_info *sibling_die (struct die_info *);
+static struct die_info *sibling_die (struct die_info *);
 
-void dump_die (struct die_info *);
+static void dump_die (struct die_info *);
 
-void dump_die_list (struct die_info *);
+static void dump_die_list (struct die_info *);
 
-void store_in_ref_table (unsigned int, struct die_info *);
+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 *);
 
-struct die_info *follow_die_ref (unsigned int);
+static struct die_info *follow_die_ref (unsigned int);
 
 static struct type *dwarf2_fundamental_type (struct objfile *, int);
 
 /* memory allocation interface */
 
-static void dwarf2_free_tmp_obstack (PTR);
+static void dwarf2_free_tmp_obstack (void *);
 
 static struct dwarf_block *dwarf_alloc_block (void);
 
@@ -776,13 +930,37 @@ static struct abbrev_info *dwarf_alloc_abbrev (void);
 
 static struct die_info *dwarf_alloc_die (void);
 
+static void initialize_cu_func_list (void);
+
+static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR);
+
+static void dwarf_decode_macros (struct line_header *, unsigned int,
+                                 char *, bfd *, const struct comp_unit_head *,
+                                 struct objfile *);
+
+static int attr_form_is_block (struct attribute *);
+
+static void
+dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+                            const struct comp_unit_head *,
+                            struct objfile *objfile);
+
 /* 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 = dwarf_abbrev_offset = dwarf_line_offset = 0;
+  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;
+  dwarf_ranges_offset = 0;
+  dwarf_loc_offset = 0;
+  
   bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
   if (dwarf_info_offset && dwarf_abbrev_offset)
     {
@@ -799,47 +977,77 @@ 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))
     {
       dwarf_info_offset = sectp->filepos;
       dwarf_info_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf_info_section = sectp;
     }
   else if (STREQ (sectp->name, ABBREV_SECTION))
     {
       dwarf_abbrev_offset = sectp->filepos;
       dwarf_abbrev_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf_abbrev_section = sectp;
     }
   else if (STREQ (sectp->name, LINE_SECTION))
     {
       dwarf_line_offset = sectp->filepos;
       dwarf_line_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf_line_section = sectp;
     }
   else if (STREQ (sectp->name, PUBNAMES_SECTION))
     {
       dwarf_pubnames_offset = sectp->filepos;
       dwarf_pubnames_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf_pubnames_section = sectp;
     }
   else if (STREQ (sectp->name, ARANGES_SECTION))
     {
       dwarf_aranges_offset = sectp->filepos;
       dwarf_aranges_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf_aranges_section = sectp;
     }
   else if (STREQ (sectp->name, LOC_SECTION))
     {
       dwarf_loc_offset = sectp->filepos;
       dwarf_loc_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf_loc_section = sectp;
     }
   else if (STREQ (sectp->name, MACINFO_SECTION))
     {
       dwarf_macinfo_offset = sectp->filepos;
       dwarf_macinfo_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf_macinfo_section = sectp;
     }
   else if (STREQ (sectp->name, STR_SECTION))
     {
       dwarf_str_offset = sectp->filepos;
       dwarf_str_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf_str_section = sectp;
+    }
+  else if (STREQ (sectp->name, FRAME_SECTION))
+    {
+      dwarf_frame_offset = sectp->filepos;
+      dwarf_frame_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf_frame_section = sectp;
+    }
+  else if (STREQ (sectp->name, EH_FRAME_SECTION))
+    {
+      flagword aflag = bfd_get_section_flags (ignore_abfd, sectp);
+      if (aflag & SEC_HAS_CONTENTS)
+        {
+          dwarf_eh_frame_offset = sectp->filepos;
+          dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
+          dwarf_eh_frame_section = sectp;
+        }
+    }
+  else if (STREQ (sectp->name, RANGES_SECTION))
+    {
+      dwarf_ranges_offset = sectp->filepos;
+      dwarf_ranges_size = bfd_get_section_size_before_reloc (sectp);
+      dwarf_ranges_section = sectp;
     }
 }
 
@@ -853,16 +1061,56 @@ dwarf2_build_psymtabs (struct objfile *objfile, int mainline)
 
   dwarf_info_buffer = dwarf2_read_section (objfile,
                                           dwarf_info_offset,
-                                          dwarf_info_size);
+                                          dwarf_info_size,
+                                          dwarf_info_section);
   dwarf_abbrev_buffer = dwarf2_read_section (objfile,
                                             dwarf_abbrev_offset,
-                                            dwarf_abbrev_size);
-  dwarf_line_buffer = dwarf2_read_section (objfile,
-                                          dwarf_line_offset,
-                                          dwarf_line_size);
+                                            dwarf_abbrev_size,
+                                            dwarf_abbrev_section);
+
+  if (dwarf_line_offset)
+    dwarf_line_buffer = dwarf2_read_section (objfile,
+                                            dwarf_line_offset,
+                                            dwarf_line_size,
+                                            dwarf_line_section);
+  else
+    dwarf_line_buffer = NULL;
+
+  if (dwarf_str_offset)
+    dwarf_str_buffer = dwarf2_read_section (objfile,
+                                           dwarf_str_offset,
+                                           dwarf_str_size,
+                                           dwarf_str_section);
+  else
+    dwarf_str_buffer = NULL;
+
+  if (dwarf_macinfo_offset)
+    dwarf_macinfo_buffer = dwarf2_read_section (objfile,
+                                                dwarf_macinfo_offset,
+                                                dwarf_macinfo_size,
+                                               dwarf_macinfo_section);
+  else
+    dwarf_macinfo_buffer = NULL;
+
+  if (dwarf_ranges_offset)
+    dwarf_ranges_buffer = dwarf2_read_section (objfile,
+                                              dwarf_ranges_offset,
+                                              dwarf_ranges_size,
+                                              dwarf_ranges_section);
+  else
+    dwarf_ranges_buffer = NULL;
+
+  if (dwarf_loc_offset)
+    dwarf_loc_buffer = dwarf2_read_section (objfile,
+                                           dwarf_loc_offset,
+                                           dwarf_loc_size,
+                                           dwarf_loc_section);
+  else
+    dwarf_loc_buffer = NULL;
 
-  if (mainline || objfile->global_psymbols.size == 0 ||
-      objfile->static_psymbols.size == 0)
+  if (mainline
+      || (objfile->global_psymbols.size == 0
+         && objfile->static_psymbols.size == 0))
     {
       init_psymbol_list (objfile, 1024);
     }
@@ -898,7 +1146,8 @@ dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
 
   pubnames_buffer = dwarf2_read_section (objfile,
                                         dwarf_pubnames_offset,
-                                        dwarf_pubnames_size);
+                                        dwarf_pubnames_size,
+                                        dwarf_pubnames_section);
   pubnames_ptr = pubnames_buffer;
   while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
     {
@@ -918,7 +1167,8 @@ dwarf2_build_psymtabs_easy (struct objfile *objfile, int mainline)
 
   aranges_buffer = dwarf2_read_section (objfile,
                                        dwarf_aranges_offset,
-                                       dwarf_aranges_size);
+                                       dwarf_aranges_size,
+                                       dwarf_aranges_section);
 
 }
 #endif
@@ -944,7 +1194,8 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
   info_ptr += 1;
   signed_addr = bfd_get_sign_extend_vma (abfd);
   if (signed_addr < 0)
-    internal_error ("read_comp_unit_head: dwarf from non elf file");
+    internal_error (__FILE__, __LINE__,
+                   "read_comp_unit_head: dwarf from non elf file");
   cu_header->signed_addr_p = signed_addr;
   return info_ptr;
 }
@@ -963,17 +1214,56 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
   struct partial_die_info comp_unit_die;
   struct partial_symtab *pst;
   struct cleanup *back_to;
-  int comp_unit_has_pc_info;
   CORE_ADDR lowpc, highpc;
 
   info_ptr = dwarf_info_buffer;
   abbrev_ptr = dwarf_abbrev_buffer;
 
+  /* We use dwarf2_tmp_obstack for objects that don't need to survive
+     the partial symbol scan, like attribute values.
+
+     We could reduce our peak memory consumption during partial symbol
+     table construction by freeing stuff from this obstack more often
+     --- say, after processing each compilation unit, or each die ---
+     but it turns out that this saves almost nothing.  For an
+     executable with 11Mb of Dwarf 2 data, I found about 64k allocated
+     on dwarf2_tmp_obstack.  Some investigation showed:
+
+     1) 69% of the attributes used forms DW_FORM_addr, DW_FORM_data*,
+        DW_FORM_flag, DW_FORM_[su]data, and DW_FORM_ref*.  These are
+        all fixed-length values not requiring dynamic allocation.
+
+     2) 30% of the attributes used the form DW_FORM_string.  For
+        DW_FORM_string, read_attribute simply hands back a pointer to
+        the null-terminated string in dwarf_info_buffer, so no dynamic
+        allocation is needed there either.
+
+     3) The remaining 1% of the attributes all used DW_FORM_block1.
+        75% of those were DW_AT_frame_base location lists for
+        functions; the rest were DW_AT_location attributes, probably
+        for the global variables.
+
+     Anyway, what this all means is that the memory the dwarf2
+     reader uses as temporary space reading partial symbols is about
+     0.5% as much as we use for dwarf_*_buffer.  That's noise.  */
+
   obstack_init (&dwarf2_tmp_obstack);
   back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
 
-  while ((unsigned int) (info_ptr - dwarf_info_buffer)
-        + ((info_ptr - dwarf_info_buffer) % 4) < dwarf_info_size)
+  /* Since the objects we're extracting from dwarf_info_buffer vary in
+     length, only the individual functions to extract them (like
+     read_comp_unit_head and read_partial_die) can really know whether
+     the buffer is large enough to hold another complete object.
+
+     At the moment, they don't actually check that.  If
+     dwarf_info_buffer holds just one extra byte after the last
+     compilation unit's dies, then read_comp_unit_head will happily
+     read off the end of the buffer.  read_partial_die is similarly
+     casual.  Those functions should be fixed.
+
+     For this loop condition, simply checking whether there's any data
+     left at all should be sufficient.  */
+  while (info_ptr < dwarf_info_buffer + dwarf_info_size)
     {
       struct comp_unit_head cu_header;
       beg_of_comp_unit = info_ptr;
@@ -981,31 +1271,38 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
 
       if (cu_header.version != 2)
        {
-         error ("Dwarf Error: wrong version in compilation unit header.");
+         error ("Dwarf Error: wrong version in compilation unit header (is %d, should be %d) [in module %s]", cu_header.version, 2, bfd_get_filename (abfd));
          return;
        }
       if (cu_header.abbrev_offset >= dwarf_abbrev_size)
        {
-         error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).",
+         error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6) [in module %s]",
                 (long) cu_header.abbrev_offset,
-                (long) (beg_of_comp_unit - dwarf_info_buffer));
+                (long) (beg_of_comp_unit - dwarf_info_buffer),
+                bfd_get_filename (abfd));
          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).",
+         error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0) [in module %s]",
                 (long) cu_header.length,
-                (long) (beg_of_comp_unit - dwarf_info_buffer));
+                (long) (beg_of_comp_unit - dwarf_info_buffer),
+                bfd_get_filename (abfd));
          return;
        }
+      /* Complete the cu_header */
+      cu_header.offset = beg_of_comp_unit - dwarf_info_buffer;
+      cu_header.first_die_ptr = info_ptr;
+      cu_header.cu_head_ptr = beg_of_comp_unit;
+
       /* 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_header);
+      make_cleanup (dwarf2_empty_abbrev_table, cu_header.dwarf2_abbrevs);
 
       /* Read the compilation unit die */
       info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr,
-                                  &comp_unit_has_pc_info, &cu_header);
+                                  &cu_header);
 
       /* Set the language we're debugging */
       set_cu_language (comp_unit_die.language);
@@ -1025,6 +1322,15 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
       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;
+      DWARF_RANGES_BUFFER (pst) = dwarf_ranges_buffer;
+      DWARF_RANGES_SIZE (pst) = dwarf_ranges_size;
+      DWARF_LOC_BUFFER (pst) = dwarf_loc_buffer;
+      DWARF_LOC_SIZE (pst) = dwarf_loc_size;
       baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
       /* Store the function that reads in the rest of the symbol table */
@@ -1035,12 +1341,20 @@ 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)
        {
+         lowpc = ((CORE_ADDR) -1);
+         highpc = ((CORE_ADDR) 0);
+
          info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc,
-                                          &cu_header);
+                                          &cu_header, NULL);
 
+         /* 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.  */
-         if (!comp_unit_has_pc_info)
+         if (! comp_unit_die.has_pc_info)
            {
              comp_unit_die.lowpc = lowpc;
              comp_unit_die.highpc = highpc;
@@ -1066,39 +1380,45 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile, int mainline)
   do_cleanups (back_to);
 }
 
-/* Read in all interesting dies to the end of the compilation unit.  */
+/* Read in all interesting dies to the end of the compilation unit or
+   to the end of the current namespace.  NAMESPACE is NULL if we
+   haven't yet encountered any DW_TAG_namespace entries; otherwise,
+   it's the name of the current namespace.  In particular, it's the
+   empty string if we're currently in the global namespace but have
+   previously encountered a DW_TAG_namespace.  */
 
 static char *
 scan_partial_symbols (char *info_ptr, struct objfile *objfile,
                      CORE_ADDR *lowpc, CORE_ADDR *highpc,
-                     const struct comp_unit_head *cu_header)
+                     const struct comp_unit_head *cu_header,
+                     const char *namespace)
 {
   bfd *abfd = objfile->obfd;
   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;
-  int has_pc_info;
+  while (1)
+    {
+      /* This flag tells whether or not info_ptr has gotten updated
+        inside the loop.  */
+      int info_ptr_updated = 0;
 
-  *lowpc = ((CORE_ADDR) -1);
-  *highpc = ((CORE_ADDR) 0);
+      info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
 
-  while (nesting_level)
-    {
-      info_ptr = read_partial_die (&pdi, abfd, info_ptr,
-                                  &has_pc_info, cu_header);
+      /* 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)
            {
            case DW_TAG_subprogram:
-             if (has_pc_info)
+             if (pdi.has_pc_info)
                {
                  if (pdi.lowpc < *lowpc)
                    {
@@ -1108,74 +1428,77 @@ scan_partial_symbols (char *info_ptr, struct objfile *objfile,
                    {
                      *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, objfile, cu_header, namespace);
                    }
                }
              break;
            case DW_TAG_variable:
            case DW_TAG_typedef:
+           case DW_TAG_union_type:
            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, objfile, cu_header, namespace);
                }
              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)
+               {
+                 info_ptr = add_partial_enumeration (&pdi, info_ptr,
+                                                     objfile, cu_header,
+                                                     namespace);
+                 info_ptr_updated = 1;
+               }
              break;
            case DW_TAG_base_type:
              /* File scope base type definitions are added to the partial
                 symbol table.  */
-             if (nesting_level == 1)
-               add_partial_symbol (&pdi, objfile, cu_header);
+             add_partial_symbol (&pdi, objfile, cu_header, namespace);
+             break;
+           case DW_TAG_namespace:
+             /* We've hit a DW_TAG_namespace entry, so we know this
+                file has been compiled using a compiler that
+                generates them; update NAMESPACE to reflect that.  */
+             if (namespace == NULL)
+               namespace = "";
+             info_ptr = add_partial_namespace (&pdi, info_ptr, objfile,
+                                               lowpc, highpc, cu_header,
+                                               namespace);
+             info_ptr_updated = 1;
              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 (pdi.tag == 0)
-       {
-         nesting_level--;
-       }
+       break;
+
+      /* If the die has a sibling, skip to the sibling, unless another
+        function has already updated info_ptr for us.  */
+
+      /* NOTE: carlton/2003-06-16: This is a bit hackish, but whether
+        or not we want to update this depends on enough stuff (not
+        only pdi.tag but also whether or not pdi.name is NULL) that
+        this seems like the easiest way to handle the issue.  */
+
+      if (!info_ptr_updated)
+         info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header);
     }
 
-  /* If we didn't find a lowpc, set it to highpc to avoid complaints
-     from `maint check'.  */
-  if (*lowpc == ((CORE_ADDR) -1))
-    *lowpc = *highpc;
   return info_ptr;
 }
 
 static void
 add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
-                   const struct comp_unit_head *cu_header)
+                   const struct comp_unit_head *cu_header,
+                   const char *namespace)
 {
   CORE_ADDR addr = 0;
+  const struct partial_symbol *psym = NULL;
 
   switch (pdi->tag)
     {
@@ -1184,19 +1507,21 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
        {
          /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
             mst_text, objfile); */
-         add_psymbol_to_list (pdi->name, strlen (pdi->name),
-                              VAR_NAMESPACE, LOC_BLOCK,
-                              &objfile->global_psymbols,
-                           0, pdi->lowpc + baseaddr, cu_language, objfile);
+         psym = add_psymbol_to_list (pdi->name, strlen (pdi->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,
             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 (pdi->name, strlen (pdi->name),
+                                     VAR_DOMAIN, LOC_BLOCK,
+                                     &objfile->static_psymbols,
+                                     0, pdi->lowpc + baseaddr,
+                                     cu_language, objfile);
        }
       break;
     case DW_TAG_variable:
@@ -1218,10 +1543,11 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
          if (pdi->locdesc)
            addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
          if (pdi->locdesc || pdi->has_type)
-           add_psymbol_to_list (pdi->name, strlen (pdi->name),
-                                VAR_NAMESPACE, LOC_STATIC,
-                                &objfile->global_psymbols,
-                                0, addr + baseaddr, cu_language, objfile);
+           psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+                                       VAR_DOMAIN, LOC_STATIC,
+                                       &objfile->global_psymbols,
+                                       0, addr + baseaddr,
+                                       cu_language, objfile);
        }
       else
        {
@@ -1231,16 +1557,17 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
          addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
          /*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
             mst_file_data, objfile); */
-         add_psymbol_to_list (pdi->name, strlen (pdi->name),
-                              VAR_NAMESPACE, LOC_STATIC,
-                              &objfile->static_psymbols,
-                              0, addr + baseaddr, cu_language, objfile);
+         psym = add_psymbol_to_list (pdi->name, strlen (pdi->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,
+                          VAR_DOMAIN, LOC_TYPEDEF,
                           &objfile->static_psymbols,
                           0, (CORE_ADDR) 0, cu_language, objfile);
       break;
@@ -1253,7 +1580,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
       if (pdi->has_children == 0)
        return;
       add_psymbol_to_list (pdi->name, strlen (pdi->name),
-                          STRUCT_NAMESPACE, LOC_TYPEDEF,
+                          STRUCT_DOMAIN, LOC_TYPEDEF,
                           &objfile->static_psymbols,
                           0, (CORE_ADDR) 0, cu_language, objfile);
 
@@ -1261,20 +1588,138 @@ add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
        {
          /* For C++, these implicitly act as typedefs as well. */
          add_psymbol_to_list (pdi->name, strlen (pdi->name),
-                              VAR_NAMESPACE, LOC_TYPEDEF,
+                              VAR_DOMAIN, LOC_TYPEDEF,
                               &objfile->static_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,
+                          VAR_DOMAIN, LOC_CONST,
                           &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.  */
+
+  if (cu_language == language_cplus
+      && namespace == NULL
+      && psym != NULL
+      && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL)
+    cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym),
+                                        objfile);
+}
+
+/* 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 char *
+add_partial_namespace (struct partial_die_info *pdi, char *info_ptr,
+                      struct objfile *objfile,
+                      CORE_ADDR *lowpc, CORE_ADDR *highpc,
+                      const struct comp_unit_head *cu_header,
+                      const char *namespace)
+{
+  /* Calculate the full name of the namespace that we just entered.  */
+
+  const char *new_name = pdi->name;
+  char *full_name;
+
+  if (new_name == NULL)
+    new_name = "(anonymous namespace)";
+  full_name = alloca (strlen (namespace) + 2 + strlen (new_name) + 1);
+  strcpy (full_name, namespace);
+  if (*namespace != '\0')
+    strcat (full_name, "::");
+  strcat (full_name, new_name);
+
+  /* FIXME: carlton/2003-06-27: Once we build qualified names for more
+     symbols than just namespaces, we should replace this by a call to
+     add_partial_symbol.  */
+
+  add_psymbol_to_list (full_name, strlen (full_name),
+                      VAR_DOMAIN, LOC_TYPEDEF,
+                      &objfile->global_psymbols,
+                      0, 0, cu_language, objfile);
+
+  /* Now scan partial symbols in that namespace.  */
+
+  if (pdi->has_children)
+    info_ptr = scan_partial_symbols (info_ptr, objfile,
+                                    lowpc, highpc,
+                                    cu_header, full_name);
+
+  return info_ptr;
+}
+
+/* Read a partial die corresponding to an enumeration type.  */
+
+static char *
+add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr,
+                        struct objfile *objfile,
+                        const struct comp_unit_head *cu_header,
+                        const char *namespace)
+{
+  bfd *abfd = objfile->obfd;
+  struct partial_die_info pdi;
+
+  if (enum_pdi->name != NULL)
+    add_partial_symbol (enum_pdi, objfile, cu_header, namespace);
+  
+  while (1)
+    {
+      info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
+      if (pdi.tag == 0)
+       break;
+      if (pdi.tag != DW_TAG_enumerator || pdi.name == NULL)
+       complaint (&symfile_complaints, "malformed enumerator DIE ignored");
+      else
+       add_partial_symbol (&pdi, objfile, cu_header, namespace);
+    }
+
+  return info_ptr;
+}
+
+/* Locate ORIG_PDI's sibling; INFO_PTR should point to the next DIE
+   after ORIG_PDI.  */
+
+static char *
+locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr,
+                   bfd *abfd, const struct comp_unit_head *cu_header)
+{
+  /* 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;
+
+  /* Okay, we don't know the sibling, but we have children that we
+     want to skip.  So read children until we run into one without a
+     tag; return whatever follows it.  */
+
+  while (1)
+    {
+      struct partial_die_info pdi;
+      
+      info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
+
+      if (pdi.tag == 0)
+       return info_ptr;
+      else
+       info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu_header);
+    }
 }
 
 /* Expand this partial symbol table into a full symbol table.  */
@@ -1319,6 +1764,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
   char *info_ptr;
   struct symtab *symtab;
   struct cleanup *back_to;
+  struct attribute *attr;
 
   /* Set local variables from the partial symbol table info.  */
   offset = DWARF_INFO_OFFSET (pst);
@@ -1326,6 +1772,15 @@ psymtab_to_symtab_1 (struct partial_symtab *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);
+  dwarf_ranges_buffer = DWARF_RANGES_BUFFER (pst);
+  dwarf_ranges_size = DWARF_RANGES_SIZE (pst);
+  dwarf_loc_buffer = DWARF_LOC_BUFFER (pst);
+  dwarf_loc_size = DWARF_LOC_SIZE (pst);
   baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
   cu_header_offset = offset;
   info_ptr = dwarf_info_buffer + offset;
@@ -1340,17 +1795,42 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
   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_header);
+  make_cleanup (dwarf2_empty_abbrev_table, cu_header.dwarf2_abbrevs);
 
   dies = read_comp_unit (info_ptr, abfd, &cu_header);
 
   make_cleanup_free_die_list (dies);
 
+  /* 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.  */
+
+  cu_header.base_known = 0;
+  cu_header.base_address = 0;
+
+  attr = dwarf_attr (dies, DW_AT_entry_pc);
+  if (attr)
+    {
+      cu_header.base_address = DW_ADDR (attr);
+      cu_header.base_known = 1;
+    }
+  else
+    {
+      attr = dwarf_attr (dies, DW_AT_low_pc);
+      if (attr)
+       {
+         cu_header.base_address = DW_ADDR (attr);
+         cu_header.base_known = 1;
+       }
+    }
+
   /* Do line number decoding in read_file_scope () */
   process_die (dies, objfile, &cu_header);
 
-  if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
+  if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile, &cu_header))
     {
       /* Some compilers don't define a DW_AT_high_pc attribute for
          the compilation unit.   If the DW_AT_high_pc is missing,
@@ -1365,7 +1845,8 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
                {
                  CORE_ADDR low, high;
 
-                 if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
+                 if (dwarf2_get_pc_bounds (child_die, &low, &high,
+                                           objfile, &cu_header))
                    {
                      highpc = max (highpc, high);
                    }
@@ -1386,7 +1867,6 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
     }
   pst->symtab = symtab;
   pst->readin = 1;
-  sort_symtab_syms (pst->symtab);
 
   do_cleanups (back_to);
 }
@@ -1414,6 +1894,8 @@ 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:
+    case DW_TAG_try_block:
+    case DW_TAG_catch_block:
       read_lexical_block_scope (die, objfile, cu_header);
       break;
     case DW_TAG_class_type:
@@ -1455,17 +1937,46 @@ process_die (struct die_info *die, struct objfile *objfile,
       break;
     case DW_TAG_common_inclusion:
       break;
+    case DW_TAG_namespace:
+      if (!processing_has_namespace_info)
+       {
+         processing_has_namespace_info = 1;
+         processing_current_namespace = "";
+       }
+      read_namespace (die, objfile, cu_header);
+      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.  */
+      if (!processing_has_namespace_info)
+       {
+         processing_has_namespace_info = 1;
+         processing_current_namespace = "";
+       }
+      gdb_assert (!die->has_children);
+      break;
     default:
       new_symbol (die, NULL, objfile, cu_header);
       break;
     }
 }
 
+static void
+initialize_cu_func_list (void)
+{
+  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)
 {
-  unsigned int line_offset = 0;
+  struct cleanup *back_to = make_cleanup (null_cleanup, 0);
   CORE_ADDR lowpc = ((CORE_ADDR) -1);
   CORE_ADDR highpc = ((CORE_ADDR) 0);
   struct attribute *attr;
@@ -1473,8 +1984,9 @@ read_file_scope (struct die_info *die, struct objfile *objfile,
   char *comp_dir = NULL;
   struct die_info *child_die;
   bfd *abfd = objfile->obfd;
+  struct line_header *line_header = 0;
 
-  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+  if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
     {
       if (die->has_children)
        {
@@ -1485,7 +1997,8 @@ read_file_scope (struct die_info *die, struct objfile *objfile,
                {
                  CORE_ADDR low, high;
 
-                 if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
+                 if (dwarf2_get_pc_bounds (child_die, &low, &high,
+                                           objfile, cu_header))
                    {
                      lowpc = min (lowpc, low);
                      highpc = max (highpc, high);
@@ -1526,8 +2039,8 @@ 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;
+      objfile->ei.deprecated_entry_file_lowpc = lowpc;
+      objfile->ei.deprecated_entry_file_highpc = highpc;
     }
 
   attr = dwarf_attr (die, DW_AT_language);
@@ -1553,13 +2066,7 @@ read_file_scope (struct die_info *die, struct objfile *objfile,
   start_symtab (name, comp_dir, lowpc);
   record_debugformat ("DWARF 2");
 
-  /* Decode line number information if present.  */
-  attr = dwarf_attr (die, DW_AT_stmt_list);
-  if (attr)
-    {
-      line_offset = DW_UNSND (attr);
-      dwarf_decode_lines (line_offset, comp_dir, abfd, cu_header);
-    }
+  initialize_cu_func_list ();
 
   /* Process all dies in compilation unit.  */
   if (die->has_children)
@@ -1571,13 +2078,62 @@ read_file_scope (struct die_info *die, struct objfile *objfile,
          child_die = sibling_die (child_die);
        }
     }
+
+  /* Decode line number information if present.  */
+  attr = dwarf_attr (die, DW_AT_stmt_list);
+  if (attr)
+    {
+      unsigned int line_offset = DW_UNSND (attr);
+      line_header = dwarf_decode_line_header (line_offset,
+                                              abfd, cu_header);
+      if (line_header)
+        {
+          make_cleanup ((make_cleanup_ftype *) free_line_header,
+                        (void *) line_header);
+          dwarf_decode_lines (line_header, comp_dir, abfd, cu_header);
+        }
+    }
+
+  /* Decode macro information, if present.  Dwarf 2 macro information
+     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);
+  if (attr && line_header)
+    {
+      unsigned int macro_offset = DW_UNSND (attr);
+      dwarf_decode_macros (line_header, macro_offset,
+                           comp_dir, abfd, cu_header, objfile);
+    }
+  do_cleanups (back_to);
+}
+
+static void
+add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc)
+{
+  struct function_range *thisfn;
+
+  thisfn = (struct function_range *)
+    obstack_alloc (&dwarf2_tmp_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;
+  else
+      cu_last_fn->next = thisfn;
+
+  cu_last_fn = thisfn;
 }
 
 static void
 read_func_scope (struct die_info *die, struct objfile *objfile,
                 const struct comp_unit_head *cu_header)
 {
-  register struct context_stack *new;
+  struct context_stack *new;
   CORE_ADDR lowpc;
   CORE_ADDR highpc;
   struct die_info *child_die;
@@ -1588,12 +2144,15 @@ read_func_scope (struct die_info *die, struct objfile *objfile,
 
   /* 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, objfile, cu_header))
     return;
 
   lowpc += baseaddr;
   highpc += baseaddr;
 
+  /* Record the function range for dwarf_decode_lines.  */
+  add_to_cu_func_list (name, lowpc, highpc);
+
   if (objfile->ei.entry_point >= lowpc &&
       objfile->ei.entry_point < highpc)
     {
@@ -1608,9 +2167,26 @@ read_func_scope (struct die_info *die, struct objfile *objfile,
   attr = dwarf_attr (die, DW_AT_frame_base);
   if (attr)
     {
-      CORE_ADDR addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+      CORE_ADDR addr;
+
+      /* 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)
+        {
+         dwarf2_complex_location_expr_complaint ();
+          addr = 0;
+        }
+      else
+        {
+         dwarf2_invalid_attrib_class_complaint ("DW_AT_frame_base", name);
+          addr = 0;
+        }
+    
       if (isderef)
-       complain (&dwarf2_unsupported_at_frame_base, name);
+       dwarf2_unsupported_at_frame_base_complaint (name);
       else if (isreg)
        frame_base_reg = addr;
       else if (offreg)
@@ -1619,11 +2195,18 @@ read_func_scope (struct die_info *die, struct objfile *objfile,
          frame_base_offset = addr;
        }
       else
-       complain (&dwarf2_unsupported_at_frame_base, name);
+       dwarf2_unsupported_at_frame_base_complaint (name);
     }
 
   new = push_context (0, lowpc);
   new->name = new_symbol (die, die->type, objfile, cu_header);
+
+  /* If there was a location expression for DW_AT_frame_base above,
+     record it.  We still need to decode it above because not all
+     symbols use location expressions exclusively.  */
+  if (attr)
+    dwarf2_symbol_mark_computed (attr, new->name, cu_header, objfile);
+
   list_in_scope = &local_symbols;
 
   if (die->has_children)
@@ -1640,7 +2223,18 @@ 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 ())
+    list_in_scope = &file_symbols;
 }
 
 /* Process all the DIES contained within a lexical block scope.  Start
@@ -1650,12 +2244,16 @@ static void
 read_lexical_block_scope (struct die_info *die, struct objfile *objfile,
                          const struct comp_unit_head *cu_header)
 {
-  register struct context_stack *new;
+  struct context_stack *new;
   CORE_ADDR lowpc, highpc;
   struct die_info *child_die;
 
   /* 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, objfile, cu_header))
     return;
   lowpc += baseaddr;
   highpc += baseaddr;
@@ -1680,27 +2278,148 @@ 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 objfile *objfile)
+dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
+                     CORE_ADDR *highpc, struct objfile *objfile,
+                     const struct comp_unit_head *cu_header)
 {
   struct attribute *attr;
-  CORE_ADDR low;
-  CORE_ADDR high;
+  bfd *obfd = objfile->obfd;
+  CORE_ADDR low = 0;
+  CORE_ADDR high = 0;
+  int ret = 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);
+    {
+      high = DW_ADDR (attr);
+      attr = dwarf_attr (die, DW_AT_low_pc);
+      if (attr)
+       low = DW_ADDR (attr);
+      else
+       /* Found high w/o low attribute.  */
+       return 0;
+
+      /* Found consecutive range of addresses.  */
+      ret = 1;
+    }
   else
-    return 0;
+    {
+      attr = dwarf_attr (die, DW_AT_ranges);
+      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;
+         unsigned int i;
+         char *buffer;
+         CORE_ADDR marker;
+         int low_set;
+         found_base = cu_header->base_known;
+         base = cu_header->base_address;
+
+         if (offset >= dwarf_ranges_size)
+           {
+             complaint (&symfile_complaints,
+                        "Offset %d out of bounds for DW_AT_ranges attribute",
+                        offset);
+             return 0;
+           }
+         buffer = dwarf_ranges_buffer + offset;
+
+         /* Read in the largest possible address.  */
+         marker = read_address (obfd, buffer, cu_header, &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_header, &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_header, &dummy);
+             buffer += addr_size;
+             range_end = read_address (obfd, buffer, cu_header, &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_header, &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;
+               }
+           }
+
+         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;
+
+         ret = -1;
+       }
+    }
 
   if (high < low)
     return 0;
@@ -1713,12 +2432,12 @@ 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;
 }
 
 /* Add an aggregate field to the field list.  */
@@ -1735,7 +2454,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
 
   /* Allocate a new field list entry and link it in.  */
   new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
-  make_cleanup (free, new_field);
+  make_cleanup (xfree, new_field);
   memset (new_field, 0, sizeof (struct nextfield));
   new_field->next = fip->fields;
   fip->fields = new_field;
@@ -1760,11 +2479,16 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
     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))
     {
+      /* Data member other than a C++ static data member.  */
+      
       /* Get type of field.  */
       fp->type = die_type (die, objfile, cu_header);
 
+      FIELD_STATIC_KIND (*fp) = 0;
+
       /* Get bit size of field (zero if none).  */
       attr = dwarf_attr (die, DW_AT_bit_size);
       if (attr)
@@ -1844,12 +2568,18 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
          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.  */
+      /* Get name of field.  */
       attr = dwarf_attr (die, DW_AT_name);
       if (attr && DW_STRING (attr))
        fieldname = DW_STRING (attr);
@@ -1873,6 +2603,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
        FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), objfile, cu_header)
                              * bits_per_byte);
       FIELD_BITSIZE (*fp) = 0;
+      FIELD_STATIC_KIND (*fp) = 0;
       FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
       FIELD_NAME (*fp) = type_name_no_tag (fp->type);
       fip->nbaseclasses++;
@@ -1947,8 +2678,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;
        }
@@ -2022,7 +2753,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
   /* Create a new member function field and chain it to the field list
      entry. */
   new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield));
-  make_cleanup (free, new_fnfield);
+  make_cleanup (xfree, new_fnfield);
   memset (new_fnfield, 0, sizeof (struct nextfnfield));
   new_fnfield->next = flp->head;
   flp->head = new_fnfield;
@@ -2036,23 +2767,15 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
   if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
     {
       struct type *return_type = TYPE_TARGET_TYPE (die->type);
-      struct type **arg_types;
       int nparams = TYPE_NFIELDS (die->type);
-      int iparams;
-
-      /* Copy argument types from the subroutine type.  */
-      arg_types = (struct type **)
-       TYPE_ALLOC (fnp->type, (nparams + 1) * sizeof (struct type *));
-      for (iparams = 0; iparams < nparams; iparams++)
-       arg_types[iparams] = TYPE_FIELD_TYPE (die->type, iparams);
 
-      /* Set last entry in argument type vector.  */
-      if (TYPE_FLAGS (die->type) & TYPE_FLAG_VARARGS)
-       arg_types[nparams] = NULL;
-      else
-       arg_types[nparams] = dwarf2_fundamental_type (objfile, FT_VOID);
-
-      smash_to_method_type (fnp->type, type, return_type, arg_types);
+      /* TYPE is the domain of this method, and DIE->TYPE is the type
+          of the method itself (TYPE_CODE_METHOD).  */
+      smash_to_method_type (fnp->type, type,
+                           TYPE_TARGET_TYPE (die->type),
+                           TYPE_FIELDS (die->type),
+                           TYPE_NFIELDS (die->type),
+                           TYPE_VARARGS (die->type));
 
       /* Handle static member functions.
          Dwarf2 has no clean way to discern C++ static and non-static
@@ -2064,7 +2787,8 @@ 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)
@@ -2088,10 +2812,30 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
        }
     }
 
+  /* Check for artificial methods.  */
+  attr = dwarf_attr (die, DW_AT_artificial);
+  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);
   if (attr)
-    fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2;
+    {
+      /* Support the .debug_loc offsets */
+      if (attr_form_is_block (attr))
+        {
+          fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2;
+        }
+      else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+        {
+         dwarf2_complex_location_expr_complaint ();
+        }
+      else
+        {
+         dwarf2_invalid_attrib_class_complaint ("DW_AT_vtable_elem_location",
+                                                fieldname);
+        }
+   }
 }
 
 /* Create the vector of member function fields, and attach it to the type.  */
@@ -2204,13 +2948,14 @@ read_structure_scope (struct die_info *die, struct objfile *objfile,
 
       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.  */
+             /* 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, objfile, cu_header);
            }
          else if (child_die->tag == DW_TAG_subprogram)
@@ -2270,8 +3015,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
                {
@@ -2289,8 +3036,6 @@ read_structure_scope (struct die_info *die, struct objfile *objfile,
       /* No children, must be stub. */
       TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
     }
-
-  die->type = type;
 }
 
 /* Given a pointer to a die which begins an enumeration, process all
@@ -2363,10 +3108,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++;
                }
@@ -2382,7 +3128,7 @@ read_enumeration (struct die_info *die, struct objfile *objfile,
            TYPE_ALLOC (type, sizeof (struct field) * num_fields);
          memcpy (TYPE_FIELDS (type), fields,
                  sizeof (struct field) * num_fields);
-         free (fields);
+         xfree (fields);
        }
       if (unsigned_enum)
        TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
@@ -2453,14 +3199,15 @@ read_array_type (struct die_info *die, struct objfile *objfile,
              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_data4
+                      || attr->form == DW_FORM_data8)
                {
                  low = DW_UNSND (attr);
                }
              else
                {
-                 complain (&dwarf2_non_const_array_bound_ignored,
-                           dwarf_form_name (attr->form));
+                 dwarf2_non_const_array_bound_ignored_complaint
+                   (dwarf_form_name (attr->form));
 #ifdef FORTRAN_HACK
                  die->type = lookup_pointer_type (element_type);
                  return;
@@ -2479,7 +3226,8 @@ read_array_type (struct die_info *die, struct objfile *objfile,
              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_data4
+                      || attr->form == DW_FORM_data8)
                {
                  high = DW_UNSND (attr);
                }
@@ -2494,8 +3242,8 @@ read_array_type (struct die_info *die, struct objfile *objfile,
                }
              else
                {
-                 complain (&dwarf2_non_const_array_bound_ignored,
-                           dwarf_form_name (attr->form));
+                 dwarf2_non_const_array_bound_ignored_complaint
+                   (dwarf_form_name (attr->form));
 #ifdef FORTRAN_HACK
                  die->type = lookup_pointer_type (element_type);
                  return;
@@ -2525,6 +3273,16 @@ read_array_type (struct die_info *die, struct objfile *objfile,
   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
+     array type.  This is not part of the Dwarf2/3 standard yet, but a
+     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);
+  if (attr)
+    TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
+
   do_cleanups (back_to);
 
   /* Install the type in the die. */
@@ -2545,7 +3303,20 @@ read_common_block (struct die_info *die, struct objfile *objfile,
   attr = dwarf_attr (die, DW_AT_location);
   if (attr)
     {
-      base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+      /* Support the .debug_loc offsets */
+      if (attr_form_is_block (attr))
+        {
+          base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+        }
+      else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+        {
+         dwarf2_complex_location_expr_complaint ();
+        }
+      else
+        {
+         dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+                                                "common block member");
+        }
     }
   if (die->has_children)
     {
@@ -2565,6 +3336,90 @@ read_common_block (struct die_info *die, struct objfile *objfile,
     }
 }
 
+/* Read a C++ namespace.  */
+
+static void
+read_namespace (struct die_info *die, struct objfile *objfile,
+               const struct comp_unit_head *cu_header)
+{
+  const char *previous_namespace = processing_current_namespace;
+  const char *name = NULL;
+  int is_anonymous;
+  struct die_info *current_die;
+
+  /* Loop through the extensions until we find a name.  */
+
+  for (current_die = die;
+       current_die != NULL;
+       current_die = dwarf2_extension (die))
+    {
+      name = dwarf2_name (current_die);
+      if (name != NULL)
+       break;
+    }
+
+  /* Is it an anonymous namespace?  */
+
+  is_anonymous = (name == NULL);
+  if (is_anonymous)
+    name = "(anonymous namespace)";
+
+  /* Now build the name of the current namespace.  */
+
+  if (previous_namespace[0] == '\0')
+    {
+      processing_current_namespace = name;
+    }
+  else
+    {
+      /* We need temp_name around because processing_current_namespace
+        is a const char *.  */
+      char *temp_name = alloca (strlen (previous_namespace)
+                               + 2 + strlen(name) + 1);
+      strcpy (temp_name, previous_namespace);
+      strcat (temp_name, "::");
+      strcat (temp_name, name);
+
+      processing_current_namespace = 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) == 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_namespace,
+                       objfile);
+      TYPE_TAG_NAME (type) = TYPE_NAME (type);
+
+      new_symbol (die, type, objfile, cu_header);
+
+      if (is_anonymous)
+       cp_add_using_directive (processing_current_namespace,
+                               strlen (previous_namespace),
+                               strlen (processing_current_namespace));
+    }
+
+  if (die->has_children)
+    {
+      struct die_info *child_die = die->next;
+      
+      while (child_die && child_die->tag)
+       {
+         process_die (child_die, objfile, cu_header);
+         child_die = sibling_die (child_die);
+       }
+    }
+
+  processing_current_namespace = previous_namespace;
+}
+
 /* Extract all information from a DW_TAG_pointer_type DIE and add to
    the user defined type vector.  */
 
@@ -2573,7 +3428,9 @@ read_tag_pointer_type (struct die_info *die, struct objfile *objfile,
                       const struct comp_unit_head *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)
     {
@@ -2581,15 +3438,42 @@ read_tag_pointer_type (struct die_info *die, struct objfile *objfile,
     }
 
   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);
-    }
+
+  attr_byte_size = dwarf_attr (die, DW_AT_byte_size);
+  if (attr_byte_size)
+    byte_size = DW_UNSND (attr_byte_size);
   else
+    byte_size = cu_header->addr_size;
+
+  attr_address_class = dwarf_attr (die, DW_AT_address_class);
+  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;
 }
 
@@ -2649,26 +3533,30 @@ static void
 read_tag_const_type (struct die_info *die, struct objfile *objfile,
                     const struct comp_unit_head *cu_header)
 {
+  struct type *base_type;
+
   if (die->type)
     {
       return;
     }
 
-  complain (&dwarf2_const_ignored);
-  die->type = die_type (die, objfile, cu_header);
+  base_type = die_type (die, objfile, cu_header);
+  die->type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
 }
 
 static void
 read_tag_volatile_type (struct die_info *die, struct objfile *objfile,
                        const struct comp_unit_head *cu_header)
 {
+  struct type *base_type;
+
   if (die->type)
     {
       return;
     }
 
-  complain (&dwarf2_volatile_ignored);
-  die->type = die_type (die, objfile, cu_header);
+  base_type = die_type (die, objfile, cu_header);
+  die->type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
 }
 
 /* Extract all information from a DW_TAG_string_type DIE and add to
@@ -2695,12 +3583,30 @@ read_tag_string_type (struct die_info *die, struct objfile *objfile)
     }
   else
     {
-      length = 1;
+      /* check for the DW_AT_byte_size attribute */
+      attr = dwarf_attr (die, DW_AT_byte_size);
+      if (attr)
+        {
+          length = DW_UNSND (attr);
+        }
+      else
+        {
+          length = 1;
+        }
     }
   index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
   range_type = create_range_type (NULL, index_type, 1, length);
-  char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
-  type = create_string_type (char_type, range_type);
+  if (cu_language == language_fortran)
+    {
+      /* Need to create a unique string type for bounds
+         information */
+      type = create_string_type (0, range_type);
+    }
+  else
+    {
+      char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
+      type = create_string_type (char_type, range_type);
+    }
   die->type = type;
 }
 
@@ -2791,26 +3697,18 @@ static void
 read_typedef (struct die_info *die, struct objfile *objfile,
              const struct comp_unit_head *cu_header)
 {
-  struct type *type;
+  struct attribute *attr;
+  char *name = NULL;
 
   if (!die->type)
     {
-      struct attribute *attr;
-      struct type *xtype;
-
-      xtype = die_type (die, objfile, cu_header);
-
-      type = alloc_type (objfile);
-      TYPE_CODE (type) = TYPE_CODE_TYPEDEF;
-      TYPE_FLAGS (type) |= TYPE_FLAG_TARGET_STUB;
-      TYPE_TARGET_TYPE (type) = xtype;
       attr = dwarf_attr (die, DW_AT_name);
       if (attr && DW_STRING (attr))
-       TYPE_NAME (type) = obsavestring (DW_STRING (attr),
-                                        strlen (DW_STRING (attr)),
-                                        &objfile->type_obstack);
-
-      die->type = type;
+       {
+         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);
     }
 }
 
@@ -2844,18 +3742,18 @@ read_base_type (struct die_info *die, struct objfile *objfile)
   if (attr && DW_STRING (attr))
     {
       enum type_code code = TYPE_CODE_INT;
-      int is_unsigned = 0;
+      int type_flags = 0;
 
       switch (encoding)
        {
        case DW_ATE_address:
          /* Turn DW_ATE_address into a void * pointer.  */
          code = TYPE_CODE_PTR;
-         is_unsigned = 1;
+         type_flags |= TYPE_FLAG_UNSIGNED;
          break;
        case DW_ATE_boolean:
          code = TYPE_CODE_BOOL;
-         is_unsigned = 1;
+         type_flags |= TYPE_FLAG_UNSIGNED;
          break;
        case DW_ATE_complex_float:
          code = TYPE_CODE_COMPLEX;
@@ -2868,16 +3766,28 @@ read_base_type (struct die_info *die, struct objfile *objfile)
          break;
        case DW_ATE_unsigned:
        case DW_ATE_unsigned_char:
-         is_unsigned = 1;
+         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, is_unsigned, DW_STRING (attr), objfile);
+      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);
+      else if (encoding == DW_ATE_complex_float)
+       {
+         if (size == 32)
+           TYPE_TARGET_TYPE (type)
+             = dwarf2_fundamental_type (objfile, FT_EXT_PREC_FLOAT);
+         else if (size == 16)
+           TYPE_TARGET_TYPE (type)
+             = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
+         else if (size == 8)
+           TYPE_TARGET_TYPE (type)
+             = dwarf2_fundamental_type (objfile, FT_FLOAT);
+       }
     }
   else
     {
@@ -2888,7 +3798,7 @@ read_base_type (struct die_info *die, struct objfile *objfile)
 
 /* Read a whole compilation unit into a linked list of dies.  */
 
-struct die_info *
+static struct die_info *
 read_comp_unit (char *info_ptr, bfd *abfd,
                const struct comp_unit_head *cu_header)
 {
@@ -2945,8 +3855,8 @@ free_die_list (struct die_info *dies)
   while (die)
     {
       next = die->next;
-      free (die->attrs);
-      free (die);
+      xfree (die->attrs);
+      xfree (die);
       die = next;
     }
 }
@@ -2967,19 +3877,24 @@ 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.  */
 
-static char *
+char *
 dwarf2_read_section (struct objfile *objfile, file_ptr offset,
-                    unsigned int size)
+                    unsigned int size, asection *sectp)
 {
   bfd *abfd = objfile->obfd;
-  char *buf;
+  char *buf, *retbuf;
 
   if (size == 0)
     return NULL;
 
   buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
+  retbuf
+    = (char *) symfile_relocate_debug_section (abfd, sectp, (bfd_byte *) buf);
+  if (retbuf != NULL)
+    return retbuf;
+
   if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
-      (bfd_read (buf, size, 1, abfd) != size))
+      (bfd_bread (buf, size, abfd) != size))
     {
       buf = NULL;
       error ("Dwarf Error: Can't read DWARF data from '%s'",
@@ -2994,17 +3909,18 @@ dwarf2_read_section (struct objfile *objfile, file_ptr offset,
    in a hash table.  */
 
 static void
-dwarf2_read_abbrevs (bfd *abfd, unsigned int offset)
+dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *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);
+  /* Initialize dwarf2 abbrevs */
+  memset (cu_header->dwarf2_abbrevs, 0,
+          ABBREV_HASH_SIZE*sizeof (struct abbrev_info *));
 
-  abbrev_ptr = dwarf_abbrev_buffer + offset;
+  abbrev_ptr = dwarf_abbrev_buffer + cu_header->abbrev_offset;
   abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
   abbrev_ptr += bytes_read;
 
@@ -3043,8 +3959,8 @@ dwarf2_read_abbrevs (bfd *abfd, unsigned int offset)
        }
 
       hash_number = abbrev_number % ABBREV_HASH_SIZE;
-      cur_abbrev->next = dwarf2_abbrevs[hash_number];
-      dwarf2_abbrevs[hash_number] = cur_abbrev;
+      cur_abbrev->next = cu_header->dwarf2_abbrevs[hash_number];
+      cu_header->dwarf2_abbrevs[hash_number] = cur_abbrev;
 
       /* Get next abbreviation.
          Under Irix6 the abbreviations for a compilation unit are not
@@ -3058,7 +3974,7 @@ dwarf2_read_abbrevs (bfd *abfd, unsigned int offset)
        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_header) != NULL)
        break;
     }
 }
@@ -3067,36 +3983,39 @@ dwarf2_read_abbrevs (bfd *abfd, unsigned int offset)
 
 /* ARGSUSED */
 static void
-dwarf2_empty_abbrev_table (PTR ignore)
+dwarf2_empty_abbrev_table (void *ptr_to_abbrevs_table)
 {
   int i;
   struct abbrev_info *abbrev, *next;
+  struct abbrev_info **abbrevs;
+
+  abbrevs = (struct abbrev_info **)ptr_to_abbrevs_table;
 
   for (i = 0; i < ABBREV_HASH_SIZE; ++i)
     {
       next = NULL;
-      abbrev = dwarf2_abbrevs[i];
+      abbrev = abbrevs[i];
       while (abbrev)
        {
          next = abbrev->next;
-         free (abbrev->attrs);
-         free (abbrev);
+         xfree (abbrev->attrs);
+         xfree (abbrev);
          abbrev = next;
        }
-      dwarf2_abbrevs[i] = NULL;
+      abbrevs[i] = 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, const struct comp_unit_head *cu_header)
 {
   unsigned int hash_number;
   struct abbrev_info *abbrev;
 
   hash_number = number % ABBREV_HASH_SIZE;
-  abbrev = dwarf2_abbrevs[hash_number];
+  abbrev = cu_header->dwarf2_abbrevs[hash_number];
 
   while (abbrev)
     {
@@ -3112,8 +4031,7 @@ dwarf2_lookup_abbrev (unsigned int number)
 
 static char *
 read_partial_die (struct partial_die_info *part_die, bfd *abfd,
-                 char *info_ptr, int *has_pc_info,
-                 const struct comp_unit_head *cu_header)
+                 char *info_ptr, const struct comp_unit_head *cu_header)
 {
   unsigned int abbrev_number, bytes_read, i;
   struct abbrev_info *abbrev;
@@ -3124,16 +4042,16 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd,
   int has_high_pc_attr = 0;
 
   *part_die = zeroed_partial_die;
-  *has_pc_info = 0;
   abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
   info_ptr += bytes_read;
   if (!abbrev_number)
     return info_ptr;
 
-  abbrev = dwarf2_lookup_abbrev (abbrev_number);
+  abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header);
   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));
     }
   part_die->offset = info_ptr - dwarf_info_buffer;
   part_die->tag = abbrev->tag;
@@ -3167,7 +4085,20 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd,
          part_die->highpc = DW_ADDR (&attr);
          break;
        case DW_AT_location:
-         part_die->locdesc = DW_BLOCK (&attr);
+          /* Support the .debug_loc offsets */
+          if (attr_form_is_block (&attr))
+            {
+              part_die->locdesc = DW_BLOCK (&attr);
+            }
+          else if (attr.form == DW_FORM_data4 || attr.form == DW_FORM_data8)
+            {
+             dwarf2_complex_location_expr_complaint ();
+            }
+          else
+            {
+             dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+                                                    "partial symbol information");
+            }
          break;
        case DW_AT_language:
          part_die->language = DW_UNSND (&attr);
@@ -3190,7 +4121,7 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd,
          /* 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);
@@ -3210,7 +4141,7 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd,
       int dummy;
 
       spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr);
-      read_partial_die (&spec_die, abfd, spec_ptr, &dummy, cu_header);
+      read_partial_die (&spec_die, abfd, spec_ptr, cu_header);
       if (spec_die.name)
        {
          part_die->name = spec_die.name;
@@ -3233,7 +4164,7 @@ read_partial_die (struct partial_die_info *part_die, bfd *abfd,
       && part_die->lowpc < part_die->highpc
       && (part_die->lowpc != 0
          || (bfd_get_file_flags (abfd) & HAS_RELOC)))
-    *has_pc_info = 1;
+    part_die->has_pc_info = 1;
   return info_ptr;
 }
 
@@ -3261,10 +4192,11 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
       return info_ptr;
     }
 
-  abbrev = dwarf2_lookup_abbrev (abbrev_number);
+  abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header);
   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;
@@ -3287,19 +4219,18 @@ read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
   return info_ptr;
 }
 
-/* Read an attribute described by an abbreviated attribute.  */
+/* Read an attribute value described by an attribute form.  */
 
 static char *
-read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
+read_attribute_value (struct attribute *attr, unsigned form,
                bfd *abfd, char *info_ptr,
                const struct comp_unit_head *cu_header)
 {
   unsigned int bytes_read;
   struct dwarf_block *blk;
 
-  attr->name = abbrev->name;
-  attr->form = abbrev->form;
-  switch (abbrev->form)
+  attr->form = form;
+  switch (form)
     {
     case DW_FORM_addr:
     case DW_FORM_ref_addr:
@@ -3338,6 +4269,11 @@ read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
       DW_STRING (attr) = read_string (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
       break;
+    case DW_FORM_strp:
+      DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header,
+                                              &bytes_read);
+      info_ptr += bytes_read;
+      break;
     case DW_FORM_block:
       blk = dwarf_alloc_block ();
       blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
@@ -3390,15 +4326,30 @@ read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
       DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
       info_ptr += bytes_read;
       break;
-    case DW_FORM_strp:
     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);
+      break;
     default:
-      error ("Dwarf Error: Cannot handle %s in DWARF reader.",
-            dwarf_form_name (abbrev->form));
+      error ("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]",
+            dwarf_form_name (form),
+            bfd_get_filename (abfd));
     }
   return info_ptr;
 }
 
+/* Read an attribute described by an abbreviated attribute.  */
+
+static char *
+read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
+               bfd *abfd, char *info_ptr,
+               const struct comp_unit_head *cu_header)
+{
+  attr->name = abbrev->name;
+  return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu_header);
+}
+
 /* read dwarf information from a buffer */
 
 static unsigned int
@@ -3463,7 +4414,9 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
          retval = bfd_get_signed_64 (abfd, (bfd_byte *) buf);
          break;
        default:
-         internal_error ("read_address: bad switch, signed");
+         internal_error (__FILE__, __LINE__,
+                         "read_address: bad switch, signed [in module %s]",
+                         bfd_get_filename (abfd));
        }
     }
   else
@@ -3480,7 +4433,9 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
          retval = bfd_get_64 (abfd, (bfd_byte *) buf);
          break;
        default:
-         internal_error ("read_address: bad switch, unsigned");
+         internal_error (__FILE__, __LINE__,
+                         "read_address: bad switch, unsigned [in module %s]",
+                         bfd_get_filename (abfd));
        }
     }
 
@@ -3488,12 +4443,25 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
   return retval;
 }
 
-/* Reads the initial length from a section.  The (draft) DWARF 2.1
+/* Read the initial length from a section.  The (draft) DWARF 3
    specification allows the initial length to take up either 4 bytes
    or 12 bytes.  If the first 4 bytes are 0xffffffff, then the next 8
    bytes describe the length and all offsets will be 8 bytes in length
    instead of 4.
 
+   An older, non-standard 64-bit format is also handled by this
+   function.  The older format in question stores the initial length
+   as an 8-byte quantity without an escape value.  Lengths greater
+   than 2^32 aren't very common which means that the initial 4 bytes
+   is almost always zero.  Since a length value of zero doesn't make
+   sense for the 32-bit format, this initial zero can be considered to
+   be an escape value which indicates the presence of the older 64-bit
+   format.  As written, the code can't detect (old format) lengths
+   greater than 4GB.  If it becomes necessary to handle lengths somewhat
+   larger than 4GB, we could allow other small values (such as the
+   non-sensical values of 1, 2, and 3) to also be used as escape values
+   indicating the presence of the old format.
+
    The value returned via bytes_read should be used to increment
    the relevant pointer after calling read_initial_length().
    
@@ -3504,14 +4472,18 @@ read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
    
    [ Note:  read_initial_length() and read_offset() are based on the
      document entitled "DWARF Debugging Information Format", revision
-     2.1, draft 4, dated July 20, 2000.  This document was obtained
+     3, draft 8, dated November 19, 2001.  This document was obtained
      from:
 
-       http://reality.sgi.com/dehnert_engr/dwarf/dwarf2p1-draft4-000720.pdf
+       http://reality.sgiweb.org/davea/dwarf3-draft8-011125.pdf
      
      This document is only a draft and is subject to change.  (So beware.)
 
-     - Kevin, Aug 4, 2000
+     Details regarding the older, non-standard 64-bit format were
+     determined empirically by examining 64-bit ELF files produced
+     by the SGI toolchain on an IRIX 6.5 machine.
+
+     - Kevin, July 16, 2002
    ] */
 
 static LONGEST
@@ -3532,6 +4504,18 @@ read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header,
          cu_header->offset_size = 8;
        }
     }
+  else if (retval == 0)
+    {
+      /* Handle (non-standard) 64-bit DWARF2 formats such as that used
+         by IRIX.  */
+      retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+      *bytes_read = 8;
+      if (cu_header != NULL)
+       {
+         cu_header->initial_length_size = 8;
+         cu_header->offset_size = 8;
+       }
+    }
   else
     {
       *bytes_read = 4;
@@ -3565,7 +4549,9 @@ read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
       *bytes_read = 8;
       break;
     default:
-      internal_error ("read_offset: bad switch");
+      internal_error (__FILE__, __LINE__,
+                     "read_offset: bad switch [in module %s]",
+                     bfd_get_filename (abfd));
     }
 
  return retval;
@@ -3577,20 +4563,8 @@ read_n_bytes (bfd *abfd, char *buf, unsigned int size)
   /* If the size of a host char is 8 bits, we can return a pointer
      to the buffer, otherwise we have to copy the data to a buffer
      allocated on the temporary obstack.  */
-#if HOST_CHAR_BIT == 8
+  gdb_assert (HOST_CHAR_BIT == 8);
   return buf;
-#else
-  char *ret;
-  unsigned int i;
-
-  ret = obstack_alloc (&dwarf2_tmp_obstack, size);
-  for (i = 0; i < size; ++i)
-    {
-      ret[i] = bfd_get_8 (abfd, (bfd_byte *) buf);
-      buf++;
-    }
-  return ret;
-#endif
 }
 
 static char *
@@ -3599,7 +4573,7 @@ read_string (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
   /* If the size of a host char is 8 bits, we can return a pointer
      to the string, otherwise we have to copy the string to a buffer
      allocated on the temporary obstack.  */
-#if HOST_CHAR_BIT == 8
+  gdb_assert (HOST_CHAR_BIT == 8);
   if (*buf == '\0')
     {
       *bytes_read_ptr = 1;
@@ -3607,25 +4581,32 @@ read_string (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
     }
   *bytes_read_ptr = strlen (buf) + 1;
   return buf;
-#else
-  int byte;
-  unsigned int i = 0;
+}
+
+static char *
+read_indirect_string (bfd *abfd, char *buf,
+                     const struct comp_unit_head *cu_header,
+                     unsigned int *bytes_read_ptr)
+{
+  LONGEST str_offset = read_offset (abfd, buf, cu_header,
+                                   (int *) bytes_read_ptr);
 
-  while ((byte = bfd_get_8 (abfd, (bfd_byte *) buf)) != 0)
+  if (dwarf_str_buffer == NULL)
     {
-      obstack_1grow (&dwarf2_tmp_obstack, byte);
-      i++;
-      buf++;
+      error ("DW_FORM_strp used without .debug_str section [in module %s]",
+                     bfd_get_filename (abfd));
+      return NULL;
     }
-  if (i == 0)
+  if (str_offset >= dwarf_str_size)
     {
-      *bytes_read_ptr = 1;
+      error ("DW_FORM_strp pointing outside of .debug_str section [in module %s]",
+                     bfd_get_filename (abfd));
       return NULL;
     }
-  obstack_1grow (&dwarf2_tmp_obstack, '\0');
-  *bytes_read_ptr = i + 1;
-  return obstack_finish (&dwarf2_tmp_obstack);
-#endif
+  gdb_assert (HOST_CHAR_BIT == 8);
+  if (dwarf_str_buffer[str_offset] == '\0')
+    return NULL;
+  return dwarf_str_buffer + str_offset;
 }
 
 static unsigned long
@@ -3702,18 +4683,23 @@ set_cu_language (unsigned int lang)
       break;
     case DW_LANG_Fortran77:
     case DW_LANG_Fortran90:
+    case DW_LANG_Fortran95:
       cu_language = language_fortran;
       break;
     case DW_LANG_Mips_Assembler:
       cu_language = language_asm;
       break;
+    case DW_LANG_Java:
+      cu_language = language_java;
+      break;
     case DW_LANG_Ada83:
+    case DW_LANG_Ada95:
     case DW_LANG_Cobol74:
     case DW_LANG_Cobol85:
     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);
@@ -3756,87 +4742,153 @@ die_is_declaration (struct die_info *die)
          && ! dwarf_attr (die, DW_AT_specification));
 }
 
-/* Decode the line number information for the compilation unit whose
-   line number info is at OFFSET in the .debug_line section.
-   The compilation directory of the file is passed in COMP_DIR.  */
 
-struct filenames
+/* Free the line_header structure *LH, and any arrays and strings it
+   refers to.  */
+static void
+free_line_header (struct line_header *lh)
+{
+  if (lh->standard_opcode_lengths)
+    xfree (lh->standard_opcode_lengths);
+
+  /* Remember that all the lh->file_names[i].name pointers are
+     pointers into debug_line_buffer, and don't need to be freed.  */
+  if (lh->file_names)
+    xfree (lh->file_names);
+
+  /* Similarly for the include directory names.  */
+  if (lh->include_dirs)
+    xfree (lh->include_dirs);
+
+  xfree (lh);
+}
+
+
+/* Add an entry to LH's include directory table.  */
+static void
+add_include_dir (struct line_header *lh, char *include_dir)
 {
-  unsigned int num_files;
-  struct fileinfo
+  /* Grow the array if necessary.  */
+  if (lh->include_dirs_size == 0)
     {
-      char *name;
-      unsigned int dir;
-      unsigned int time;
-      unsigned int size;
+      lh->include_dirs_size = 1; /* for testing */
+      lh->include_dirs = xmalloc (lh->include_dirs_size
+                                  * sizeof (*lh->include_dirs));
+    }
+  else if (lh->num_include_dirs >= lh->include_dirs_size)
+    {
+      lh->include_dirs_size *= 2;
+      lh->include_dirs = xrealloc (lh->include_dirs,
+                                   (lh->include_dirs_size
+                                    * sizeof (*lh->include_dirs)));
     }
-   *files;
-};
 
-struct directories
-  {
-    unsigned int num_dirs;
-    char **dirs;
-  };
+  lh->include_dirs[lh->num_include_dirs++] = include_dir;
+}
 
+/* Add an entry to LH's file name table.  */
 static void
-dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
-                   const struct comp_unit_head *cu_header)
+add_file_name (struct line_header *lh,
+               char *name,
+               unsigned int dir_index,
+               unsigned int mod_time,
+               unsigned int length)
 {
-  char *line_ptr;
-  char *line_end;
-  struct line_head lh;
-  struct cleanup *back_to;
-  unsigned int i, bytes_read;
-  char *cur_file, *cur_dir;
-  unsigned char op_code, extended_op, adj_opcode;
+  struct file_entry *fe;
 
-#define FILE_ALLOC_CHUNK 5
-#define DIR_ALLOC_CHUNK 5
+  /* Grow the array if necessary.  */
+  if (lh->file_names_size == 0)
+    {
+      lh->file_names_size = 1; /* for testing */
+      lh->file_names = xmalloc (lh->file_names_size
+                                * sizeof (*lh->file_names));
+    }
+  else if (lh->num_file_names >= lh->file_names_size)
+    {
+      lh->file_names_size *= 2;
+      lh->file_names = xrealloc (lh->file_names,
+                                 (lh->file_names_size
+                                  * sizeof (*lh->file_names)));
+    }
 
-  struct filenames files;
-  struct directories dirs;
+  fe = &lh->file_names[lh->num_file_names++];
+  fe->name = name;
+  fe->dir_index = dir_index;
+  fe->mod_time = mod_time;
+  fe->length = length;
+}
+
+/* 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.
+
+   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 cleanup *back_to;
+  struct line_header *lh;
+  char *line_ptr;
+  int bytes_read;
+  int i;
+  char *cur_dir, *cur_file;
 
   if (dwarf_line_buffer == NULL)
     {
-      complain (&dwarf2_missing_line_number_section);
-      return;
+      complaint (&symfile_complaints, "missing .debug_line section");
+      return 0;
     }
 
-  files.num_files = 0;
-  files.files = NULL;
+  /* 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)
+    {
+      dwarf2_statement_list_fits_in_line_number_section_complaint ();
+      return 0;
+    }
 
-  dirs.num_dirs = 0;
-  dirs.dirs = NULL;
+  lh = xmalloc (sizeof (*lh));
+  memset (lh, 0, sizeof (*lh));
+  back_to = make_cleanup ((make_cleanup_ftype *) free_line_header,
+                          (void *) lh);
 
   line_ptr = dwarf_line_buffer + offset;
 
-  /* read in the prologue */
-  lh.total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
+  /* read in the header */
+  lh->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
   line_ptr += bytes_read;
-  line_end = line_ptr + lh.total_length;
-  lh.version = read_2_bytes (abfd, line_ptr);
+  if (line_ptr + lh->total_length > dwarf_line_buffer + dwarf_line_size)
+    {
+      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.prologue_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);
+  lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
-  lh.default_is_stmt = read_1_byte (abfd, line_ptr);
+  lh->default_is_stmt = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
-  lh.line_base = read_1_signed_byte (abfd, line_ptr);
+  lh->line_base = read_1_signed_byte (abfd, line_ptr);
   line_ptr += 1;
-  lh.line_range = read_1_byte (abfd, line_ptr);
+  lh->line_range = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
-  lh.opcode_base = read_1_byte (abfd, line_ptr);
+  lh->opcode_base = read_1_byte (abfd, line_ptr);
   line_ptr += 1;
-  lh.standard_opcode_lengths = (unsigned char *)
-    xmalloc (lh.opcode_base * sizeof (unsigned char));
-  back_to = make_cleanup (free_current_contents, &lh.standard_opcode_lengths);
+  lh->standard_opcode_lengths
+    = (unsigned char *) xmalloc (lh->opcode_base * sizeof (unsigned char));
 
-  lh.standard_opcode_lengths[0] = 1;
-  for (i = 1; i < lh.opcode_base; ++i)
+  lh->standard_opcode_lengths[0] = 1;  /* This should never be used anyway.  */
+  for (i = 1; i < lh->opcode_base; ++i)
     {
-      lh.standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
+      lh->standard_opcode_lengths[i] = read_1_byte (abfd, line_ptr);
       line_ptr += 1;
     }
 
@@ -3844,44 +4896,98 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
   while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
     {
       line_ptr += bytes_read;
-      if ((dirs.num_dirs % DIR_ALLOC_CHUNK) == 0)
-       {
-         dirs.dirs = (char **)
-           xrealloc (dirs.dirs,
-                     (dirs.num_dirs + DIR_ALLOC_CHUNK) * sizeof (char *));
-         if (dirs.num_dirs == 0)
-           make_cleanup (free_current_contents, &dirs.dirs);
-       }
-      dirs.dirs[dirs.num_dirs++] = cur_dir;
+      add_include_dir (lh, cur_dir);
     }
   line_ptr += bytes_read;
 
   /* Read file name table */
   while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
     {
+      unsigned int dir_index, mod_time, length;
+
       line_ptr += bytes_read;
-      if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
-       {
-         files.files = (struct fileinfo *)
-           xrealloc (files.files,
-                     (files.num_files + FILE_ALLOC_CHUNK)
-                     * sizeof (struct fileinfo));
-         if (files.num_files == 0)
-           make_cleanup (free_current_contents, &files.files);
-       }
-      files.files[files.num_files].name = cur_file;
-      files.files[files.num_files].dir =
-       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
       line_ptr += bytes_read;
-      files.files[files.num_files].time =
-       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
       line_ptr += bytes_read;
-      files.files[files.num_files].size =
-       read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+      length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
       line_ptr += bytes_read;
-      files.num_files++;
+
+      add_file_name (lh, cur_file, dir_index, mod_time, length);
     }
   line_ptr += bytes_read;
+  lh->statement_program_start = line_ptr; 
+
+  if (line_ptr > dwarf_line_buffer + dwarf_line_size)
+    complaint (&symfile_complaints,
+              "line number info header doesn't fit in `.debug_line' section");
+
+  discard_cleanups (back_to);
+  return lh;
+}
+
+/* This function exists to work around a bug in certain compilers
+   (particularly GCC 2.95), in which the first line number marker of a
+   function does not show up until after the prologue, right before
+   the second line number marker.  This function shifts ADDRESS down
+   to the beginning of the function if necessary, and is called on
+   addresses passed to record_line.  */
+
+static CORE_ADDR
+check_cu_functions (CORE_ADDR address)
+{
+  struct function_range *fn;
+
+  /* Find the function_range containing address.  */
+  if (!cu_first_fn)
+    return address;
+
+  if (!cu_cached_fn)
+    cu_cached_fn = cu_first_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)
+    if (fn->lowpc <= address && fn->highpc > address)
+      goto found;
+    else
+      fn = fn->next;
+
+  return address;
+
+ found:
+  if (fn->seen_line)
+    return address;
+  if (address != fn->lowpc)
+    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.  */
+
+static void
+dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
+                   const struct comp_unit_head *cu_header)
+{
+  char *line_ptr;
+  char *line_end;
+  unsigned int i, bytes_read;
+  char *cur_dir;
+  unsigned char op_code, extended_op, adj_opcode;
+
+  line_ptr = lh->statement_program_start;
+  line_end = lh->statement_program_end;
 
   /* Read the statement sequences until there's nothing left.  */
   while (line_ptr < line_end)
@@ -3891,19 +4997,23 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
       unsigned int file = 1;
       unsigned int line = 1;
       unsigned int column = 0;
-      int is_stmt = lh.default_is_stmt;
+      int is_stmt = lh->default_is_stmt;
       int basic_block = 0;
       int end_sequence = 0;
 
       /* Start a subfile for the current file of the state machine.  */
-      if (files.num_files >= file)
+      if (lh->num_file_names >= file)
        {
-         /* The file and directory tables are 0 based, the references
-            are 1 based.  */
-         dwarf2_start_subfile (files.files[file - 1].name,
-                               (files.files[file - 1].dir
-                                ? dirs.dirs[files.files[file - 1].dir - 1]
-                                : comp_dir));
+         /* lh->include_dirs and lh->file_names are 0-based, but the
+            directory and file name numbers in the statement program
+            are 1-based.  */
+          struct file_entry *fe = &lh->file_names[file - 1];
+          char *dir;
+          if (fe->dir_index)
+            dir = lh->include_dirs[fe->dir_index - 1];
+          else
+            dir = comp_dir;
+         dwarf2_start_subfile (fe->name, dir);
        }
 
       /* Decode the table. */
@@ -3911,7 +5021,19 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
        {
          op_code = read_1_byte (abfd, line_ptr);
          line_ptr += 1;
-         switch (op_code)
+
+         if (op_code >= lh->opcode_base)
+           {           /* Special operand.  */
+             adj_opcode = op_code - lh->opcode_base;
+             address += (adj_opcode / lh->line_range)
+               * lh->minimum_instruction_length;
+             line += lh->line_base + (adj_opcode % lh->line_range);
+             /* append row to matrix using current values */
+             record_line (current_subfile, line, 
+                          check_cu_functions (address));
+             basic_block = 1;
+           }
+         else switch (op_code)
            {
            case DW_LNS_extended_op:
              line_ptr += 1;    /* ignore length */
@@ -3921,12 +5043,7 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
                {
                case DW_LNE_end_sequence:
                  end_sequence = 1;
-                 /* Don't call record_line here.  The end_sequence
-                    instruction provides the address of the first byte
-                    *after* the last line in the sequence; it's not the
-                    address of any real source line.  However, the GDB
-                    linetable structure only records the starts of lines,
-                    not the ends.  This is a weakness of GDB.  */
+                 record_line (current_subfile, 0, address);
                  break;
                case DW_LNE_set_address:
                  address = read_address (abfd, line_ptr, cu_header, &bytes_read);
@@ -3934,40 +5051,37 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
                  address += baseaddr;
                  break;
                case DW_LNE_define_file:
-                 cur_file = read_string (abfd, line_ptr, &bytes_read);
-                 line_ptr += bytes_read;
-                 if ((files.num_files % FILE_ALLOC_CHUNK) == 0)
-                   {
-                     files.files = (struct fileinfo *)
-                       xrealloc (files.files,
-                                 (files.num_files + FILE_ALLOC_CHUNK)
-                                 * sizeof (struct fileinfo));
-                     if (files.num_files == 0)
-                       make_cleanup (free_current_contents, &files.files);
-                   }
-                 files.files[files.num_files].name = cur_file;
-                 files.files[files.num_files].dir =
-                   read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-                 line_ptr += bytes_read;
-                 files.files[files.num_files].time =
-                   read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-                 line_ptr += bytes_read;
-                 files.files[files.num_files].size =
-                   read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-                 line_ptr += bytes_read;
-                 files.num_files++;
+                  {
+                    char *cur_file;
+                    unsigned int dir_index, mod_time, length;
+                    
+                    cur_file = read_string (abfd, line_ptr, &bytes_read);
+                    line_ptr += bytes_read;
+                    dir_index =
+                      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                    line_ptr += bytes_read;
+                    mod_time =
+                      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                    line_ptr += bytes_read;
+                    length =
+                      read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                    line_ptr += bytes_read;
+                    add_file_name (lh, cur_file, dir_index, mod_time, length);
+                  }
                  break;
                default:
-                 complain (&dwarf2_mangled_line_number_section);
-                 goto done;
+                 complaint (&symfile_complaints,
+                            "mangled .debug_line section");
+                 return;
                }
              break;
            case DW_LNS_copy:
-             record_line (current_subfile, line, address);
+             record_line (current_subfile, line, 
+                          check_cu_functions (address));
              basic_block = 0;
              break;
            case DW_LNS_advance_pc:
-             address += lh.minimum_instruction_length
+             address += lh->minimum_instruction_length
                * read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
              line_ptr += bytes_read;
              break;
@@ -3976,15 +5090,21 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
              line_ptr += bytes_read;
              break;
            case DW_LNS_set_file:
-             /* The file and directory tables are 0 based, the references
-                are 1 based.  */
-             file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
-             line_ptr += bytes_read;
-             dwarf2_start_subfile
-               (files.files[file - 1].name,
-                (files.files[file - 1].dir
-                 ? dirs.dirs[files.files[file - 1].dir - 1]
-                 : comp_dir));
+              {
+                /* lh->include_dirs and lh->file_names are 0-based,
+                   but the directory and file name numbers in the
+                   statement program are 1-based.  */
+                struct file_entry *fe;
+                char *dir;
+                file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                line_ptr += bytes_read;
+                fe = &lh->file_names[file - 1];
+                if (fe->dir_index)
+                  dir = lh->include_dirs[fe->dir_index - 1];
+                else
+                  dir = comp_dir;
+                dwarf2_start_subfile (fe->name, dir);
+              }
              break;
            case DW_LNS_set_column:
              column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
@@ -4002,26 +5122,25 @@ dwarf_decode_lines (unsigned int offset, char *comp_dir, bfd *abfd,
               length since special opcode 255 would have scaled the
               the increment.  */
            case DW_LNS_const_add_pc:
-             address += (lh.minimum_instruction_length
-                         * ((255 - lh.opcode_base) / lh.line_range));
+             address += (lh->minimum_instruction_length
+                         * ((255 - lh->opcode_base) / lh->line_range));
              break;
            case DW_LNS_fixed_advance_pc:
              address += read_2_bytes (abfd, line_ptr);
              line_ptr += 2;
              break;
-           default:            /* special operand */
-             adj_opcode = op_code - lh.opcode_base;
-             address += (adj_opcode / lh.line_range)
-               * lh.minimum_instruction_length;
-             line += lh.line_base + (adj_opcode % lh.line_range);
-             /* append row to matrix using current values */
-             record_line (current_subfile, line, address);
-             basic_block = 1;
+           default:
+             {  /* Unknown standard opcode, ignore it.  */
+               int i;
+               for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++)
+                 {
+                   (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+                   line_ptr += bytes_read;
+                 }
+             }
            }
        }
     }
-done:
-  do_cleanups (back_to);
 }
 
 /* Start a subfile for DWARF.  FILENAME is the name of the file and
@@ -4050,25 +5169,80 @@ dwarf2_start_subfile (char *filename, char *dirname)
   /* If the filename isn't absolute, try to match an existing subfile
      with the full pathname.  */
 
-  if (*filename != '/' && dirname != NULL)
+  if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL)
     {
       struct subfile *subfile;
       char *fullname = concat (dirname, "/", filename, NULL);
 
       for (subfile = subfiles; subfile; subfile = subfile->next)
        {
-         if (STREQ (subfile->name, fullname))
+         if (FILENAME_CMP (subfile->name, fullname) == 0)
            {
              current_subfile = subfile;
-             free (fullname);
+             xfree (fullname);
              return;
            }
        }
-      free (fullname);
+      xfree (fullname);
     }
   start_subfile (filename, dirname);
 }
 
+static void
+var_decode_location (struct attribute *attr, struct symbol *sym,
+                    struct objfile *objfile,
+                    const struct comp_unit_head *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_header,
+                     &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_header, objfile);
+  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.
@@ -4083,21 +5257,27 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
   char *name;
   struct attribute *attr = NULL;
   struct attribute *attr2 = NULL;
-  CORE_ADDR addr;
+  CORE_ADDR addr = 0;
+
+  if (die->tag != DW_TAG_namespace)
+    name = dwarf2_linkage_name (die);
+  else
+    name = TYPE_NAME (type);
 
-  name = dwarf2_linkage_name (die);
   if (name)
     {
       sym = (struct symbol *) obstack_alloc (&objfile->symbol_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;
@@ -4108,15 +5288,6 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
        {
          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:
@@ -4164,62 +5335,12 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
          attr = dwarf_attr (die, DW_AT_location);
          if (attr)
            {
+             var_decode_location (attr, sym, objfile, cu_header);
              attr2 = dwarf_attr (die, DW_AT_external);
              if (attr2 && (DW_UNSND (attr2) != 0))
-               {
-                 SYMBOL_VALUE_ADDRESS (sym) =
-                   decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
-                 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
-               {
-                 SYMBOL_VALUE (sym) = addr =
-                   decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
-                 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;
-                   }
-                 else if (offreg)
-                   {
-                     SYMBOL_CLASS (sym) = LOC_BASEREG;
-                     SYMBOL_BASEREG (sym) = 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, list_in_scope);
            }
          else
            {
@@ -4242,30 +5363,10 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
          attr = dwarf_attr (die, DW_AT_location);
          if (attr)
            {
-             SYMBOL_VALUE (sym) =
-               decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
-             if (isreg)
-               {
-                 SYMBOL_CLASS (sym) = LOC_REGPARM;
-               }
-             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) = basereg;
-                   }
-               }
-             else
-               {
-                 SYMBOL_CLASS (sym) = LOC_ARG;
-               }
+             var_decode_location (attr, sym, objfile, cu_header);
+             /* 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);
          if (attr)
@@ -4284,7 +5385,7 @@ 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;
+         SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
          add_symbol_to_list (sym, list_in_scope);
 
          /* The semantics of C++ state that "struct foo { ... }" also
@@ -4296,11 +5397,11 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
              obstack_alloc (&objfile->symbol_obstack,
                             sizeof (struct symbol));
              *typedef_sym = *sym;
-             SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
+             SYMBOL_DOMAIN (typedef_sym) = VAR_DOMAIN;
              if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
                TYPE_NAME (SYMBOL_TYPE (sym)) =
-                 obsavestring (SYMBOL_NAME (sym),
-                               strlen (SYMBOL_NAME (sym)),
+                 obsavestring (DEPRECATED_SYMBOL_NAME (sym),
+                               strlen (DEPRECATED_SYMBOL_NAME (sym)),
                                &objfile->type_obstack);
              add_symbol_to_list (typedef_sym, list_in_scope);
            }
@@ -4308,7 +5409,7 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
        case DW_TAG_typedef:
        case DW_TAG_base_type:
          SYMBOL_CLASS (sym) = LOC_TYPEDEF;
-         SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+         SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
          add_symbol_to_list (sym, list_in_scope);
          break;
        case DW_TAG_enumerator:
@@ -4319,12 +5420,17 @@ new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
            }
          add_symbol_to_list (sym, list_in_scope);
          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;
        }
     }
@@ -4344,12 +5450,16 @@ dwarf2_const_value (struct attribute *attr, struct symbol *sym,
     {
     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));
+      /* 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:
@@ -4358,8 +5468,10 @@ 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);
       memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size);
@@ -4395,8 +5507,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;
@@ -4449,7 +5562,8 @@ die_type (struct die_info *die, struct objfile *objfile,
       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, objfile->name);
          return NULL;
        }
     }
@@ -4457,7 +5571,8 @@ die_type (struct die_info *die, struct objfile *objfile,
   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]",
+                     objfile->name);
     }
   return type;
 }
@@ -4481,7 +5596,8 @@ die_containing_type (struct die_info *die, struct objfile *objfile,
       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, 
+                         objfile->name);
          return NULL;
        }
       type = tag_type_to_type (type_die, objfile, cu_header);
@@ -4490,7 +5606,8 @@ die_containing_type (struct die_info *die, struct objfile *objfile,
     {
       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]", 
+                     objfile->name);
     }
   return type;
 }
@@ -4527,7 +5644,8 @@ tag_type_to_type (struct die_info *die, struct objfile *objfile,
       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]", 
+                         objfile->name);
        }
       return die->type;
     }
@@ -4579,7 +5697,8 @@ read_type_die (struct die_info *die, struct objfile *objfile,
       read_base_type (die, objfile);
       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;
     }
 }
@@ -4695,7 +5814,7 @@ copy_die (struct die_info *old_die)
 
 /* Return sibling of die, NULL if no sibling.  */
 
-struct die_info *
+static struct die_info *
 sibling_die (struct die_info *die)
 {
   int nesting_level = 0;
@@ -4753,10 +5872,47 @@ dwarf2_linkage_name (struct die_info *die)
   return NULL;
 }
 
+/* Get name of a die, return NULL if not found.  */
+
+static char *
+dwarf2_name (struct die_info *die)
+{
+  struct attribute *attr;
+
+  attr = dwarf_attr (die, DW_AT_name);
+  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 attribute *attr;
+  struct die_info *extension_die;
+  unsigned int ref;
+
+  attr = dwarf_attr (die, DW_AT_extension);
+  if (attr == NULL)
+    return NULL;
+
+  ref = dwarf2_get_ref_die_offset (attr);
+  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)
     {
@@ -4856,6 +6012,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:
@@ -4872,7 +6044,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)
     {
@@ -5000,7 +6172,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";
@@ -5014,9 +6209,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";
@@ -5030,6 +6225,8 @@ dwarf_attr_name (register unsigned attr)
       return "DW_AT_body_begin";
     case DW_AT_body_end:
       return "DW_AT_body_end";
+    case DW_AT_GNU_vector:
+      return "DW_AT_GNU_vector";
     default:
       return "DW_AT_<unknown>";
     }
@@ -5038,7 +6235,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)
     {
@@ -5092,7 +6289,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)
     {
@@ -5386,6 +6583,18 @@ dwarf_stack_op_name (register unsigned op)
       return "DW_OP_xderef_size";
     case DW_OP_nop:
       return "DW_OP_nop";
+      /* DWARF 3 extensions.  */
+    case DW_OP_push_object_address:
+      return "DW_OP_push_object_address";
+    case DW_OP_call2:
+      return "DW_OP_call2";
+    case DW_OP_call4:
+      return "DW_OP_call4";
+    case DW_OP_call_ref:
+      return "DW_OP_call_ref";
+      /* GNU extensions.  */
+    case DW_OP_GNU_push_tls_address:
+      return "DW_OP_GNU_push_tls_address";
     default:
       return "OP_<unknown>";
     }
@@ -5403,7 +6612,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)
     {
@@ -5423,6 +6632,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>";
     }
@@ -5432,7 +6643,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)
     {
@@ -5472,43 +6683,65 @@ dwarf_cfi_name (register unsigned cfi_opc)
       return "DW_CFA_def_cfa_register";
     case DW_CFA_def_cfa_offset:
       return "DW_CFA_def_cfa_offset";
+
+    /* DWARF 3 */
+    case DW_CFA_def_cfa_expression:
+      return "DW_CFA_def_cfa_expression";
+    case DW_CFA_expression:
+      return "DW_CFA_expression";
+    case DW_CFA_offset_extended_sf:
+      return "DW_CFA_offset_extended_sf";
+    case DW_CFA_def_cfa_sf:
+      return "DW_CFA_def_cfa_sf";
+    case DW_CFA_def_cfa_offset_sf:
+      return "DW_CFA_def_cfa_offset_sf";
+
       /* SGI/MIPS specific */
     case DW_CFA_MIPS_advance_loc8:
       return "DW_CFA_MIPS_advance_loc8";
+
+    /* GNU extensions */
+    case DW_CFA_GNU_window_save:
+      return "DW_CFA_GNU_window_save";
+    case DW_CFA_GNU_args_size:
+      return "DW_CFA_GNU_args_size";
+    case DW_CFA_GNU_negative_offset_extended:
+      return "DW_CFA_GNU_negative_offset_extended";
+
     default:
       return "DW_CFA_<unknown>";
     }
 }
 #endif
 
-void
+static void
 dump_die (struct die_info *die)
 {
   unsigned int i;
 
-  fprintf (stderr, "Die: %s (abbrev = %d, offset = %d)\n",
+  fprintf_unfiltered (gdb_stderr, "Die: %s (abbrev = %d, offset = %d)\n",
           dwarf_tag_name (die->tag), die->abbrev, die->offset);
-  fprintf (stderr, "\thas children: %s\n",
+  fprintf_unfiltered (gdb_stderr, "\thas children: %s\n",
           dwarf_bool_name (die->has_children));
 
-  fprintf (stderr, "\tattributes:\n");
+  fprintf_unfiltered (gdb_stderr, "\tattributes:\n");
   for (i = 0; i < die->num_attrs; ++i)
     {
-      fprintf (stderr, "\t\t%s (%s) ",
+      fprintf_unfiltered (gdb_stderr, "\t\t%s (%s) ",
               dwarf_attr_name (die->attrs[i].name),
               dwarf_form_name (die->attrs[i].form));
       switch (die->attrs[i].form)
        {
        case DW_FORM_ref_addr:
        case DW_FORM_addr:
-         fprintf (stderr, "address: ");
+         fprintf_unfiltered (gdb_stderr, "address: ");
          print_address_numeric (DW_ADDR (&die->attrs[i]), 1, gdb_stderr);
          break;
        case DW_FORM_block2:
        case DW_FORM_block4:
        case DW_FORM_block:
        case DW_FORM_block1:
-         fprintf (stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
+         fprintf_unfiltered (gdb_stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
          break;
        case DW_FORM_data1:
        case DW_FORM_data2:
@@ -5519,31 +6752,34 @@ dump_die (struct die_info *die)
        case DW_FORM_ref4:
        case DW_FORM_udata:
        case DW_FORM_sdata:
-         fprintf (stderr, "constant: %ld", DW_UNSND (&die->attrs[i]));
+         fprintf_unfiltered (gdb_stderr, "constant: %ld", DW_UNSND (&die->attrs[i]));
          break;
        case DW_FORM_string:
-         fprintf (stderr, "string: \"%s\"",
+       case DW_FORM_strp:
+         fprintf_unfiltered (gdb_stderr, "string: \"%s\"",
                   DW_STRING (&die->attrs[i])
                   ? DW_STRING (&die->attrs[i]) : "");
          break;
        case DW_FORM_flag:
          if (DW_UNSND (&die->attrs[i]))
-           fprintf (stderr, "flag: TRUE");
+           fprintf_unfiltered (gdb_stderr, "flag: TRUE");
          else
-           fprintf (stderr, "flag: FALSE");
+           fprintf_unfiltered (gdb_stderr, "flag: FALSE");
+         break;
+       case DW_FORM_indirect:
+         /* the reader will have reduced the indirect form to
+            the "base form" so this form should not occur */
+         fprintf_unfiltered (gdb_stderr, "unexpected attribute form: DW_FORM_indirect");
          break;
-       case DW_FORM_strp:      /* we do not support separate string
-                                  section yet */
-       case DW_FORM_indirect:  /* we do not handle indirect yet */
        default:
-         fprintf (stderr, "unsupported attribute form: %d.",
+         fprintf_unfiltered (gdb_stderr, "unsupported attribute form: %d.",
                   die->attrs[i].form);
        }
-      fprintf (stderr, "\n");
+      fprintf_unfiltered (gdb_stderr, "\n");
     }
 }
 
-void
+static void
 dump_die_list (struct die_info *die)
 {
   while (die)
@@ -5553,7 +6789,7 @@ dump_die_list (struct die_info *die)
     }
 }
 
-void
+static void
 store_in_ref_table (unsigned int offset, struct die_info *die)
 {
   int h;
@@ -5590,12 +6826,14 @@ dwarf2_get_ref_die_offset (struct attribute *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;
 }
 
-struct die_info *
+static struct die_info *
 follow_die_ref (unsigned int offset)
 {
   struct die_info *die;
@@ -5619,8 +6857,8 @@ dwarf2_fundamental_type (struct objfile *objfile, int typeid)
 {
   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
@@ -5690,6 +6928,41 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
       op = data[i++];
       switch (op)
        {
+       case DW_OP_lit0:
+       case DW_OP_lit1:
+       case DW_OP_lit2:
+       case DW_OP_lit3:
+       case DW_OP_lit4:
+       case DW_OP_lit5:
+       case DW_OP_lit6:
+       case DW_OP_lit7:
+       case DW_OP_lit8:
+       case DW_OP_lit9:
+       case DW_OP_lit10:
+       case DW_OP_lit11:
+       case DW_OP_lit12:
+       case DW_OP_lit13:
+       case DW_OP_lit14:
+       case DW_OP_lit15:
+       case DW_OP_lit16:
+       case DW_OP_lit17:
+       case DW_OP_lit18:
+       case DW_OP_lit19:
+       case DW_OP_lit20:
+       case DW_OP_lit21:
+       case DW_OP_lit22:
+       case DW_OP_lit23:
+       case DW_OP_lit24:
+       case DW_OP_lit25:
+       case DW_OP_lit26:
+       case DW_OP_lit27:
+       case DW_OP_lit28:
+       case DW_OP_lit29:
+       case DW_OP_lit30:
+       case DW_OP_lit31:
+         stack[++stacki] = op - DW_OP_lit0;
+         break;
+
        case DW_OP_reg0:
        case DW_OP_reg1:
        case DW_OP_reg2:
@@ -5730,12 +7003,6 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
          isreg = 1;
          unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
          i += bytes_read;
-#if defined(HARRIS_TARGET) && defined(_M88K)
-         /* The Harris 88110 gdb ports have long kept their special reg
-            numbers between their gp-regs and their x-regs.  This is
-            not how our dwarf is generated.  Punt. */
-         unsnd += 6;
-#endif
          stack[++stacki] = unsnd;
          break;
 
@@ -5796,7 +7063,8 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
            }
          else
            {
-             complain (&dwarf2_missing_at_frame_base);
+             complaint (&symfile_complaints,
+                        "DW_AT_frame_base missing for DW_OP_fbreg");
              islocal = 1;
            }
          break;
@@ -5848,6 +7116,11 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
          i += bytes_read;
          break;
 
+       case DW_OP_dup:
+         stack[stacki + 1] = stack[stacki];
+         stacki++;
+         break;
+
        case DW_OP_plus:
          stack[stacki - 1] += stack[stacki];
          stacki--;
@@ -5859,7 +7132,7 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
          break;
 
        case DW_OP_minus:
-         stack[stacki - 1] = stack[stacki] - stack[stacki - 1];
+         stack[stacki - 1] -= stack[stacki];
          stacki--;
          break;
 
@@ -5868,11 +7141,21 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
          /* If we're not the last op, then we definitely can't encode
             this using GDB's address_class enum.  */
          if (i < size)
-           complain (&dwarf2_complex_location_expr);
+           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.  */
+         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]);
        }
     }
@@ -5883,7 +7166,7 @@ decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
 
 /* ARGSUSED */
 static void
-dwarf2_free_tmp_obstack (PTR ignore)
+dwarf2_free_tmp_obstack (void *ignore)
 {
   obstack_free (&dwarf2_tmp_obstack, NULL);
 }
@@ -5917,3 +7200,448 @@ dwarf_alloc_die (void)
   memset (die, 0, sizeof (struct die_info));
   return (die);
 }
+
+\f
+/* Macro support.  */
+
+
+/* Return the full name of file number I in *LH's file name table.
+   Use COMP_DIR as the name of the current directory of the
+   compilation.  The result is allocated using xmalloc; the caller is
+   responsible for freeing it.  */
+static char *
+file_full_name (int file, struct line_header *lh, const char *comp_dir)
+{
+  struct file_entry *fe = &lh->file_names[file - 1];
+  
+  if (IS_ABSOLUTE_PATH (fe->name))
+    return xstrdup (fe->name);
+  else
+    {
+      const char *dir;
+      int dir_len;
+      char *full_name;
+
+      if (fe->dir_index)
+        dir = lh->include_dirs[fe->dir_index - 1];
+      else
+        dir = comp_dir;
+
+      if (dir)
+        {
+          dir_len = strlen (dir);
+          full_name = xmalloc (dir_len + 1 + strlen (fe->name) + 1);
+          strcpy (full_name, dir);
+          full_name[dir_len] = '/';
+          strcpy (full_name + dir_len + 1, fe->name);
+          return full_name;
+        }
+      else
+        return xstrdup (fe->name);
+    }
+}
+
+
+static struct macro_source_file *
+macro_start_file (int file, int line,
+                  struct macro_source_file *current_file,
+                  const char *comp_dir,
+                  struct line_header *lh, struct objfile *objfile)
+{
+  /* The full name of this source file.  */
+  char *full_name = file_full_name (file, lh, comp_dir);
+
+  /* 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,
+                                      objfile->macro_cache);
+
+  if (! current_file)
+    /* If we have no current file, then this must be the start_file
+       directive for the compilation unit's main source file.  */
+    current_file = macro_set_main (pending_macros, full_name);
+  else
+    current_file = macro_include (current_file, line, full_name);
+
+  xfree (full_name);
+              
+  return current_file;
+}
+
+
+/* Copy the LEN characters at BUF to a xmalloc'ed block of memory,
+   followed by a null byte.  */
+static char *
+copy_string (const char *buf, int len)
+{
+  char *s = xmalloc (len + 1);
+  memcpy (s, buf, len);
+  s[len] = '\0';
+
+  return s;
+}
+
+
+static const char *
+consume_improper_spaces (const char *p, const char *body)
+{
+  if (*p == ' ')
+    {
+      complaint (&symfile_complaints,
+                "macro definition contains spaces in formal argument list:\n`%s'",
+                body);
+
+      while (*p == ' ')
+        p++;
+    }
+
+  return p;
+}
+
+
+static void
+parse_macro_definition (struct macro_source_file *file, int line,
+                        const char *body)
+{
+  const char *p;
+
+  /* The body string takes one of two forms.  For object-like macro
+     definitions, it should be:
+
+        <macro name> " " <definition>
+
+     For function-like macro definitions, it should be:
+
+        <macro name> "() " <definition>
+     or
+        <macro name> "(" <arg name> ( "," <arg name> ) * ") " <definition>
+
+     Spaces may appear only where explicitly indicated, and in the
+     <definition>.
+
+     The Dwarf 2 spec says that an object-like macro's name is always
+     followed by a space, but versions of GCC around March 2002 omit
+     the space when the macro's definition is the empty string. 
+
+     The Dwarf 2 spec says that there should be no spaces between the
+     formal arguments in a function-like macro's formal argument list,
+     but versions of GCC around March 2002 include spaces after the
+     commas.  */
+
+
+  /* Find the extent of the macro name.  The macro name is terminated
+     by either a space or null character (for an object-like macro) or
+     an opening paren (for a function-like macro).  */
+  for (p = body; *p; p++)
+    if (*p == ' ' || *p == '(')
+      break;
+
+  if (*p == ' ' || *p == '\0')
+    {
+      /* It's an object-like macro.  */
+      int name_len = p - body;
+      char *name = copy_string (body, name_len);
+      const char *replacement;
+
+      if (*p == ' ')
+        replacement = body + name_len + 1;
+      else
+        {
+         dwarf2_macro_malformed_definition_complaint (body);
+          replacement = body + name_len;
+        }
+      
+      macro_define_object (file, line, name, replacement);
+
+      xfree (name);
+    }
+  else if (*p == '(')
+    {
+      /* It's a function-like macro.  */
+      char *name = copy_string (body, p - body);
+      int argc = 0;
+      int argv_size = 1;
+      char **argv = xmalloc (argv_size * sizeof (*argv));
+
+      p++;
+
+      p = consume_improper_spaces (p, body);
+
+      /* Parse the formal argument list.  */
+      while (*p && *p != ')')
+        {
+          /* Find the extent of the current argument name.  */
+          const char *arg_start = p;
+
+          while (*p && *p != ',' && *p != ')' && *p != ' ')
+            p++;
+
+          if (! *p || p == arg_start)
+           dwarf2_macro_malformed_definition_complaint (body);
+          else
+            {
+              /* Make sure argv has room for the new argument.  */
+              if (argc >= argv_size)
+                {
+                  argv_size *= 2;
+                  argv = xrealloc (argv, argv_size * sizeof (*argv));
+                }
+
+              argv[argc++] = copy_string (arg_start, p - arg_start);
+            }
+
+          p = consume_improper_spaces (p, body);
+
+          /* Consume the comma, if present.  */
+          if (*p == ',')
+            {
+              p++;
+
+              p = consume_improper_spaces (p, body);
+            }
+        }
+
+      if (*p == ')')
+        {
+          p++;
+
+          if (*p == ' ')
+            /* Perfectly formed definition, no complaints.  */
+            macro_define_function (file, line, name,
+                                   argc, (const char **) argv, 
+                                   p + 1);
+          else if (*p == '\0')
+            {
+              /* Complain, but do define it.  */
+             dwarf2_macro_malformed_definition_complaint (body);
+              macro_define_function (file, line, name,
+                                     argc, (const char **) argv, 
+                                     p);
+            }
+          else
+            /* Just complain.  */
+           dwarf2_macro_malformed_definition_complaint (body);
+        }
+      else
+        /* Just complain.  */
+       dwarf2_macro_malformed_definition_complaint (body);
+
+      xfree (name);
+      {
+        int i;
+
+        for (i = 0; i < argc; i++)
+          xfree (argv[i]);
+      }
+      xfree (argv);
+    }
+  else
+    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)
+{
+  char *mac_ptr, *mac_end;
+  struct macro_source_file *current_file = 0;
+
+  if (dwarf_macinfo_buffer == NULL)
+    {
+      complaint (&symfile_complaints, "missing .debug_macinfo section");
+      return;
+    }
+
+  mac_ptr = dwarf_macinfo_buffer + offset;
+  mac_end = dwarf_macinfo_buffer + dwarf_macinfo_size;
+
+  for (;;)
+    {
+      enum dwarf_macinfo_record_type macinfo_type;
+
+      /* Do we at least have room for a macinfo type byte?  */
+      if (mac_ptr >= mac_end)
+        {
+         dwarf2_macros_too_long_complaint ();
+          return;
+        }
+
+      macinfo_type = read_1_byte (abfd, mac_ptr);
+      mac_ptr++;
+
+      switch (macinfo_type)
+        {
+          /* A zero macinfo type indicates the end of the macro
+             information.  */
+        case 0:
+          return;
+
+        case DW_MACINFO_define:
+        case DW_MACINFO_undef:
+          {
+            int bytes_read;
+            int line;
+            char *body;
+
+            line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+            mac_ptr += bytes_read;
+            body = read_string (abfd, mac_ptr, &bytes_read);
+            mac_ptr += bytes_read;
+
+            if (! current_file)
+             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)
+                  parse_macro_definition (current_file, line, body);
+                else if (macinfo_type == DW_MACINFO_undef)
+                  macro_undef (current_file, line, body);
+              }
+          }
+          break;
+
+        case DW_MACINFO_start_file:
+          {
+            int bytes_read;
+            int line, file;
+
+            line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+            mac_ptr += bytes_read;
+            file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+            mac_ptr += bytes_read;
+
+            current_file = macro_start_file (file, line,
+                                             current_file, comp_dir,
+                                             lh, objfile);
+          }
+          break;
+
+        case DW_MACINFO_end_file:
+          if (! current_file)
+           complaint (&symfile_complaints,
+                      "macro debug info has an unmatched `close_file' directive");
+          else
+            {
+              current_file = current_file->included_by;
+              if (! current_file)
+                {
+                  enum dwarf_macinfo_record_type next_type;
+
+                  /* GCC circa March 2002 doesn't produce the zero
+                     type byte marking the end of the compilation
+                     unit.  Complain if it's not there, but exit no
+                     matter what.  */
+
+                  /* Do we at least have room for a macinfo type byte?  */
+                  if (mac_ptr >= mac_end)
+                    {
+                     dwarf2_macros_too_long_complaint ();
+                      return;
+                    }
+
+                  /* We don't increment mac_ptr here, so this is just
+                     a look-ahead.  */
+                  next_type = read_1_byte (abfd, mac_ptr);
+                  if (next_type != 0)
+                   complaint (&symfile_complaints,
+                              "no terminating 0-type entry for macros in `.debug_macinfo' section");
+
+                  return;
+                }
+            }
+          break;
+
+        case DW_MACINFO_vendor_ext:
+          {
+            int bytes_read;
+            int constant;
+            char *string;
+
+            constant = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
+            mac_ptr += bytes_read;
+            string = read_string (abfd, mac_ptr, &bytes_read);
+            mac_ptr += bytes_read;
+
+            /* We don't recognize any vendor extensions.  */
+          }
+          break;
+        }
+    }
+}
+
+/* Check if the attribute's form is a DW_FORM_block*
+   if so return true else false. */
+static int
+attr_form_is_block (struct attribute *attr)
+{
+  return (attr == NULL ? 0 :
+      attr->form == DW_FORM_block1
+      || attr->form == DW_FORM_block2
+      || attr->form == DW_FORM_block4
+      || attr->form == DW_FORM_block);
+}
+
+static void
+dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+                            const struct comp_unit_head *cu_header,
+                            struct objfile *objfile)
+{
+  if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+    {
+      struct dwarf2_loclist_baton *baton;
+
+      baton = obstack_alloc (&objfile->symbol_obstack,
+                            sizeof (struct dwarf2_loclist_baton));
+      baton->objfile = 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 = dwarf_loc_size - DW_UNSND (attr);
+      baton->data = dwarf_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_LOCATION_FUNCS (sym) = &dwarf2_loclist_funcs;
+      SYMBOL_LOCATION_BATON (sym) = baton;
+    }
+  else
+    {
+      struct dwarf2_locexpr_baton *baton;
+
+      baton = obstack_alloc (&objfile->symbol_obstack,
+                            sizeof (struct dwarf2_locexpr_baton));
+      baton->objfile = 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
+            dwarf_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_LOCATION_FUNCS (sym) = &dwarf2_locexpr_funcs;
+      SYMBOL_LOCATION_BATON (sym) = baton;
+    }
+}
This page took 0.07992 seconds and 4 git commands to generate.