/* DWARF 2 debugging format support for GDB.
- Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
#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"
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_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 */
#define INFO_SECTION ".debug_info"
#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"
/* 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;
};
+/* Internal state when decoding a particular compilation unit. */
+struct dwarf2_cu
+{
+ /* The objfile containing this compilation unit. */
+ struct objfile *objfile;
+
+ /* The header of the compilation unit.
+
+ FIXME drow/2003-11-10: Some of the things from the comp_unit_head
+ should be moved to the dwarf2_cu structure; for instance the abbrevs
+ hash table. */
+ struct comp_unit_head header;
+};
+
/* 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 die_info
{
enum dwarf_tag tag; /* Tag indicating type of die */
- unsigned short has_children; /* Does the die have children */
unsigned int abbrev; /* Abbrev number */
unsigned int offset; /* Offset in .debug_info section */
unsigned int num_attrs; /* Number of attributes */
struct attribute *attrs; /* An array of attributes */
struct die_info *next_ref; /* Next die in ref hash table */
- struct die_info *next; /* Next die in linked list */
+
+ /* The dies in a compilation unit form an n-ary tree. PARENT
+ points to this die's parent; CHILD points to the first child of
+ this node; and all the children of a given node are chained
+ together via their SIBLING fields, terminated by a die whose
+ tag is zero. */
+ struct die_info *child; /* Its first child, if any. */
+ struct die_info *sibling; /* Its next sibling, if any. */
+ struct die_info *parent; /* Its parent, if any. */
+
struct type *type; /* Cached type information */
};
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;
none of the flags are set, the object lives at the address returned
by decode_locdesc. */
-static int optimized_out; /* No ops in location in expression,
- so object was optimized out. */
static int isreg; /* Object lives in register.
decode_locdesc's return value is
the register number. */
-static int offreg; /* Object's address is the sum of the
- register specified by basereg, plus
- the offset returned. */
-static int basereg; /* See `offreg'. */
-static int isderef; /* Value described by flags above is
- the address of a pointer to the object. */
-static int islocal; /* Variable is at the returned offset
- from the frame start, but there's
- no identified frame pointer for
- this function, so we can't say
- which register it's relative to;
- use LOC_LOCAL. */
-static int is_thread_local; /* Variable is at a constant offset in the
- thread-local storage block for the
- current thread and the dynamic linker
- module containing this expression.
- decode_locdesc returns the offset from
- that base. */
-
-/* DW_AT_frame_base values for the current function.
- frame_base_reg is -1 if DW_AT_frame_base is missing, otherwise it
- contains the register number for the frame register.
- frame_base_offset is the offset from the frame register to the
- virtual stack frame. */
-static int frame_base_reg;
-static CORE_ADDR frame_base_offset;
/* This value is added to each symbol value. FIXME: Generalize to
the section_offsets structure used by dbxread (once this is done,
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)
#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
/* Various complaints about symbol reading that don't abort the process */
-static struct deprecated_complaint dwarf2_const_ignored =
-{
- "type qualifier 'const' ignored", 0, 0
-};
-static struct deprecated_complaint dwarf2_volatile_ignored =
-{
- "type qualifier 'volatile' ignored", 0, 0
-};
-static struct deprecated_complaint dwarf2_non_const_array_bound_ignored =
-{
- "non-constant array bounds form '%s' ignored", 0, 0
-};
-static struct deprecated_complaint dwarf2_missing_line_number_section =
-{
- "missing .debug_line section", 0, 0
-};
-static struct deprecated_complaint dwarf2_statement_list_fits_in_line_number_section =
-{
- "statement list doesn't fit in .debug_line section", 0, 0
-};
-static struct deprecated_complaint dwarf2_mangled_line_number_section =
-{
- "mangled .debug_line section", 0, 0
-};
-static struct deprecated_complaint dwarf2_unsupported_die_ref_attr =
-{
- "unsupported die ref attribute form: '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_unsupported_stack_op =
-{
- "unsupported stack op: '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_complex_location_expr =
-{
- "location expression too complex", 0, 0
-};
-static struct deprecated_complaint dwarf2_unsupported_tag =
-{
- "unsupported tag: '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_unsupported_at_encoding =
-{
- "unsupported DW_AT_encoding: '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_unsupported_at_frame_base =
-{
- "unsupported DW_AT_frame_base for function '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_unexpected_tag =
-{
- "unexepected tag in read_type_die: '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_missing_at_frame_base =
-{
- "DW_AT_frame_base missing for DW_OP_fbreg", 0, 0
-};
-static struct deprecated_complaint dwarf2_bad_static_member_name =
-{
- "unrecognized static data member name '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_unsupported_accessibility =
-{
- "unsupported accessibility %d", 0, 0
-};
-static struct deprecated_complaint dwarf2_bad_member_name_complaint =
-{
- "cannot extract member name from '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_missing_member_fn_type_complaint =
-{
- "member function type missing for '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_vtbl_not_found_complaint =
-{
- "virtual function table pointer not found when defining class '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_absolute_sibling_complaint =
-{
- "ignoring absolute DW_AT_sibling", 0, 0
-};
-static struct deprecated_complaint dwarf2_const_value_length_mismatch =
-{
- "const value length mismatch for '%s', got %d, expected %d", 0, 0
-};
-static struct deprecated_complaint dwarf2_unsupported_const_value_attr =
-{
- "unsupported const value attribute form: '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_misplaced_line_number =
-{
- "misplaced first line number at 0x%lx for '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_line_header_too_long =
-{
- "line number info header doesn't fit in `.debug_line' section", 0, 0
-};
-static struct deprecated_complaint dwarf2_missing_macinfo_section =
-{
- "missing .debug_macinfo section", 0, 0
-};
-static struct deprecated_complaint dwarf2_macros_too_long =
+static void
+dwarf2_non_const_array_bound_ignored_complaint (const char *arg1)
{
- "macro info runs off end of `.debug_macinfo' section", 0, 0
-};
-static struct deprecated_complaint dwarf2_macros_not_terminated =
+ complaint (&symfile_complaints, "non-constant array bounds form '%s' ignored",
+ arg1);
+}
+
+static void
+dwarf2_statement_list_fits_in_line_number_section_complaint (void)
{
- "no terminating 0-type entry for macros in `.debug_macinfo' section", 0, 0
-};
-static struct deprecated_complaint dwarf2_macro_outside_file =
+ complaint (&symfile_complaints,
+ "statement list doesn't fit in .debug_line section");
+}
+
+static void
+dwarf2_complex_location_expr_complaint (void)
{
- "debug info gives macro %s outside of any file: %s", 0, 0
-};
-static struct deprecated_complaint dwarf2_macro_unmatched_end_file =
+ complaint (&symfile_complaints, "location expression too complex");
+}
+
+static void
+dwarf2_unsupported_at_frame_base_complaint (const char *arg1)
{
- "macro debug info has an unmatched `close_file' directive", 0, 0
-};
-static struct deprecated_complaint dwarf2_macro_malformed_definition =
+ 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)
{
- "macro debug info contains a malformed macro definition:\n`%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_macro_spaces_in_definition =
+ complaint (&symfile_complaints,
+ "const value length mismatch for '%s', got %d, expected %d", arg1,
+ arg2, arg3);
+}
+
+static void
+dwarf2_macros_too_long_complaint (void)
{
- "macro definition contains spaces in formal argument list:\n`%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_invalid_attrib_class =
+ complaint (&symfile_complaints,
+ "macro info runs off end of `.debug_macinfo' section");
+}
+
+static void
+dwarf2_macro_malformed_definition_complaint (const char *arg1)
{
- "invalid attribute class or form for '%s' in '%s'", 0, 0
-};
-static struct deprecated_complaint dwarf2_invalid_pointer_size =
+ complaint (&symfile_complaints,
+ "macro debug info contains a malformed macro definition:\n`%s'",
+ arg1);
+}
+
+static void
+dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
{
- "invalid pointer size %d", 0, 0
-};
+ complaint (&symfile_complaints,
+ "invalid attribute class or form for '%s' in '%s'", arg1, arg2);
+}
/* local function prototypes */
-static void dwarf2_locate_sections (bfd *, asection *, PTR);
+static void dwarf2_locate_sections (bfd *, asection *, void *);
#if 0
static void dwarf2_build_psymtabs_easy (struct objfile *, int);
static void dwarf2_build_psymtabs_hard (struct objfile *, int);
-static char *scan_partial_symbols (char *, struct objfile *,
- CORE_ADDR *, CORE_ADDR *,
- const struct comp_unit_head *);
+static char *scan_partial_symbols (char *, CORE_ADDR *, CORE_ADDR *,
+ struct dwarf2_cu *,
+ const char *namespace);
+
+static void add_partial_symbol (struct partial_die_info *, struct dwarf2_cu *,
+ const char *namespace);
+
+static char *add_partial_namespace (struct partial_die_info *pdi,
+ char *info_ptr,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ struct dwarf2_cu *cu,
+ const char *namespace);
+
+static char *add_partial_enumeration (struct partial_die_info *enum_pdi,
+ char *info_ptr,
+ struct dwarf2_cu *cu,
+ const char *namespace);
-static void add_partial_symbol (struct partial_die_info *, struct objfile *,
- const struct comp_unit_head *);
+static char *locate_pdi_sibling (struct partial_die_info *orig_pdi,
+ char *info_ptr,
+ bfd *abfd,
+ struct dwarf2_cu *cu);
static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
static void psymtab_to_symtab_1 (struct partial_symtab *);
-char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int);
+char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int,
+ asection *);
-static void dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header);
+static void dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu);
-static void dwarf2_empty_abbrev_table (PTR);
+static void dwarf2_empty_abbrev_table (void *);
static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int,
- const struct comp_unit_head *cu_header);
+ struct dwarf2_cu *);
static char *read_partial_die (struct partial_die_info *,
- bfd *, char *,
- const struct comp_unit_head *);
+ bfd *, char *, struct dwarf2_cu *);
static char *read_full_die (struct die_info **, bfd *, char *,
- const struct comp_unit_head *);
+ struct dwarf2_cu *, int *);
static char *read_attribute (struct attribute *, struct attr_abbrev *,
- bfd *, char *, const struct comp_unit_head *);
+ bfd *, char *, struct dwarf2_cu *);
static char *read_attribute_value (struct attribute *, unsigned,
- bfd *, char *, const struct comp_unit_head *);
+ bfd *, char *, struct dwarf2_cu *);
static unsigned int read_1_byte (bfd *, char *);
static unsigned long read_8_bytes (bfd *, char *);
-static CORE_ADDR read_address (bfd *, char *ptr, const struct comp_unit_head *,
+static CORE_ADDR read_address (bfd *, char *ptr, struct dwarf2_cu *,
int *bytes_read);
static LONGEST read_initial_length (bfd *, char *,
static struct line_header *(dwarf_decode_line_header
(unsigned int offset,
- bfd *abfd,
- const struct comp_unit_head *cu_header));
+ bfd *abfd, struct dwarf2_cu *cu));
static void dwarf_decode_lines (struct line_header *, char *, bfd *,
- const struct comp_unit_head *);
+ struct dwarf2_cu *);
static void dwarf2_start_subfile (char *, char *);
static struct symbol *new_symbol (struct die_info *, struct type *,
- struct objfile *, const struct comp_unit_head *);
+ struct dwarf2_cu *);
static void dwarf2_const_value (struct attribute *, struct symbol *,
- struct objfile *, const struct comp_unit_head *);
+ struct dwarf2_cu *);
static void dwarf2_const_value_data (struct attribute *attr,
struct symbol *sym,
int bits);
-static struct type *die_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static struct type *die_type (struct die_info *, struct dwarf2_cu *);
-static struct type *die_containing_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static struct type *die_containing_type (struct die_info *,
+ struct dwarf2_cu *);
#if 0
static struct type *type_at_offset (unsigned int, struct objfile *);
#endif
-static struct type *tag_type_to_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static struct type *tag_type_to_type (struct die_info *, struct dwarf2_cu *);
-static void read_type_die (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_type_die (struct die_info *, struct dwarf2_cu *);
-static void read_typedef (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_typedef (struct die_info *, struct dwarf2_cu *);
-static void read_base_type (struct die_info *, struct objfile *);
+static void read_base_type (struct die_info *, struct dwarf2_cu *);
-static void read_file_scope (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_file_scope (struct die_info *, struct dwarf2_cu *);
-static void read_func_scope (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_func_scope (struct die_info *, struct dwarf2_cu *);
-static void read_lexical_block_scope (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *);
static int dwarf2_get_pc_bounds (struct die_info *,
- CORE_ADDR *, CORE_ADDR *, struct objfile *);
+ CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *);
static void dwarf2_add_field (struct field_info *, struct die_info *,
- struct objfile *, const struct comp_unit_head *);
+ struct dwarf2_cu *);
static void dwarf2_attach_fields_to_type (struct field_info *,
- struct type *, struct objfile *);
+ struct type *, struct dwarf2_cu *);
static void dwarf2_add_member_fn (struct field_info *,
struct die_info *, struct type *,
- struct objfile *objfile,
- const struct comp_unit_head *);
+ struct dwarf2_cu *);
static void dwarf2_attach_fn_fields_to_type (struct field_info *,
- struct type *, struct objfile *);
+ struct type *, struct dwarf2_cu *);
-static void read_structure_scope (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_structure_scope (struct die_info *, struct dwarf2_cu *);
-static void read_common_block (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_common_block (struct die_info *, struct dwarf2_cu *);
-static void read_namespace (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header);
+static void read_namespace (struct die_info *die, struct dwarf2_cu *);
-static void read_enumeration (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_enumeration (struct die_info *, struct dwarf2_cu *);
-static struct type *dwarf_base_type (int, int, struct objfile *);
+static struct type *dwarf_base_type (int, int, struct dwarf2_cu *);
-static CORE_ADDR decode_locdesc (struct dwarf_block *, struct objfile *,
- const struct comp_unit_head *);
+static CORE_ADDR decode_locdesc (struct dwarf_block *, struct dwarf2_cu *);
-static void read_array_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_array_type (struct die_info *, struct dwarf2_cu *);
-static void read_tag_pointer_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_tag_pointer_type (struct die_info *, struct dwarf2_cu *);
-static void read_tag_ptr_to_member_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_tag_ptr_to_member_type (struct die_info *,
+ struct dwarf2_cu *);
-static void read_tag_reference_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_tag_reference_type (struct die_info *, struct dwarf2_cu *);
-static void read_tag_const_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_tag_const_type (struct die_info *, struct dwarf2_cu *);
-static void read_tag_volatile_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_tag_volatile_type (struct die_info *, struct dwarf2_cu *);
-static void read_tag_string_type (struct die_info *, struct objfile *);
+static void read_tag_string_type (struct die_info *, struct dwarf2_cu *);
-static void read_subroutine_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_subroutine_type (struct die_info *, struct dwarf2_cu *);
-static struct die_info *read_comp_unit (char *, bfd *,
- const struct comp_unit_head *);
+static struct die_info *read_comp_unit (char *, bfd *, struct dwarf2_cu *);
+
+static struct die_info *read_die_and_children (char *info_ptr, bfd *abfd,
+ struct dwarf2_cu *,
+ char **new_info_ptr,
+ struct die_info *parent);
+
+static struct die_info *read_die_and_siblings (char *info_ptr, bfd *abfd,
+ struct dwarf2_cu *,
+ char **new_info_ptr,
+ struct die_info *parent);
static void free_die_list (struct die_info *);
static struct cleanup *make_cleanup_free_die_list (struct die_info *);
-static void process_die (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void process_die (struct die_info *, struct dwarf2_cu *);
static char *dwarf2_linkage_name (struct die_info *);
+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);
/* 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);
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 *);
+ char *, bfd *, struct dwarf2_cu *);
static int attr_form_is_block (struct attribute *);
+static void
+dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+ struct dwarf2_cu *cu);
+
/* Try to locate the sections we need for DWARF 2 debugging
information and return true if we have enough to do something. */
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)
{
in. */
static void
-dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, PTR ignore_ptr)
+dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, void *ignore_ptr)
{
- if (STREQ (sectp->name, INFO_SECTION))
+ if (strcmp (sectp->name, INFO_SECTION) == 0)
{
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))
+ else if (strcmp (sectp->name, ABBREV_SECTION) == 0)
{
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))
+ else if (strcmp (sectp->name, LINE_SECTION) == 0)
{
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))
+ else if (strcmp (sectp->name, PUBNAMES_SECTION) == 0)
{
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))
+ else if (strcmp (sectp->name, ARANGES_SECTION) == 0)
{
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))
+ else if (strcmp (sectp->name, LOC_SECTION) == 0)
{
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))
+ else if (strcmp (sectp->name, MACINFO_SECTION) == 0)
{
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))
+ else if (strcmp (sectp->name, STR_SECTION) == 0)
{
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))
+ else if (strcmp (sectp->name, FRAME_SECTION) == 0)
{
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))
+ else if (strcmp (sectp->name, EH_FRAME_SECTION) == 0)
{
- dwarf_eh_frame_offset = sectp->filepos;
- dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
+ 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 (strcmp (sectp->name, RANGES_SECTION) == 0)
+ {
+ dwarf_ranges_offset = sectp->filepos;
+ dwarf_ranges_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_ranges_section = sectp;
}
}
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_abbrev_size,
+ dwarf_abbrev_section);
if (dwarf_line_offset)
dwarf_line_buffer = dwarf2_read_section (objfile,
dwarf_line_offset,
- dwarf_line_size);
+ 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_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_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))
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)
{
aranges_buffer = dwarf2_read_section (objfile,
dwarf_aranges_offset,
- dwarf_aranges_size);
+ dwarf_aranges_size,
+ dwarf_aranges_section);
}
#endif
left at all should be sufficient. */
while (info_ptr < dwarf_info_buffer + dwarf_info_size)
{
- struct comp_unit_head cu_header;
+ struct dwarf2_cu cu;
beg_of_comp_unit = info_ptr;
- info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd);
- if (cu_header.version != 2)
+ cu.objfile = objfile;
+ info_ptr = read_comp_unit_head (&cu.header, info_ptr, abfd);
+
+ if (cu.header.version != 2)
{
- error ("Dwarf Error: wrong version in compilation unit header.");
+ 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)
+ if (cu.header.abbrev_offset >= dwarf_abbrev_size)
{
- error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6).",
- (long) cu_header.abbrev_offset,
- (long) (beg_of_comp_unit - dwarf_info_buffer));
+ 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),
+ bfd_get_filename (abfd));
return;
}
- if (beg_of_comp_unit + cu_header.length + cu_header.initial_length_size
+ if (beg_of_comp_unit + cu.header.length + cu.header.initial_length_size
> dwarf_info_buffer + dwarf_info_size)
{
- error ("Dwarf Error: bad length (0x%lx) in compilation unit header (offset 0x%lx + 0).",
- (long) cu_header.length,
- (long) (beg_of_comp_unit - dwarf_info_buffer));
+ 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),
+ 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;
+ 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);
- make_cleanup (dwarf2_empty_abbrev_table, cu_header.dwarf2_abbrevs);
+ dwarf2_read_abbrevs (abfd, &cu);
+ 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,
- &cu_header);
+ &cu);
/* Set the language we're debugging */
set_cu_language (comp_unit_die.language);
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 */
If not, there's no more debug_info for this comp unit. */
if (comp_unit_die.has_children)
{
- info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc,
- &cu_header);
+ lowpc = ((CORE_ADDR) -1);
+ highpc = ((CORE_ADDR) 0);
+ info_ptr = scan_partial_symbols (info_ptr, &lowpc, &highpc,
+ &cu, 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_die.has_pc_info)
also happen.) This happens in VxWorks. */
free_named_symtabs (pst->filename);
- info_ptr = beg_of_comp_unit + cu_header.length
- + cu_header.initial_length_size;
+ info_ptr = beg_of_comp_unit + cu.header.length
+ + cu.header.initial_length_size;
}
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)
+scan_partial_symbols (char *info_ptr, CORE_ADDR *lowpc,
+ CORE_ADDR *highpc, struct dwarf2_cu *cu,
+ const char *namespace)
{
+ struct objfile *objfile = cu->objfile;
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. */
-
- int nesting_level = 1;
-
- /* We only want to read in symbols corresponding to variables or
- other similar objects that are global or static. Normally, these
- are all children of the DW_TAG_compile_unit die, so are all at
- level 1. But C++ namespaces give ries to DW_TAG_namespace dies
- whose children are global objects. So we keep track of what
- level we currently think of as referring to file scope; this
- should always equal 1 plus the number of namespaces that we are
- currently nested within. */
-
- int file_scope_level = 1;
-
- *lowpc = ((CORE_ADDR) -1);
- *highpc = ((CORE_ADDR) 0);
+ /* 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. */
- while (nesting_level)
+ while (1)
{
- info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
+ /* This flag tells whether or not info_ptr has gotten updated
+ inside the loop. */
+ int info_ptr_updated = 0;
+
+ info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu);
- if (pdi.name)
+ /* Anonymous namespaces have no name but have interesting
+ children, so we need to look at them. Ditto for anonymous
+ enums. */
+
+ if (pdi.name != NULL || pdi.tag == DW_TAG_namespace
+ || pdi.tag == DW_TAG_enumeration_type)
{
switch (pdi.tag)
{
{
*highpc = pdi.highpc;
}
- if ((pdi.is_external || nesting_level == file_scope_level)
- && !pdi.is_declaration)
+ if (!pdi.is_declaration)
{
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (&pdi, cu, 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 == file_scope_level)
- && !pdi.is_declaration)
+ if (!pdi.is_declaration)
{
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (&pdi, cu, namespace);
}
break;
- case DW_TAG_enumerator:
- /* File scope enumerators are added to the partial
- symbol table. They're children of the enumeration
- type die, so they occur at a level one higher than we
- normally look for. */
- if (nesting_level == file_scope_level + 1)
- add_partial_symbol (&pdi, objfile, cu_header);
+ case DW_TAG_enumeration_type:
+ if (!pdi.is_declaration)
+ {
+ info_ptr = add_partial_enumeration (&pdi, info_ptr, cu,
+ 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 == file_scope_level)
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (&pdi, cu, namespace);
break;
case DW_TAG_namespace:
- /* FIXME: carlton/2002-10-16: we're not yet doing
- anything useful with this, but for now make sure that
- these tags at least don't cause us to miss any
- important symbols. */
- if (pdi.has_children)
- file_scope_level++;
+ /* 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, lowpc, highpc,
+ cu, 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. Do
- not skip namespaces, we want to record symbols inside
- them. */
- if (pdi.sibling
- && pdi.tag != DW_TAG_enumeration_type
- && pdi.tag != DW_TAG_namespace)
- {
- info_ptr = pdi.sibling;
- }
- else if (pdi.has_children)
- {
- /* Die has children, but either the optional DW_AT_sibling
- attribute is missing or we want to look at them. */
- nesting_level++;
- }
-
if (pdi.tag == 0)
- {
- nesting_level--;
- /* If this is the end of a DW_TAG_namespace entry, then
- decrease the file_scope_level, too. */
- if (nesting_level < file_scope_level)
- {
- file_scope_level--;
- gdb_assert (nesting_level == file_scope_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);
}
- /* 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)
+add_partial_symbol (struct partial_die_info *pdi,
+ struct dwarf2_cu *cu, const char *namespace)
{
+ struct objfile *objfile = cu->objfile;
CORE_ADDR addr = 0;
+ const struct partial_symbol *psym = NULL;
switch (pdi->tag)
{
{
/*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:
table building. */
if (pdi->locdesc)
- addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
+ addr = decode_locdesc (pdi->locdesc, cu);
if (pdi->locdesc || pdi->has_type)
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_STATIC,
- &objfile->global_psymbols,
- 0, addr + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (pdi->name, strlen (pdi->name),
+ VAR_DOMAIN, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, addr + baseaddr,
+ cu_language, objfile);
}
else
{
/* Static Variable. Skip symbols without location descriptors. */
if (pdi->locdesc == NULL)
return;
- addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
+ addr = decode_locdesc (pdi->locdesc, cu);
/*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;
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);
{
/* 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,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ struct dwarf2_cu *cu, const char *namespace)
+{
+ struct objfile *objfile = cu->objfile;
+ const char *new_name = pdi->name;
+ char *full_name;
+
+ /* Calculate the full name of the namespace that we just entered. */
+
+ 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, lowpc, highpc, cu, 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 dwarf2_cu *cu, const char *namespace)
+{
+ struct objfile *objfile = cu->objfile;
+ bfd *abfd = objfile->obfd;
+ struct partial_die_info pdi;
+
+ if (enum_pdi->name != NULL)
+ add_partial_symbol (enum_pdi, cu, namespace);
+
+ while (1)
+ {
+ info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu);
+ 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, cu, 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, struct dwarf2_cu *cu)
+{
+ /* Do we know the sibling already? */
+
+ if (orig_pdi->sibling)
+ return orig_pdi->sibling;
+
+ /* Are there any children to deal with? */
+
+ if (!orig_pdi->has_children)
+ return info_ptr;
+
+ /* 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);
+
+ if (pdi.tag == 0)
+ return info_ptr;
+ else
+ info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, cu);
+ }
}
/* Expand this partial symbol table into a full symbol table. */
{
struct objfile *objfile = pst->objfile;
bfd *abfd = objfile->obfd;
- struct comp_unit_head cu_header;
+ struct dwarf2_cu cu;
struct die_info *dies;
unsigned long offset;
CORE_ADDR lowpc, highpc;
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);
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;
buildsym_init ();
make_cleanup (really_free_pendings, NULL);
+ cu.objfile = objfile;
+
/* read in the comp_unit header */
- info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd);
+ info_ptr = read_comp_unit_head (&cu.header, info_ptr, abfd);
/* Read the abbrevs for this compilation unit */
- dwarf2_read_abbrevs (abfd, &cu_header);
- make_cleanup (dwarf2_empty_abbrev_table, cu_header.dwarf2_abbrevs);
+ dwarf2_read_abbrevs (abfd, &cu);
+ make_cleanup (dwarf2_empty_abbrev_table, cu.header.dwarf2_abbrevs);
- dies = read_comp_unit (info_ptr, abfd, &cu_header);
+ dies = read_comp_unit (info_ptr, abfd, &cu);
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);
+ process_die (dies, &cu);
- if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile))
+ if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, &cu))
{
/* Some compilers don't define a DW_AT_high_pc attribute for
the compilation unit. If the DW_AT_high_pc is missing,
synthesize it, by scanning the DIE's below the compilation unit. */
highpc = 0;
- if (dies->has_children)
+ if (dies->child != NULL)
{
- child_die = dies->next;
+ child_die = dies->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_subprogram)
{
CORE_ADDR low, high;
- if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
+ if (dwarf2_get_pc_bounds (child_die, &low, &high, &cu))
{
highpc = max (highpc, high);
}
}
pst->symtab = symtab;
pst->readin = 1;
- sort_symtab_syms (pst->symtab);
do_cleanups (back_to);
}
/* Process a die and its children. */
static void
-process_die (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+process_die (struct die_info *die, struct dwarf2_cu *cu)
{
switch (die->tag)
{
case DW_TAG_padding:
break;
case DW_TAG_compile_unit:
- read_file_scope (die, objfile, cu_header);
+ read_file_scope (die, cu);
break;
case DW_TAG_subprogram:
- read_subroutine_type (die, objfile, cu_header);
- read_func_scope (die, objfile, cu_header);
+ read_subroutine_type (die, cu);
+ read_func_scope (die, cu);
break;
case DW_TAG_inlined_subroutine:
/* FIXME: These are ignored for now.
of a function and make GDB `next' properly over inlined functions. */
break;
case DW_TAG_lexical_block:
- read_lexical_block_scope (die, objfile, cu_header);
+ case DW_TAG_try_block:
+ case DW_TAG_catch_block:
+ read_lexical_block_scope (die, cu);
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
- read_structure_scope (die, objfile, cu_header);
+ read_structure_scope (die, cu);
break;
case DW_TAG_enumeration_type:
- read_enumeration (die, objfile, cu_header);
+ read_enumeration (die, cu);
break;
case DW_TAG_subroutine_type:
- read_subroutine_type (die, objfile, cu_header);
+ read_subroutine_type (die, cu);
break;
case DW_TAG_array_type:
- read_array_type (die, objfile, cu_header);
+ read_array_type (die, cu);
break;
case DW_TAG_pointer_type:
- read_tag_pointer_type (die, objfile, cu_header);
+ read_tag_pointer_type (die, cu);
break;
case DW_TAG_ptr_to_member_type:
- read_tag_ptr_to_member_type (die, objfile, cu_header);
+ read_tag_ptr_to_member_type (die, cu);
break;
case DW_TAG_reference_type:
- read_tag_reference_type (die, objfile, cu_header);
+ read_tag_reference_type (die, cu);
break;
case DW_TAG_string_type:
- read_tag_string_type (die, objfile);
+ read_tag_string_type (die, cu);
break;
case DW_TAG_base_type:
- read_base_type (die, objfile);
+ read_base_type (die, cu);
if (dwarf_attr (die, DW_AT_name))
{
/* Add a typedef symbol for the base type definition. */
- new_symbol (die, die->type, objfile, cu_header);
+ new_symbol (die, die->type, cu);
}
break;
case DW_TAG_common_block:
- read_common_block (die, objfile, cu_header);
+ read_common_block (die, cu);
break;
case DW_TAG_common_inclusion:
break;
case DW_TAG_namespace:
- read_namespace (die, objfile, cu_header);
+ if (!processing_has_namespace_info)
+ {
+ processing_has_namespace_info = 1;
+ processing_current_namespace = "";
+ }
+ read_namespace (die, cu);
break;
case DW_TAG_imported_declaration:
case DW_TAG_imported_module:
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. */
- gdb_assert (!die->has_children);
+ if (!processing_has_namespace_info)
+ {
+ processing_has_namespace_info = 1;
+ processing_current_namespace = "";
+ }
+ gdb_assert (die->child == NULL);
break;
default:
- new_symbol (die, NULL, objfile, cu_header);
+ new_symbol (die, NULL, cu);
break;
}
}
}
static void
-read_file_scope (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
+ struct comp_unit_head *cu_header = &cu->header;
struct cleanup *back_to = make_cleanup (null_cleanup, 0);
CORE_ADDR lowpc = ((CORE_ADDR) -1);
CORE_ADDR highpc = ((CORE_ADDR) 0);
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, cu))
{
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_subprogram)
{
CORE_ADDR low, high;
- if (dwarf2_get_pc_bounds (child_die, &low, &high, objfile))
+ if (dwarf2_get_pc_bounds (child_die, &low, &high, cu))
{
lowpc = min (lowpc, low);
highpc = max (highpc, high);
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);
initialize_cu_func_list ();
/* Process all dies in compilation unit. */
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
- process_die (child_die, objfile, cu_header);
+ process_die (child_die, cu);
child_die = sibling_die (child_die);
}
}
if (attr)
{
unsigned int line_offset = DW_UNSND (attr);
- line_header = dwarf_decode_line_header (line_offset,
- abfd, cu_header);
+ line_header = dwarf_decode_line_header (line_offset, abfd, cu);
if (line_header)
{
make_cleanup ((make_cleanup_ftype *) free_line_header,
(void *) line_header);
- dwarf_decode_lines (line_header, comp_dir, abfd, cu_header);
+ dwarf_decode_lines (line_header, comp_dir, abfd, cu);
}
}
{
unsigned int macro_offset = DW_UNSND (attr);
dwarf_decode_macros (line_header, macro_offset,
- comp_dir, abfd, cu_header, objfile);
+ comp_dir, abfd, cu);
}
do_cleanups (back_to);
}
}
static void
-read_func_scope (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
{
- register struct context_stack *new;
+ struct objfile *objfile = cu->objfile;
+ struct context_stack *new;
CORE_ADDR lowpc;
CORE_ADDR highpc;
struct die_info *child_die;
/* Ignore functions with missing or empty names and functions with
missing or invalid low and high pc attributes. */
- if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+ if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu))
return;
lowpc += baseaddr;
objfile->ei.entry_func_highpc = highpc;
}
- /* Decode DW_AT_frame_base location descriptor if present, keep result
- for DW_OP_fbreg operands in decode_locdesc. */
- frame_base_reg = -1;
- frame_base_offset = 0;
+ new = push_context (0, lowpc);
+ new->name = new_symbol (die, die->type, cu);
+
+ /* If there is a location expression for DW_AT_frame_base, record
+ it. */
attr = dwarf_attr (die, DW_AT_frame_base);
if (attr)
- {
- CORE_ADDR addr;
+ dwarf2_symbol_mark_computed (attr, new->name, cu);
- /* Support the .debug_loc offsets */
- if (attr_form_is_block (attr))
- {
- addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
- }
- else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
- {
- complain (&dwarf2_complex_location_expr);
- addr = 0;
- }
- else
- {
- complain (&dwarf2_invalid_attrib_class, "DW_AT_frame_base", name);
- addr = 0;
- }
-
- if (isderef)
- complain (&dwarf2_unsupported_at_frame_base, name);
- else if (isreg)
- frame_base_reg = addr;
- else if (offreg)
- {
- frame_base_reg = basereg;
- frame_base_offset = addr;
- }
- else
- complain (&dwarf2_unsupported_at_frame_base, name);
- }
-
- new = push_context (0, lowpc);
- new->name = new_symbol (die, die->type, objfile, cu_header);
list_in_scope = &local_symbols;
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
- process_die (child_die, objfile, cu_header);
+ process_die (child_die, cu);
child_die = sibling_die (child_die);
}
}
local_symbols = new->locals;
param_symbols = new->params;
- list_in_scope = &file_symbols;
+ /* 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
a new scope, process the dies, and then close the scope. */
static void
-read_lexical_block_scope (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
{
- register struct context_stack *new;
+ struct objfile *objfile = cu->objfile;
+ struct context_stack *new;
CORE_ADDR lowpc, highpc;
struct die_info *child_die;
/* Ignore blocks with missing or invalid low and high pc attributes. */
- if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile))
+ /* ??? Perhaps consider discontiguous blocks defined by DW_AT_ranges
+ as multiple lexical blocks? Handling children in a sane way would
+ be nasty. Might be easier to properly extend generic blocks to
+ describe ranges. */
+ if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu))
return;
lowpc += baseaddr;
highpc += baseaddr;
push_context (0, lowpc);
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
- process_die (child_die, objfile, cu_header);
+ process_die (child_die, cu);
child_die = sibling_die (child_die);
}
}
local_symbols = new->locals;
}
-/* Get low and high pc attributes from a die.
- Return 1 if the attributes are present and valid, otherwise, return 0. */
+/* Get low and high pc attributes from a die. Return 1 if the attributes
+ are present and valid, otherwise, return 0. Return -1 if the range is
+ discontinuous, i.e. derived from DW_AT_ranges information. */
+static int
+dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
+ CORE_ADDR *highpc, struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+ struct comp_unit_head *cu_header = &cu->header;
+ struct attribute *attr;
+ bfd *obfd = objfile->obfd;
+ CORE_ADDR low = 0;
+ CORE_ADDR high = 0;
+ int ret = 0;
+
+ attr = dwarf_attr (die, DW_AT_high_pc);
+ if (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
+ {
+ 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;
+ 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, &dummy);
+ if ((marker & mask) == mask)
+ {
+ /* If we found the largest possible address, then
+ read the base address. */
+ base = read_address (obfd, buffer + addr_size, cu, &dummy);
+ buffer += 2 * addr_size;
+ offset += 2 * addr_size;
+ found_base = 1;
+ }
+
+ low_set = 0;
+
+ while (1)
+ {
+ CORE_ADDR range_beginning, range_end;
+
+ range_beginning = read_address (obfd, buffer, cu, &dummy);
+ buffer += addr_size;
+ range_end = read_address (obfd, buffer, cu, &dummy);
+ buffer += addr_size;
+ offset += 2 * addr_size;
+
+ /* An end of list marker is a pair of zero addresses. */
+ if (range_beginning == 0 && range_end == 0)
+ /* Found the end of list entry. */
+ break;
+
+ /* Each base address selection entry is a pair of 2 values.
+ The first is the largest possible address, the second is
+ the base address. Check for a base address here. */
+ if ((range_beginning & mask) == mask)
+ {
+ /* If we found the largest possible address, then
+ read the base address. */
+ base = read_address (obfd, buffer + addr_size, cu, &dummy);
+ found_base = 1;
+ continue;
+ }
+
+ if (!found_base)
+ {
+ /* We have no valid base address for the ranges
+ data. */
+ complaint (&symfile_complaints,
+ "Invalid .debug_ranges data (no base address)");
+ return 0;
+ }
+
+ range_beginning += base;
+ range_end += base;
+
+ /* FIXME: This is recording everything as a low-high
+ segment of consecutive addresses. We should have a
+ data structure for discontiguous block ranges
+ instead. */
+ if (! low_set)
+ {
+ low = range_beginning;
+ high = range_end;
+ low_set = 1;
+ }
+ else
+ {
+ if (range_beginning < low)
+ low = range_beginning;
+ if (range_end > high)
+ high = range_end;
+ }
+ }
-static int
-dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc,
- struct objfile *objfile)
-{
- struct attribute *attr;
- CORE_ADDR low;
- CORE_ADDR high;
+ if (! low_set)
+ /* If the first entry is an end-of-list marker, the range
+ describes an empty scope, i.e. no instructions. */
+ return 0;
- attr = dwarf_attr (die, DW_AT_low_pc);
- if (attr)
- low = DW_ADDR (attr);
- else
- return 0;
- attr = dwarf_attr (die, DW_AT_high_pc);
- if (attr)
- high = DW_ADDR (attr);
- else
- return 0;
+ ret = -1;
+ }
+ }
if (high < low)
return 0;
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. */
static void
dwarf2_add_field (struct field_info *fip, struct die_info *die,
- struct objfile *objfile,
- const struct comp_unit_head *cu_header)
-{
+ struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
struct nextfield *new_field;
struct attribute *attr;
struct field *fp;
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);
+ fp->type = die_type (die, cu);
+
+ FIELD_STATIC_KIND (*fp) = 0;
/* Get bit size of field (zero if none). */
attr = dwarf_attr (die, DW_AT_bit_size);
if (attr)
{
FIELD_BITPOS (*fp) =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header) * bits_per_byte;
+ decode_locdesc (DW_BLOCK (attr), cu) * bits_per_byte;
}
else
FIELD_BITPOS (*fp) = 0;
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);
SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname),
&objfile->type_obstack));
- FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
+ FIELD_TYPE (*fp) = die_type (die, cu);
FIELD_NAME (*fp) = obsavestring (fieldname, strlen (fieldname),
&objfile->type_obstack);
}
/* C++ base class field. */
attr = dwarf_attr (die, DW_AT_data_member_location);
if (attr)
- FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), objfile, cu_header)
+ FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), cu)
* bits_per_byte);
FIELD_BITSIZE (*fp) = 0;
- FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
+ FIELD_STATIC_KIND (*fp) = 0;
+ FIELD_TYPE (*fp) = die_type (die, cu);
FIELD_NAME (*fp) = type_name_no_tag (fp->type);
fip->nbaseclasses++;
}
static void
dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
- struct objfile *objfile)
+ struct dwarf2_cu *cu)
{
int nfields = fip->nfields;
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;
}
static void
dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
- struct type *type, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+ struct type *type, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct attribute *attr;
struct fnfieldlist *flp;
int i;
/* Look up member function name in fieldlist. */
for (i = 0; i < fip->nfnfields; i++)
{
- if (STREQ (fip->fnfieldlists[i].name, fieldname))
+ if (DEPRECATED_STREQ (fip->fnfieldlists[i].name, fieldname))
break;
}
fnp->type = alloc_type (objfile);
if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
{
- struct type *return_type = TYPE_TARGET_TYPE (die->type);
int nparams = TYPE_NFIELDS (die->type);
/* TYPE is the domain of this method, and DIE->TYPE is the type
fnp->voffset = VOFFSET_STATIC;
}
else
- complain (&dwarf2_missing_member_fn_type_complaint, physname);
+ complaint (&symfile_complaints, "member function type missing for '%s'",
+ physname);
/* Get fcontext from DW_AT_containing_type if present. */
if (dwarf_attr (die, DW_AT_containing_type) != NULL)
- fnp->fcontext = die_containing_type (die, objfile, cu_header);
+ fnp->fcontext = die_containing_type (die, cu);
/* dwarf2 doesn't have stubbed physical names, so the setting of is_const
and is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */
/* Support the .debug_loc offsets */
if (attr_form_is_block (attr))
{
- fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2;
+ fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu) + 2;
}
else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
{
- complain (&dwarf2_complex_location_expr);
+ dwarf2_complex_location_expr_complaint ();
}
else
{
- complain (&dwarf2_invalid_attrib_class, "DW_AT_vtable_elem_location",
- fieldname);
+ dwarf2_invalid_attrib_class_complaint ("DW_AT_vtable_elem_location",
+ fieldname);
}
}
}
static void
dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
- struct objfile *objfile)
+ struct dwarf2_cu *cu)
{
struct fnfieldlist *flp;
int total_length = 0;
suppresses creating a symbol table entry itself). */
static void
-read_structure_scope (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct type *type;
struct attribute *attr;
type within the structure itself. */
die->type = type;
- if (die->has_children && ! die_is_declaration (die))
+ if (die->child != NULL && ! die_is_declaration (die))
{
struct field_info fi;
struct die_info *child_die;
memset (&fi, 0, sizeof (struct field_info));
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
- if (child_die->tag == DW_TAG_member)
- {
- dwarf2_add_field (&fi, child_die, objfile, cu_header);
- }
- else if (child_die->tag == DW_TAG_variable)
+ if (child_die->tag == DW_TAG_member
+ || child_die->tag == DW_TAG_variable)
{
- /* C++ static member. */
- dwarf2_add_field (&fi, child_die, objfile, cu_header);
+ /* NOTE: carlton/2002-11-05: A C++ static data member
+ should be a DW_TAG_member that is a declaration, but
+ all versions of G++ as of this writing (so through at
+ least 3.2.1) incorrectly generate DW_TAG_variable
+ tags for them instead. */
+ dwarf2_add_field (&fi, child_die, cu);
}
else if (child_die->tag == DW_TAG_subprogram)
{
/* C++ member function. */
- process_die (child_die, objfile, cu_header);
- dwarf2_add_member_fn (&fi, child_die, type, objfile, cu_header);
+ process_die (child_die, cu);
+ dwarf2_add_member_fn (&fi, child_die, type, cu);
}
else if (child_die->tag == DW_TAG_inheritance)
{
/* C++ base class field. */
- dwarf2_add_field (&fi, child_die, objfile, cu_header);
+ dwarf2_add_field (&fi, child_die, cu);
}
else
{
- process_die (child_die, objfile, cu_header);
+ process_die (child_die, cu);
}
child_die = sibling_die (child_die);
}
/* Attach fields and member functions to the type. */
if (fi.nfields)
- dwarf2_attach_fields_to_type (&fi, type, objfile);
+ dwarf2_attach_fields_to_type (&fi, type, cu);
if (fi.nfnfields)
{
- dwarf2_attach_fn_fields_to_type (&fi, type, objfile);
+ dwarf2_attach_fn_fields_to_type (&fi, type, cu);
/* Get the type which refers to the base class (possibly this
class itself) which contains the vtable pointer for the current
if (dwarf_attr (die, DW_AT_containing_type) != NULL)
{
- struct type *t = die_containing_type (die, objfile, cu_header);
+ struct type *t = die_containing_type (die, cu);
TYPE_VPTR_BASETYPE (type) = t;
if (type == t)
{
char *fieldname = TYPE_FIELD_NAME (t, i);
- if (STREQN (fieldname, vptr_name, strlen (vptr_name) - 1)
+ if (DEPRECATED_STREQN (fieldname, vptr_name, strlen (vptr_name) - 1)
&& is_cplus_marker (fieldname[strlen (vptr_name)]))
{
TYPE_VPTR_FIELDNO (type) = i;
/* 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
{
}
}
- new_symbol (die, type, objfile, cu_header);
+ new_symbol (die, type, cu);
do_cleanups (back_to);
}
NOTE: We reverse the order of the element list. */
static void
-read_enumeration (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_enumeration (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct die_info *child_die;
struct type *type;
struct field *fields;
num_fields = 0;
fields = NULL;
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag != DW_TAG_enumerator)
{
- process_die (child_die, objfile, cu_header);
+ process_die (child_die, cu);
}
else
{
attr = dwarf_attr (child_die, DW_AT_name);
if (attr)
{
- sym = new_symbol (child_die, type, objfile, cu_header);
+ sym = new_symbol (child_die, type, cu);
if (SYMBOL_VALUE (sym) < 0)
unsigned_enum = 0;
* 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++;
}
TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
}
die->type = type;
- new_symbol (die, type, objfile, cu_header);
+ new_symbol (die, type, cu);
}
/* Extract all information from a DW_TAG_array_type DIE and put it in
arrays. */
static void
-read_array_type (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_array_type (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct die_info *child_die;
struct type *type = NULL;
struct type *element_type, *range_type, *index_type;
return;
}
- element_type = die_type (die, objfile, cu_header);
+ element_type = die_type (die, cu);
/* Irix 6.2 native cc creates array types without children for
arrays with unspecified length. */
- if (die->has_children == 0)
+ if (die->child == NULL)
{
index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
range_type = create_range_type (NULL, index_type, 0, -1);
}
back_to = make_cleanup (null_cleanup, NULL);
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_subrange_type)
low = 1;
}
- index_type = die_type (child_die, objfile, cu_header);
+ index_type = die_type (child_die, cu);
attr = dwarf_attr (child_die, DW_AT_lower_bound);
if (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;
with a DW_FORM_block1 attribute.
FIXME: GDB does not yet know how to handle dynamic
arrays properly, treat them as arrays with unspecified
- length for now. */
- high = -1;
+ length for now.
+
+ FIXME: jimb/2003-09-22: GDB does not really know
+ how to handle arrays of unspecified length
+ either; we just represent them as zero-length
+ arrays. Choose an appropriate upper bound given
+ the lower bound we've computed above. */
+ high = low - 1;
}
else
{
- 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;
/* First cut: install each common block member as a global variable. */
static void
-read_common_block (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_common_block (struct die_info *die, struct dwarf2_cu *cu)
{
struct die_info *child_die;
struct attribute *attr;
/* Support the .debug_loc offsets */
if (attr_form_is_block (attr))
{
- base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ base = decode_locdesc (DW_BLOCK (attr), cu);
}
else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
{
- complain (&dwarf2_complex_location_expr);
+ dwarf2_complex_location_expr_complaint ();
}
else
{
- complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
- "common block member");
+ dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+ "common block member");
}
}
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
- sym = new_symbol (child_die, NULL, objfile, cu_header);
+ sym = new_symbol (child_die, NULL, cu);
attr = dwarf_attr (child_die, DW_AT_data_member_location);
if (attr)
{
SYMBOL_VALUE_ADDRESS (sym) =
- base + decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ base + decode_locdesc (DW_BLOCK (attr), cu);
add_symbol_to_list (sym, &global_symbols);
}
child_die = sibling_die (child_die);
/* Read a C++ namespace. */
-/* FIXME: carlton/2002-10-16: For now, we don't actually do anything
- useful with the namespace data: we just process its children. */
-
static void
-read_namespace (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_namespace (struct die_info *die, struct dwarf2_cu *cu)
{
- if (die->has_children)
+ struct objfile *objfile = cu->objfile;
+ 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, cu);
+
+ if (is_anonymous)
+ cp_add_using_directive (processing_current_namespace,
+ strlen (previous_namespace),
+ strlen (processing_current_namespace));
+ }
+
+ if (die->child != NULL)
{
- struct die_info *child_die = die->next;
+ struct die_info *child_die = die->child;
while (child_die && child_die->tag)
{
- process_die (child_die, objfile, cu_header);
+ process_die (child_die, cu);
child_die = sibling_die (child_die);
}
}
+
+ processing_current_namespace = previous_namespace;
}
/* Extract all information from a DW_TAG_pointer_type DIE and add to
the user defined type vector. */
static void
-read_tag_pointer_type (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct comp_unit_head *cu_header = &cu->header;
struct type *type;
struct attribute *attr_byte_size;
struct attribute *attr_address_class;
return;
}
- type = lookup_pointer_type (die_type (die, objfile, cu_header));
+ type = lookup_pointer_type (die_type (die, cu));
attr_byte_size = dwarf_attr (die, DW_AT_byte_size);
if (attr_byte_size)
}
else if (TYPE_LENGTH (type) != byte_size)
{
- complain (&dwarf2_invalid_pointer_size, byte_size);
+ complaint (&symfile_complaints, "invalid pointer size %d", byte_size);
}
else {
/* Should we also complain about unhandled address classes? */
the user defined type vector. */
static void
-read_tag_ptr_to_member_type (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct type *type;
struct type *to_type;
struct type *domain;
}
type = alloc_type (objfile);
- to_type = die_type (die, objfile, cu_header);
- domain = die_containing_type (die, objfile, cu_header);
+ to_type = die_type (die, cu);
+ domain = die_containing_type (die, cu);
smash_to_member_type (type, domain, to_type);
die->type = type;
the user defined type vector. */
static void
-read_tag_reference_type (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct comp_unit_head *cu_header = &cu->header;
struct type *type;
struct attribute *attr;
return;
}
- type = lookup_reference_type (die_type (die, objfile, cu_header));
+ type = lookup_reference_type (die_type (die, cu));
attr = dwarf_attr (die, DW_AT_byte_size);
if (attr)
{
}
static void
-read_tag_const_type (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_tag_const_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *base_type;
return;
}
- base_type = die_type (die, objfile, cu_header);
+ base_type = die_type (die, cu);
die->type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
}
static void
-read_tag_volatile_type (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_tag_volatile_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *base_type;
return;
}
- base_type = die_type (die, objfile, cu_header);
+ base_type = die_type (die, cu);
die->type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
}
attribute to reference it. */
static void
-read_tag_string_type (struct die_info *die, struct objfile *objfile)
+read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct type *type, *range_type, *index_type, *char_type;
struct attribute *attr;
unsigned int length;
*/
static void
-read_subroutine_type (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *type; /* Type that this function returns */
struct type *ftype; /* Function that returns above type */
{
return;
}
- type = die_type (die, objfile, cu_header);
+ type = die_type (die, cu);
ftype = lookup_function_type (type);
/* All functions in C++ have prototypes. */
|| cu_language == language_cplus)
TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
- if (die->has_children)
+ if (die->child != NULL)
{
struct die_info *child_die;
int nparams = 0;
/* Count the number of parameters.
FIXME: GDB currently ignores vararg functions, but knows about
vararg member functions. */
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_formal_parameter)
TYPE_FIELDS (ftype) = (struct field *)
TYPE_ALLOC (ftype, nparams * sizeof (struct field));
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_formal_parameter)
TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr);
else
TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0;
- TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, objfile,
- cu_header);
+ TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, cu);
iparams++;
}
child_die = sibling_die (child_die);
}
static void
-read_typedef (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_typedef (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct attribute *attr;
char *name = NULL;
name = DW_STRING (attr);
}
die->type = init_type (TYPE_CODE_TYPEDEF, 0, TYPE_FLAG_TARGET_STUB, name, objfile);
- TYPE_TARGET_TYPE (die->type) = die_type (die, objfile, cu_header);
+ TYPE_TARGET_TYPE (die->type) = die_type (die, cu);
}
}
it in the TYPE field of the die. */
static void
-read_base_type (struct die_info *die, struct objfile *objfile)
+read_base_type (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct type *type;
struct attribute *attr;
int encoding = 0, size = 0;
type_flags |= TYPE_FLAG_UNSIGNED;
break;
default:
- complain (&dwarf2_unsupported_at_encoding,
- dwarf_type_encoding_name (encoding));
+ complaint (&symfile_complaints, "unsupported DW_AT_encoding: '%s'",
+ dwarf_type_encoding_name (encoding));
break;
}
type = init_type (code, size, type_flags, DW_STRING (attr), objfile);
}
else
{
- type = dwarf_base_type (encoding, size, objfile);
+ type = dwarf_base_type (encoding, size, cu);
}
die->type = type;
}
/* Read a whole compilation unit into a linked list of dies. */
static struct die_info *
-read_comp_unit (char *info_ptr, bfd *abfd,
- const struct comp_unit_head *cu_header)
+read_comp_unit (char *info_ptr, bfd *abfd, struct dwarf2_cu *cu)
{
- struct die_info *first_die, *last_die, *die;
- char *cur_ptr;
- int nesting_level;
-
/* Reset die reference table; we are
building new ones now. */
dwarf2_empty_hash_tables ();
+ return read_die_and_children (info_ptr, abfd, cu, &info_ptr, NULL);
+}
+
+/* Read a single die and all its descendents. Set the die's sibling
+ field to NULL; set other fields in the die correctly, and set all
+ of the descendents' fields correctly. Set *NEW_INFO_PTR to the
+ location of the info_ptr after reading all of those dies. PARENT
+ is the parent of the die in question. */
+
+static struct die_info *
+read_die_and_children (char *info_ptr, bfd *abfd,
+ struct dwarf2_cu *cu,
+ char **new_info_ptr,
+ struct die_info *parent)
+{
+ struct die_info *die;
+ char *cur_ptr;
+ int has_children;
+
+ cur_ptr = read_full_die (&die, abfd, info_ptr, cu, &has_children);
+ store_in_ref_table (die->offset, die);
+
+ if (has_children)
+ {
+ die->child = read_die_and_siblings (cur_ptr, abfd, cu,
+ new_info_ptr, die);
+ }
+ else
+ {
+ die->child = NULL;
+ *new_info_ptr = cur_ptr;
+ }
+
+ die->sibling = NULL;
+ die->parent = parent;
+ return die;
+}
+
+/* Read a die, all of its descendents, and all of its siblings; set
+ all of the fields of all of the dies correctly. Arguments are as
+ in read_die_and_children. */
+
+static struct die_info *
+read_die_and_siblings (char *info_ptr, bfd *abfd,
+ struct dwarf2_cu *cu,
+ char **new_info_ptr,
+ struct die_info *parent)
+{
+ struct die_info *first_die, *last_sibling;
+ char *cur_ptr;
+
cur_ptr = info_ptr;
- nesting_level = 0;
- first_die = last_die = NULL;
- do
+ first_die = last_sibling = NULL;
+
+ while (1)
{
- cur_ptr = read_full_die (&die, abfd, cur_ptr, cu_header);
- if (die->has_children)
+ struct die_info *die
+ = read_die_and_children (cur_ptr, abfd, cu, &cur_ptr, parent);
+
+ if (!first_die)
{
- nesting_level++;
+ first_die = die;
}
- if (die->tag == 0)
+ else
{
- nesting_level--;
+ last_sibling->sibling = die;
}
- die->next = NULL;
-
- /* Enter die in reference hash table */
- store_in_ref_table (die->offset, die);
-
- if (!first_die)
+ if (die->tag == 0)
{
- first_die = last_die = die;
+ *new_info_ptr = cur_ptr;
+ return first_die;
}
else
{
- last_die->next = die;
- last_die = die;
+ last_sibling = die;
}
}
- while (nesting_level > 0);
- return first_die;
}
/* Free a linked list of dies. */
die = dies;
while (die)
{
- next = die->next;
+ if (die->child != NULL)
+ free_die_list (die->child);
+ next = die->sibling;
xfree (die->attrs);
xfree (die);
die = next;
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_bread (buf, size, abfd) != size))
{
in a hash table. */
static void
-dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header)
+dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu)
{
+ struct comp_unit_head *cu_header = &cu->header;
char *abbrev_ptr;
struct abbrev_info *cur_abbrev;
unsigned int abbrev_number, bytes_read, abbrev_name;
break;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
- if (dwarf2_lookup_abbrev (abbrev_number, cu_header) != NULL)
+ if (dwarf2_lookup_abbrev (abbrev_number, cu) != NULL)
break;
}
}
/* Empty the abbrev table for a new compilation unit. */
-/* ARGSUSED */
static void
-dwarf2_empty_abbrev_table (PTR ptr_to_abbrevs_table)
+dwarf2_empty_abbrev_table (void *ptr_to_abbrevs_table)
{
int i;
struct abbrev_info *abbrev, *next;
/* Lookup an abbrev_info structure in the abbrev hash table. */
static struct abbrev_info *
-dwarf2_lookup_abbrev (unsigned int number, const struct comp_unit_head *cu_header)
+dwarf2_lookup_abbrev (unsigned int number, struct dwarf2_cu *cu)
{
+ struct comp_unit_head *cu_header = &cu->header;
unsigned int hash_number;
struct abbrev_info *abbrev;
static char *
read_partial_die (struct partial_die_info *part_die, bfd *abfd,
- char *info_ptr, const struct comp_unit_head *cu_header)
+ char *info_ptr, struct dwarf2_cu *cu)
{
unsigned int abbrev_number, bytes_read, i;
struct abbrev_info *abbrev;
if (!abbrev_number)
return info_ptr;
- abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header);
+ abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
if (!abbrev)
{
- error ("Dwarf Error: Could not find abbrev number %d.", abbrev_number);
+ error ("Dwarf Error: Could not find abbrev number %d [in module %s]", abbrev_number,
+ bfd_get_filename (abfd));
}
part_die->offset = info_ptr - dwarf_info_buffer;
part_die->tag = abbrev->tag;
for (i = 0; i < abbrev->num_attrs; ++i)
{
- info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd,
- info_ptr, cu_header);
+ info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, info_ptr, cu);
/* Store the data if it is of an attribute we want to keep in a
partial symbol table. */
}
else if (attr.form == DW_FORM_data4 || attr.form == DW_FORM_data8)
{
- complain (&dwarf2_complex_location_expr);
+ dwarf2_complex_location_expr_complaint ();
}
else
{
- complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
- "partial symbol information");
+ dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
+ "partial symbol information");
}
break;
case DW_AT_language:
/* 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);
{
struct partial_die_info spec_die;
char *spec_ptr;
- int dummy;
spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr);
- read_partial_die (&spec_die, abfd, spec_ptr, cu_header);
+ read_partial_die (&spec_die, abfd, spec_ptr, cu);
if (spec_die.name)
{
part_die->name = spec_die.name;
return info_ptr;
}
-/* Read the die from the .debug_info section buffer. And set diep to
- point to a newly allocated die with its information. */
+/* Read the die from the .debug_info section buffer. Set DIEP to
+ point to a newly allocated die with its information, except for its
+ child, sibling, and parent fields. Set HAS_CHILDREN to tell
+ whether the die has children or not. */
static char *
read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
- const struct comp_unit_head *cu_header)
+ struct dwarf2_cu *cu, int *has_children)
{
unsigned int abbrev_number, bytes_read, i, offset;
struct abbrev_info *abbrev;
die->abbrev = abbrev_number;
die->type = NULL;
*diep = die;
+ *has_children = 0;
return info_ptr;
}
- abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header);
+ abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
if (!abbrev)
{
- error ("Dwarf Error: could not find abbrev number %d.", abbrev_number);
+ error ("Dwarf Error: could not find abbrev number %d [in module %s]",
+ abbrev_number,
+ bfd_get_filename (abfd));
}
die = dwarf_alloc_die ();
die->offset = offset;
die->tag = abbrev->tag;
- die->has_children = abbrev->has_children;
die->abbrev = abbrev_number;
die->type = NULL;
for (i = 0; i < abbrev->num_attrs; ++i)
{
info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
- abfd, info_ptr, cu_header);
+ abfd, info_ptr, cu);
}
*diep = die;
+ *has_children = abbrev->has_children;
return info_ptr;
}
static char *
read_attribute_value (struct attribute *attr, unsigned form,
- bfd *abfd, char *info_ptr,
- const struct comp_unit_head *cu_header)
+ bfd *abfd, char *info_ptr,
+ struct dwarf2_cu *cu)
{
+ struct comp_unit_head *cu_header = &cu->header;
unsigned int bytes_read;
struct dwarf_block *blk;
{
case DW_FORM_addr:
case DW_FORM_ref_addr:
- DW_ADDR (attr) = read_address (abfd, info_ptr, cu_header, &bytes_read);
+ DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_block2:
case DW_FORM_indirect:
form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
- info_ptr = read_attribute_value (attr, form, abfd, info_ptr, cu_header);
+ info_ptr = read_attribute_value (attr, form, abfd, info_ptr, cu);
break;
default:
- error ("Dwarf Error: Cannot handle %s in DWARF reader.",
- dwarf_form_name (form));
+ error ("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]",
+ dwarf_form_name (form),
+ bfd_get_filename (abfd));
}
return info_ptr;
}
static char *
read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
- bfd *abfd, char *info_ptr,
- const struct comp_unit_head *cu_header)
+ bfd *abfd, char *info_ptr, struct dwarf2_cu *cu)
{
attr->name = abbrev->name;
- return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu_header);
+ return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu);
}
/* read dwarf information from a buffer */
}
static CORE_ADDR
-read_address (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
- int *bytes_read)
+read_address (bfd *abfd, char *buf, struct dwarf2_cu *cu, int *bytes_read)
{
+ struct comp_unit_head *cu_header = &cu->header;
CORE_ADDR retval = 0;
if (cu_header->signed_addr_p)
break;
default:
internal_error (__FILE__, __LINE__,
- "read_address: bad switch, signed");
+ "read_address: bad switch, signed [in module %s]",
+ bfd_get_filename (abfd));
}
}
else
break;
default:
internal_error (__FILE__, __LINE__,
- "read_address: bad switch, unsigned");
+ "read_address: bad switch, unsigned [in module %s]",
+ bfd_get_filename (abfd));
}
}
break;
default:
internal_error (__FILE__, __LINE__,
- "read_offset: bad switch");
+ "read_offset: bad switch [in module %s]",
+ bfd_get_filename (abfd));
}
return retval;
if (dwarf_str_buffer == NULL)
{
- error ("DW_FORM_strp used without .debug_str section");
+ error ("DW_FORM_strp used without .debug_str section [in module %s]",
+ bfd_get_filename (abfd));
return NULL;
}
if (str_offset >= dwarf_str_size)
{
- error ("DW_FORM_strp pointing outside of .debug_str section");
+ error ("DW_FORM_strp pointing outside of .debug_str section [in module %s]",
+ bfd_get_filename (abfd));
return NULL;
}
gdb_assert (HOST_CHAR_BIT == 8);
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);
freed. */
static struct line_header *
dwarf_decode_line_header (unsigned int offset, bfd *abfd,
- const struct comp_unit_head *cu_header)
+ struct dwarf2_cu *cu)
{
struct cleanup *back_to;
struct line_header *lh;
if (dwarf_line_buffer == NULL)
{
- complain (&dwarf2_missing_line_number_section);
+ complaint (&symfile_complaints, "missing .debug_line section");
return 0;
}
could be 12 bytes long, but we're just going to fudge that. */
if (offset + 4 >= dwarf_line_size)
{
- complain (&dwarf2_statement_list_fits_in_line_number_section);
+ dwarf2_statement_list_fits_in_line_number_section_complaint ();
return 0;
}
line_ptr += bytes_read;
if (line_ptr + lh->total_length > dwarf_line_buffer + dwarf_line_size)
{
- complain (&dwarf2_statement_list_fits_in_line_number_section);
+ dwarf2_statement_list_fits_in_line_number_section_complaint ();
return 0;
}
lh->statement_program_end = line_ptr + lh->total_length;
lh->version = read_2_bytes (abfd, line_ptr);
line_ptr += 2;
- lh->header_length = read_offset (abfd, line_ptr, cu_header, &bytes_read);
+ lh->header_length = read_offset (abfd, line_ptr, &cu->header, &bytes_read);
line_ptr += bytes_read;
lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
line_ptr += 1;
lh->statement_program_start = line_ptr;
if (line_ptr > dwarf_line_buffer + dwarf_line_size)
- complain (&dwarf2_line_header_too_long);
+ complaint (&symfile_complaints,
+ "line number info header doesn't fit in `.debug_line' section");
discard_cleanups (back_to);
return lh;
if (fn->seen_line)
return address;
if (address != fn->lowpc)
- complain (&dwarf2_misplaced_line_number,
- (unsigned long) address, fn->name);
+ complaint (&symfile_complaints,
+ "misplaced first line number at 0x%lx for '%s'",
+ (unsigned long) address, fn->name);
fn->seen_line = 1;
return fn->lowpc;
}
static void
dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
- const struct comp_unit_head *cu_header)
+ struct dwarf2_cu *cu)
{
char *line_ptr;
char *line_end;
- unsigned int i, bytes_read;
- char *cur_dir;
+ unsigned int bytes_read;
unsigned char op_code, extended_op, adj_opcode;
line_ptr = lh->statement_program_start;
* lh->minimum_instruction_length;
line += lh->line_base + (adj_opcode % lh->line_range);
/* append row to matrix using current values */
- address = check_cu_functions (address);
- record_line (current_subfile, line, address);
+ record_line (current_subfile, line,
+ check_cu_functions (address));
basic_block = 1;
}
else switch (op_code)
record_line (current_subfile, 0, address);
break;
case DW_LNE_set_address:
- address = read_address (abfd, line_ptr, cu_header, &bytes_read);
+ address = read_address (abfd, line_ptr, cu, &bytes_read);
line_ptr += bytes_read;
address += baseaddr;
break;
}
break;
default:
- complain (&dwarf2_mangled_line_number_section);
+ complaint (&symfile_complaints,
+ "mangled .debug_line section");
return;
}
break;
case DW_LNS_copy:
- address = check_cu_functions (address);
- record_line (current_subfile, line, address);
+ record_line (current_subfile, line,
+ check_cu_functions (address));
basic_block = 0;
break;
case DW_LNS_advance_pc:
start_subfile (filename, dirname);
}
+static void
+var_decode_location (struct attribute *attr, struct symbol *sym,
+ struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+ struct comp_unit_head *cu_header = &cu->header;
+
+ /* NOTE drow/2003-01-30: There used to be a comment and some special
+ code here to turn a symbol with DW_AT_external and a
+ SYMBOL_VALUE_ADDRESS of 0 into a LOC_UNRESOLVED symbol. This was
+ necessary for platforms (maybe Alpha, certainly PowerPC GNU/Linux
+ with some versions of binutils) where shared libraries could have
+ relocations against symbols in their debug information - the
+ minimal symbol would have the right address, but the debug info
+ would not. It's no longer necessary, because we will explicitly
+ apply relocations when we read in the debug information now. */
+
+ /* A DW_AT_location attribute with no contents indicates that a
+ variable has been optimized away. */
+ if (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0)
+ {
+ SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
+ return;
+ }
+
+ /* Handle one degenerate form of location expression specially, to
+ preserve GDB's previous behavior when section offsets are
+ specified. If this is just a DW_OP_addr then mark this symbol
+ as LOC_STATIC. */
+
+ if (attr_form_is_block (attr)
+ && DW_BLOCK (attr)->size == 1 + cu_header->addr_size
+ && DW_BLOCK (attr)->data[0] == DW_OP_addr)
+ {
+ int dummy;
+
+ SYMBOL_VALUE_ADDRESS (sym) =
+ read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu, &dummy);
+ fixup_symbol_section (sym, objfile);
+ SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets,
+ SYMBOL_SECTION (sym));
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ return;
+ }
+
+ /* NOTE drow/2002-01-30: It might be worthwhile to have a static
+ expression evaluator, and use LOC_COMPUTED only when necessary
+ (i.e. when the value of a register or memory location is
+ referenced, or a thread-local block, etc.). Then again, it might
+ not be worthwhile. I'm assuming that it isn't unless performance
+ or memory numbers show me otherwise. */
+
+ dwarf2_symbol_mark_computed (attr, sym, cu);
+ SYMBOL_CLASS (sym) = LOC_COMPUTED;
+}
+
/* Given a pointer to a DWARF information entry, figure out if we need
to make a symbol table entry for it, and if so, create a new entry
and return a pointer to it.
used the passed type. */
static struct symbol *
-new_symbol (struct die_info *die, struct type *type, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct symbol *sym = NULL;
char *name;
struct attribute *attr = NULL;
struct attribute *attr2 = NULL;
- CORE_ADDR addr = 0;
- name = dwarf2_linkage_name (die);
+ if (die->tag != DW_TAG_namespace)
+ name = dwarf2_linkage_name (die);
+ else
+ name = TYPE_NAME (type);
+
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;
else
- SYMBOL_TYPE (sym) = die_type (die, objfile, cu_header);
+ SYMBOL_TYPE (sym) = die_type (die, cu);
attr = dwarf_attr (die, DW_AT_decl_line);
if (attr)
{
SYMBOL_LINE (sym) = DW_UNSND (attr);
}
-
- /* If this symbol is from a C++ compilation, then attempt to
- cache the demangled form for future reference. This is a
- typical time versus space tradeoff, that was decided in favor
- of time because it sped up C++ symbol lookups by a factor of
- about 20. */
-
- SYMBOL_LANGUAGE (sym) = cu_language;
- SYMBOL_INIT_DEMANGLED_NAME (sym, &objfile->symbol_obstack);
switch (die->tag)
{
case DW_TAG_label:
attr = dwarf_attr (die, DW_AT_const_value);
if (attr)
{
- dwarf2_const_value (attr, sym, objfile, cu_header);
+ dwarf2_const_value (attr, sym, cu);
attr2 = dwarf_attr (die, DW_AT_external);
if (attr2 && (DW_UNSND (attr2) != 0))
add_symbol_to_list (sym, &global_symbols);
attr = dwarf_attr (die, DW_AT_location);
if (attr)
{
+ var_decode_location (attr, sym, cu);
attr2 = dwarf_attr (die, DW_AT_external);
if (attr2 && (DW_UNSND (attr2) != 0))
- {
- /* Support the .debug_loc offsets */
- if (attr_form_is_block (attr))
- {
- SYMBOL_VALUE_ADDRESS (sym) =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
- }
- else if (attr->form == DW_FORM_data4
- || attr->form == DW_FORM_data8)
- {
- complain (&dwarf2_complex_location_expr);
- }
- else
- {
- complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
- "external variable");
- }
- add_symbol_to_list (sym, &global_symbols);
- if (is_thread_local)
- {
- /* SYMBOL_VALUE_ADDRESS contains at this point the
- offset of the variable within the thread local
- storage. */
- SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
- SYMBOL_OBJFILE (sym) = objfile;
- }
-
- /* 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. */
- else if (SYMBOL_VALUE_ADDRESS (sym))
- {
- fixup_symbol_section (sym, objfile);
- SYMBOL_VALUE_ADDRESS (sym) +=
- ANOFFSET (objfile->section_offsets,
- SYMBOL_SECTION (sym));
- SYMBOL_CLASS (sym) = LOC_STATIC;
- }
- else
- SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
- }
+ add_symbol_to_list (sym, &global_symbols);
else
- {
- /* Support the .debug_loc offsets */
- if (attr_form_is_block (attr))
- {
- SYMBOL_VALUE (sym) = addr =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
- }
- else if (attr->form == DW_FORM_data4
- || attr->form == DW_FORM_data8)
- {
- complain (&dwarf2_complex_location_expr);
- }
- else
- {
- complain (&dwarf2_invalid_attrib_class, "DW_AT_location",
- "external variable");
- addr = 0;
- }
- add_symbol_to_list (sym, list_in_scope);
- if (optimized_out)
- {
- SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
- }
- else if (isreg)
- {
- SYMBOL_CLASS (sym) = LOC_REGISTER;
- SYMBOL_VALUE (sym) =
- DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
- }
- else if (offreg)
- {
- SYMBOL_CLASS (sym) = LOC_BASEREG;
- SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
- }
- else if (islocal)
- {
- SYMBOL_CLASS (sym) = LOC_LOCAL;
- }
- else if (is_thread_local)
- {
- SYMBOL_CLASS (sym) = LOC_THREAD_LOCAL_STATIC;
- SYMBOL_OBJFILE (sym) = objfile;
- }
- 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
{
attr = dwarf_attr (die, DW_AT_location);
if (attr)
{
- SYMBOL_VALUE (sym) =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
- if (isreg)
- {
- SYMBOL_CLASS (sym) = LOC_REGPARM;
- SYMBOL_VALUE (sym) =
- DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
- }
- else if (offreg)
- {
- if (isderef)
- {
- if (basereg != frame_base_reg)
- complain (&dwarf2_complex_location_expr);
- SYMBOL_CLASS (sym) = LOC_REF_ARG;
- }
- else
- {
- SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
- SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
- }
- }
- else
- {
- SYMBOL_CLASS (sym) = LOC_ARG;
- }
+ var_decode_location (attr, sym, cu);
+ /* FIXME drow/2003-07-31: Is LOC_COMPUTED_ARG necessary? */
+ if (SYMBOL_CLASS (sym) == LOC_COMPUTED)
+ SYMBOL_CLASS (sym) = LOC_COMPUTED_ARG;
}
attr = dwarf_attr (die, DW_AT_const_value);
if (attr)
{
- dwarf2_const_value (attr, sym, objfile, cu_header);
+ dwarf2_const_value (attr, sym, cu);
}
add_symbol_to_list (sym, list_in_scope);
break;
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
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);
}
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:
attr = dwarf_attr (die, DW_AT_const_value);
if (attr)
{
- dwarf2_const_value (attr, sym, objfile, cu_header);
+ dwarf2_const_value (attr, sym, cu);
}
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;
}
}
static void
dwarf2_const_value (struct attribute *attr, struct symbol *sym,
- struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+ struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
+ struct comp_unit_head *cu_header = &cu->header;
struct dwarf_block *blk;
switch (attr->form)
{
case DW_FORM_addr:
if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != cu_header->addr_size)
- complain (&dwarf2_const_value_length_mismatch, SYMBOL_NAME (sym),
- cu_header->addr_size, TYPE_LENGTH (SYMBOL_TYPE (sym)));
+ dwarf2_const_value_length_mismatch_complaint (DEPRECATED_SYMBOL_NAME (sym),
+ cu_header->addr_size,
+ TYPE_LENGTH (SYMBOL_TYPE
+ (sym)));
SYMBOL_VALUE_BYTES (sym) = (char *)
obstack_alloc (&objfile->symbol_obstack, cu_header->addr_size);
- store_address (SYMBOL_VALUE_BYTES (sym), cu_header->addr_size,
- DW_ADDR (attr));
+ /* 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:
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);
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;
/* Return the type of the die in question using its DW_AT_type attribute. */
static struct type *
-die_type (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+die_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *type;
struct attribute *type_attr;
if (!type_attr)
{
/* A missing DW_AT_type represents a void type. */
- return dwarf2_fundamental_type (objfile, FT_VOID);
+ return dwarf2_fundamental_type (cu->objfile, FT_VOID);
}
else
{
type_die = follow_die_ref (ref);
if (!type_die)
{
- error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+ error ("Dwarf Error: Cannot find referent at offset %d [in module %s]",
+ ref, cu->objfile->name);
return NULL;
}
}
- type = tag_type_to_type (type_die, objfile, cu_header);
+ type = tag_type_to_type (type_die, cu);
if (!type)
{
dump_die (type_die);
- error ("Dwarf Error: Problem turning type die at offset into gdb type.");
+ error ("Dwarf Error: Problem turning type die at offset into gdb type [in module %s]",
+ cu->objfile->name);
}
return type;
}
DW_AT_containing_type attribute. */
static struct type *
-die_containing_type (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+die_containing_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *type = NULL;
struct attribute *type_attr;
type_die = follow_die_ref (ref);
if (!type_die)
{
- error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+ error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", ref,
+ cu->objfile->name);
return NULL;
}
- type = tag_type_to_type (type_die, objfile, cu_header);
+ type = tag_type_to_type (type_die, cu);
}
if (!type)
{
if (type_die)
dump_die (type_die);
- error ("Dwarf Error: Problem turning containing type into gdb type.");
+ error ("Dwarf Error: Problem turning containing type into gdb type [in module %s]",
+ cu->objfile->name);
}
return type;
}
#if 0
static struct type *
-type_at_offset (unsigned int offset, struct objfile *objfile)
+type_at_offset (unsigned int offset, struct dwarf2_cu *cu)
{
struct die_info *die;
struct type *type;
error ("Dwarf Error: Cannot find type referent at offset %d.", offset);
return NULL;
}
- type = tag_type_to_type (die, objfile);
+ type = tag_type_to_type (die, cu);
return type;
}
#endif
static struct type *
-tag_type_to_type (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+tag_type_to_type (struct die_info *die, struct dwarf2_cu *cu)
{
if (die->type)
{
}
else
{
- read_type_die (die, objfile, cu_header);
+ read_type_die (die, cu);
if (!die->type)
{
dump_die (die);
- error ("Dwarf Error: Cannot find type of die.");
+ error ("Dwarf Error: Cannot find type of die [in module %s]",
+ cu->objfile->name);
}
return die->type;
}
}
static void
-read_type_die (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_type_die (struct die_info *die, struct dwarf2_cu *cu)
{
switch (die->tag)
{
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
- read_structure_scope (die, objfile, cu_header);
+ read_structure_scope (die, cu);
break;
case DW_TAG_enumeration_type:
- read_enumeration (die, objfile, cu_header);
+ read_enumeration (die, cu);
break;
case DW_TAG_subprogram:
case DW_TAG_subroutine_type:
- read_subroutine_type (die, objfile, cu_header);
+ read_subroutine_type (die, cu);
break;
case DW_TAG_array_type:
- read_array_type (die, objfile, cu_header);
+ read_array_type (die, cu);
break;
case DW_TAG_pointer_type:
- read_tag_pointer_type (die, objfile, cu_header);
+ read_tag_pointer_type (die, cu);
break;
case DW_TAG_ptr_to_member_type:
- read_tag_ptr_to_member_type (die, objfile, cu_header);
+ read_tag_ptr_to_member_type (die, cu);
break;
case DW_TAG_reference_type:
- read_tag_reference_type (die, objfile, cu_header);
+ read_tag_reference_type (die, cu);
break;
case DW_TAG_const_type:
- read_tag_const_type (die, objfile, cu_header);
+ read_tag_const_type (die, cu);
break;
case DW_TAG_volatile_type:
- read_tag_volatile_type (die, objfile, cu_header);
+ read_tag_volatile_type (die, cu);
break;
case DW_TAG_string_type:
- read_tag_string_type (die, objfile);
+ read_tag_string_type (die, cu);
break;
case DW_TAG_typedef:
- read_typedef (die, objfile, cu_header);
+ read_typedef (die, cu);
break;
case DW_TAG_base_type:
- read_base_type (die, objfile);
+ read_base_type (die, cu);
break;
default:
- complain (&dwarf2_unexpected_tag, dwarf_tag_name (die->tag));
+ complaint (&symfile_complaints, "unexepected tag in read_type_die: '%s'",
+ dwarf_tag_name (die->tag));
break;
}
}
static struct type *
-dwarf_base_type (int encoding, int size, struct objfile *objfile)
+dwarf_base_type (int encoding, int size, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
+
/* FIXME - this should not produce a new (struct type *)
every time. It should cache base types. */
struct type *type;
static struct die_info *
sibling_die (struct die_info *die)
{
- int nesting_level = 0;
-
- if (!die->has_children)
- {
- if (die->next && (die->next->tag == 0))
- {
- return NULL;
- }
- else
- {
- return die->next;
- }
- }
- else
- {
- do
- {
- if (die->has_children)
- {
- nesting_level++;
- }
- if (die->tag == 0)
- {
- nesting_level--;
- }
- die = die->next;
- }
- while (nesting_level);
- if (die && (die->tag == 0))
- {
- return NULL;
- }
- else
- {
- return die;
- }
- }
+ return die->sibling;
}
/* Get linkage name of a die, return NULL if not found. */
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)
{
/* Convert a DWARF attribute code into its string name. */
static char *
-dwarf_attr_name (register unsigned attr)
+dwarf_attr_name (unsigned attr)
{
switch (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";
/* 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)
{
/* 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)
{
/* 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)
{
#if 0
static char *
-dwarf_cfi_name (register unsigned cfi_opc)
+dwarf_cfi_name (unsigned cfi_opc)
{
switch (cfi_opc)
{
fprintf_unfiltered (gdb_stderr, "Die: %s (abbrev = %d, offset = %d)\n",
dwarf_tag_name (die->tag), die->abbrev, die->offset);
fprintf_unfiltered (gdb_stderr, "\thas children: %s\n",
- dwarf_bool_name (die->has_children));
+ dwarf_bool_name (die->child != NULL));
fprintf_unfiltered (gdb_stderr, "\tattributes:\n");
for (i = 0; i < die->num_attrs; ++i)
while (die)
{
dump_die (die);
- die = die->next;
+ if (die->child != NULL)
+ dump_die_list (die->child);
+ if (die->sibling != NULL)
+ dump_die_list (die->sibling);
}
}
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;
}
{
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
Given a pointer to a dwarf block that defines a location, compute
the location and return the value.
- FIXME: This is a kludge until we figure out a better
- way to handle the location descriptions.
- Gdb's design does not mesh well with the DWARF2 notion of a location
- computing interpreter, which is a shame because the flexibility goes unused.
- FIXME: Implement more operations as necessary.
+ NOTE drow/2003-11-18: This function is called in two situations
+ now: for the address of static or global variables (partial symbols
+ only) and for offsets into structures which are expected to be
+ (more or less) constant. The partial symbol case should go away,
+ and only the constant case should remain. That will let this
+ function complain more accurately. A few special modes are allowed
+ without complaint for global variables (for instance, global
+ register values and thread-local values).
A location description containing no operations indicates that the
- object is optimized out. The global optimized_out flag is set for
- those, the return value is meaningless.
+ object is optimized out. The return value is 0 for that case.
+ FIXME drow/2003-11-16: No callers check for this case any more; soon all
+ callers will only want a very basic result and this can become a
+ complaint.
When the result is a register number, the global isreg flag is set,
otherwise it is cleared.
- When the result is a base register offset, the global offreg flag is set
- and the register number is returned in basereg, otherwise it is cleared.
-
- When the DW_OP_fbreg operation is encountered without a corresponding
- DW_AT_frame_base attribute, the global islocal flag is set.
- Hopefully the machine dependent code knows how to set up a virtual
- frame pointer for the local references.
-
Note that stack[0] is unused except as a default error return.
Note that stack overflow is not yet handled. */
static CORE_ADDR
-decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
+ struct comp_unit_head *cu_header = &cu->header;
int i;
int size = blk->size;
char *data = blk->data;
stacki = 0;
stack[stacki] = 0;
isreg = 0;
- offreg = 0;
- isderef = 0;
- islocal = 0;
- is_thread_local = 0;
- optimized_out = 1;
while (i < size)
{
- optimized_out = 0;
op = data[i++];
switch (op)
{
case DW_OP_reg31:
isreg = 1;
stack[++stacki] = op - DW_OP_reg0;
+ if (i < size)
+ dwarf2_complex_location_expr_complaint ();
break;
case DW_OP_regx:
unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
i += bytes_read;
stack[++stacki] = unsnd;
- break;
-
- case DW_OP_breg0:
- case DW_OP_breg1:
- case DW_OP_breg2:
- case DW_OP_breg3:
- case DW_OP_breg4:
- case DW_OP_breg5:
- case DW_OP_breg6:
- case DW_OP_breg7:
- case DW_OP_breg8:
- case DW_OP_breg9:
- case DW_OP_breg10:
- case DW_OP_breg11:
- case DW_OP_breg12:
- case DW_OP_breg13:
- case DW_OP_breg14:
- case DW_OP_breg15:
- case DW_OP_breg16:
- case DW_OP_breg17:
- case DW_OP_breg18:
- case DW_OP_breg19:
- case DW_OP_breg20:
- case DW_OP_breg21:
- case DW_OP_breg22:
- case DW_OP_breg23:
- case DW_OP_breg24:
- case DW_OP_breg25:
- case DW_OP_breg26:
- case DW_OP_breg27:
- case DW_OP_breg28:
- case DW_OP_breg29:
- case DW_OP_breg30:
- case DW_OP_breg31:
- offreg = 1;
- basereg = op - DW_OP_breg0;
- stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
- i += bytes_read;
- break;
-
- case DW_OP_bregx:
- offreg = 1;
- basereg = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
- i += bytes_read;
- stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
- i += bytes_read;
- break;
-
- case DW_OP_fbreg:
- stack[++stacki] = read_signed_leb128 (NULL, (data + i), &bytes_read);
- i += bytes_read;
- if (frame_base_reg >= 0)
- {
- offreg = 1;
- basereg = frame_base_reg;
- stack[stacki] += frame_base_offset;
- }
- else
- {
- complain (&dwarf2_missing_at_frame_base);
- islocal = 1;
- }
+ if (i < size)
+ dwarf2_complex_location_expr_complaint ();
break;
case DW_OP_addr:
stack[++stacki] = read_address (objfile->obfd, &data[i],
- cu_header, &bytes_read);
+ cu, &bytes_read);
i += bytes_read;
break;
break;
case DW_OP_deref:
- isderef = 1;
/* If we're not the last op, then we definitely can't encode
- this using GDB's address_class enum. */
+ this using GDB's address_class enum. This is valid for partial
+ global symbols, although the variable's address will be bogus
+ in the psymtab. */
if (i < size)
- complain (&dwarf2_complex_location_expr);
+ dwarf2_complex_location_expr_complaint ();
break;
case DW_OP_GNU_push_tls_address:
- is_thread_local = 1;
/* The top of the stack has the offset from the beginning
of the thread control block at which the variable is located. */
/* Nothing should follow this operator, so the top of stack would
be returned. */
+ /* This is valid for partial global symbols, but the variable's
+ address will be bogus in the psymtab. */
if (i < size)
- complain (&dwarf2_complex_location_expr);
+ 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]);
}
}
/* memory allocation interface */
-/* ARGSUSED */
static void
-dwarf2_free_tmp_obstack (PTR ignore)
+dwarf2_free_tmp_obstack (void *ignore)
{
obstack_free (&dwarf2_tmp_obstack, NULL);
}
{
if (*p == ' ')
{
- complain (&dwarf2_macro_spaces_in_definition, body);
+ complaint (&symfile_complaints,
+ "macro definition contains spaces in formal argument list:\n`%s'",
+ body);
while (*p == ' ')
p++;
replacement = body + name_len + 1;
else
{
- complain (&dwarf2_macro_malformed_definition, body);
+ dwarf2_macro_malformed_definition_complaint (body);
replacement = body + name_len;
}
p++;
if (! *p || p == arg_start)
- complain (&dwarf2_macro_malformed_definition,
- body);
+ dwarf2_macro_malformed_definition_complaint (body);
else
{
/* Make sure argv has room for the new argument. */
else if (*p == '\0')
{
/* Complain, but do define it. */
- complain (&dwarf2_macro_malformed_definition, body);
+ dwarf2_macro_malformed_definition_complaint (body);
macro_define_function (file, line, name,
argc, (const char **) argv,
p);
}
else
/* Just complain. */
- complain (&dwarf2_macro_malformed_definition, body);
+ dwarf2_macro_malformed_definition_complaint (body);
}
else
/* Just complain. */
- complain (&dwarf2_macro_malformed_definition, body);
+ dwarf2_macro_malformed_definition_complaint (body);
xfree (name);
{
xfree (argv);
}
else
- complain (&dwarf2_macro_malformed_definition, body);
+ dwarf2_macro_malformed_definition_complaint (body);
}
static void
dwarf_decode_macros (struct line_header *lh, unsigned int offset,
char *comp_dir, bfd *abfd,
- const struct comp_unit_head *cu_header,
- struct objfile *objfile)
+ struct dwarf2_cu *cu)
{
char *mac_ptr, *mac_end;
struct macro_source_file *current_file = 0;
if (dwarf_macinfo_buffer == NULL)
{
- complain (&dwarf2_missing_macinfo_section);
+ complaint (&symfile_complaints, "missing .debug_macinfo section");
return;
}
/* Do we at least have room for a macinfo type byte? */
if (mac_ptr >= mac_end)
{
- complain (&dwarf2_macros_too_long);
+ dwarf2_macros_too_long_complaint ();
return;
}
mac_ptr += bytes_read;
if (! current_file)
- complain (&dwarf2_macro_outside_file,
- macinfo_type == DW_MACINFO_define ? "definition" :
- macinfo_type == DW_MACINFO_undef ? "undefinition" :
- "something-or-other",
- body);
+ complaint (&symfile_complaints,
+ "debug info gives macro %s outside of any file: %s",
+ macinfo_type ==
+ DW_MACINFO_define ? "definition" : macinfo_type ==
+ DW_MACINFO_undef ? "undefinition" :
+ "something-or-other", body);
else
{
if (macinfo_type == DW_MACINFO_define)
current_file = macro_start_file (file, line,
current_file, comp_dir,
- lh, objfile);
+ lh, cu->objfile);
}
break;
case DW_MACINFO_end_file:
if (! current_file)
- complain (&dwarf2_macro_unmatched_end_file);
+ complaint (&symfile_complaints,
+ "macro debug info has an unmatched `close_file' directive");
else
{
current_file = current_file->included_by;
/* Do we at least have room for a macinfo type byte? */
if (mac_ptr >= mac_end)
{
- complain (&dwarf2_macros_too_long);
+ dwarf2_macros_too_long_complaint ();
return;
}
a look-ahead. */
next_type = read_1_byte (abfd, mac_ptr);
if (next_type != 0)
- complain (&dwarf2_macros_not_terminated);
+ complaint (&symfile_complaints,
+ "no terminating 0-type entry for macros in `.debug_macinfo' section");
return;
}
|| attr->form == DW_FORM_block4
|| attr->form == DW_FORM_block);
}
+
+static void
+dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+ struct dwarf2_cu *cu)
+{
+ if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+ {
+ struct dwarf2_loclist_baton *baton;
+
+ baton = obstack_alloc (&cu->objfile->symbol_obstack,
+ sizeof (struct dwarf2_loclist_baton));
+ baton->objfile = cu->objfile;
+
+ /* We don't know how long the location list is, but make sure we
+ don't run off the edge of the section. */
+ baton->size = 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 (&cu->objfile->symbol_obstack,
+ sizeof (struct dwarf2_locexpr_baton));
+ baton->objfile = cu->objfile;
+
+ if (attr_form_is_block (attr))
+ {
+ /* Note that we're just copying the block's data pointer
+ here, not the actual data. We're still pointing into the
+ 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;
+ }
+}