/* DWARF 2 debugging format support for GDB.
- Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004
Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
#include "bfd.h"
#include "symtab.h"
#include "gdbtypes.h"
-#include "symfile.h"
#include "objfiles.h"
#include "elf/dwarf2.h"
#include "buildsym.h"
#include "expression.h"
#include "filenames.h" /* for DOSish file names */
#include "macrotab.h"
-
#include "language.h"
#include "complaints.h"
#include "bcache.h"
+#include "dwarf2expr.h"
+#include "dwarf2loc.h"
+#include "cp-support.h"
+#include "hashtab.h"
+
#include <fcntl.h>
#include "gdb_string.h"
#include "gdb_assert.h"
#include <sys/types.h>
+/* A note on memory usage for this file.
+
+ At the present time, this code reads the debug info sections into
+ the objfile's objfile_obstack. A definite improvement for startup
+ time, on platforms which do not emit relocations for debug
+ sections, would be to use mmap instead. The object's complete
+ debug information is loaded into memory, partly to simplify
+ absolute DIE references.
+
+ Whether using obstacks or mmap, the sections should remain loaded
+ until the objfile is released, and pointers into the section data
+ can be used for any other data associated to the objfile (symbol
+ names, type names, location expressions to name a few). */
+
#ifndef DWARF2_REG_TO_REGNUM
#define DWARF2_REG_TO_REGNUM(REG) (REG)
#endif
}
_STATEMENT_PROLOGUE;
-/* offsets and sizes of debugging sections */
-
-static file_ptr dwarf_info_offset;
-static file_ptr dwarf_abbrev_offset;
-static file_ptr dwarf_line_offset;
-static file_ptr dwarf_pubnames_offset;
-static file_ptr dwarf_aranges_offset;
-static file_ptr dwarf_loc_offset;
-static file_ptr dwarf_macinfo_offset;
-static file_ptr dwarf_str_offset;
-static file_ptr dwarf_ranges_offset;
-file_ptr dwarf_frame_offset;
-file_ptr dwarf_eh_frame_offset;
-
-static unsigned int dwarf_info_size;
-static unsigned int dwarf_abbrev_size;
-static unsigned int dwarf_line_size;
-static unsigned int dwarf_pubnames_size;
-static unsigned int dwarf_aranges_size;
-static unsigned int dwarf_loc_size;
-static unsigned int dwarf_macinfo_size;
-static unsigned int dwarf_str_size;
-static unsigned int dwarf_ranges_size;
-unsigned int dwarf_frame_size;
-unsigned int dwarf_eh_frame_size;
+static const struct objfile_data *dwarf2_objfile_data_key;
+
+struct dwarf2_per_objfile
+{
+ /* Sizes of debugging sections. */
+ unsigned int info_size;
+ unsigned int abbrev_size;
+ unsigned int line_size;
+ unsigned int pubnames_size;
+ unsigned int aranges_size;
+ unsigned int loc_size;
+ unsigned int macinfo_size;
+ unsigned int str_size;
+ unsigned int ranges_size;
+ unsigned int frame_size;
+ unsigned int eh_frame_size;
+
+ /* Loaded data from the sections. */
+ char *info_buffer;
+ char *abbrev_buffer;
+ char *line_buffer;
+ char *str_buffer;
+ char *macinfo_buffer;
+ char *ranges_buffer;
+ char *loc_buffer;
+};
+
+static struct dwarf2_per_objfile *dwarf2_per_objfile;
static asection *dwarf_info_section;
static asection *dwarf_abbrev_section;
struct comp_unit_head *next;
- /* DWARF abbreviation table associated with this compilation unit */
+ /* Base address of this compilation unit. */
- struct abbrev_info *dwarf2_abbrevs[ABBREV_HASH_SIZE];
+ CORE_ADDR base_address;
- /* Pointer to the DIE associated with the compilation unit. */
+ /* Non-zero if base_address has been set. */
- struct die_info *die;
+ int base_known;
};
+/* Internal state when decoding a particular compilation unit. */
+struct dwarf2_cu
+{
+ /* The objfile containing this compilation unit. */
+ struct objfile *objfile;
+
+ /* The header of the compilation unit.
+
+ FIXME drow/2003-11-10: Some of the things from the comp_unit_head
+ should logically be moved to the dwarf2_cu structure. */
+ struct comp_unit_head header;
+
+ struct function_range *first_fn, *last_fn, *cached_fn;
+
+ /* The language we are debugging. */
+ enum language language;
+ const struct language_defn *language_defn;
+
+ /* The generic symbol table building routines have separate lists for
+ file scope symbols and all all other scopes (local scopes). So
+ we need to select the right one to pass to add_symbol_to_list().
+ We do it by keeping a pointer to the correct list in list_in_scope.
+
+ FIXME: The original dwarf code just treated the file scope as the
+ first local scope, and all other local scopes as nested local
+ scopes, and worked fine. Check to see if we really need to
+ distinguish these in buildsym.c. */
+ struct pending **list_in_scope;
+
+ /* Maintain an array of referenced fundamental types for the current
+ compilation unit being read. For DWARF version 1, we have to construct
+ the fundamental types on the fly, since no information about the
+ fundamental types is supplied. Each such fundamental type is created by
+ calling a language dependent routine to create the type, and then a
+ pointer to that type is then placed in the array at the index specified
+ by it's FT_<TYPENAME> value. The array has a fixed size set by the
+ FT_NUM_MEMBERS compile time constant, which is the number of predefined
+ fundamental types gdb knows how to construct. */
+ struct type *ftypes[FT_NUM_MEMBERS]; /* Fundamental types */
+
+ /* DWARF abbreviation table associated with this compilation unit. */
+ struct abbrev_info **dwarf2_abbrevs;
+
+ /* Storage for the abbrev table. */
+ struct obstack abbrev_obstack;
+
+ /* Hash table holding all the loaded partial DIEs. */
+ htab_t partial_dies;
+
+ /* Storage for things with the same lifetime as this read-in compilation
+ unit, including partial DIEs. */
+ struct obstack comp_unit_obstack;
+
+ /* This flag will be set if this compilation unit includes any
+ DW_TAG_namespace DIEs. If we know that there are explicit
+ DIEs for namespaces, we don't need to try to infer them
+ from mangled names. */
+ unsigned int has_namespace_info : 1;
+};
+
/* The line number information for a compilation unit (found in the
.debug_line section) begins with a "statement program header",
which contains the following information. */
unsigned int dir_index;
unsigned int mod_time;
unsigned int length;
+ int included_p; /* Non-zero if referenced by the Line Number Program. */
} *file_names;
/* The start and end of the statement program following this
- header. These point into dwarf_line_buffer. */
+ header. These point into dwarf2_per_objfile->line_buffer. */
char *statement_program_start, *statement_program_end;
};
need this much information. */
struct partial_die_info
{
- enum dwarf_tag tag;
- unsigned char has_children;
- unsigned char is_external;
- unsigned char is_declaration;
- unsigned char has_type;
+ /* Offset of this DIE. */
unsigned int offset;
- unsigned int abbrev;
+
+ /* DWARF-2 tag for this DIE. */
+ ENUM_BITFIELD(dwarf_tag) tag : 16;
+
+ /* Language code associated with this DIE. This is only used
+ for the compilation unit DIE. */
+ unsigned int language : 8;
+
+ /* Assorted flags describing the data found in this DIE. */
+ unsigned int has_children : 1;
+ unsigned int is_external : 1;
+ unsigned int is_declaration : 1;
+ unsigned int has_type : 1;
+ unsigned int has_specification : 1;
+ unsigned int has_stmt_list : 1;
+ unsigned int has_pc_info : 1;
+
+ /* Flag set if the SCOPE field of this structure has been
+ computed. */
+ unsigned int scope_set : 1;
+
+ /* The name of this DIE. Normally the value of DW_AT_name, but
+ sometimes DW_TAG_MIPS_linkage_name or a string computed in some
+ other fashion. */
char *name;
- int has_pc_info;
+ char *dirname;
+
+ /* The scope to prepend to our children. This is generally
+ allocated on the comp_unit_obstack, so will disappear
+ when this compilation unit leaves the cache. */
+ char *scope;
+
+ /* The location description associated with this DIE, if any. */
+ struct dwarf_block *locdesc;
+
+ /* If HAS_PC_INFO, the PC range associated with this DIE. */
CORE_ADDR lowpc;
CORE_ADDR highpc;
- struct dwarf_block *locdesc;
- unsigned int language;
+
+ /* Pointer into the info_buffer pointing at the target of
+ DW_AT_sibling, if any. */
char *sibling;
+
+ /* If HAS_SPECIFICATION, the offset of the DIE referred to by
+ DW_AT_specification (or DW_AT_abstract_origin or
+ DW_AT_extension). */
+ unsigned int spec_offset;
+
+ /* If HAS_STMT_LIST, the offset of the Line Number Information data. */
+ unsigned int line_offset;
+
+ /* Pointers to this DIE's parent, first child, and next sibling,
+ if any. */
+ struct partial_die_info *die_parent, *die_child, *die_sibling;
};
/* This data structure holds the information of an abbrev. */
{
unsigned int number; /* number identifying abbrev */
enum dwarf_tag tag; /* dwarf tag */
- int has_children; /* boolean */
- unsigned int num_attrs; /* number of attributes */
+ unsigned short has_children; /* boolean */
+ unsigned short num_attrs; /* number of attributes */
struct attr_abbrev *attrs; /* an array of attribute descriptions */
struct abbrev_info *next; /* next in chain */
};
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 */
};
struct function_range *next;
};
-static struct function_range *cu_first_fn, *cu_last_fn, *cu_cached_fn;
-
/* Get at parts of an attribute structure */
#define DW_STRING(attr) ((attr)->u.str)
static struct die_info *die_ref_table[REF_HASH_SIZE];
-/* Obstack for allocating temporary storage used during symbol reading. */
-static struct obstack dwarf2_tmp_obstack;
-
-/* Offset to the first byte of the current compilation unit header,
- for resolving relative reference dies. */
-static unsigned int cu_header_offset;
-
/* Allocate fields for structs, unions and enums in this size. */
#ifndef DW_FIELD_ALLOC_CHUNK
#define DW_FIELD_ALLOC_CHUNK 4
#endif
-/* The language we are debugging. */
-static enum language cu_language;
-static const struct language_defn *cu_language_defn;
-
-/* Actually data from the sections. */
-static char *dwarf_info_buffer;
-static char *dwarf_abbrev_buffer;
-static char *dwarf_line_buffer;
-static char *dwarf_str_buffer;
-static char *dwarf_macinfo_buffer;
-static char *dwarf_ranges_buffer;
-
/* A zeroed version of a partial die for initialization purposes. */
static struct partial_die_info zeroed_partial_die;
-/* The generic symbol table building routines have separate lists for
- file scope symbols and all all other scopes (local scopes). So
- we need to select the right one to pass to add_symbol_to_list().
- We do it by keeping a pointer to the correct list in list_in_scope.
-
- FIXME: The original dwarf code just treated the file scope as the first
- local scope, and all other local scopes as nested local scopes, and worked
- fine. Check to see if we really need to distinguish these
- in buildsym.c. */
-static struct pending **list_in_scope = &file_symbols;
-
/* FIXME: decode_locdesc sets these variables to describe the location
to the caller. These ought to be a structure or something. If
none of the flags are set, the object lives at the address returned
by decode_locdesc. */
-static int optimized_out; /* No ops in location in expression,
- so object was optimized out. */
static int isreg; /* Object lives in register.
decode_locdesc's return value is
the register number. */
-static int offreg; /* Object's address is the sum of the
- register specified by basereg, plus
- the offset returned. */
-static int basereg; /* See `offreg'. */
-static int isderef; /* Value described by flags above is
- the address of a pointer to the object. */
-static int islocal; /* Variable is at the returned offset
- from the frame start, but there's
- no identified frame pointer for
- this function, so we can't say
- which register it's relative to;
- use LOC_LOCAL. */
-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,
- pass the appropriate section number to end_symtab). */
-static CORE_ADDR baseaddr; /* Add to each symbol value */
/* We put a pointer to this structure in the read_symtab_private field
- of the psymtab.
- The complete dwarf information for an objfile is kept in the
- psymbol_obstack, so that absolute die references can be handled.
- Most of the information in this structure is related to an entire
- object file and could be passed via the sym_private field of the objfile.
- It is however conceivable that dwarf2 might not be the only type
- of symbols read from an object file. */
+ of the psymtab. */
struct dwarf2_pinfo
{
- /* Pointer to start of dwarf info buffer for the objfile. */
-
- char *dwarf_info_buffer;
-
- /* Offset in dwarf_info_buffer for this compilation unit. */
+ /* Offset in .debug_info for this compilation unit. */
unsigned long dwarf_info_offset;
-
- /* Pointer to start of dwarf abbreviation buffer for the objfile. */
-
- char *dwarf_abbrev_buffer;
-
- /* Size of dwarf abbreviation section for the objfile. */
-
- unsigned int dwarf_abbrev_size;
-
- /* Pointer to start of dwarf line buffer for the objfile. */
-
- char *dwarf_line_buffer;
-
- /* Size of dwarf_line_buffer, in bytes. */
-
- unsigned int dwarf_line_size;
-
- /* Pointer to start of dwarf string buffer for the objfile. */
-
- char *dwarf_str_buffer;
-
- /* Size of dwarf string section for the objfile. */
-
- unsigned int dwarf_str_size;
-
- /* Pointer to start of dwarf macro buffer for the objfile. */
-
- char *dwarf_macinfo_buffer;
-
- /* Size of dwarf macinfo section for the objfile. */
-
- unsigned int dwarf_macinfo_size;
-
- /* 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;
-
};
#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
-#define DWARF_INFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_info_buffer)
#define DWARF_INFO_OFFSET(p) (PST_PRIVATE(p)->dwarf_info_offset)
-#define DWARF_ABBREV_BUFFER(p) (PST_PRIVATE(p)->dwarf_abbrev_buffer)
-#define DWARF_ABBREV_SIZE(p) (PST_PRIVATE(p)->dwarf_abbrev_size)
-#define DWARF_LINE_BUFFER(p) (PST_PRIVATE(p)->dwarf_line_buffer)
-#define DWARF_LINE_SIZE(p) (PST_PRIVATE(p)->dwarf_line_size)
-#define DWARF_STR_BUFFER(p) (PST_PRIVATE(p)->dwarf_str_buffer)
-#define DWARF_STR_SIZE(p) (PST_PRIVATE(p)->dwarf_str_size)
-#define DWARF_MACINFO_BUFFER(p) (PST_PRIVATE(p)->dwarf_macinfo_buffer)
-#define DWARF_MACINFO_SIZE(p) (PST_PRIVATE(p)->dwarf_macinfo_size)
-#define DWARF_RANGES_BUFFER(p) (PST_PRIVATE(p)->dwarf_ranges_buffer)
-#define DWARF_RANGES_SIZE(p) (PST_PRIVATE(p)->dwarf_ranges_size)
-
-/* Maintain an array of referenced fundamental types for the current
- compilation unit being read. For DWARF version 1, we have to construct
- the fundamental types on the fly, since no information about the
- fundamental types is supplied. Each such fundamental type is created by
- calling a language dependent routine to create the type, and then a
- pointer to that type is then placed in the array at the index specified
- by it's FT_<TYPENAME> value. The array has a fixed size set by the
- FT_NUM_MEMBERS compile time constant, which is the number of predefined
- fundamental types gdb knows how to construct. */
-static struct type *ftypes[FT_NUM_MEMBERS]; /* Fundamental types */
/* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte,
but this would require a corresponding change in unpack_field_as_long
/* Various complaints about symbol reading that don't abort the process */
-static void
-dwarf2_non_const_array_bound_ignored_complaint (const char *arg1)
-{
- complaint (&symfile_complaints, "non-constant array bounds form '%s' ignored",
- arg1);
-}
-
static void
dwarf2_statement_list_fits_in_line_number_section_complaint (void)
{
complaint (&symfile_complaints, "location expression too complex");
}
-static void
-dwarf2_unsupported_at_frame_base_complaint (const char *arg1)
-{
- 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)
static void dwarf2_build_psymtabs_easy (struct objfile *, int);
#endif
+static void dwarf2_create_include_psymtab (char *, struct partial_symtab *,
+ struct objfile *);
+
+static void dwarf2_build_include_psymtabs (struct dwarf2_cu *,
+ struct partial_die_info *,
+ struct partial_symtab *);
+
static void dwarf2_build_psymtabs_hard (struct objfile *, int);
-static char *scan_partial_symbols (char *, struct objfile *,
- CORE_ADDR *, CORE_ADDR *,
- const struct comp_unit_head *);
+static void scan_partial_symbols (struct partial_die_info *,
+ CORE_ADDR *, CORE_ADDR *,
+ struct dwarf2_cu *);
+
+static void add_partial_symbol (struct partial_die_info *,
+ struct dwarf2_cu *);
+
+static int pdi_needs_namespace (enum dwarf_tag tag);
+
+static void add_partial_namespace (struct partial_die_info *pdi,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ struct dwarf2_cu *cu);
-static void add_partial_symbol (struct partial_die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void add_partial_enumeration (struct partial_die_info *enum_pdi,
+ struct dwarf2_cu *cu);
+
+static char *locate_pdi_sibling (struct partial_die_info *orig_pdi,
+ char *info_ptr,
+ bfd *abfd,
+ struct dwarf2_cu *cu);
static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
static void psymtab_to_symtab_1 (struct partial_symtab *);
-char *dwarf2_read_section (struct objfile *, file_ptr, unsigned int,
- asection *);
+char *dwarf2_read_section (struct objfile *, asection *);
+
+static void dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu);
-static void dwarf2_read_abbrevs (bfd *abfd, struct comp_unit_head *cu_header);
+static void dwarf2_free_abbrev_table (void *);
-static void dwarf2_empty_abbrev_table (void *);
+static struct abbrev_info *peek_die_abbrev (char *, int *, struct dwarf2_cu *);
static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int,
- const struct comp_unit_head *cu_header);
+ struct dwarf2_cu *);
+
+static struct partial_die_info *load_partial_dies (bfd *, char *, int,
+ struct dwarf2_cu *);
static char *read_partial_die (struct partial_die_info *,
- bfd *, char *,
- const struct comp_unit_head *);
+ struct abbrev_info *abbrev, unsigned int,
+ bfd *, char *, struct dwarf2_cu *);
+
+static struct partial_die_info *find_partial_die (unsigned long,
+ struct dwarf2_cu *,
+ struct dwarf2_cu **);
+
+static void fixup_partial_die (struct partial_die_info *,
+ struct dwarf2_cu *);
static char *read_full_die (struct die_info **, bfd *, char *,
- const struct comp_unit_head *);
+ struct dwarf2_cu *, int *);
static char *read_attribute (struct attribute *, struct attr_abbrev *,
- bfd *, char *, const struct comp_unit_head *);
+ bfd *, char *, struct dwarf2_cu *);
static char *read_attribute_value (struct attribute *, unsigned,
- bfd *, char *, const struct comp_unit_head *);
+ bfd *, char *, struct dwarf2_cu *);
static unsigned int read_1_byte (bfd *, char *);
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 long read_signed_leb128 (bfd *, char *, unsigned int *);
-static void set_cu_language (unsigned int);
+static char *skip_leb128 (bfd *, char *);
+
+static void set_cu_language (unsigned int, struct dwarf2_cu *);
+
+static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
+ struct dwarf2_cu *);
-static struct attribute *dwarf_attr (struct die_info *, unsigned int);
+static int dwarf2_flag_true_p (struct die_info *die, unsigned name,
+ struct dwarf2_cu *cu);
-static int die_is_declaration (struct die_info *);
+static int die_is_declaration (struct die_info *, struct dwarf2_cu *cu);
+
+static struct die_info *die_specification (struct die_info *die,
+ struct dwarf2_cu *);
static void free_line_header (struct line_header *lh);
+static void add_file_name (struct line_header *, char *, unsigned int,
+ unsigned int, unsigned int);
+
static struct line_header *(dwarf_decode_line_header
(unsigned int offset,
- bfd *abfd,
- const struct comp_unit_head *cu_header));
+ bfd *abfd, struct dwarf2_cu *cu));
static void dwarf_decode_lines (struct line_header *, char *, bfd *,
- const struct comp_unit_head *);
+ struct dwarf2_cu *, struct partial_symtab *);
static void dwarf2_start_subfile (char *, char *);
static struct symbol *new_symbol (struct die_info *, struct type *,
- struct objfile *, const struct comp_unit_head *);
+ struct dwarf2_cu *);
static void dwarf2_const_value (struct attribute *, struct symbol *,
- struct objfile *, const struct comp_unit_head *);
+ struct dwarf2_cu *);
static void dwarf2_const_value_data (struct attribute *attr,
struct symbol *sym,
int bits);
-static struct type *die_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static struct type *die_type (struct die_info *, struct dwarf2_cu *);
-static struct type *die_containing_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static struct type *die_containing_type (struct die_info *,
+ struct dwarf2_cu *);
#if 0
static struct type *type_at_offset (unsigned int, struct objfile *);
#endif
-static struct type *tag_type_to_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static struct type *tag_type_to_type (struct die_info *, struct dwarf2_cu *);
+
+static void read_type_die (struct die_info *, struct dwarf2_cu *);
-static void read_type_die (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static char *determine_prefix (struct die_info *die, struct dwarf2_cu *);
-static void read_typedef (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static char *typename_concat (const char *prefix, const char *suffix);
-static void read_base_type (struct die_info *, struct objfile *);
+static void read_typedef (struct die_info *, struct dwarf2_cu *);
-static void read_file_scope (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_base_type (struct die_info *, struct dwarf2_cu *);
-static void read_func_scope (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_subrange_type (struct die_info *die, struct dwarf2_cu *cu);
-static void read_lexical_block_scope (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_file_scope (struct die_info *, struct dwarf2_cu *);
+
+static void read_func_scope (struct die_info *, struct dwarf2_cu *);
+
+static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *);
static int dwarf2_get_pc_bounds (struct die_info *,
- CORE_ADDR *, CORE_ADDR *, struct objfile *,
- const struct comp_unit_head *);
+ CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *);
+
+static void get_scope_pc_bounds (struct die_info *,
+ CORE_ADDR *, CORE_ADDR *,
+ struct dwarf2_cu *);
static void dwarf2_add_field (struct field_info *, struct die_info *,
- struct objfile *, const struct comp_unit_head *);
+ struct dwarf2_cu *);
static void dwarf2_attach_fields_to_type (struct field_info *,
- struct type *, struct objfile *);
+ struct type *, struct dwarf2_cu *);
static void dwarf2_add_member_fn (struct field_info *,
struct die_info *, struct type *,
- struct objfile *objfile,
- const struct comp_unit_head *);
+ struct dwarf2_cu *);
static void dwarf2_attach_fn_fields_to_type (struct field_info *,
- struct type *, struct objfile *);
+ struct type *, struct dwarf2_cu *);
-static void read_structure_scope (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_structure_type (struct die_info *, struct dwarf2_cu *);
-static void read_common_block (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void process_structure_scope (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 char *determine_class_name (struct die_info *die, struct dwarf2_cu *cu);
-static void read_enumeration (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_common_block (struct die_info *, struct dwarf2_cu *);
-static struct type *dwarf_base_type (int, int, struct objfile *);
+static void read_namespace (struct die_info *die, struct dwarf2_cu *);
-static CORE_ADDR decode_locdesc (struct dwarf_block *, struct objfile *,
- const struct comp_unit_head *);
+static const char *namespace_name (struct die_info *die,
+ int *is_anonymous, struct dwarf2_cu *);
-static void read_array_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_enumeration_type (struct die_info *, struct dwarf2_cu *);
-static void read_tag_pointer_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void process_enumeration_scope (struct die_info *, struct dwarf2_cu *);
-static void read_tag_ptr_to_member_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static struct type *dwarf_base_type (int, int, struct dwarf2_cu *);
-static void read_tag_reference_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static CORE_ADDR decode_locdesc (struct dwarf_block *, struct dwarf2_cu *);
-static void read_tag_const_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_array_type (struct die_info *, struct dwarf2_cu *);
-static void read_tag_volatile_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_tag_pointer_type (struct die_info *, struct dwarf2_cu *);
-static void read_tag_string_type (struct die_info *, struct objfile *);
+static void read_tag_ptr_to_member_type (struct die_info *,
+ struct dwarf2_cu *);
-static void read_subroutine_type (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void read_tag_reference_type (struct die_info *, struct dwarf2_cu *);
-static struct die_info *read_comp_unit (char *, bfd *,
- const struct comp_unit_head *);
+static void read_tag_const_type (struct die_info *, struct dwarf2_cu *);
+
+static void read_tag_volatile_type (struct die_info *, struct dwarf2_cu *);
+
+static void read_tag_string_type (struct die_info *, struct dwarf2_cu *);
+
+static void read_subroutine_type (struct die_info *, struct dwarf2_cu *);
+
+static struct die_info *read_comp_unit (char *, bfd *, struct dwarf2_cu *);
+
+static struct die_info *read_die_and_children (char *info_ptr, bfd *abfd,
+ struct dwarf2_cu *,
+ char **new_info_ptr,
+ struct die_info *parent);
+
+static struct die_info *read_die_and_siblings (char *info_ptr, bfd *abfd,
+ struct dwarf2_cu *,
+ char **new_info_ptr,
+ struct die_info *parent);
static void free_die_list (struct die_info *);
static struct cleanup *make_cleanup_free_die_list (struct die_info *);
-static void process_die (struct die_info *, struct objfile *,
- const struct comp_unit_head *);
+static void process_die (struct die_info *, struct dwarf2_cu *);
+
+static char *dwarf2_linkage_name (struct die_info *, struct dwarf2_cu *);
-static char *dwarf2_linkage_name (struct die_info *);
+static char *dwarf2_name (struct die_info *die, struct dwarf2_cu *);
+
+static struct die_info *dwarf2_extension (struct die_info *die,
+ struct dwarf2_cu *);
static char *dwarf_tag_name (unsigned int);
static void dwarf2_empty_hash_tables (void);
-static unsigned int dwarf2_get_ref_die_offset (struct attribute *);
+static unsigned int dwarf2_get_ref_die_offset (struct attribute *,
+ struct dwarf2_cu *);
+
+static int dwarf2_get_attr_constant_value (struct attribute *, int);
static struct die_info *follow_die_ref (unsigned int);
-static struct type *dwarf2_fundamental_type (struct objfile *, int);
+static struct type *dwarf2_fundamental_type (struct objfile *, int,
+ struct dwarf2_cu *);
/* memory allocation interface */
-static void dwarf2_free_tmp_obstack (void *);
-
-static struct dwarf_block *dwarf_alloc_block (void);
+static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *);
-static struct abbrev_info *dwarf_alloc_abbrev (void);
+static struct abbrev_info *dwarf_alloc_abbrev (struct dwarf2_cu *);
static struct die_info *dwarf_alloc_die (void);
-static void initialize_cu_func_list (void);
+static void initialize_cu_func_list (struct dwarf2_cu *);
-static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR);
+static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR,
+ struct dwarf2_cu *);
static void dwarf_decode_macros (struct line_header *, unsigned int,
- char *, bfd *, const struct comp_unit_head *,
- struct objfile *);
+ char *, bfd *, struct dwarf2_cu *);
static int attr_form_is_block (struct attribute *);
+static void
+dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+ struct dwarf2_cu *cu);
+
+static char *skip_one_die (char *info_ptr, struct abbrev_info *abbrev,
+ struct dwarf2_cu *cu);
+
+static void free_stack_comp_unit (void *);
+
+static void *hashtab_obstack_allocate (void *data, size_t size, size_t count);
+
+static void dummy_obstack_deallocate (void *object, void *data);
+
+static hashval_t partial_die_hash (const void *item);
+
+static int partial_die_eq (const void *item_lhs, const void *item_rhs);
+
/* Try to locate the sections we need for DWARF 2 debugging
information and return true if we have enough to do something. */
int
-dwarf2_has_info (bfd *abfd)
-{
- dwarf_info_offset = 0;
- dwarf_abbrev_offset = 0;
- dwarf_line_offset = 0;
- dwarf_str_offset = 0;
- dwarf_macinfo_offset = 0;
- dwarf_frame_offset = 0;
- dwarf_eh_frame_offset = 0;
- dwarf_ranges_offset = 0;
+dwarf2_has_info (struct objfile *objfile)
+{
+ struct dwarf2_per_objfile *data;
+
+ /* Initialize per-objfile state. */
+ data = obstack_alloc (&objfile->objfile_obstack, sizeof (*data));
+ memset (data, 0, sizeof (*data));
+ set_objfile_data (objfile, dwarf2_objfile_data_key, data);
+ dwarf2_per_objfile = data;
+
+ dwarf_info_section = 0;
+ dwarf_abbrev_section = 0;
+ dwarf_line_section = 0;
+ dwarf_str_section = 0;
+ dwarf_macinfo_section = 0;
+ dwarf_frame_section = 0;
+ dwarf_eh_frame_section = 0;
+ dwarf_ranges_section = 0;
+ dwarf_loc_section = 0;
- bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
- if (dwarf_info_offset && dwarf_abbrev_offset)
- {
- return 1;
- }
- else
- {
- return 0;
- }
+ bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL);
+ return (dwarf_info_section != NULL && dwarf_abbrev_section != NULL);
}
/* This function is mapped across the sections and remembers the
static void
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);
+ dwarf2_per_objfile->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);
+ dwarf2_per_objfile->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);
+ dwarf2_per_objfile->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);
+ dwarf2_per_objfile->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);
+ dwarf2_per_objfile->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);
+ dwarf2_per_objfile->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);
+ dwarf2_per_objfile->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);
+ dwarf2_per_objfile->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);
+ dwarf2_per_objfile->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);
- dwarf_eh_frame_section = sectp;
+ flagword aflag = bfd_get_section_flags (ignore_abfd, sectp);
+ if (aflag & SEC_HAS_CONTENTS)
+ {
+ dwarf2_per_objfile->eh_frame_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf_eh_frame_section = sectp;
+ }
}
- else if (STREQ (sectp->name, RANGES_SECTION))
+ else if (strcmp (sectp->name, RANGES_SECTION) == 0)
{
- dwarf_ranges_offset = sectp->filepos;
- dwarf_ranges_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->ranges_size = bfd_get_section_size_before_reloc (sectp);
dwarf_ranges_section = sectp;
}
}
void
dwarf2_build_psymtabs (struct objfile *objfile, int mainline)
{
-
/* We definitely need the .debug_info and .debug_abbrev sections */
- dwarf_info_buffer = dwarf2_read_section (objfile,
- dwarf_info_offset,
- dwarf_info_size,
- dwarf_info_section);
- dwarf_abbrev_buffer = dwarf2_read_section (objfile,
- dwarf_abbrev_offset,
- dwarf_abbrev_size,
- dwarf_abbrev_section);
-
- if (dwarf_line_offset)
- dwarf_line_buffer = dwarf2_read_section (objfile,
- dwarf_line_offset,
- dwarf_line_size,
- dwarf_line_section);
+ dwarf2_per_objfile->info_buffer = dwarf2_read_section (objfile, dwarf_info_section);
+ dwarf2_per_objfile->abbrev_buffer = dwarf2_read_section (objfile, dwarf_abbrev_section);
+
+ if (dwarf_line_section)
+ dwarf2_per_objfile->line_buffer = dwarf2_read_section (objfile, dwarf_line_section);
else
- dwarf_line_buffer = NULL;
+ dwarf2_per_objfile->line_buffer = NULL;
- if (dwarf_str_offset)
- dwarf_str_buffer = dwarf2_read_section (objfile,
- dwarf_str_offset,
- dwarf_str_size,
- dwarf_str_section);
+ if (dwarf_str_section)
+ dwarf2_per_objfile->str_buffer = dwarf2_read_section (objfile, dwarf_str_section);
else
- dwarf_str_buffer = NULL;
+ dwarf2_per_objfile->str_buffer = NULL;
- if (dwarf_macinfo_offset)
- dwarf_macinfo_buffer = dwarf2_read_section (objfile,
- dwarf_macinfo_offset,
- dwarf_macinfo_size,
+ if (dwarf_macinfo_section)
+ dwarf2_per_objfile->macinfo_buffer = dwarf2_read_section (objfile,
dwarf_macinfo_section);
else
- dwarf_macinfo_buffer = NULL;
+ dwarf2_per_objfile->macinfo_buffer = NULL;
- if (dwarf_ranges_offset)
- dwarf_ranges_buffer = dwarf2_read_section (objfile,
- dwarf_ranges_offset,
- dwarf_ranges_size,
- dwarf_ranges_section);
+ if (dwarf_ranges_section)
+ dwarf2_per_objfile->ranges_buffer = dwarf2_read_section (objfile, dwarf_ranges_section);
else
- dwarf_ranges_buffer = NULL;
+ dwarf2_per_objfile->ranges_buffer = NULL;
+
+ if (dwarf_loc_section)
+ dwarf2_per_objfile->loc_buffer = dwarf2_read_section (objfile, dwarf_loc_section);
+ else
+ dwarf2_per_objfile->loc_buffer = NULL;
if (mainline
|| (objfile->global_psymbols.size == 0
unsigned int entry_length, version, info_offset, info_size;
pubnames_buffer = dwarf2_read_section (objfile,
- dwarf_pubnames_offset,
- dwarf_pubnames_size,
dwarf_pubnames_section);
pubnames_ptr = pubnames_buffer;
- while ((pubnames_ptr - pubnames_buffer) < dwarf_pubnames_size)
+ while ((pubnames_ptr - pubnames_buffer) < dwarf2_per_objfile->pubnames_size)
{
struct comp_unit_head cu_header;
int bytes_read;
}
aranges_buffer = dwarf2_read_section (objfile,
- dwarf_aranges_offset,
- dwarf_aranges_size,
dwarf_aranges_section);
}
return info_ptr;
}
+static char *
+partial_read_comp_unit_head (struct comp_unit_head *header, char *info_ptr,
+ bfd *abfd)
+{
+ char *beg_of_comp_unit = info_ptr;
+
+ info_ptr = read_comp_unit_head (header, info_ptr, abfd);
+
+ if (header->version != 2)
+ error ("Dwarf Error: wrong version in compilation unit header "
+ "(is %d, should be %d) [in module %s]", header->version,
+ 2, bfd_get_filename (abfd));
+
+ if (header->abbrev_offset >= dwarf2_per_objfile->abbrev_size)
+ error ("Dwarf Error: bad offset (0x%lx) in compilation unit header "
+ "(offset 0x%lx + 6) [in module %s]",
+ (long) header->abbrev_offset,
+ (long) (beg_of_comp_unit - dwarf2_per_objfile->info_buffer),
+ bfd_get_filename (abfd));
+
+ if (beg_of_comp_unit + header->length + header->initial_length_size
+ > dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size)
+ error ("Dwarf Error: bad length (0x%lx) in compilation unit header "
+ "(offset 0x%lx + 0) [in module %s]",
+ (long) header->length,
+ (long) (beg_of_comp_unit - dwarf2_per_objfile->info_buffer),
+ bfd_get_filename (abfd));
+
+ return info_ptr;
+}
+
+/* Allocate a new partial symtab for file named NAME and mark this new
+ partial symtab as being an include of PST. */
+
+static void
+dwarf2_create_include_psymtab (char *name, struct partial_symtab *pst,
+ struct objfile *objfile)
+{
+ struct partial_symtab *subpst = allocate_psymtab (name, objfile);
+
+ subpst->section_offsets = pst->section_offsets;
+ subpst->textlow = 0;
+ subpst->texthigh = 0;
+
+ subpst->dependencies = (struct partial_symtab **)
+ obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct partial_symtab *));
+ subpst->dependencies[0] = pst;
+ subpst->number_of_dependencies = 1;
+
+ subpst->globals_offset = 0;
+ subpst->n_global_syms = 0;
+ subpst->statics_offset = 0;
+ subpst->n_static_syms = 0;
+ subpst->symtab = NULL;
+ subpst->read_symtab = pst->read_symtab;
+ subpst->readin = 0;
+
+ /* No private part is necessary for include psymtabs. This property
+ can be used to differentiate between such include psymtabs and
+ the regular ones. If it ever happens that a regular psymtab can
+ legitimally have a NULL private part, then we'll have to add a
+ dedicated field for that in the dwarf2_pinfo structure. */
+ subpst->read_symtab_private = NULL;
+}
+
+/* Read the Line Number Program data and extract the list of files
+ included by the source file represented by PST. Build an include
+ partial symtab for each of these included files.
+
+ This procedure assumes that there *is* a Line Number Program in
+ the given CU. Callers should check that PDI->HAS_STMT_LIST is set
+ before calling this procedure. */
+
+static void
+dwarf2_build_include_psymtabs (struct dwarf2_cu *cu,
+ struct partial_die_info *pdi,
+ struct partial_symtab *pst)
+{
+ struct objfile *objfile = cu->objfile;
+ bfd *abfd = objfile->obfd;
+ struct line_header *lh;
+
+ lh = dwarf_decode_line_header (pdi->line_offset, abfd, cu);
+ if (lh == NULL)
+ return; /* No linetable, so no includes. */
+
+ dwarf_decode_lines (lh, NULL, abfd, cu, pst);
+
+ free_line_header (lh);
+}
+
+
/* Build the partial symbol table by doing a quick pass through the
.debug_info and .debug_abbrev sections. */
/* Instead of reading this into a big buffer, we should probably use
mmap() on architectures that support it. (FIXME) */
bfd *abfd = objfile->obfd;
- char *info_ptr, *abbrev_ptr;
+ char *info_ptr;
char *beg_of_comp_unit;
struct partial_die_info comp_unit_die;
struct partial_symtab *pst;
- struct cleanup *back_to;
- CORE_ADDR lowpc, highpc;
-
- info_ptr = dwarf_info_buffer;
- abbrev_ptr = dwarf_abbrev_buffer;
-
- /* We use dwarf2_tmp_obstack for objects that don't need to survive
- the partial symbol scan, like attribute values.
+ CORE_ADDR lowpc, highpc, baseaddr;
- We could reduce our peak memory consumption during partial symbol
- table construction by freeing stuff from this obstack more often
- --- say, after processing each compilation unit, or each die ---
- but it turns out that this saves almost nothing. For an
- executable with 11Mb of Dwarf 2 data, I found about 64k allocated
- on dwarf2_tmp_obstack. Some investigation showed:
+ info_ptr = dwarf2_per_objfile->info_buffer;
- 1) 69% of the attributes used forms DW_FORM_addr, DW_FORM_data*,
- DW_FORM_flag, DW_FORM_[su]data, and DW_FORM_ref*. These are
- all fixed-length values not requiring dynamic allocation.
-
- 2) 30% of the attributes used the form DW_FORM_string. For
- DW_FORM_string, read_attribute simply hands back a pointer to
- the null-terminated string in dwarf_info_buffer, so no dynamic
- allocation is needed there either.
-
- 3) The remaining 1% of the attributes all used DW_FORM_block1.
- 75% of those were DW_AT_frame_base location lists for
- functions; the rest were DW_AT_location attributes, probably
- for the global variables.
-
- Anyway, what this all means is that the memory the dwarf2
- reader uses as temporary space reading partial symbols is about
- 0.5% as much as we use for dwarf_*_buffer. That's noise. */
-
- obstack_init (&dwarf2_tmp_obstack);
- back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
-
- /* Since the objects we're extracting from dwarf_info_buffer vary in
+ /* Since the objects we're extracting from .debug_info vary in
length, only the individual functions to extract them (like
- read_comp_unit_head and read_partial_die) can really know whether
+ read_comp_unit_head and load_partial_die) can really know whether
the buffer is large enough to hold another complete object.
- At the moment, they don't actually check that. If
- dwarf_info_buffer holds just one extra byte after the last
- compilation unit's dies, then read_comp_unit_head will happily
- read off the end of the buffer. read_partial_die is similarly
- casual. Those functions should be fixed.
+ At the moment, they don't actually check that. If .debug_info
+ holds just one extra byte after the last compilation unit's dies,
+ then read_comp_unit_head will happily read off the end of the
+ buffer. read_partial_die is similarly casual. Those functions
+ should be fixed.
For this loop condition, simply checking whether there's any data
left at all should be sufficient. */
- while (info_ptr < dwarf_info_buffer + dwarf_info_size)
+ while (info_ptr < (dwarf2_per_objfile->info_buffer
+ + dwarf2_per_objfile->info_size))
{
- struct comp_unit_head cu_header;
+ struct cleanup *back_to_inner;
+ struct dwarf2_cu cu;
+ struct abbrev_info *abbrev;
+ unsigned int bytes_read;
+ struct dwarf2_per_cu_data *this_cu;
+
beg_of_comp_unit = info_ptr;
- 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 (is %d, should be %d) [in module %s]", cu_header.version, 2, bfd_get_filename (abfd));
- return;
- }
- if (cu_header.abbrev_offset >= dwarf_abbrev_size)
- {
- error ("Dwarf Error: bad offset (0x%lx) in compilation unit header (offset 0x%lx + 6) [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
- > dwarf_info_buffer + dwarf_info_size)
- {
- 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;
- }
+ memset (&cu, 0, sizeof (cu));
+
+ obstack_init (&cu.comp_unit_obstack);
+
+ back_to_inner = make_cleanup (free_stack_comp_unit, &cu);
+
+ cu.objfile = objfile;
+ info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, abfd);
+
/* 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 - dwarf2_per_objfile->info_buffer;
+ cu.header.first_die_ptr = info_ptr;
+ cu.header.cu_head_ptr = beg_of_comp_unit;
+
+ cu.list_in_scope = &file_symbols;
+
+ cu.partial_dies = NULL;
/* 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_free_abbrev_table, &cu);
/* Read the compilation unit die */
- info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr,
- &cu_header);
+ abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu);
+ info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read,
+ abfd, info_ptr, &cu);
/* Set the language we're debugging */
- set_cu_language (comp_unit_die.language);
+ set_cu_language (comp_unit_die.language, &cu);
/* Allocate a new partial symbol table structure */
pst = start_psymtab_common (objfile, objfile->section_offsets,
objfile->global_psymbols.next,
objfile->static_psymbols.next);
+ if (comp_unit_die.dirname)
+ pst->dirname = xstrdup (comp_unit_die.dirname);
+
pst->read_symtab_private = (char *)
- obstack_alloc (&objfile->psymbol_obstack, sizeof (struct dwarf2_pinfo));
- cu_header_offset = beg_of_comp_unit - dwarf_info_buffer;
- DWARF_INFO_BUFFER (pst) = dwarf_info_buffer;
- DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf_info_buffer;
- DWARF_ABBREV_BUFFER (pst) = dwarf_abbrev_buffer;
- DWARF_ABBREV_SIZE (pst) = dwarf_abbrev_size;
- DWARF_LINE_BUFFER (pst) = dwarf_line_buffer;
- DWARF_LINE_SIZE (pst) = dwarf_line_size;
- DWARF_STR_BUFFER (pst) = dwarf_str_buffer;
- DWARF_STR_SIZE (pst) = dwarf_str_size;
- DWARF_MACINFO_BUFFER (pst) = dwarf_macinfo_buffer;
- DWARF_MACINFO_SIZE (pst) = dwarf_macinfo_size;
- DWARF_RANGES_BUFFER (pst) = dwarf_ranges_buffer;
- DWARF_RANGES_SIZE (pst) = dwarf_ranges_size;
+ obstack_alloc (&objfile->objfile_obstack, sizeof (struct dwarf2_pinfo));
+ DWARF_INFO_OFFSET (pst) = beg_of_comp_unit - dwarf2_per_objfile->info_buffer;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
/* Store the function that reads in the rest of the symbol table */
If not, there's no more debug_info for this comp unit. */
if (comp_unit_die.has_children)
{
- info_ptr = scan_partial_symbols (info_ptr, objfile, &lowpc, &highpc,
- &cu_header);
+ struct partial_die_info *first_die;
+
+ lowpc = ((CORE_ADDR) -1);
+ highpc = ((CORE_ADDR) 0);
+
+ first_die = load_partial_dies (abfd, info_ptr, 1, &cu);
+
+ scan_partial_symbols (first_die, &lowpc, &highpc, &cu);
+
+ /* If we didn't find a lowpc, set it to highpc to avoid
+ complaints from `maint check'. */
+ if (lowpc == ((CORE_ADDR) -1))
+ lowpc = highpc;
/* If the compilation unit didn't have an explicit address range,
then use the information extracted from its child dies. */
also happen.) This happens in VxWorks. */
free_named_symtabs (pst->filename);
- info_ptr = beg_of_comp_unit + cu_header.length
- + cu_header.initial_length_size;
+ if (comp_unit_die.has_stmt_list)
+ {
+ /* Get the list of files included in the current compilation unit,
+ and build a psymtab for each of them. */
+ dwarf2_build_include_psymtabs (&cu, &comp_unit_die, pst);
+ }
+
+ info_ptr = beg_of_comp_unit + cu.header.length
+ + cu.header.initial_length_size;
+
+ do_cleanups (back_to_inner);
}
- do_cleanups (back_to);
}
-/* Read in all interesting dies to the end of the compilation unit. */
+/* Process all loaded DIEs for compilation unit CU, starting at FIRST_DIE.
+ Also set *LOWPC and *HIGHPC to the lowest and highest PC values found
+ in CU. */
-static char *
-scan_partial_symbols (char *info_ptr, struct objfile *objfile,
- CORE_ADDR *lowpc, CORE_ADDR *highpc,
- const struct comp_unit_head *cu_header)
+static void
+scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
+ CORE_ADDR *highpc, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
bfd *abfd = objfile->obfd;
- struct partial_die_info pdi;
+ struct partial_die_info *pdi;
- /* This function is called after we've read in the comp_unit_die in
- order to read its children. We start the nesting level at 1 since
- we have pushed 1 level down in order to read the comp unit's children.
- The comp unit itself is at level 0, so we stop reading when we pop
- back to that level. */
+ /* Now, march along the PDI's, descending into ones which have
+ interesting children but skipping the children of the other ones,
+ until we reach the end of the compilation unit. */
- int nesting_level = 1;
-
- /* 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);
+ pdi = first_die;
- while (nesting_level)
+ while (pdi != NULL)
{
- info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu_header);
+ fixup_partial_die (pdi, cu);
- /* Anonymous namespaces have no name but are interesting. */
+ /* 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)
+ if (pdi->name != NULL || pdi->tag == DW_TAG_namespace
+ || pdi->tag == DW_TAG_enumeration_type)
{
- switch (pdi.tag)
+ switch (pdi->tag)
{
case DW_TAG_subprogram:
- if (pdi.has_pc_info)
+ if (pdi->has_pc_info)
{
- if (pdi.lowpc < *lowpc)
+ if (pdi->lowpc < *lowpc)
{
- *lowpc = pdi.lowpc;
+ *lowpc = pdi->lowpc;
}
- if (pdi.highpc > *highpc)
+ if (pdi->highpc > *highpc)
{
- *highpc = pdi.highpc;
+ *highpc = pdi->highpc;
}
- if ((pdi.is_external || nesting_level == file_scope_level)
- && !pdi.is_declaration)
+ if (!pdi->is_declaration)
{
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (pdi, cu);
}
}
break;
case DW_TAG_variable:
case DW_TAG_typedef:
+ case DW_TAG_union_type:
+ if (!pdi->is_declaration)
+ {
+ add_partial_symbol (pdi, cu);
+ }
+ break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
- case DW_TAG_union_type:
- case DW_TAG_enumeration_type:
- if ((pdi.is_external || nesting_level == file_scope_level)
- && !pdi.is_declaration)
+ if (!pdi->is_declaration)
{
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (pdi, cu);
}
break;
- case DW_TAG_enumerator:
- /* File scope enumerators are added to the partial
- symbol table. 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)
+ add_partial_enumeration (pdi, cu);
break;
case DW_TAG_base_type:
+ case DW_TAG_subrange_type:
/* File scope base type definitions are added to the partial
symbol table. */
- if (nesting_level == file_scope_level)
- add_partial_symbol (&pdi, objfile, cu_header);
+ add_partial_symbol (pdi, cu);
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++;
+ add_partial_namespace (pdi, lowpc, highpc, cu);
+ break;
default:
break;
}
}
- /* If the die has a sibling, skip to the sibling. Do not skip
- enumeration types, we want to record their enumerators. 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 the die has a sibling, skip to the sibling. */
- 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);
- }
- }
+ pdi = pdi->die_sibling;
}
+}
- /* If we didn't find a lowpc, set it to highpc to avoid complaints
- from `maint check'. */
- if (*lowpc == ((CORE_ADDR) -1))
- *lowpc = *highpc;
- return info_ptr;
+/* Functions used to compute the fully scoped name of a partial DIE.
+
+ Normally, this is simple. For C++, the parent DIE's fully scoped
+ name is concatenated with "::" and the partial DIE's name.
+ Enumerators are an exception; they use the scope of their parent
+ enumeration type, i.e. the name of the enumeration type is not
+ prepended to the enumerator.
+
+ There are two complexities. One is DW_AT_specification; in this
+ case "parent" means the parent of the target of the specification,
+ instead of the direct parent of the DIE. The other is compilers
+ which do not emit DW_TAG_namespace; in this case we try to guess
+ the fully qualified name of structure types from their members'
+ linkage names. This must be done using the DIE's children rather
+ than the children of any DW_AT_specification target. We only need
+ to do this for structures at the top level, i.e. if the target of
+ any DW_AT_specification (if any; otherwise the DIE itself) does not
+ have a parent. */
+
+/* Compute the scope prefix associated with PDI's parent, in
+ compilation unit CU. The result will be allocated on CU's
+ comp_unit_obstack, or a copy of the already allocated PDI->NAME
+ field. NULL is returned if no prefix is necessary. */
+static char *
+partial_die_parent_scope (struct partial_die_info *pdi,
+ struct dwarf2_cu *cu)
+{
+ char *grandparent_scope;
+ struct partial_die_info *parent, *real_pdi;
+ struct dwarf2_cu *spec_cu;
+
+ /* We need to look at our parent DIE; if we have a DW_AT_specification,
+ then this means the parent of the specification DIE. */
+
+ real_pdi = pdi;
+ spec_cu = cu;
+ while (real_pdi->has_specification)
+ real_pdi = find_partial_die (real_pdi->spec_offset, spec_cu, &spec_cu);
+
+ parent = real_pdi->die_parent;
+ if (parent == NULL)
+ return NULL;
+
+ if (parent->scope_set)
+ return parent->scope;
+
+ fixup_partial_die (parent, cu);
+
+ grandparent_scope = partial_die_parent_scope (parent, spec_cu);
+
+ if (parent->tag == DW_TAG_namespace
+ || parent->tag == DW_TAG_structure_type
+ || parent->tag == DW_TAG_class_type
+ || parent->tag == DW_TAG_union_type)
+ {
+ if (grandparent_scope == NULL)
+ parent->scope = parent->name;
+ else
+ parent->scope = obconcat (&cu->comp_unit_obstack, grandparent_scope,
+ "::", parent->name);
+ }
+ else if (parent->tag == DW_TAG_enumeration_type)
+ /* Enumerators should not get the name of the enumeration as a prefix. */
+ parent->scope = grandparent_scope;
+ else
+ {
+ /* FIXME drow/2004-04-01: What should we be doing with
+ function-local names? For partial symbols, we should probably be
+ ignoring them. */
+ complaint (&symfile_complaints,
+ "unhandled containing DIE tag %d for DIE at %d",
+ parent->tag, pdi->offset);
+ parent->scope = grandparent_scope;
+ }
+
+ parent->scope_set = 1;
+ return parent->scope;
+}
+
+/* Return the fully scoped name associated with PDI, from compilation unit
+ CU. The result will be allocated with malloc. */
+static char *
+partial_die_full_name (struct partial_die_info *pdi,
+ struct dwarf2_cu *cu)
+{
+ char *parent_scope;
+
+ parent_scope = partial_die_parent_scope (pdi, cu);
+ if (parent_scope == NULL)
+ return NULL;
+ else
+ return concat (parent_scope, "::", pdi->name, NULL);
}
static void
-add_partial_symbol (struct partial_die_info *pdi, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
CORE_ADDR addr = 0;
+ char *actual_name;
+ const char *my_prefix;
+ const struct partial_symbol *psym = NULL;
+ CORE_ADDR baseaddr;
+ int built_actual_name = 0;
+
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+ actual_name = NULL;
+
+ if (pdi_needs_namespace (pdi->tag))
+ {
+ actual_name = partial_die_full_name (pdi, cu);
+ if (actual_name)
+ built_actual_name = 1;
+ }
+
+ if (actual_name == NULL)
+ actual_name = pdi->name;
switch (pdi->tag)
{
case DW_TAG_subprogram:
if (pdi->is_external)
{
- /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+ /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
mst_text, objfile); */
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_BLOCK,
- &objfile->global_psymbols,
- 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+ VAR_DOMAIN, LOC_BLOCK,
+ &objfile->global_psymbols,
+ 0, pdi->lowpc + baseaddr,
+ cu->language, objfile);
}
else
{
- /*prim_record_minimal_symbol (pdi->name, pdi->lowpc + baseaddr,
+ /*prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
mst_file_text, objfile); */
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_BLOCK,
- &objfile->static_psymbols,
- 0, pdi->lowpc + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+ VAR_DOMAIN, LOC_BLOCK,
+ &objfile->static_psymbols,
+ 0, pdi->lowpc + baseaddr,
+ cu->language, objfile);
}
break;
case DW_TAG_variable:
table building. */
if (pdi->locdesc)
- addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
+ addr = decode_locdesc (pdi->locdesc, cu);
if (pdi->locdesc || pdi->has_type)
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_STATIC,
- &objfile->global_psymbols,
- 0, addr + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+ VAR_DOMAIN, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, addr + baseaddr,
+ cu->language, objfile);
}
else
{
/* Static Variable. Skip symbols without location descriptors. */
if (pdi->locdesc == NULL)
return;
- addr = decode_locdesc (pdi->locdesc, objfile, cu_header);
- /*prim_record_minimal_symbol (pdi->name, addr + baseaddr,
+ addr = decode_locdesc (pdi->locdesc, cu);
+ /*prim_record_minimal_symbol (actual_name, addr + baseaddr,
mst_file_data, objfile); */
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_STATIC,
- &objfile->static_psymbols,
- 0, addr + baseaddr, cu_language, objfile);
+ psym = add_psymbol_to_list (actual_name, strlen (actual_name),
+ VAR_DOMAIN, LOC_STATIC,
+ &objfile->static_psymbols,
+ 0, addr + baseaddr,
+ cu->language, objfile);
}
break;
case DW_TAG_typedef:
case DW_TAG_base_type:
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_TYPEDEF,
+ case DW_TAG_subrange_type:
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
- 0, (CORE_ADDR) 0, cu_language, objfile);
+ 0, (CORE_ADDR) 0, cu->language, objfile);
+ break;
+ case DW_TAG_namespace:
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ VAR_DOMAIN, LOC_TYPEDEF,
+ &objfile->global_psymbols,
+ 0, (CORE_ADDR) 0, cu->language, objfile);
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_enumeration_type:
/* Skip aggregate types without children, these are external
references. */
+ /* NOTE: carlton/2003-10-07: See comment in new_symbol about
+ static vs. global. */
if (pdi->has_children == 0)
return;
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- STRUCT_NAMESPACE, LOC_TYPEDEF,
- &objfile->static_psymbols,
- 0, (CORE_ADDR) 0, cu_language, objfile);
-
- if (cu_language == language_cplus)
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ STRUCT_DOMAIN, LOC_TYPEDEF,
+ cu->language == language_cplus
+ ? &objfile->global_psymbols
+ : &objfile->static_psymbols,
+ 0, (CORE_ADDR) 0, cu->language, objfile);
+
+ if (cu->language == language_cplus)
{
/* For C++, these implicitly act as typedefs as well. */
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_TYPEDEF,
- &objfile->static_psymbols,
- 0, (CORE_ADDR) 0, cu_language, objfile);
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ VAR_DOMAIN, LOC_TYPEDEF,
+ &objfile->global_psymbols,
+ 0, (CORE_ADDR) 0, cu->language, objfile);
}
break;
case DW_TAG_enumerator:
- add_psymbol_to_list (pdi->name, strlen (pdi->name),
- VAR_NAMESPACE, LOC_CONST,
- &objfile->static_psymbols,
- 0, (CORE_ADDR) 0, cu_language, objfile);
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ VAR_DOMAIN, LOC_CONST,
+ cu->language == language_cplus
+ ? &objfile->global_psymbols
+ : &objfile->static_psymbols,
+ 0, (CORE_ADDR) 0, cu->language, objfile);
break;
default:
break;
}
+
+ /* Check to see if we should scan the name for possible namespace
+ info. Only do this if this is C++, if we don't have namespace
+ debugging info in the file, if the psym is of an appropriate type
+ (otherwise we'll have psym == NULL), and if we actually had a
+ mangled name to begin with. */
+
+ /* FIXME drow/2004-02-22: Why don't we do this for classes, i.e. the
+ cases which do not set PSYM above? */
+
+ if (cu->language == language_cplus
+ && cu->has_namespace_info == 0
+ && psym != NULL
+ && SYMBOL_CPLUS_DEMANGLED_NAME (psym) != NULL)
+ cp_check_possible_namespace_symbols (SYMBOL_CPLUS_DEMANGLED_NAME (psym),
+ objfile);
+
+ if (built_actual_name)
+ xfree (actual_name);
+}
+
+/* Determine whether a die of type TAG living in a C++ class or
+ namespace needs to have the name of the scope prepended to the
+ name listed in the die. */
+
+static int
+pdi_needs_namespace (enum dwarf_tag tag)
+{
+ switch (tag)
+ {
+ case DW_TAG_namespace:
+ case DW_TAG_typedef:
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_enumerator:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* Read a partial die corresponding to a namespace; also, add a symbol
+ corresponding to that namespace to the symbol table. NAMESPACE is
+ the name of the enclosing namespace. */
+
+static void
+add_partial_namespace (struct partial_die_info *pdi,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+
+ /* Add a symbol for the namespace. */
+
+ add_partial_symbol (pdi, cu);
+
+ /* Now scan partial symbols in that namespace. */
+
+ if (pdi->has_children)
+ scan_partial_symbols (pdi->die_child, lowpc, highpc, cu);
+}
+
+/* See if we can figure out if the class lives in a namespace. We do
+ this by looking for a member function; its demangled name will
+ contain namespace info, if there is any. */
+
+static void
+guess_structure_name (struct partial_die_info *struct_pdi,
+ struct dwarf2_cu *cu)
+{
+ if (cu->language == language_cplus
+ && cu->has_namespace_info == 0
+ && struct_pdi->has_children)
+ {
+ /* NOTE: carlton/2003-10-07: Getting the info this way changes
+ what template types look like, because the demangler
+ frequently doesn't give the same name as the debug info. We
+ could fix this by only using the demangled name to get the
+ prefix (but see comment in read_structure_type). */
+
+ struct partial_die_info *child_pdi = struct_pdi->die_child;
+ struct partial_die_info *real_pdi;
+ struct dwarf2_cu *spec_cu;
+
+ /* If this DIE (this DIE's specification, if any) has a parent, then
+ we should not do this. We'll prepend the parent's fully qualified
+ name when we create the partial symbol. */
+
+ real_pdi = struct_pdi;
+ spec_cu = cu;
+ while (real_pdi->has_specification)
+ real_pdi = find_partial_die (real_pdi->spec_offset, spec_cu, &spec_cu);
+
+ if (real_pdi->die_parent != NULL)
+ return;
+
+ while (child_pdi != NULL)
+ {
+ if (child_pdi->tag == DW_TAG_subprogram)
+ {
+ char *actual_class_name
+ = class_name_from_physname (child_pdi->name);
+ if (actual_class_name != NULL)
+ {
+ struct_pdi->name
+ = obsavestring (actual_class_name,
+ strlen (actual_class_name),
+ &cu->comp_unit_obstack);
+ xfree (actual_class_name);
+ }
+ break;
+ }
+
+ child_pdi = child_pdi->die_sibling;
+ }
+ }
+}
+
+/* Read a partial die corresponding to an enumeration type. */
+
+static void
+add_partial_enumeration (struct partial_die_info *enum_pdi,
+ struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+ bfd *abfd = objfile->obfd;
+ struct partial_die_info *pdi;
+
+ if (enum_pdi->name != NULL)
+ add_partial_symbol (enum_pdi, cu);
+
+ pdi = enum_pdi->die_child;
+ while (pdi)
+ {
+ if (pdi->tag != DW_TAG_enumerator || pdi->name == NULL)
+ complaint (&symfile_complaints, "malformed enumerator DIE ignored");
+ else
+ add_partial_symbol (pdi, cu);
+ pdi = pdi->die_sibling;
+ }
+}
+
+/* Read the initial uleb128 in the die at INFO_PTR in compilation unit CU.
+ Return the corresponding abbrev, or NULL if the number is zero (indicating
+ an empty DIE). In either case *BYTES_READ will be set to the length of
+ the initial number. */
+
+static struct abbrev_info *
+peek_die_abbrev (char *info_ptr, int *bytes_read, struct dwarf2_cu *cu)
+{
+ bfd *abfd = cu->objfile->obfd;
+ unsigned int abbrev_number;
+ struct abbrev_info *abbrev;
+
+ abbrev_number = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
+
+ if (abbrev_number == 0)
+ return NULL;
+
+ abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
+ if (!abbrev)
+ {
+ error ("Dwarf Error: Could not find abbrev number %d [in module %s]", abbrev_number,
+ bfd_get_filename (abfd));
+ }
+
+ return abbrev;
+}
+
+/* Scan the debug information for CU starting at INFO_PTR. Returns a
+ pointer to the end of a series of DIEs, terminated by an empty
+ DIE. Any children of the skipped DIEs will also be skipped. */
+
+static char *
+skip_children (char *info_ptr, struct dwarf2_cu *cu)
+{
+ struct abbrev_info *abbrev;
+ unsigned int bytes_read;
+
+ while (1)
+ {
+ abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu);
+ if (abbrev == NULL)
+ return info_ptr + bytes_read;
+ else
+ info_ptr = skip_one_die (info_ptr + bytes_read, abbrev, cu);
+ }
+}
+
+/* Scan the debug information for CU starting at INFO_PTR. INFO_PTR
+ should point just after the initial uleb128 of a DIE, and the
+ abbrev corresponding to that skipped uleb128 should be passed in
+ ABBREV. Returns a pointer to this DIE's sibling, skipping any
+ children. */
+
+static char *
+skip_one_die (char *info_ptr, struct abbrev_info *abbrev,
+ struct dwarf2_cu *cu)
+{
+ unsigned int bytes_read;
+ struct attribute attr;
+ bfd *abfd = cu->objfile->obfd;
+ unsigned int form, i;
+
+ for (i = 0; i < abbrev->num_attrs; i++)
+ {
+ /* The only abbrev we care about is DW_AT_sibling. */
+ if (abbrev->attrs[i].name == DW_AT_sibling)
+ {
+ read_attribute (&attr, &abbrev->attrs[i],
+ abfd, info_ptr, cu);
+ if (attr.form == DW_FORM_ref_addr)
+ complaint (&symfile_complaints, "ignoring absolute DW_AT_sibling");
+ else
+ return dwarf2_per_objfile->info_buffer
+ + dwarf2_get_ref_die_offset (&attr, cu);
+ }
+
+ /* If it isn't DW_AT_sibling, skip this attribute. */
+ form = abbrev->attrs[i].form;
+ skip_attribute:
+ switch (form)
+ {
+ case DW_FORM_addr:
+ case DW_FORM_ref_addr:
+ info_ptr += cu->header.addr_size;
+ break;
+ case DW_FORM_data1:
+ case DW_FORM_ref1:
+ case DW_FORM_flag:
+ info_ptr += 1;
+ break;
+ case DW_FORM_data2:
+ case DW_FORM_ref2:
+ info_ptr += 2;
+ break;
+ case DW_FORM_data4:
+ case DW_FORM_ref4:
+ info_ptr += 4;
+ break;
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ info_ptr += 8;
+ break;
+ case DW_FORM_string:
+ read_string (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ break;
+ case DW_FORM_strp:
+ info_ptr += cu->header.offset_size;
+ break;
+ case DW_FORM_block:
+ info_ptr += read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ break;
+ case DW_FORM_block1:
+ info_ptr += 1 + read_1_byte (abfd, info_ptr);
+ break;
+ case DW_FORM_block2:
+ info_ptr += 2 + read_2_bytes (abfd, info_ptr);
+ break;
+ case DW_FORM_block4:
+ info_ptr += 4 + read_4_bytes (abfd, info_ptr);
+ break;
+ case DW_FORM_sdata:
+ case DW_FORM_udata:
+ case DW_FORM_ref_udata:
+ info_ptr = skip_leb128 (abfd, info_ptr);
+ break;
+ case DW_FORM_indirect:
+ form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ /* We need to continue parsing from here, so just go back to
+ the top. */
+ goto skip_attribute;
+
+ default:
+ error ("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]",
+ dwarf_form_name (form),
+ bfd_get_filename (abfd));
+ }
+ }
+
+ if (abbrev->has_children)
+ return skip_children (info_ptr, cu);
+ else
+ return info_ptr;
+}
+
+/* Locate ORIG_PDI's sibling; INFO_PTR should point to the start of
+ the next DIE after ORIG_PDI. */
+
+static char *
+locate_pdi_sibling (struct partial_die_info *orig_pdi, char *info_ptr,
+ bfd *abfd, struct dwarf2_cu *cu)
+{
+ /* Do we know the sibling already? */
+
+ if (orig_pdi->sibling)
+ return orig_pdi->sibling;
+
+ /* Are there any children to deal with? */
+
+ if (!orig_pdi->has_children)
+ return info_ptr;
+
+ /* Skip the children the long way. */
+
+ return skip_children (info_ptr, cu);
}
/* Expand this partial symbol table into a full symbol table. */
{
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;
+ CORE_ADDR baseaddr;
+ int i;
+
+ for (i = 0; i < pst->number_of_dependencies; i++)
+ if (!pst->dependencies[i]->readin)
+ {
+ /* Inform about additional files that need to be read in. */
+ if (info_verbose)
+ {
+ fputs_filtered (" ", gdb_stdout);
+ wrap_here ("");
+ fputs_filtered ("and ", gdb_stdout);
+ wrap_here ("");
+ printf_filtered ("%s...", pst->dependencies[i]->filename);
+ wrap_here (""); /* Flush output */
+ gdb_flush (gdb_stdout);
+ }
+ psymtab_to_symtab_1 (pst->dependencies[i]);
+ }
+
+ if (pst->read_symtab_private == NULL)
+ {
+ /* It's an include file, no symbols to read for it.
+ Everything is in the parent symtab. */
+ pst->readin = 1;
+ return;
+ }
+
+ dwarf2_per_objfile = objfile_data (pst->objfile, dwarf2_objfile_data_key);
/* Set local variables from the partial symbol table info. */
offset = DWARF_INFO_OFFSET (pst);
- dwarf_info_buffer = DWARF_INFO_BUFFER (pst);
- dwarf_abbrev_buffer = DWARF_ABBREV_BUFFER (pst);
- dwarf_abbrev_size = DWARF_ABBREV_SIZE (pst);
- dwarf_line_buffer = DWARF_LINE_BUFFER (pst);
- dwarf_line_size = DWARF_LINE_SIZE (pst);
- dwarf_str_buffer = DWARF_STR_BUFFER (pst);
- dwarf_str_size = DWARF_STR_SIZE (pst);
- dwarf_macinfo_buffer = DWARF_MACINFO_BUFFER (pst);
- dwarf_macinfo_size = DWARF_MACINFO_SIZE (pst);
- dwarf_ranges_buffer = DWARF_RANGES_BUFFER (pst);
- dwarf_ranges_size = DWARF_RANGES_SIZE (pst);
- baseaddr = ANOFFSET (pst->section_offsets, SECT_OFF_TEXT (objfile));
- cu_header_offset = offset;
- info_ptr = dwarf_info_buffer + offset;
-
- obstack_init (&dwarf2_tmp_obstack);
- back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
+
+ info_ptr = dwarf2_per_objfile->info_buffer + offset;
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+ /* We're in the global namespace. */
+ processing_current_prefix = "";
+
+ obstack_init (&cu.comp_unit_obstack);
+ back_to = make_cleanup (free_stack_comp_unit, &cu);
buildsym_init ();
make_cleanup (really_free_pendings, NULL);
+ cu.objfile = objfile;
+
/* read in the comp_unit header */
- info_ptr = read_comp_unit_head (&cu_header, info_ptr, abfd);
+ info_ptr = read_comp_unit_head (&cu.header, info_ptr, abfd);
/* Read the abbrevs for this compilation unit */
- dwarf2_read_abbrevs (abfd, &cu_header);
- make_cleanup (dwarf2_empty_abbrev_table, cu_header.dwarf2_abbrevs);
+ dwarf2_read_abbrevs (abfd, &cu);
+ make_cleanup (dwarf2_free_abbrev_table, &cu);
+
+ cu.header.offset = offset;
+
+ cu.list_in_scope = &file_symbols;
- dies = read_comp_unit (info_ptr, abfd, &cu_header);
+ dies = read_comp_unit (info_ptr, abfd, &cu);
make_cleanup_free_die_list (dies);
- /* Do line number decoding in read_file_scope () */
- cu_header.die = dies;
- process_die (dies, objfile, &cu_header);
+ /* Find the base address of the compilation unit for range lists and
+ location lists. It will normally be specified by DW_AT_low_pc.
+ In DWARF-3 draft 4, the base address could be overridden by
+ DW_AT_entry_pc. It's been removed, but GCC still uses this for
+ compilation units with discontinuous ranges. */
+
+ cu.header.base_known = 0;
+ cu.header.base_address = 0;
- if (!dwarf2_get_pc_bounds (dies, &lowpc, &highpc, objfile, &cu_header))
+ attr = dwarf2_attr (dies, DW_AT_entry_pc, &cu);
+ if (attr)
+ {
+ cu.header.base_address = DW_ADDR (attr);
+ cu.header.base_known = 1;
+ }
+ else
{
- /* 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)
+ attr = dwarf2_attr (dies, DW_AT_low_pc, &cu);
+ if (attr)
{
- child_die = dies->next;
- while (child_die && child_die->tag)
- {
- if (child_die->tag == DW_TAG_subprogram)
- {
- CORE_ADDR low, high;
-
- if (dwarf2_get_pc_bounds (child_die, &low, &high,
- objfile, &cu_header))
- {
- highpc = max (highpc, high);
- }
- }
- child_die = sibling_die (child_die);
- }
+ cu.header.base_address = DW_ADDR (attr);
+ cu.header.base_known = 1;
}
}
+
+ /* Do line number decoding in read_file_scope () */
+ process_die (dies, &cu);
+
+ /* Some compilers don't define a DW_AT_high_pc attribute for the
+ compilation unit. If the DW_AT_high_pc is missing, synthesize
+ it, by scanning the DIE's below the compilation unit. */
+ get_scope_pc_bounds (dies, &lowpc, &highpc, &cu);
+
symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
/* Set symtab language to language from DW_AT_language.
If the compilation is from a C file generated by language preprocessors,
do not set the language if it was already deduced by start_subfile. */
if (symtab != NULL
- && !(cu_language == language_c && symtab->language != language_c))
+ && !(cu.language == language_c && symtab->language != language_c))
{
- symtab->language = cu_language;
+ symtab->language = cu.language;
}
pst->symtab = symtab;
pst->readin = 1;
- sort_symtab_syms (pst->symtab);
do_cleanups (back_to);
}
/* 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_type (die, cu);
+ process_structure_scope (die, cu);
break;
case DW_TAG_enumeration_type:
- read_enumeration (die, objfile, cu_header);
+ read_enumeration_type (die, cu);
+ process_enumeration_scope (die, cu);
break;
+
+ /* FIXME drow/2004-03-14: These initialize die->type, but do not create
+ a symbol or process any children. Therefore it doesn't do anything
+ that won't be done on-demand by read_type_die. */
case DW_TAG_subroutine_type:
- read_subroutine_type (die, objfile, cu_header);
+ read_subroutine_type (die, cu);
break;
case DW_TAG_array_type:
- read_array_type (die, objfile, cu_header);
+ read_array_type (die, cu);
break;
case DW_TAG_pointer_type:
- read_tag_pointer_type (die, objfile, cu_header);
+ read_tag_pointer_type (die, cu);
break;
case DW_TAG_ptr_to_member_type:
- read_tag_ptr_to_member_type (die, objfile, cu_header);
+ read_tag_ptr_to_member_type (die, cu);
break;
case DW_TAG_reference_type:
- read_tag_reference_type (die, objfile, cu_header);
+ read_tag_reference_type (die, cu);
break;
case DW_TAG_string_type:
- read_tag_string_type (die, objfile);
+ read_tag_string_type (die, cu);
break;
+ /* END FIXME */
+
case DW_TAG_base_type:
- read_base_type (die, objfile);
- if (dwarf_attr (die, DW_AT_name))
- {
- /* Add a typedef symbol for the base type definition. */
- new_symbol (die, die->type, objfile, cu_header);
- }
+ read_base_type (die, cu);
+ /* Add a typedef symbol for the type definition, if it has a
+ DW_AT_name. */
+ new_symbol (die, die->type, cu);
+ break;
+ case DW_TAG_subrange_type:
+ read_subrange_type (die, cu);
+ /* Add a typedef symbol for the type definition, if it has a
+ DW_AT_name. */
+ new_symbol (die, die->type, cu);
break;
case DW_TAG_common_block:
- read_common_block (die, objfile, cu_header);
+ read_common_block (die, cu);
break;
case DW_TAG_common_inclusion:
break;
case DW_TAG_namespace:
- read_namespace (die, objfile, cu_header);
+ processing_has_namespace_info = 1;
+ 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);
+ processing_has_namespace_info = 1;
+ gdb_assert (die->child == NULL);
break;
default:
- new_symbol (die, NULL, objfile, cu_header);
+ new_symbol (die, NULL, cu);
break;
}
}
static void
-initialize_cu_func_list (void)
+initialize_cu_func_list (struct dwarf2_cu *cu)
{
- cu_first_fn = cu_last_fn = cu_cached_fn = NULL;
+ cu->first_fn = cu->last_fn = cu->cached_fn = NULL;
}
static void
-read_file_scope (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
+ struct comp_unit_head *cu_header = &cu->header;
struct cleanup *back_to = make_cleanup (null_cleanup, 0);
CORE_ADDR lowpc = ((CORE_ADDR) -1);
CORE_ADDR highpc = ((CORE_ADDR) 0);
struct die_info *child_die;
bfd *abfd = objfile->obfd;
struct line_header *line_header = 0;
+ CORE_ADDR baseaddr;
+
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
- if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
- {
- if (die->has_children)
- {
- child_die = die->next;
- while (child_die && child_die->tag)
- {
- if (child_die->tag == DW_TAG_subprogram)
- {
- CORE_ADDR low, high;
-
- if (dwarf2_get_pc_bounds (child_die, &low, &high,
- objfile, cu_header))
- {
- lowpc = min (lowpc, low);
- highpc = max (highpc, high);
- }
- }
- child_die = sibling_die (child_die);
- }
- }
- }
+ get_scope_pc_bounds (die, &lowpc, &highpc, cu);
/* If we didn't find a lowpc, set it to highpc to avoid complaints
from finish_block. */
lowpc += baseaddr;
highpc += baseaddr;
- attr = dwarf_attr (die, DW_AT_name);
+ attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr)
{
name = DW_STRING (attr);
}
- attr = dwarf_attr (die, DW_AT_comp_dir);
+ attr = dwarf2_attr (die, DW_AT_comp_dir, cu);
if (attr)
{
comp_dir = DW_STRING (attr);
}
}
- if (objfile->ei.entry_point >= lowpc &&
- objfile->ei.entry_point < highpc)
- {
- objfile->ei.entry_file_lowpc = lowpc;
- objfile->ei.entry_file_highpc = highpc;
- }
-
- attr = dwarf_attr (die, DW_AT_language);
+ attr = dwarf2_attr (die, DW_AT_language, cu);
if (attr)
{
- set_cu_language (DW_UNSND (attr));
+ set_cu_language (DW_UNSND (attr), cu);
}
/* We assume that we're processing GCC output. */
/* The compilation unit may be in a different language or objfile,
zero out all remembered fundamental types. */
- memset (ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
+ memset (cu->ftypes, 0, FT_NUM_MEMBERS * sizeof (struct type *));
start_symtab (name, comp_dir, lowpc);
record_debugformat ("DWARF 2");
- initialize_cu_func_list ();
+ initialize_cu_func_list (cu);
/* Process all dies in compilation unit. */
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
- process_die (child_die, objfile, cu_header);
+ process_die (child_die, cu);
child_die = sibling_die (child_die);
}
}
/* Decode line number information if present. */
- attr = dwarf_attr (die, DW_AT_stmt_list);
+ attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
if (attr)
{
unsigned int line_offset = DW_UNSND (attr);
- line_header = dwarf_decode_line_header (line_offset,
- abfd, cu_header);
+ line_header = dwarf_decode_line_header (line_offset, abfd, cu);
if (line_header)
{
make_cleanup ((make_cleanup_ftype *) free_line_header,
(void *) line_header);
- dwarf_decode_lines (line_header, comp_dir, abfd, cu_header);
+ dwarf_decode_lines (line_header, comp_dir, abfd, cu, NULL);
}
}
refers to information in the line number info statement program
header, so we can only read it if we've read the header
successfully. */
- attr = dwarf_attr (die, DW_AT_macro_info);
+ attr = dwarf2_attr (die, DW_AT_macro_info, cu);
if (attr && line_header)
{
unsigned int macro_offset = DW_UNSND (attr);
dwarf_decode_macros (line_header, macro_offset,
- comp_dir, abfd, cu_header, objfile);
+ comp_dir, abfd, cu);
}
do_cleanups (back_to);
}
static void
-add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc)
+add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc,
+ struct dwarf2_cu *cu)
{
struct function_range *thisfn;
thisfn = (struct function_range *)
- obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct function_range));
+ obstack_alloc (&cu->comp_unit_obstack, sizeof (struct function_range));
thisfn->name = name;
thisfn->lowpc = lowpc;
thisfn->highpc = highpc;
thisfn->seen_line = 0;
thisfn->next = NULL;
- if (cu_last_fn == NULL)
- cu_first_fn = thisfn;
+ if (cu->last_fn == NULL)
+ cu->first_fn = thisfn;
else
- cu_last_fn->next = thisfn;
+ cu->last_fn->next = thisfn;
- cu_last_fn = thisfn;
+ cu->last_fn = thisfn;
}
static void
-read_func_scope (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
{
- register struct context_stack *new;
+ struct objfile *objfile = cu->objfile;
+ struct context_stack *new;
CORE_ADDR lowpc;
CORE_ADDR highpc;
struct die_info *child_die;
struct attribute *attr;
char *name;
+ const char *previous_prefix = processing_current_prefix;
+ struct cleanup *back_to = NULL;
+ CORE_ADDR baseaddr;
- name = dwarf2_linkage_name (die);
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+ name = dwarf2_linkage_name (die, cu);
/* Ignore functions with missing or empty names and functions with
missing or invalid low and high pc attributes. */
- if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
+ if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu))
return;
+ if (cu->language == language_cplus)
+ {
+ struct die_info *spec_die = die_specification (die, cu);
+
+ /* NOTE: carlton/2004-01-23: We have to be careful in the
+ presence of DW_AT_specification. For example, with GCC 3.4,
+ given the code
+
+ namespace N {
+ void foo() {
+ // Definition of N::foo.
+ }
+ }
+
+ then we'll have a tree of DIEs like this:
+
+ 1: DW_TAG_compile_unit
+ 2: DW_TAG_namespace // N
+ 3: DW_TAG_subprogram // declaration of N::foo
+ 4: DW_TAG_subprogram // definition of N::foo
+ DW_AT_specification // refers to die #3
+
+ Thus, when processing die #4, we have to pretend that we're
+ in the context of its DW_AT_specification, namely the contex
+ of die #3. */
+
+ if (spec_die != NULL)
+ {
+ char *specification_prefix = determine_prefix (spec_die, cu);
+ processing_current_prefix = specification_prefix;
+ back_to = make_cleanup (xfree, specification_prefix);
+ }
+ }
+
lowpc += baseaddr;
highpc += baseaddr;
/* Record the function range for dwarf_decode_lines. */
- add_to_cu_func_list (name, lowpc, highpc);
+ add_to_cu_func_list (name, lowpc, highpc, cu);
if (objfile->ei.entry_point >= lowpc &&
objfile->ei.entry_point < highpc)
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;
- attr = dwarf_attr (die, DW_AT_frame_base);
- if (attr)
- {
- CORE_ADDR addr;
-
- /* Support the .debug_loc offsets */
- if (attr_form_is_block (attr))
- {
- addr = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
- }
- else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
- {
- dwarf2_complex_location_expr_complaint ();
- addr = 0;
- }
- else
- {
- dwarf2_invalid_attrib_class_complaint ("DW_AT_frame_base", name);
- addr = 0;
- }
-
- if (isderef)
- dwarf2_unsupported_at_frame_base_complaint (name);
- else if (isreg)
- frame_base_reg = addr;
- else if (offreg)
- {
- frame_base_reg = basereg;
- frame_base_offset = addr;
- }
- else
- dwarf2_unsupported_at_frame_base_complaint (name);
- }
-
new = push_context (0, lowpc);
- new->name = new_symbol (die, die->type, objfile, cu_header);
- list_in_scope = &local_symbols;
+ new->name = new_symbol (die, die->type, cu);
- if (die->has_children)
- {
- child_die = die->next;
+ /* If there is a location expression for DW_AT_frame_base, record
+ it. */
+ attr = dwarf2_attr (die, DW_AT_frame_base, cu);
+ if (attr)
+ /* FIXME: cagney/2004-01-26: The DW_AT_frame_base's location
+ expression is being recorded directly in the function's symbol
+ and not in a separate frame-base object. I guess this hack is
+ to avoid adding some sort of frame-base adjunct/annex to the
+ function's symbol :-(. The problem with doing this is that it
+ results in a function symbol with a location expression that
+ has nothing to do with the location of the function, ouch! The
+ relationship should be: a function's symbol has-a frame base; a
+ frame-base has-a location expression. */
+ dwarf2_symbol_mark_computed (attr, new->name, cu);
+
+ cu->list_in_scope = &local_symbols;
+
+ if (die->child != NULL)
+ {
+ child_die = die->child;
while (child_die && child_die->tag)
{
- process_die (child_die, objfile, cu_header);
+ process_die (child_die, cu);
child_die = sibling_die (child_die);
}
}
/* 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;
+ cu->list_in_scope = &file_symbols;
+
+ processing_current_prefix = previous_prefix;
+ if (back_to != NULL)
+ do_cleanups (back_to);
}
/* Process all the DIES contained within a lexical block scope. Start
a new scope, process the dies, and then close the scope. */
static void
-read_lexical_block_scope (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
{
- register struct context_stack *new;
+ struct objfile *objfile = cu->objfile;
+ struct context_stack *new;
CORE_ADDR lowpc, highpc;
struct die_info *child_die;
+ CORE_ADDR baseaddr;
+
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
/* Ignore blocks with missing or invalid low and high pc attributes. */
/* ??? Perhaps consider discontiguous blocks defined by DW_AT_ranges
as multiple lexical blocks? Handling children in a sane way would
be nasty. Might be easier to properly extend generic blocks to
describe ranges. */
- if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, objfile, cu_header))
+ 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);
}
}
discontinuous, i.e. derived from DW_AT_ranges information. */
static int
dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+ 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);
+ attr = dwarf2_attr (die, DW_AT_high_pc, cu);
if (attr)
{
high = DW_ADDR (attr);
- attr = dwarf_attr (die, DW_AT_low_pc);
+ attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
low = DW_ADDR (attr);
else
}
else
{
- attr = dwarf_attr (die, DW_AT_ranges);
+ attr = dwarf2_attr (die, DW_AT_ranges, cu);
if (attr != NULL)
{
unsigned int addr_size = cu_header->addr_size;
CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
/* Value of the DW_AT_ranges attribute is the offset in the
- .debug_renges section. */
+ .debug_ranges section. */
unsigned int offset = DW_UNSND (attr);
/* Base address selection entry. */
- CORE_ADDR base = 0;
- int found_base = 0;
+ CORE_ADDR base;
+ int found_base;
int dummy;
- unsigned int i;
char *buffer;
CORE_ADDR marker;
int low_set;
- /* The applicable base address is determined by (1) the closest
- preceding base address selection entry in the range list or
- (2) the DW_AT_low_pc of the compilation unit. */
-
- /* ??? Was in dwarf3 draft4, and has since been removed.
- GCC still uses it though. */
- attr = dwarf_attr (cu_header->die, DW_AT_entry_pc);
- if (attr)
- {
- base = DW_ADDR (attr);
- found_base = 1;
- }
+ found_base = cu_header->base_known;
+ base = cu_header->base_address;
- if (!found_base)
+ if (offset >= dwarf2_per_objfile->ranges_size)
{
- attr = dwarf_attr (cu_header->die, DW_AT_low_pc);
- if (attr)
- {
- base = DW_ADDR (attr);
- found_base = 1;
- }
+ complaint (&symfile_complaints,
+ "Offset %d out of bounds for DW_AT_ranges attribute",
+ offset);
+ return 0;
}
-
- buffer = dwarf_ranges_buffer + offset;
-
+ buffer = dwarf2_per_objfile->ranges_buffer + offset;
/* Read in the largest possible address. */
- marker = read_address (obfd, buffer, cu_header, &dummy);
+ 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_header, &dummy);
+ base = read_address (obfd, buffer + addr_size, cu, &dummy);
buffer += 2 * addr_size;
offset += 2 * addr_size;
found_base = 1;
{
CORE_ADDR range_beginning, range_end;
- range_beginning = read_address (obfd, buffer,
- cu_header, &dummy);
+ range_beginning = read_address (obfd, buffer, cu, &dummy);
buffer += addr_size;
- range_end = read_address (obfd, buffer, cu_header, &dummy);
+ range_end = read_address (obfd, buffer, cu, &dummy);
buffer += addr_size;
offset += 2 * addr_size;
{
/* If we found the largest possible address, then
read the base address. */
- base = read_address (obfd, buffer + addr_size,
- cu_header, &dummy);
+ base = read_address (obfd, buffer + addr_size, cu, &dummy);
found_base = 1;
continue;
}
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
return ret;
}
+/* Get the low and high pc's represented by the scope DIE, and store
+ them in *LOWPC and *HIGHPC. If the correct values can't be
+ determined, set *LOWPC to -1 and *HIGHPC to 0. */
+
+static void
+get_scope_pc_bounds (struct die_info *die,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ struct dwarf2_cu *cu)
+{
+ CORE_ADDR best_low = (CORE_ADDR) -1;
+ CORE_ADDR best_high = (CORE_ADDR) 0;
+ CORE_ADDR current_low, current_high;
+
+ if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu))
+ {
+ best_low = current_low;
+ best_high = current_high;
+ }
+ else
+ {
+ struct die_info *child = die->child;
+
+ while (child && child->tag)
+ {
+ switch (child->tag) {
+ case DW_TAG_subprogram:
+ if (dwarf2_get_pc_bounds (child, ¤t_low, ¤t_high, cu))
+ {
+ best_low = min (best_low, current_low);
+ best_high = max (best_high, current_high);
+ }
+ break;
+ case DW_TAG_namespace:
+ /* FIXME: carlton/2004-01-16: Should we do this for
+ DW_TAG_class_type/DW_TAG_structure_type, too? I think
+ that current GCC's always emit the DIEs corresponding
+ to definitions of methods of classes as children of a
+ DW_TAG_compile_unit or DW_TAG_namespace (as opposed to
+ the DIEs giving the declarations, which could be
+ anywhere). But I don't see any reason why the
+ standards says that they have to be there. */
+ get_scope_pc_bounds (child, ¤t_low, ¤t_high, cu);
+
+ if (current_low != ((CORE_ADDR) -1))
+ {
+ best_low = min (best_low, current_low);
+ best_high = max (best_high, current_high);
+ }
+ break;
+ default:
+ /* Ignore. */
+ break;
+ }
+
+ child = sibling_die (child);
+ }
+ }
+
+ *lowpc = best_low;
+ *highpc = best_high;
+}
+
/* Add an aggregate field to the field list. */
static void
dwarf2_add_field (struct field_info *fip, struct die_info *die,
- struct objfile *objfile,
- const struct comp_unit_head *cu_header)
-{
+ struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
struct nextfield *new_field;
struct attribute *attr;
struct field *fp;
new_field->accessibility = DW_ACCESS_private;
new_field->virtuality = DW_VIRTUALITY_none;
- attr = dwarf_attr (die, DW_AT_accessibility);
+ attr = dwarf2_attr (die, DW_AT_accessibility, cu);
if (attr)
new_field->accessibility = DW_UNSND (attr);
if (new_field->accessibility != DW_ACCESS_public)
fip->non_public_fields = 1;
- attr = dwarf_attr (die, DW_AT_virtuality);
+ attr = dwarf2_attr (die, DW_AT_virtuality, cu);
if (attr)
new_field->virtuality = DW_UNSND (attr);
fp = &new_field->field;
- if (die->tag == DW_TAG_member && ! die_is_declaration (die))
+ if (die->tag == DW_TAG_member && ! die_is_declaration (die, cu))
{
/* Data member other than a C++ static data member. */
/* Get type of field. */
- fp->type = die_type (die, objfile, cu_header);
+ fp->type = die_type (die, cu);
FIELD_STATIC_KIND (*fp) = 0;
/* Get bit size of field (zero if none). */
- attr = dwarf_attr (die, DW_AT_bit_size);
+ attr = dwarf2_attr (die, DW_AT_bit_size, cu);
if (attr)
{
FIELD_BITSIZE (*fp) = DW_UNSND (attr);
}
/* Get bit offset of field. */
- attr = dwarf_attr (die, DW_AT_data_member_location);
+ attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
if (attr)
{
FIELD_BITPOS (*fp) =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header) * bits_per_byte;
+ decode_locdesc (DW_BLOCK (attr), cu) * bits_per_byte;
}
else
FIELD_BITPOS (*fp) = 0;
- attr = dwarf_attr (die, DW_AT_bit_offset);
+ attr = dwarf2_attr (die, DW_AT_bit_offset, cu);
if (attr)
{
if (BITS_BIG_ENDIAN)
int anonymous_size;
int bit_offset = DW_UNSND (attr);
- attr = dwarf_attr (die, DW_AT_byte_size);
+ attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
/* The size of the anonymous object containing
}
/* Get name of field. */
- attr = dwarf_attr (die, DW_AT_name);
+ attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
fieldname = DW_STRING (attr);
- fp->name = obsavestring (fieldname, strlen (fieldname),
- &objfile->type_obstack);
+
+ /* The name is already allocated along with this objfile, so we don't
+ need to duplicate it for the type. */
+ fp->name = fieldname;
/* Change accessibility for artificial fields (e.g. virtual table
pointer or virtual base class pointer) to private. */
- if (dwarf_attr (die, DW_AT_artificial))
+ if (dwarf2_attr (die, DW_AT_artificial, cu))
{
new_field->accessibility = DW_ACCESS_private;
fip->non_public_fields = 1;
char *physname;
/* Get name of field. */
- attr = dwarf_attr (die, DW_AT_name);
+ attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
fieldname = DW_STRING (attr);
else
return;
/* Get physical name. */
- physname = dwarf2_linkage_name (die);
+ physname = dwarf2_linkage_name (die, cu);
- SET_FIELD_PHYSNAME (*fp, obsavestring (physname, strlen (physname),
- &objfile->type_obstack));
- FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
- FIELD_NAME (*fp) = obsavestring (fieldname, strlen (fieldname),
- &objfile->type_obstack);
+ /* The name is already allocated along with this objfile, so we don't
+ need to duplicate it for the type. */
+ SET_FIELD_PHYSNAME (*fp, physname ? physname : "");
+ FIELD_TYPE (*fp) = die_type (die, cu);
+ FIELD_NAME (*fp) = fieldname;
}
else if (die->tag == DW_TAG_inheritance)
{
/* C++ base class field. */
- attr = dwarf_attr (die, DW_AT_data_member_location);
+ attr = dwarf2_attr (die, DW_AT_data_member_location, cu);
if (attr)
- FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), objfile, cu_header)
+ FIELD_BITPOS (*fp) = (decode_locdesc (DW_BLOCK (attr), cu)
* bits_per_byte);
FIELD_BITSIZE (*fp) = 0;
FIELD_STATIC_KIND (*fp) = 0;
- FIELD_TYPE (*fp) = die_type (die, objfile, cu_header);
+ 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;
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;
struct nextfnfield *new_fnfield;
/* Get name of member function. */
- attr = dwarf_attr (die, DW_AT_name);
+ attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
fieldname = DW_STRING (attr);
else
return;
/* Get the mangled name. */
- physname = dwarf2_linkage_name (die);
+ physname = dwarf2_linkage_name (die, cu);
/* Look up member function name in fieldlist. */
for (i = 0; i < fip->nfnfields; i++)
{
- if (STREQ (fip->fnfieldlists[i].name, fieldname))
+ if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0)
break;
}
/* Fill in the member function field info. */
fnp = &new_fnfield->fnfield;
- fnp->physname = obsavestring (physname, strlen (physname),
- &objfile->type_obstack);
+ /* The name is already allocated along with this objfile, so we don't
+ need to duplicate it for the type. */
+ fnp->physname = physname ? physname : "";
fnp->type = alloc_type (objfile);
if (die->type && TYPE_CODE (die->type) == TYPE_CODE_FUNC)
{
- struct type *return_type = TYPE_TARGET_TYPE (die->type);
int nparams = TYPE_NFIELDS (die->type);
/* TYPE is the domain of this method, and DIE->TYPE is the type
physname);
/* Get fcontext from DW_AT_containing_type if present. */
- if (dwarf_attr (die, DW_AT_containing_type) != NULL)
- fnp->fcontext = die_containing_type (die, objfile, cu_header);
+ if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL)
+ fnp->fcontext = die_containing_type (die, cu);
/* dwarf2 doesn't have stubbed physical names, so the setting of is_const
and is_volatile is irrelevant, as it is needed by gdb_mangle_name only. */
/* Get accessibility. */
- attr = dwarf_attr (die, DW_AT_accessibility);
+ attr = dwarf2_attr (die, DW_AT_accessibility, cu);
if (attr)
{
switch (DW_UNSND (attr))
}
/* Check for artificial methods. */
- attr = dwarf_attr (die, DW_AT_artificial);
+ attr = dwarf2_attr (die, DW_AT_artificial, cu);
if (attr && DW_UNSND (attr) != 0)
fnp->is_artificial = 1;
/* Get index in virtual function table if it is a virtual member function. */
- attr = dwarf_attr (die, DW_AT_vtable_elem_location);
+ attr = dwarf2_attr (die, DW_AT_vtable_elem_location, cu);
if (attr)
{
/* Support the .debug_loc offsets */
if (attr_form_is_block (attr))
{
- fnp->voffset = decode_locdesc (DW_BLOCK (attr), objfile, cu_header) + 2;
+ fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu) + 2;
}
else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
{
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_type (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct type *type;
struct attribute *attr;
+ const char *previous_prefix = processing_current_prefix;
+ struct cleanup *back_to = NULL;
+
+ if (die->type)
+ return;
type = alloc_type (objfile);
INIT_CPLUS_SPECIFIC (type);
- attr = dwarf_attr (die, DW_AT_name);
+ attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
{
- TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
- strlen (DW_STRING (attr)),
- &objfile->type_obstack);
+ if (cu->language == language_cplus)
+ {
+ char *new_prefix = determine_class_name (die, cu);
+ TYPE_TAG_NAME (type) = obsavestring (new_prefix,
+ strlen (new_prefix),
+ &objfile->objfile_obstack);
+ back_to = make_cleanup (xfree, new_prefix);
+ processing_current_prefix = new_prefix;
+ }
+ else
+ {
+ /* The name is already allocated along with this objfile, so
+ we don't need to duplicate it for the type. */
+ TYPE_TAG_NAME (type) = DW_STRING (attr);
+ }
}
if (die->tag == DW_TAG_structure_type)
TYPE_CODE (type) = TYPE_CODE_CLASS;
}
- attr = dwarf_attr (die, DW_AT_byte_size);
+ attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
TYPE_LENGTH (type) = DW_UNSND (attr);
TYPE_LENGTH (type) = 0;
}
+ if (die_is_declaration (die, cu))
+ TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+
/* We need to add the type field to the die immediately so we don't
infinitely recurse when dealing with pointers to the structure
type within the structure itself. */
die->type = type;
- if (die->has_children && ! die_is_declaration (die))
+ if (die->child != NULL && ! die_is_declaration (die, cu))
{
struct field_info fi;
struct die_info *child_die;
memset (&fi, 0, sizeof (struct field_info));
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
all versions of G++ as of this writing (so through at
least 3.2.1) incorrectly generate DW_TAG_variable
tags for them instead. */
- dwarf2_add_field (&fi, child_die, objfile, cu_header);
+ dwarf2_add_field (&fi, child_die, cu);
}
else if (child_die->tag == DW_TAG_subprogram)
{
/* C++ member function. */
- process_die (child_die, objfile, cu_header);
- dwarf2_add_member_fn (&fi, child_die, type, objfile, cu_header);
+ read_type_die (child_die, cu);
+ dwarf2_add_member_fn (&fi, child_die, type, cu);
}
else if (child_die->tag == DW_TAG_inheritance)
{
/* C++ base class field. */
- dwarf2_add_field (&fi, child_die, objfile, cu_header);
- }
- else
- {
- process_die (child_die, objfile, cu_header);
+ dwarf2_add_field (&fi, child_die, cu);
}
child_die = sibling_die (child_die);
}
/* Attach fields and member functions to the type. */
if (fi.nfields)
- dwarf2_attach_fields_to_type (&fi, type, objfile);
+ dwarf2_attach_fields_to_type (&fi, type, cu);
if (fi.nfnfields)
{
- dwarf2_attach_fn_fields_to_type (&fi, type, objfile);
+ dwarf2_attach_fn_fields_to_type (&fi, type, cu);
/* Get the type which refers to the base class (possibly this
class itself) which contains the vtable pointer for the current
class from the DW_AT_containing_type attribute. */
- if (dwarf_attr (die, DW_AT_containing_type) != NULL)
+ if (dwarf2_attr (die, DW_AT_containing_type, cu) != NULL)
{
- struct type *t = die_containing_type (die, objfile, cu_header);
+ struct type *t = die_containing_type (die, cu);
TYPE_VPTR_BASETYPE (type) = t;
if (type == t)
{
char *fieldname = TYPE_FIELD_NAME (t, i);
- if (STREQN (fieldname, vptr_name, strlen (vptr_name) - 1)
+ if ((strncmp (fieldname, vptr_name,
+ strlen (vptr_name) - 1)
+ == 0)
&& is_cplus_marker (fieldname[strlen (vptr_name)]))
{
TYPE_VPTR_FIELDNO (type) = i;
}
}
- new_symbol (die, type, objfile, cu_header);
-
do_cleanups (back_to);
}
- else
+
+ processing_current_prefix = previous_prefix;
+ if (back_to != NULL)
+ do_cleanups (back_to);
+}
+
+static void
+process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+ const char *previous_prefix = processing_current_prefix;
+ struct die_info *child_die = die->child;
+
+ if (TYPE_TAG_NAME (die->type) != NULL)
+ processing_current_prefix = TYPE_TAG_NAME (die->type);
+
+ /* NOTE: carlton/2004-03-16: GCC 3.4 (or at least one of its
+ snapshots) has been known to create a die giving a declaration
+ for a class that has, as a child, a die giving a definition for a
+ nested class. So we have to process our children even if the
+ current die is a declaration. Normally, of course, a declaration
+ won't have any children at all. */
+
+ while (child_die != NULL && child_die->tag)
{
- /* No children, must be stub. */
- TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
+ if (child_die->tag == DW_TAG_member
+ || child_die->tag == DW_TAG_variable
+ || child_die->tag == DW_TAG_inheritance)
+ {
+ /* Do nothing. */
+ }
+ else
+ process_die (child_die, cu);
+
+ child_die = sibling_die (child_die);
}
-}
-/* Given a pointer to a die which begins an enumeration, process all
- the dies that define the members of the enumeration.
+ if (die->child != NULL && ! die_is_declaration (die, cu))
+ new_symbol (die, die->type, cu);
- This will be much nicer in draft 6 of the DWARF spec when our
- members will be dies instead squished into the DW_AT_element_list
- attribute.
+ processing_current_prefix = previous_prefix;
+}
- NOTE: We reverse the order of the element list. */
+/* Given a DW_AT_enumeration_type die, set its type. We do not
+ complete the type's fields yet, or create any symbols. */
static void
-read_enumeration (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
{
- struct die_info *child_die;
+ struct objfile *objfile = cu->objfile;
struct type *type;
- struct field *fields;
struct attribute *attr;
- struct symbol *sym;
- int num_fields;
- int unsigned_enum = 1;
+
+ if (die->type)
+ return;
type = alloc_type (objfile);
TYPE_CODE (type) = TYPE_CODE_ENUM;
- attr = dwarf_attr (die, DW_AT_name);
+ attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
{
- TYPE_TAG_NAME (type) = obsavestring (DW_STRING (attr),
- strlen (DW_STRING (attr)),
- &objfile->type_obstack);
+ char *name = DW_STRING (attr);
+
+ if (processing_has_namespace_info)
+ {
+ TYPE_TAG_NAME (type) = obconcat (&objfile->objfile_obstack,
+ processing_current_prefix,
+ processing_current_prefix[0] == '\0'
+ ? "" : "::",
+ name);
+ }
+ else
+ {
+ /* The name is already allocated along with this objfile, so
+ we don't need to duplicate it for the type. */
+ TYPE_TAG_NAME (type) = name;
+ }
}
- attr = dwarf_attr (die, DW_AT_byte_size);
+ attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
TYPE_LENGTH (type) = DW_UNSND (attr);
TYPE_LENGTH (type) = 0;
}
+ die->type = type;
+}
+
+/* Determine the name of the type represented by DIE, which should be
+ a named C++ compound type. Return the name in question; the caller
+ is responsible for xfree()'ing it. */
+
+static char *
+determine_class_name (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct cleanup *back_to = NULL;
+ struct die_info *spec_die = die_specification (die, cu);
+ char *new_prefix = NULL;
+
+ /* If this is the definition of a class that is declared by another
+ die, then processing_current_prefix may not be accurate; see
+ read_func_scope for a similar example. */
+ if (spec_die != NULL)
+ {
+ char *specification_prefix = determine_prefix (spec_die, cu);
+ processing_current_prefix = specification_prefix;
+ back_to = make_cleanup (xfree, specification_prefix);
+ }
+
+ /* If we don't have namespace debug info, guess the name by trying
+ to demangle the names of members, just like we did in
+ guess_structure_name. */
+ if (!processing_has_namespace_info)
+ {
+ struct die_info *child;
+
+ for (child = die->child;
+ child != NULL && child->tag != 0;
+ child = sibling_die (child))
+ {
+ if (child->tag == DW_TAG_subprogram)
+ {
+ new_prefix = class_name_from_physname (dwarf2_linkage_name
+ (child, cu));
+
+ if (new_prefix != NULL)
+ break;
+ }
+ }
+ }
+
+ if (new_prefix == NULL)
+ {
+ const char *name = dwarf2_name (die, cu);
+ new_prefix = typename_concat (processing_current_prefix,
+ name ? name : "<<anonymous>>");
+ }
+
+ if (back_to != NULL)
+ do_cleanups (back_to);
+
+ return new_prefix;
+}
+
+/* Given a pointer to a die which begins an enumeration, process all
+ the dies that define the members of the enumeration, and create the
+ symbol for the enumeration type.
+
+ NOTE: We reverse the order of the element list. */
+
+static void
+process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+ struct die_info *child_die;
+ struct field *fields;
+ struct attribute *attr;
+ struct symbol *sym;
+ int num_fields;
+ int unsigned_enum = 1;
+
num_fields = 0;
fields = NULL;
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag != DW_TAG_enumerator)
{
- process_die (child_die, objfile, cu_header);
+ process_die (child_die, cu);
}
else
{
- attr = dwarf_attr (child_die, DW_AT_name);
+ attr = dwarf2_attr (child_die, DW_AT_name, cu);
if (attr)
{
- sym = new_symbol (child_die, type, objfile, cu_header);
+ sym = new_symbol (child_die, die->type, cu);
if (SYMBOL_VALUE (sym) < 0)
unsigned_enum = 0;
* 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;
if (num_fields)
{
- TYPE_NFIELDS (type) = num_fields;
- TYPE_FIELDS (type) = (struct field *)
- TYPE_ALLOC (type, sizeof (struct field) * num_fields);
- memcpy (TYPE_FIELDS (type), fields,
+ TYPE_NFIELDS (die->type) = num_fields;
+ TYPE_FIELDS (die->type) = (struct field *)
+ TYPE_ALLOC (die->type, sizeof (struct field) * num_fields);
+ memcpy (TYPE_FIELDS (die->type), fields,
sizeof (struct field) * num_fields);
xfree (fields);
}
if (unsigned_enum)
- TYPE_FLAGS (type) |= TYPE_FLAG_UNSIGNED;
+ TYPE_FLAGS (die->type) |= TYPE_FLAG_UNSIGNED;
}
- die->type = type;
- new_symbol (die, type, objfile, cu_header);
+
+ new_symbol (die, die->type, cu);
}
/* Extract all information from a DW_TAG_array_type DIE and put it in
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);
+ index_type = dwarf2_fundamental_type (objfile, FT_INTEGER, cu);
range_type = create_range_type (NULL, index_type, 0, -1);
die->type = create_array_type (NULL, element_type, range_type);
return;
}
back_to = make_cleanup (null_cleanup, NULL);
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
if (child_die->tag == DW_TAG_subrange_type)
{
- unsigned int low, high;
-
- /* Default bounds to an array with unspecified length. */
- low = 0;
- high = -1;
- if (cu_language == language_fortran)
- {
- /* FORTRAN implies a lower bound of 1, if not given. */
- low = 1;
- }
-
- index_type = die_type (child_die, objfile, cu_header);
- attr = dwarf_attr (child_die, DW_AT_lower_bound);
- if (attr)
- {
- if (attr->form == DW_FORM_sdata)
- {
- low = DW_SND (attr);
- }
- else if (attr->form == DW_FORM_udata
- || attr->form == DW_FORM_data1
- || attr->form == DW_FORM_data2
- || attr->form == DW_FORM_data4
- || attr->form == DW_FORM_data8)
- {
- low = DW_UNSND (attr);
- }
- else
- {
- dwarf2_non_const_array_bound_ignored_complaint
- (dwarf_form_name (attr->form));
-#ifdef FORTRAN_HACK
- die->type = lookup_pointer_type (element_type);
- return;
-#else
- low = 0;
-#endif
- }
- }
- attr = dwarf_attr (child_die, DW_AT_upper_bound);
- if (attr)
- {
- if (attr->form == DW_FORM_sdata)
- {
- high = DW_SND (attr);
- }
- else if (attr->form == DW_FORM_udata
- || attr->form == DW_FORM_data1
- || attr->form == DW_FORM_data2
- || attr->form == DW_FORM_data4
- || attr->form == DW_FORM_data8)
- {
- high = DW_UNSND (attr);
- }
- else if (attr->form == DW_FORM_block1)
- {
- /* GCC encodes arrays with unspecified or dynamic length
- with a DW_FORM_block1 attribute.
- FIXME: GDB does not yet know how to handle dynamic
- arrays properly, treat them as arrays with unspecified
- length for now. */
- high = -1;
- }
- else
- {
- dwarf2_non_const_array_bound_ignored_complaint
- (dwarf_form_name (attr->form));
-#ifdef FORTRAN_HACK
- die->type = lookup_pointer_type (element_type);
- return;
-#else
- high = 1;
-#endif
- }
- }
+ read_subrange_type (child_die, cu);
- /* Create a range type and save it for array type creation. */
- if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0)
- {
- range_types = (struct type **)
- xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
- * sizeof (struct type *));
- if (ndim == 0)
- make_cleanup (free_current_contents, &range_types);
- }
- range_types[ndim++] = create_range_type (NULL, index_type, low, high);
+ if (child_die->type != NULL)
+ {
+ /* The range type was succesfully read. Save it for
+ the array type creation. */
+ if ((ndim % DW_FIELD_ALLOC_CHUNK) == 0)
+ {
+ range_types = (struct type **)
+ xrealloc (range_types, (ndim + DW_FIELD_ALLOC_CHUNK)
+ * sizeof (struct type *));
+ if (ndim == 0)
+ make_cleanup (free_current_contents, &range_types);
+ }
+ range_types[ndim++] = child_die->type;
+ }
}
child_die = sibling_die (child_die);
}
custom vendor extension. The main difference between a regular
array and the vector variant is that vectors are passed by value
to functions. */
- attr = dwarf_attr (die, DW_AT_GNU_vector);
+ attr = dwarf2_attr (die, DW_AT_GNU_vector, cu);
if (attr)
TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
/* First cut: install each common block member as a global variable. */
static void
-read_common_block (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_common_block (struct die_info *die, struct dwarf2_cu *cu)
{
struct die_info *child_die;
struct attribute *attr;
struct symbol *sym;
CORE_ADDR base = (CORE_ADDR) 0;
- attr = dwarf_attr (die, DW_AT_location);
+ attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr)
{
/* Support the .debug_loc offsets */
if (attr_form_is_block (attr))
{
- base = decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ base = decode_locdesc (DW_BLOCK (attr), cu);
}
else if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
{
"common block member");
}
}
- if (die->has_children)
+ if (die->child != NULL)
{
- child_die = die->next;
+ child_die = die->child;
while (child_die && child_die->tag)
{
- sym = new_symbol (child_die, NULL, objfile, cu_header);
- attr = dwarf_attr (child_die, DW_AT_data_member_location);
+ sym = new_symbol (child_die, NULL, cu);
+ attr = dwarf2_attr (child_die, DW_AT_data_member_location, cu);
if (attr)
{
SYMBOL_VALUE_ADDRESS (sym) =
- base + decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
+ base + decode_locdesc (DW_BLOCK (attr), cu);
add_symbol_to_list (sym, &global_symbols);
}
child_die = sibling_die (child_die);
/* 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_prefix = processing_current_prefix;
+ const char *name;
+ int is_anonymous;
+ struct die_info *current_die;
+
+ name = namespace_name (die, &is_anonymous, cu);
+
+ /* Now build the name of the current namespace. */
+
+ if (previous_prefix[0] == '\0')
+ {
+ processing_current_prefix = name;
+ }
+ else
+ {
+ /* We need temp_name around because processing_current_prefix
+ is a const char *. */
+ char *temp_name = alloca (strlen (previous_prefix)
+ + 2 + strlen(name) + 1);
+ strcpy (temp_name, previous_prefix);
+ strcat (temp_name, "::");
+ strcat (temp_name, name);
+
+ processing_current_prefix = temp_name;
+ }
+
+ /* Add a symbol associated to this if we haven't seen the namespace
+ before. Also, add a using directive if it's an anonymous
+ namespace. */
+
+ if (dwarf2_extension (die, cu) == NULL)
+ {
+ struct type *type;
+
+ /* FIXME: carlton/2003-06-27: Once GDB is more const-correct,
+ this cast will hopefully become unnecessary. */
+ type = init_type (TYPE_CODE_NAMESPACE, 0, 0,
+ (char *) processing_current_prefix,
+ objfile);
+ TYPE_TAG_NAME (type) = TYPE_NAME (type);
+
+ new_symbol (die, type, cu);
+ die->type = type;
+
+ if (is_anonymous)
+ cp_add_using_directive (processing_current_prefix,
+ strlen (previous_prefix),
+ strlen (processing_current_prefix));
+ }
+
+ if (die->child != NULL)
{
- struct die_info *child_die = die->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_prefix = previous_prefix;
+}
+
+/* Return the name of the namespace represented by DIE. Set
+ *IS_ANONYMOUS to tell whether or not the namespace is an anonymous
+ namespace. */
+
+static const char *
+namespace_name (struct die_info *die, int *is_anonymous, struct dwarf2_cu *cu)
+{
+ struct die_info *current_die;
+ const char *name = NULL;
+
+ /* Loop through the extensions until we find a name. */
+
+ for (current_die = die;
+ current_die != NULL;
+ current_die = dwarf2_extension (die, cu))
+ {
+ name = dwarf2_name (current_die, cu);
+ if (name != NULL)
+ break;
+ }
+
+ /* Is it an anonymous namespace? */
+
+ *is_anonymous = (name == NULL);
+ if (*is_anonymous)
+ name = "(anonymous namespace)";
+
+ return name;
}
/* Extract all information from a DW_TAG_pointer_type DIE and add to
the user defined type vector. */
static void
-read_tag_pointer_type (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_tag_pointer_type (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct comp_unit_head *cu_header = &cu->header;
struct type *type;
struct attribute *attr_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);
+ attr_byte_size = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr_byte_size)
byte_size = DW_UNSND (attr_byte_size);
else
byte_size = cu_header->addr_size;
- attr_address_class = dwarf_attr (die, DW_AT_address_class);
+ attr_address_class = dwarf2_attr (die, DW_AT_address_class, cu);
if (attr_address_class)
addr_class = DW_UNSND (attr_address_class);
else
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));
- attr = dwarf_attr (die, DW_AT_byte_size);
+ type = lookup_reference_type (die_type (die, cu));
+ attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
TYPE_LENGTH (type) = DW_UNSND (attr);
}
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;
return;
}
- attr = dwarf_attr (die, DW_AT_string_length);
+ attr = dwarf2_attr (die, DW_AT_string_length, cu);
if (attr)
{
length = DW_UNSND (attr);
else
{
/* check for the DW_AT_byte_size attribute */
- attr = dwarf_attr (die, DW_AT_byte_size);
+ attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
length = DW_UNSND (attr);
length = 1;
}
}
- index_type = dwarf2_fundamental_type (objfile, FT_INTEGER);
+ index_type = dwarf2_fundamental_type (objfile, FT_INTEGER, cu);
range_type = create_range_type (NULL, index_type, 1, length);
- if (cu_language == language_fortran)
+ if (cu->language == language_fortran)
{
/* Need to create a unique string type for bounds
information */
}
else
{
- char_type = dwarf2_fundamental_type (objfile, FT_CHAR);
+ char_type = dwarf2_fundamental_type (objfile, FT_CHAR, cu);
type = create_string_type (char_type, range_type);
}
die->type = type;
*/
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. */
- attr = dwarf_attr (die, DW_AT_prototyped);
+ attr = dwarf2_attr (die, DW_AT_prototyped, cu);
if ((attr && (DW_UNSND (attr) != 0))
- || cu_language == language_cplus)
+ || cu->language == language_cplus)
TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
- if (die->has_children)
+ if (die->child != NULL)
{
struct die_info *child_die;
int nparams = 0;
/* 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)
parameter for non-static member functions (which is the
this pointer) as artificial. We pass this information
to dwarf2_add_member_fn via TYPE_FIELD_ARTIFICIAL. */
- attr = dwarf_attr (child_die, DW_AT_artificial);
+ attr = dwarf2_attr (child_die, DW_AT_artificial, cu);
if (attr)
TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr);
else
TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0;
- TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, objfile,
- cu_header);
+ TYPE_FIELD_TYPE (ftype, iparams) = die_type (child_die, cu);
iparams++;
}
child_die = sibling_die (child_die);
}
static void
-read_typedef (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_typedef (struct die_info *die, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
struct attribute *attr;
char *name = NULL;
if (!die->type)
{
- attr = dwarf_attr (die, DW_AT_name);
+ attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
{
name = DW_STRING (attr);
}
die->type = init_type (TYPE_CODE_TYPEDEF, 0, TYPE_FLAG_TARGET_STUB, name, objfile);
- TYPE_TARGET_TYPE (die->type) = die_type (die, objfile, cu_header);
+ TYPE_TARGET_TYPE (die->type) = die_type (die, cu);
}
}
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;
return;
}
- attr = dwarf_attr (die, DW_AT_encoding);
+ attr = dwarf2_attr (die, DW_AT_encoding, cu);
if (attr)
{
encoding = DW_UNSND (attr);
}
- attr = dwarf_attr (die, DW_AT_byte_size);
+ attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
{
size = DW_UNSND (attr);
}
- attr = dwarf_attr (die, DW_AT_name);
+ attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
{
enum type_code code = TYPE_CODE_INT;
}
type = init_type (code, size, type_flags, DW_STRING (attr), objfile);
if (encoding == DW_ATE_address)
- TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID);
+ TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID,
+ cu);
else if (encoding == DW_ATE_complex_float)
{
if (size == 32)
TYPE_TARGET_TYPE (type)
- = dwarf2_fundamental_type (objfile, FT_EXT_PREC_FLOAT);
+ = dwarf2_fundamental_type (objfile, FT_EXT_PREC_FLOAT, cu);
else if (size == 16)
TYPE_TARGET_TYPE (type)
- = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
+ = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT, cu);
else if (size == 8)
TYPE_TARGET_TYPE (type)
- = dwarf2_fundamental_type (objfile, FT_FLOAT);
+ = dwarf2_fundamental_type (objfile, FT_FLOAT, cu);
}
}
else
{
- type = dwarf_base_type (encoding, size, objfile);
+ type = dwarf_base_type (encoding, size, cu);
+ }
+ die->type = type;
+}
+
+/* Read the given DW_AT_subrange DIE. */
+
+static void
+read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct type *base_type;
+ struct type *range_type;
+ struct attribute *attr;
+ int low = 0;
+ int high = -1;
+
+ /* If we have already decoded this die, then nothing more to do. */
+ if (die->type)
+ return;
+
+ base_type = die_type (die, cu);
+ if (base_type == NULL)
+ {
+ complaint (&symfile_complaints,
+ "DW_AT_type missing from DW_TAG_subrange_type");
+ return;
}
- die->type = type;
+
+ if (TYPE_CODE (base_type) == TYPE_CODE_VOID)
+ base_type = alloc_type (NULL);
+
+ if (cu->language == language_fortran)
+ {
+ /* FORTRAN implies a lower bound of 1, if not given. */
+ low = 1;
+ }
+
+ attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
+ if (attr)
+ low = dwarf2_get_attr_constant_value (attr, 0);
+
+ attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
+ if (attr)
+ {
+ if (attr->form == DW_FORM_block1)
+ {
+ /* GCC encodes arrays with unspecified or dynamic length
+ with a DW_FORM_block1 attribute.
+ FIXME: GDB does not yet know how to handle dynamic
+ arrays properly, treat them as arrays with unspecified
+ length for now.
+
+ FIXME: jimb/2003-09-22: GDB does not really know
+ how to handle arrays of unspecified length
+ either; we just represent them as zero-length
+ arrays. Choose an appropriate upper bound given
+ the lower bound we've computed above. */
+ high = low - 1;
+ }
+ else
+ high = dwarf2_get_attr_constant_value (attr, 1);
+ }
+
+ range_type = create_range_type (NULL, base_type, low, high);
+
+ attr = dwarf2_attr (die, DW_AT_name, cu);
+ if (attr && DW_STRING (attr))
+ TYPE_NAME (range_type) = DW_STRING (attr);
+
+ attr = dwarf2_attr (die, DW_AT_byte_size, cu);
+ if (attr)
+ TYPE_LENGTH (range_type) = DW_UNSND (attr);
+
+ die->type = range_type;
}
+
/* Read a whole compilation unit into a linked list of dies. */
static struct die_info *
-read_comp_unit (char *info_ptr, bfd *abfd,
- const struct comp_unit_head *cu_header)
+read_comp_unit (char *info_ptr, bfd *abfd, struct dwarf2_cu *cu)
{
- struct die_info *first_die, *last_die, *die;
- char *cur_ptr;
- int nesting_level;
-
/* Reset die reference table; we are
building new ones now. */
dwarf2_empty_hash_tables ();
+ return read_die_and_children (info_ptr, abfd, cu, &info_ptr, NULL);
+}
+
+/* Read a single die and all its descendents. Set the die's sibling
+ field to NULL; set other fields in the die correctly, and set all
+ of the descendents' fields correctly. Set *NEW_INFO_PTR to the
+ location of the info_ptr after reading all of those dies. PARENT
+ is the parent of the die in question. */
+
+static struct die_info *
+read_die_and_children (char *info_ptr, bfd *abfd,
+ struct dwarf2_cu *cu,
+ char **new_info_ptr,
+ struct die_info *parent)
+{
+ struct die_info *die;
+ char *cur_ptr;
+ int has_children;
+
+ cur_ptr = read_full_die (&die, abfd, info_ptr, cu, &has_children);
+ store_in_ref_table (die->offset, die);
+
+ if (has_children)
+ {
+ die->child = read_die_and_siblings (cur_ptr, abfd, cu,
+ new_info_ptr, die);
+ }
+ else
+ {
+ die->child = NULL;
+ *new_info_ptr = cur_ptr;
+ }
+
+ die->sibling = NULL;
+ die->parent = parent;
+ return die;
+}
+
+/* Read a die, all of its descendents, and all of its siblings; set
+ all of the fields of all of the dies correctly. Arguments are as
+ in read_die_and_children. */
+
+static struct die_info *
+read_die_and_siblings (char *info_ptr, bfd *abfd,
+ struct dwarf2_cu *cu,
+ char **new_info_ptr,
+ struct die_info *parent)
+{
+ struct die_info *first_die, *last_sibling;
+ char *cur_ptr;
+
cur_ptr = info_ptr;
- nesting_level = 0;
- first_die = last_die = NULL;
- do
+ first_die = last_sibling = NULL;
+
+ while (1)
{
- cur_ptr = read_full_die (&die, abfd, cur_ptr, cu_header);
- if (die->has_children)
+ struct die_info *die
+ = read_die_and_children (cur_ptr, abfd, cu, &cur_ptr, parent);
+
+ if (!first_die)
{
- nesting_level++;
+ first_die = die;
}
- if (die->tag == 0)
+ else
{
- nesting_level--;
+ last_sibling->sibling = die;
}
- die->next = NULL;
-
- /* Enter die in reference hash table */
- store_in_ref_table (die->offset, die);
-
- if (!first_die)
+ if (die->tag == 0)
{
- first_die = last_die = die;
+ *new_info_ptr = cur_ptr;
+ return first_die;
}
else
{
- last_die->next = die;
- last_die = die;
+ last_sibling = die;
}
}
- while (nesting_level > 0);
- return first_die;
}
/* Free a linked list of dies. */
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;
/* Read the contents of the section at OFFSET and of size SIZE from the
- object file specified by OBJFILE into the psymbol_obstack and return it. */
+ object file specified by OBJFILE into the objfile_obstack and return it. */
char *
-dwarf2_read_section (struct objfile *objfile, file_ptr offset,
- unsigned int size, asection *sectp)
+dwarf2_read_section (struct objfile *objfile, asection *sectp)
{
bfd *abfd = objfile->obfd;
char *buf, *retbuf;
+ bfd_size_type size = bfd_get_section_size_before_reloc (sectp);
if (size == 0)
return NULL;
- buf = (char *) obstack_alloc (&objfile->psymbol_obstack, size);
+ buf = (char *) obstack_alloc (&objfile->objfile_obstack, size);
retbuf
= (char *) symfile_relocate_debug_section (abfd, sectp, (bfd_byte *) buf);
if (retbuf != NULL)
return retbuf;
- if ((bfd_seek (abfd, offset, SEEK_SET) != 0) ||
- (bfd_bread (buf, size, abfd) != size))
- {
- buf = NULL;
- error ("Dwarf Error: Can't read DWARF data from '%s'",
- bfd_get_filename (abfd));
- }
+ if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
+ || bfd_bread (buf, size, abfd) != size)
+ error ("Dwarf Error: Can't read DWARF data from '%s'",
+ bfd_get_filename (abfd));
+
return buf;
}
/* In DWARF version 2, the description of the debugging information is
stored in a separate .debug_abbrev section. Before we read any
dies from a section we read in all abbreviations and install them
- in a hash table. */
+ in a hash table. This function also sets flags in CU describing
+ the data found in the abbrev table. */
static void
-dwarf2_read_abbrevs (bfd *abfd, 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;
unsigned int abbrev_form, hash_number;
+ struct attr_abbrev *cur_attrs;
+ unsigned int allocated_attrs;
/* Initialize dwarf2 abbrevs */
- memset (cu_header->dwarf2_abbrevs, 0,
- ABBREV_HASH_SIZE*sizeof (struct abbrev_info *));
-
- abbrev_ptr = dwarf_abbrev_buffer + cu_header->abbrev_offset;
+ obstack_init (&cu->abbrev_obstack);
+ cu->dwarf2_abbrevs = obstack_alloc (&cu->abbrev_obstack,
+ (ABBREV_HASH_SIZE
+ * sizeof (struct abbrev_info *)));
+ memset (cu->dwarf2_abbrevs, 0,
+ ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
+
+ abbrev_ptr = dwarf2_per_objfile->abbrev_buffer + cu_header->abbrev_offset;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
+ allocated_attrs = ATTR_ALLOC_CHUNK;
+ cur_attrs = xmalloc (allocated_attrs * sizeof (struct attr_abbrev));
+
/* loop until we reach an abbrev number of 0 */
while (abbrev_number)
{
- cur_abbrev = dwarf_alloc_abbrev ();
+ cur_abbrev = dwarf_alloc_abbrev (cu);
/* read in abbrev header */
cur_abbrev->number = abbrev_number;
cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
abbrev_ptr += 1;
+ if (cur_abbrev->tag == DW_TAG_namespace)
+ cu->has_namespace_info = 1;
+
/* now read in declarations */
abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
abbrev_ptr += bytes_read;
while (abbrev_name)
{
- if ((cur_abbrev->num_attrs % ATTR_ALLOC_CHUNK) == 0)
+ if (cur_abbrev->num_attrs == allocated_attrs)
{
- cur_abbrev->attrs = (struct attr_abbrev *)
- xrealloc (cur_abbrev->attrs,
- (cur_abbrev->num_attrs + ATTR_ALLOC_CHUNK)
- * sizeof (struct attr_abbrev));
+ allocated_attrs += ATTR_ALLOC_CHUNK;
+ cur_attrs
+ = xrealloc (cur_attrs, (allocated_attrs
+ * sizeof (struct attr_abbrev)));
}
- cur_abbrev->attrs[cur_abbrev->num_attrs].name = abbrev_name;
- cur_abbrev->attrs[cur_abbrev->num_attrs++].form = abbrev_form;
+ cur_attrs[cur_abbrev->num_attrs].name = abbrev_name;
+ cur_attrs[cur_abbrev->num_attrs++].form = abbrev_form;
abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
}
+ cur_abbrev->attrs = obstack_alloc (&cu->abbrev_obstack,
+ (cur_abbrev->num_attrs
+ * sizeof (struct attr_abbrev)));
+ memcpy (cur_abbrev->attrs, cur_attrs,
+ cur_abbrev->num_attrs * sizeof (struct attr_abbrev));
+
hash_number = abbrev_number % ABBREV_HASH_SIZE;
- cur_abbrev->next = cu_header->dwarf2_abbrevs[hash_number];
- cu_header->dwarf2_abbrevs[hash_number] = cur_abbrev;
+ cur_abbrev->next = cu->dwarf2_abbrevs[hash_number];
+ cu->dwarf2_abbrevs[hash_number] = cur_abbrev;
/* Get next abbreviation.
Under Irix6 the abbreviations for a compilation unit are not
already read (which means we are about to read the abbreviations
for the next compile unit) or if the end of the abbreviation
table is reached. */
- if ((unsigned int) (abbrev_ptr - dwarf_abbrev_buffer)
- >= dwarf_abbrev_size)
+ if ((unsigned int) (abbrev_ptr - dwarf2_per_objfile->abbrev_buffer)
+ >= dwarf2_per_objfile->abbrev_size)
break;
abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
- if (dwarf2_lookup_abbrev (abbrev_number, cu_header) != NULL)
+ if (dwarf2_lookup_abbrev (abbrev_number, cu) != NULL)
break;
}
+
+ xfree (cur_attrs);
}
-/* Empty the abbrev table for a new compilation unit. */
+/* Release the memory used by the abbrev table for a compilation unit. */
-/* ARGSUSED */
static void
-dwarf2_empty_abbrev_table (void *ptr_to_abbrevs_table)
+dwarf2_free_abbrev_table (void *ptr_to_cu)
{
- int i;
- struct abbrev_info *abbrev, *next;
- struct abbrev_info **abbrevs;
-
- abbrevs = (struct abbrev_info **)ptr_to_abbrevs_table;
+ struct dwarf2_cu *cu = ptr_to_cu;
- for (i = 0; i < ABBREV_HASH_SIZE; ++i)
- {
- next = NULL;
- abbrev = abbrevs[i];
- while (abbrev)
- {
- next = abbrev->next;
- xfree (abbrev->attrs);
- xfree (abbrev);
- abbrev = next;
- }
- abbrevs[i] = NULL;
- }
+ obstack_free (&cu->abbrev_obstack, NULL);
+ cu->dwarf2_abbrevs = NULL;
}
/* Lookup an abbrev_info structure in the abbrev hash table. */
static struct abbrev_info *
-dwarf2_lookup_abbrev (unsigned int number, const struct comp_unit_head *cu_header)
+dwarf2_lookup_abbrev (unsigned int number, struct dwarf2_cu *cu)
{
unsigned int hash_number;
struct abbrev_info *abbrev;
hash_number = number % ABBREV_HASH_SIZE;
- abbrev = cu_header->dwarf2_abbrevs[hash_number];
+ abbrev = cu->dwarf2_abbrevs[hash_number];
while (abbrev)
{
return NULL;
}
+/* Returns nonzero if TAG represents a type that we might generate a partial
+ symbol for. */
+
+static int
+is_type_tag_for_partial (int tag)
+{
+ switch (tag)
+ {
+#if 0
+ /* Some types that would be reasonable to generate partial symbols for,
+ that we don't at present. */
+ case DW_TAG_array_type:
+ case DW_TAG_file_type:
+ case DW_TAG_ptr_to_member_type:
+ case DW_TAG_set_type:
+ case DW_TAG_string_type:
+ case DW_TAG_subroutine_type:
+#endif
+ case DW_TAG_base_type:
+ case DW_TAG_class_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_subrange_type:
+ case DW_TAG_typedef:
+ case DW_TAG_union_type:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* Load all DIEs that are interesting for partial symbols into memory. */
+
+static struct partial_die_info *
+load_partial_dies (bfd *abfd, char *info_ptr, int building_psymtab,
+ struct dwarf2_cu *cu)
+{
+ struct partial_die_info *part_die;
+ struct partial_die_info *parent_die, *last_die, *first_die = NULL;
+ struct abbrev_info *abbrev;
+ unsigned int bytes_read;
+
+ int nesting_level = 1;
+
+ parent_die = NULL;
+ last_die = NULL;
+
+ cu->partial_dies
+ = htab_create_alloc_ex (cu->header.length / 12,
+ partial_die_hash,
+ partial_die_eq,
+ NULL,
+ &cu->comp_unit_obstack,
+ hashtab_obstack_allocate,
+ dummy_obstack_deallocate);
+
+ part_die = obstack_alloc (&cu->comp_unit_obstack,
+ sizeof (struct partial_die_info));
+
+ while (1)
+ {
+ abbrev = peek_die_abbrev (info_ptr, &bytes_read, cu);
+
+ /* A NULL abbrev means the end of a series of children. */
+ if (abbrev == NULL)
+ {
+ if (--nesting_level == 0)
+ {
+ /* PART_DIE was probably the last thing allocated on the
+ comp_unit_obstack, so we could call obstack_free
+ here. We don't do that because the waste is small,
+ and will be cleaned up when we're done with this
+ compilation unit. This way, we're also more robust
+ against other users of the comp_unit_obstack. */
+ return first_die;
+ }
+ info_ptr += bytes_read;
+ last_die = parent_die;
+ parent_die = parent_die->die_parent;
+ continue;
+ }
+
+ /* Check whether this DIE is interesting enough to save. */
+ if (!is_type_tag_for_partial (abbrev->tag)
+ && abbrev->tag != DW_TAG_enumerator
+ && abbrev->tag != DW_TAG_subprogram
+ && abbrev->tag != DW_TAG_variable
+ && abbrev->tag != DW_TAG_namespace)
+ {
+ /* Otherwise we skip to the next sibling, if any. */
+ info_ptr = skip_one_die (info_ptr + bytes_read, abbrev, cu);
+ continue;
+ }
+
+ info_ptr = read_partial_die (part_die, abbrev, bytes_read,
+ abfd, info_ptr, cu);
+
+ /* This two-pass algorithm for processing partial symbols has a
+ high cost in cache pressure. Thus, handle some simple cases
+ here which cover the majority of C partial symbols. DIEs
+ which neither have specification tags in them, nor could have
+ specification tags elsewhere pointing at them, can simply be
+ processed and discarded.
+
+ This segment is also optional; scan_partial_symbols and
+ add_partial_symbol will handle these DIEs if we chain
+ them in normally. When compilers which do not emit large
+ quantities of duplicate debug information are more common,
+ this code can probably be removed. */
+
+ /* Any complete simple types at the top level (pretty much all
+ of them, for a language without namespaces), can be processed
+ directly. */
+ if (parent_die == NULL
+ && part_die->has_specification == 0
+ && part_die->is_declaration == 0
+ && (part_die->tag == DW_TAG_typedef
+ || part_die->tag == DW_TAG_base_type
+ || part_die->tag == DW_TAG_subrange_type))
+ {
+ if (building_psymtab && part_die->name != NULL)
+ add_psymbol_to_list (part_die->name, strlen (part_die->name),
+ VAR_DOMAIN, LOC_TYPEDEF,
+ &cu->objfile->static_psymbols,
+ 0, (CORE_ADDR) 0, cu->language, cu->objfile);
+ info_ptr = locate_pdi_sibling (part_die, info_ptr, abfd, cu);
+ continue;
+ }
+
+ /* If we're at the second level, and we're an enumerator, and
+ our parent has no specification (meaning possibly lives in a
+ namespace elsewhere), then we can add the partial symbol now
+ instead of queueing it. */
+ if (part_die->tag == DW_TAG_enumerator
+ && parent_die != NULL
+ && parent_die->die_parent == NULL
+ && parent_die->tag == DW_TAG_enumeration_type
+ && parent_die->has_specification == 0)
+ {
+ if (part_die->name == NULL)
+ complaint (&symfile_complaints, "malformed enumerator DIE ignored");
+ else if (building_psymtab)
+ add_psymbol_to_list (part_die->name, strlen (part_die->name),
+ VAR_DOMAIN, LOC_CONST,
+ cu->language == language_cplus
+ ? &cu->objfile->global_psymbols
+ : &cu->objfile->static_psymbols,
+ 0, (CORE_ADDR) 0, cu->language, cu->objfile);
+
+ info_ptr = locate_pdi_sibling (part_die, info_ptr, abfd, cu);
+ continue;
+ }
+
+ /* We'll save this DIE so link it in. */
+ part_die->die_parent = parent_die;
+ part_die->die_sibling = NULL;
+ part_die->die_child = NULL;
+
+ if (last_die && last_die == parent_die)
+ last_die->die_child = part_die;
+ else if (last_die)
+ last_die->die_sibling = part_die;
+
+ last_die = part_die;
+
+ if (first_die == NULL)
+ first_die = part_die;
+
+ /* Maybe add the DIE to the hash table. Not all DIEs that we
+ find interesting need to be in the hash table, because we
+ also have the parent/sibling/child chains; only those that we
+ might refer to by offset later during partial symbol reading.
+
+ For now this means things that might have be the target of a
+ DW_AT_specification, DW_AT_abstract_origin, or
+ DW_AT_extension. DW_AT_extension will refer only to
+ namespaces; DW_AT_abstract_origin refers to functions (and
+ many things under the function DIE, but we do not recurse
+ into function DIEs during partial symbol reading) and
+ possibly variables as well; DW_AT_specification refers to
+ declarations. Declarations ought to have the DW_AT_declaration
+ flag. It happens that GCC forgets to put it in sometimes, but
+ only for functions, not for types.
+
+ Adding more things than necessary to the hash table is harmless
+ except for the performance cost. Adding too few will result in
+ internal errors in find_partial_die. */
+
+ if (abbrev->tag == DW_TAG_subprogram
+ || abbrev->tag == DW_TAG_variable
+ || abbrev->tag == DW_TAG_namespace
+ || part_die->is_declaration)
+ {
+ void **slot;
+
+ slot = htab_find_slot_with_hash (cu->partial_dies, part_die,
+ part_die->offset, INSERT);
+ *slot = part_die;
+ }
+
+ part_die = obstack_alloc (&cu->comp_unit_obstack,
+ sizeof (struct partial_die_info));
+
+ /* For some DIEs we want to follow their children (if any). For C
+ we have no reason to follow the children of structures; for other
+ languages we have to, both so that we can get at method physnames
+ to infer fully qualified class names, and for DW_AT_specification. */
+ if (last_die->has_children
+ && (last_die->tag == DW_TAG_namespace
+ || last_die->tag == DW_TAG_enumeration_type
+ || (cu->language != language_c
+ && (last_die->tag == DW_TAG_class_type
+ || last_die->tag == DW_TAG_structure_type
+ || last_die->tag == DW_TAG_union_type))))
+ {
+ nesting_level++;
+ parent_die = last_die;
+ continue;
+ }
+
+ /* Otherwise we skip to the next sibling, if any. */
+ info_ptr = locate_pdi_sibling (last_die, info_ptr, abfd, cu);
+
+ /* Back to the top, do it again. */
+ }
+}
+
/* Read a minimal amount of information into the minimal die structure. */
static char *
-read_partial_die (struct partial_die_info *part_die, bfd *abfd,
- char *info_ptr, const struct comp_unit_head *cu_header)
+read_partial_die (struct partial_die_info *part_die,
+ struct abbrev_info *abbrev,
+ unsigned int abbrev_len, bfd *abfd,
+ char *info_ptr, struct dwarf2_cu *cu)
{
- unsigned int abbrev_number, bytes_read, i;
- struct abbrev_info *abbrev;
+ unsigned int bytes_read, i;
struct attribute attr;
- struct attribute spec_attr;
- int found_spec_attr = 0;
int has_low_pc_attr = 0;
int has_high_pc_attr = 0;
- *part_die = zeroed_partial_die;
- abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
- info_ptr += bytes_read;
- if (!abbrev_number)
+ memset (part_die, 0, sizeof (struct partial_die_info));
+
+ part_die->offset = info_ptr - dwarf2_per_objfile->info_buffer;
+
+ info_ptr += abbrev_len;
+
+ if (abbrev == NULL)
return info_ptr;
- abbrev = dwarf2_lookup_abbrev (abbrev_number, cu_header);
- if (!abbrev)
- {
- 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;
part_die->has_children = abbrev->has_children;
- part_die->abbrev = abbrev_number;
for (i = 0; i < abbrev->num_attrs; ++i)
{
- info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd,
- info_ptr, cu_header);
+ info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, info_ptr, cu);
/* Store the data if it is of an attribute we want to keep in a
partial symbol table. */
if (part_die->name == NULL)
part_die->name = DW_STRING (&attr);
break;
+ case DW_AT_comp_dir:
+ if (part_die->dirname == NULL)
+ part_die->dirname = DW_STRING (&attr);
+ break;
case DW_AT_MIPS_linkage_name:
part_die->name = DW_STRING (&attr);
break;
break;
case DW_AT_abstract_origin:
case DW_AT_specification:
- found_spec_attr = 1;
- spec_attr = attr;
+ case DW_AT_extension:
+ part_die->has_specification = 1;
+ part_die->spec_offset = dwarf2_get_ref_die_offset (&attr, cu);
break;
case DW_AT_sibling:
/* Ignore absolute siblings, they might point outside of
if (attr.form == DW_FORM_ref_addr)
complaint (&symfile_complaints, "ignoring absolute DW_AT_sibling");
else
- part_die->sibling =
- dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr);
+ part_die->sibling = dwarf2_per_objfile->info_buffer
+ + dwarf2_get_ref_die_offset (&attr, cu);
break;
+ case DW_AT_stmt_list:
+ part_die->has_stmt_list = 1;
+ part_die->line_offset = DW_UNSND (&attr);
+ break;
default:
break;
}
}
- /* If we found a reference attribute and the die has no name, try
- to find a name in the referred to die. */
-
- if (found_spec_attr && part_die->name == NULL)
- {
- struct partial_die_info spec_die;
- char *spec_ptr;
- int dummy;
-
- spec_ptr = dwarf_info_buffer + dwarf2_get_ref_die_offset (&spec_attr);
- read_partial_die (&spec_die, abfd, spec_ptr, cu_header);
- if (spec_die.name)
- {
- part_die->name = spec_die.name;
-
- /* Copy DW_AT_external attribute if it is set. */
- if (spec_die.is_external)
- part_die->is_external = spec_die.is_external;
- }
- }
-
/* When using the GNU linker, .gnu.linkonce. sections are used to
eliminate duplicate copies of functions and vtables and such.
The linker will arbitrarily choose one and discard the others.
return info_ptr;
}
-/* Read the die from the .debug_info section buffer. And set diep to
- point to a newly allocated die with its information. */
+/* Find a cached partial DIE at OFFSET in CU. */
+
+static struct partial_die_info *
+find_partial_die_in_comp_unit (unsigned long offset, struct dwarf2_cu *cu)
+{
+ struct partial_die_info *lookup_die = NULL;
+ struct partial_die_info part_die;
+
+ part_die.offset = offset;
+ lookup_die = htab_find_with_hash (cu->partial_dies, &part_die, offset);
+
+ if (lookup_die == NULL)
+ internal_error (__FILE__, __LINE__,
+ "could not find partial DIE in cache\n");
+
+ return lookup_die;
+}
+
+/* Find a partial DIE at OFFSET, which may or may not be in CU. */
+
+static struct partial_die_info *
+find_partial_die (unsigned long offset, struct dwarf2_cu *cu,
+ struct dwarf2_cu **target_cu)
+{
+ struct dwarf2_per_cu_data *per_cu;
+
+ if (offset >= cu->header.offset
+ && offset < cu->header.offset + cu->header.length)
+ {
+ *target_cu = cu;
+ return find_partial_die_in_comp_unit (offset, cu);
+ }
+
+ internal_error (__FILE__, __LINE__,
+ "unsupported inter-compilation-unit reference");
+}
+
+/* Adjust PART_DIE before generating a symbol for it. This function
+ may set the is_external flag or change the DIE's name. */
+
+static void
+fixup_partial_die (struct partial_die_info *part_die,
+ struct dwarf2_cu *cu)
+{
+ /* If we found a reference attribute and the DIE has no name, try
+ to find a name in the referred to DIE. */
+
+ if (part_die->name == NULL && part_die->has_specification)
+ {
+ struct partial_die_info *spec_die;
+ struct dwarf2_cu *spec_cu;
+
+ spec_die = find_partial_die (part_die->spec_offset, cu, &spec_cu);
+
+ fixup_partial_die (spec_die, spec_cu);
+
+ if (spec_die->name)
+ {
+ part_die->name = spec_die->name;
+
+ /* Copy DW_AT_external attribute if it is set. */
+ if (spec_die->is_external)
+ part_die->is_external = spec_die->is_external;
+ }
+ }
+
+ /* Set default names for some unnamed DIEs. */
+ if (part_die->name == NULL && (part_die->tag == DW_TAG_structure_type
+ || part_die->tag == DW_TAG_class_type))
+ part_die->name = "(anonymous class)";
+
+ if (part_die->name == NULL && part_die->tag == DW_TAG_namespace)
+ part_die->name = "(anonymous namespace)";
+
+ if (part_die->tag == DW_TAG_structure_type
+ || part_die->tag == DW_TAG_class_type
+ || part_die->tag == DW_TAG_union_type)
+ guess_structure_name (part_die, cu);
+}
+
+/* Read the die from the .debug_info section buffer. Set DIEP to
+ point to a newly allocated die with its information, except for its
+ child, sibling, and parent fields. Set HAS_CHILDREN to tell
+ whether the die has children or not. */
static char *
read_full_die (struct die_info **diep, bfd *abfd, char *info_ptr,
- const struct comp_unit_head *cu_header)
+ struct dwarf2_cu *cu, int *has_children)
{
unsigned int abbrev_number, bytes_read, i, offset;
struct abbrev_info *abbrev;
struct die_info *die;
- offset = info_ptr - dwarf_info_buffer;
+ offset = info_ptr - dwarf2_per_objfile->info_buffer;
abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
if (!abbrev_number)
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 [in module %s]", abbrev_number,
- bfd_get_filename (abfd));
+ 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:
- blk = dwarf_alloc_block ();
+ blk = dwarf_alloc_block (cu);
blk->size = read_2_bytes (abfd, info_ptr);
info_ptr += 2;
blk->data = read_n_bytes (abfd, info_ptr, blk->size);
DW_BLOCK (attr) = blk;
break;
case DW_FORM_block4:
- blk = dwarf_alloc_block ();
+ blk = dwarf_alloc_block (cu);
blk->size = read_4_bytes (abfd, info_ptr);
info_ptr += 4;
blk->data = read_n_bytes (abfd, info_ptr, blk->size);
info_ptr += bytes_read;
break;
case DW_FORM_block:
- blk = dwarf_alloc_block ();
+ blk = dwarf_alloc_block (cu);
blk->size = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
blk->data = read_n_bytes (abfd, info_ptr, blk->size);
DW_BLOCK (attr) = blk;
break;
case DW_FORM_block1:
- blk = dwarf_alloc_block ();
+ blk = dwarf_alloc_block (cu);
blk->size = read_1_byte (abfd, info_ptr);
info_ptr += 1;
blk->data = read_n_bytes (abfd, info_ptr, blk->size);
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 [in module %s]",
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)
LONGEST str_offset = read_offset (abfd, buf, cu_header,
(int *) bytes_read_ptr);
- if (dwarf_str_buffer == NULL)
+ if (dwarf2_per_objfile->str_buffer == NULL)
{
error ("DW_FORM_strp used without .debug_str section [in module %s]",
bfd_get_filename (abfd));
return NULL;
}
- if (str_offset >= dwarf_str_size)
+ if (str_offset >= dwarf2_per_objfile->str_size)
{
error ("DW_FORM_strp pointing outside of .debug_str section [in module %s]",
bfd_get_filename (abfd));
return NULL;
}
gdb_assert (HOST_CHAR_BIT == 8);
- if (dwarf_str_buffer[str_offset] == '\0')
+ if (dwarf2_per_objfile->str_buffer[str_offset] == '\0')
return NULL;
- return dwarf_str_buffer + str_offset;
+ return dwarf2_per_objfile->str_buffer + str_offset;
}
static unsigned long
return result;
}
+/* Return a pointer to just past the end of an LEB128 number in BUF. */
+
+static char *
+skip_leb128 (bfd *abfd, char *buf)
+{
+ int byte;
+
+ while (1)
+ {
+ byte = bfd_get_8 (abfd, (bfd_byte *) buf);
+ buf++;
+ if ((byte & 128) == 0)
+ return buf;
+ }
+}
+
static void
-set_cu_language (unsigned int lang)
+set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
{
switch (lang)
{
case DW_LANG_C89:
case DW_LANG_C:
- cu_language = language_c;
+ cu->language = language_c;
break;
case DW_LANG_C_plus_plus:
- cu_language = language_cplus;
+ cu->language = language_cplus;
break;
case DW_LANG_Fortran77:
case DW_LANG_Fortran90:
case DW_LANG_Fortran95:
- cu_language = language_fortran;
+ cu->language = language_fortran;
break;
case DW_LANG_Mips_Assembler:
- cu_language = language_asm;
+ cu->language = language_asm;
break;
case DW_LANG_Java:
- cu_language = language_java;
+ cu->language = language_java;
break;
case DW_LANG_Ada83:
case DW_LANG_Ada95:
case DW_LANG_Pascal83:
case DW_LANG_Modula2:
default:
- cu_language = language_unknown;
+ cu->language = language_minimal;
break;
}
- cu_language_defn = language_def (cu_language);
+ cu->language_defn = language_def (cu->language);
}
/* Return the named attribute or NULL if not there. */
static struct attribute *
-dwarf_attr (struct die_info *die, unsigned int name)
+dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu)
{
unsigned int i;
struct attribute *spec = NULL;
if (spec)
{
struct die_info *ref_die =
- follow_die_ref (dwarf2_get_ref_die_offset (spec));
+ follow_die_ref (dwarf2_get_ref_die_offset (spec, cu));
if (ref_die)
- return dwarf_attr (ref_die, name);
+ return dwarf2_attr (ref_die, name, cu);
}
return NULL;
}
+/* Return non-zero iff the attribute NAME is defined for the given DIE,
+ and holds a non-zero value. This function should only be used for
+ DW_FORM_flag attributes. */
+
+static int
+dwarf2_flag_true_p (struct die_info *die, unsigned name, struct dwarf2_cu *cu)
+{
+ struct attribute *attr = dwarf2_attr (die, name, cu);
+
+ return (attr && DW_UNSND (attr));
+}
+
static int
-die_is_declaration (struct die_info *die)
+die_is_declaration (struct die_info *die, struct dwarf2_cu *cu)
{
- return (dwarf_attr (die, DW_AT_declaration)
- && ! dwarf_attr (die, DW_AT_specification));
+ /* A DIE is a declaration if it has a DW_AT_declaration attribute
+ which value is non-zero. However, we have to be careful with
+ DIEs having a DW_AT_specification attribute, because dwarf2_attr()
+ (via dwarf2_flag_true_p) follows this attribute. So we may
+ end up accidently finding a declaration attribute that belongs
+ to a different DIE referenced by the specification attribute,
+ even though the given DIE does not have a declaration attribute. */
+ return (dwarf2_flag_true_p (die, DW_AT_declaration, cu)
+ && dwarf2_attr (die, DW_AT_specification, cu) == NULL);
}
+/* Return the die giving the specification for DIE, if there is
+ one. */
+
+static struct die_info *
+die_specification (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct attribute *spec_attr = dwarf2_attr (die, DW_AT_specification, cu);
+
+ if (spec_attr == NULL)
+ return NULL;
+ else
+ return follow_die_ref (dwarf2_get_ref_die_offset (spec_attr, cu));
+}
/* Free the line_header structure *LH, and any arrays and strings it
refers to. */
fe->dir_index = dir_index;
fe->mod_time = mod_time;
fe->length = length;
+ fe->included_p = 0;
}
/* Read the statement program header starting at OFFSET in
- dwarf_line_buffer, according to the endianness of ABFD. Return a
- pointer to a struct line_header, allocated using xmalloc.
+ .debug_line, according to the endianness of ABFD. Return a pointer
+ to a struct line_header, allocated using xmalloc.
NOTE: the strings in the include directory and file name tables of
the returned object point into debug_line_buffer, and must not be
freed. */
static struct line_header *
dwarf_decode_line_header (unsigned int offset, bfd *abfd,
- const struct comp_unit_head *cu_header)
+ struct dwarf2_cu *cu)
{
struct cleanup *back_to;
struct line_header *lh;
int i;
char *cur_dir, *cur_file;
- if (dwarf_line_buffer == NULL)
+ if (dwarf2_per_objfile->line_buffer == NULL)
{
complaint (&symfile_complaints, "missing .debug_line section");
return 0;
/* Make sure that at least there's room for the total_length field. That
could be 12 bytes long, but we're just going to fudge that. */
- if (offset + 4 >= dwarf_line_size)
+ if (offset + 4 >= dwarf2_per_objfile->line_size)
{
dwarf2_statement_list_fits_in_line_number_section_complaint ();
return 0;
back_to = make_cleanup ((make_cleanup_ftype *) free_line_header,
(void *) lh);
- line_ptr = dwarf_line_buffer + offset;
+ line_ptr = dwarf2_per_objfile->line_buffer + offset;
/* read in the header */
lh->total_length = read_initial_length (abfd, line_ptr, NULL, &bytes_read);
line_ptr += bytes_read;
- if (line_ptr + lh->total_length > dwarf_line_buffer + dwarf_line_size)
+ if (line_ptr + lh->total_length > (dwarf2_per_objfile->line_buffer
+ + dwarf2_per_objfile->line_size))
{
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;
line_ptr += bytes_read;
lh->statement_program_start = line_ptr;
- if (line_ptr > dwarf_line_buffer + dwarf_line_size)
+ if (line_ptr > (dwarf2_per_objfile->line_buffer
+ + dwarf2_per_objfile->line_size))
complaint (&symfile_complaints,
"line number info header doesn't fit in `.debug_line' section");
addresses passed to record_line. */
static CORE_ADDR
-check_cu_functions (CORE_ADDR address)
+check_cu_functions (CORE_ADDR address, struct dwarf2_cu *cu)
{
struct function_range *fn;
/* Find the function_range containing address. */
- if (!cu_first_fn)
+ if (!cu->first_fn)
return address;
- if (!cu_cached_fn)
- cu_cached_fn = cu_first_fn;
+ if (!cu->cached_fn)
+ cu->cached_fn = cu->first_fn;
- fn = cu_cached_fn;
+ fn = cu->cached_fn;
while (fn)
if (fn->lowpc <= address && fn->highpc > address)
goto found;
else
fn = fn->next;
- fn = cu_first_fn;
- while (fn && fn != cu_cached_fn)
+ fn = cu->first_fn;
+ while (fn && fn != cu->cached_fn)
if (fn->lowpc <= address && fn->highpc > address)
goto found;
else
return fn->lowpc;
}
-/* Decode the line number information for the compilation unit whose
- line number info is at OFFSET in the .debug_line section.
- The compilation directory of the file is passed in COMP_DIR. */
+/* Decode the Line Number Program (LNP) for the given line_header
+ structure and CU. The actual information extracted and the type
+ of structures created from the LNP depends on the value of PST.
+
+ 1. If PST is NULL, then this procedure uses the data from the program
+ to create all necessary symbol tables, and their linetables.
+ The compilation directory of the file is passed in COMP_DIR,
+ and must not be NULL.
+
+ 2. If PST is not NULL, this procedure reads the program to determine
+ the list of files included by the unit represented by PST, and
+ builds all the associated partial symbol tables. In this case,
+ the value of COMP_DIR is ignored, and can thus be NULL (the COMP_DIR
+ is not used to compute the full name of the symtab, and therefore
+ omitting it when building the partial symtab does not introduce
+ the potential for inconsistency - a partial symtab and its associated
+ symbtab having a different fullname -). */
static void
dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
- const struct comp_unit_head *cu_header)
+ struct dwarf2_cu *cu, struct partial_symtab *pst)
{
char *line_ptr;
char *line_end;
- unsigned int i, bytes_read;
- char *cur_dir;
+ unsigned int bytes_read;
unsigned char op_code, extended_op, adj_opcode;
+ CORE_ADDR baseaddr;
+ struct objfile *objfile = cu->objfile;
+ const int decode_for_pst_p = (pst != NULL);
+
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
line_ptr = lh->statement_program_start;
line_end = lh->statement_program_end;
int basic_block = 0;
int end_sequence = 0;
- /* Start a subfile for the current file of the state machine. */
- if (lh->num_file_names >= file)
+ if (!decode_for_pst_p && lh->num_file_names >= file)
{
+ /* Start a subfile for the current file of the state machine. */
/* lh->include_dirs and lh->file_names are 0-based, but the
directory and file name numbers in the statement program
are 1-based. */
address += (adj_opcode / lh->line_range)
* lh->minimum_instruction_length;
line += lh->line_base + (adj_opcode % lh->line_range);
- /* append row to matrix using current values */
- address = check_cu_functions (address);
- record_line (current_subfile, line, address);
+ if (!decode_for_pst_p)
+ {
+ /* append row to matrix using current values */
+ record_line (current_subfile, line,
+ check_cu_functions (address, cu));
+ }
basic_block = 1;
}
else switch (op_code)
{
case DW_LNE_end_sequence:
end_sequence = 1;
- record_line (current_subfile, 0, address);
+ if (!decode_for_pst_p)
+ record_line (current_subfile, 0, address);
break;
case DW_LNE_set_address:
- address = read_address (abfd, line_ptr, cu_header, &bytes_read);
+ address = read_address (abfd, line_ptr, cu, &bytes_read);
line_ptr += bytes_read;
address += baseaddr;
break;
}
break;
case DW_LNS_copy:
- address = check_cu_functions (address);
- record_line (current_subfile, line, address);
+ if (!decode_for_pst_p)
+ record_line (current_subfile, line,
+ check_cu_functions (address, cu));
basic_block = 0;
break;
case DW_LNS_advance_pc:
file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
fe = &lh->file_names[file - 1];
+ fe->included_p = 1;
if (fe->dir_index)
dir = lh->include_dirs[fe->dir_index - 1];
else
dir = comp_dir;
- dwarf2_start_subfile (fe->name, dir);
+ if (!decode_for_pst_p)
+ dwarf2_start_subfile (fe->name, dir);
}
break;
case DW_LNS_set_column:
}
}
}
+
+ if (decode_for_pst_p)
+ {
+ int file_index;
+
+ /* Now that we're done scanning the Line Header Program, we can
+ create the psymtab of each included file. */
+ for (file_index = 0; file_index < lh->num_file_names; file_index++)
+ if (lh->file_names[file_index].included_p == 1)
+ {
+ char *include_name = lh->file_names [file_index].name;
+
+ if (strcmp (include_name, pst->filename) != 0)
+ dwarf2_create_include_psymtab (include_name, pst, objfile);
+ }
+ }
}
/* Start a subfile for DWARF. FILENAME is the name of the file and
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;
+ CORE_ADDR baseaddr;
+
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+ if (die->tag != DW_TAG_namespace)
+ name = dwarf2_linkage_name (die, cu);
+ else
+ name = TYPE_NAME (type);
- name = dwarf2_linkage_name (die);
if (name)
{
- sym = (struct symbol *) obstack_alloc (&objfile->symbol_obstack,
+ sym = (struct symbol *) obstack_alloc (&objfile->objfile_obstack,
sizeof (struct symbol));
OBJSTAT (objfile, n_syms++);
memset (sym, 0, sizeof (struct symbol));
/* Cache this symbol's name and the name's demangled form (if any). */
- SYMBOL_LANGUAGE (sym) = cu_language;
+ SYMBOL_LANGUAGE (sym) = cu->language;
SYMBOL_SET_NAMES (sym, name, strlen (name), objfile);
/* Default assumptions.
Use the passed type or decode it from the die. */
- SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
+ SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
SYMBOL_CLASS (sym) = LOC_STATIC;
if (type != NULL)
SYMBOL_TYPE (sym) = type;
else
- SYMBOL_TYPE (sym) = die_type (die, objfile, cu_header);
- attr = dwarf_attr (die, DW_AT_decl_line);
+ SYMBOL_TYPE (sym) = die_type (die, cu);
+ attr = dwarf2_attr (die, DW_AT_decl_line, cu);
if (attr)
{
SYMBOL_LINE (sym) = DW_UNSND (attr);
switch (die->tag)
{
case DW_TAG_label:
- attr = dwarf_attr (die, DW_AT_low_pc);
+ attr = dwarf2_attr (die, DW_AT_low_pc, cu);
if (attr)
{
SYMBOL_VALUE_ADDRESS (sym) = DW_ADDR (attr) + baseaddr;
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
finish_block. */
SYMBOL_CLASS (sym) = LOC_BLOCK;
- attr2 = dwarf_attr (die, DW_AT_external);
+ attr2 = dwarf2_attr (die, DW_AT_external, cu);
if (attr2 && (DW_UNSND (attr2) != 0))
{
add_symbol_to_list (sym, &global_symbols);
}
else
{
- add_symbol_to_list (sym, list_in_scope);
+ add_symbol_to_list (sym, cu->list_in_scope);
}
break;
case DW_TAG_variable:
TARGET_INT_BIT / HOST_CHAR_BIT, 0,
"<variable, no debug info>",
objfile);
- attr = dwarf_attr (die, DW_AT_const_value);
+ attr = dwarf2_attr (die, DW_AT_const_value, cu);
if (attr)
{
- dwarf2_const_value (attr, sym, objfile, cu_header);
- attr2 = dwarf_attr (die, DW_AT_external);
+ dwarf2_const_value (attr, sym, cu);
+ attr2 = dwarf2_attr (die, DW_AT_external, cu);
if (attr2 && (DW_UNSND (attr2) != 0))
add_symbol_to_list (sym, &global_symbols);
else
- add_symbol_to_list (sym, list_in_scope);
+ add_symbol_to_list (sym, cu->list_in_scope);
break;
}
- attr = dwarf_attr (die, DW_AT_location);
+ attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr)
{
- attr2 = dwarf_attr (die, DW_AT_external);
+ var_decode_location (attr, sym, cu);
+ attr2 = dwarf2_attr (die, DW_AT_external, cu);
if (attr2 && (DW_UNSND (attr2) != 0))
- {
- /* Support the .debug_loc offsets */
- if (attr_form_is_block (attr))
- {
- SYMBOL_VALUE_ADDRESS (sym) =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
- }
- else if (attr->form == DW_FORM_data4
- || attr->form == DW_FORM_data8)
- {
- dwarf2_complex_location_expr_complaint ();
- }
- else
- {
- dwarf2_invalid_attrib_class_complaint ("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)
- {
- dwarf2_complex_location_expr_complaint ();
- }
- else
- {
- dwarf2_invalid_attrib_class_complaint ("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, cu->list_in_scope);
}
else
{
The address of the variable will then be determined from
the minimal symbol table whenever the variable is
referenced. */
- attr2 = dwarf_attr (die, DW_AT_external);
+ attr2 = dwarf2_attr (die, DW_AT_external, cu);
if (attr2 && (DW_UNSND (attr2) != 0)
- && dwarf_attr (die, DW_AT_type) != NULL)
+ && dwarf2_attr (die, DW_AT_type, cu) != NULL)
{
SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
add_symbol_to_list (sym, &global_symbols);
}
break;
case DW_TAG_formal_parameter:
- attr = dwarf_attr (die, DW_AT_location);
+ attr = dwarf2_attr (die, DW_AT_location, cu);
if (attr)
{
- SYMBOL_VALUE (sym) =
- decode_locdesc (DW_BLOCK (attr), objfile, cu_header);
- if (isreg)
- {
- SYMBOL_CLASS (sym) = LOC_REGPARM;
- SYMBOL_VALUE (sym) =
- DWARF2_REG_TO_REGNUM (SYMBOL_VALUE (sym));
- }
- else if (offreg)
- {
- if (isderef)
- {
- if (basereg != frame_base_reg)
- dwarf2_complex_location_expr_complaint ();
- SYMBOL_CLASS (sym) = LOC_REF_ARG;
- }
- else
- {
- SYMBOL_CLASS (sym) = LOC_BASEREG_ARG;
- SYMBOL_BASEREG (sym) = DWARF2_REG_TO_REGNUM (basereg);
- }
- }
- else
- {
- SYMBOL_CLASS (sym) = LOC_ARG;
- }
+ var_decode_location (attr, sym, cu);
+ /* FIXME drow/2003-07-31: Is LOC_COMPUTED_ARG necessary? */
+ if (SYMBOL_CLASS (sym) == LOC_COMPUTED)
+ SYMBOL_CLASS (sym) = LOC_COMPUTED_ARG;
}
- attr = dwarf_attr (die, DW_AT_const_value);
+ attr = dwarf2_attr (die, DW_AT_const_value, cu);
if (attr)
{
- dwarf2_const_value (attr, sym, objfile, cu_header);
+ dwarf2_const_value (attr, sym, cu);
}
- add_symbol_to_list (sym, list_in_scope);
+ add_symbol_to_list (sym, cu->list_in_scope);
break;
case DW_TAG_unspecified_parameters:
/* From varargs functions; gdb doesn't seem to have any
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
- SYMBOL_NAMESPACE (sym) = STRUCT_NAMESPACE;
- add_symbol_to_list (sym, list_in_scope);
+ SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
- /* The semantics of C++ state that "struct foo { ... }" also
- defines a typedef for "foo". Synthesize a typedef symbol so
- that "ptype foo" works as expected. */
- if (cu_language == language_cplus)
+ /* Make sure that the symbol includes appropriate enclosing
+ classes/namespaces in its name. These are calculated in
+ read_structure_type, and the correct name is saved in
+ the type. */
+
+ if (cu->language == language_cplus)
{
- struct symbol *typedef_sym = (struct symbol *)
- obstack_alloc (&objfile->symbol_obstack,
- sizeof (struct symbol));
- *typedef_sym = *sym;
- SYMBOL_NAMESPACE (typedef_sym) = VAR_NAMESPACE;
- if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
- TYPE_NAME (SYMBOL_TYPE (sym)) =
- obsavestring (SYMBOL_NAME (sym),
- strlen (SYMBOL_NAME (sym)),
- &objfile->type_obstack);
- add_symbol_to_list (typedef_sym, list_in_scope);
+ struct type *type = SYMBOL_TYPE (sym);
+
+ if (TYPE_TAG_NAME (type) != NULL)
+ {
+ /* FIXME: carlton/2003-11-10: Should this use
+ SYMBOL_SET_NAMES instead? (The same problem also
+ arises further down in this function.) */
+ /* The type's name is already allocated along with
+ this objfile, so we don't need to duplicate it
+ for the symbol. */
+ SYMBOL_LINKAGE_NAME (sym) = TYPE_TAG_NAME (type);
+ }
}
+
+ {
+ /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't
+ really ever be static objects: otherwise, if you try
+ to, say, break of a class's method and you're in a file
+ which doesn't mention that class, it won't work unless
+ the check for all static symbols in lookup_symbol_aux
+ saves you. See the OtherFileClass tests in
+ gdb.c++/namespace.exp. */
+
+ struct pending **list_to_add;
+
+ list_to_add = (cu->list_in_scope == &file_symbols
+ && cu->language == language_cplus
+ ? &global_symbols : cu->list_in_scope);
+
+ add_symbol_to_list (sym, list_to_add);
+
+ /* The semantics of C++ state that "struct foo { ... }" also
+ defines a typedef for "foo". Synthesize a typedef symbol so
+ that "ptype foo" works as expected. */
+ if (cu->language == language_cplus)
+ {
+ struct symbol *typedef_sym = (struct symbol *)
+ obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct symbol));
+ *typedef_sym = *sym;
+ SYMBOL_DOMAIN (typedef_sym) = VAR_DOMAIN;
+ /* The symbol's name is already allocated along with
+ this objfile, so we don't need to duplicate it for
+ the type. */
+ if (TYPE_NAME (SYMBOL_TYPE (sym)) == 0)
+ TYPE_NAME (SYMBOL_TYPE (sym)) = SYMBOL_NATURAL_NAME (sym);
+ add_symbol_to_list (typedef_sym, list_to_add);
+ }
+ }
break;
case DW_TAG_typedef:
+ if (processing_has_namespace_info
+ && processing_current_prefix[0] != '\0')
+ {
+ SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->objfile_obstack,
+ processing_current_prefix,
+ "::",
+ name);
+ }
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+ add_symbol_to_list (sym, cu->list_in_scope);
+ break;
case DW_TAG_base_type:
+ case DW_TAG_subrange_type:
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
- SYMBOL_NAMESPACE (sym) = VAR_NAMESPACE;
- add_symbol_to_list (sym, list_in_scope);
+ SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
+ add_symbol_to_list (sym, cu->list_in_scope);
break;
case DW_TAG_enumerator:
- attr = dwarf_attr (die, DW_AT_const_value);
+ if (processing_has_namespace_info
+ && processing_current_prefix[0] != '\0')
+ {
+ SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->objfile_obstack,
+ processing_current_prefix,
+ "::",
+ name);
+ }
+ attr = dwarf2_attr (die, DW_AT_const_value, cu);
if (attr)
{
- dwarf2_const_value (attr, sym, objfile, cu_header);
+ dwarf2_const_value (attr, sym, cu);
}
- add_symbol_to_list (sym, list_in_scope);
+ {
+ /* NOTE: carlton/2003-11-10: See comment above in the
+ DW_TAG_class_type, etc. block. */
+
+ struct pending **list_to_add;
+
+ list_to_add = (cu->list_in_scope == &file_symbols
+ && cu->language == language_cplus
+ ? &global_symbols : cu->list_in_scope);
+
+ add_symbol_to_list (sym, list_to_add);
+ }
+ break;
+ case DW_TAG_namespace:
+ SYMBOL_CLASS (sym) = LOC_TYPEDEF;
+ add_symbol_to_list (sym, &global_symbols);
break;
default:
/* Not a tag we recognize. Hopefully we aren't processing
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)
- dwarf2_const_value_length_mismatch_complaint (SYMBOL_NAME (sym),
+ dwarf2_const_value_length_mismatch_complaint (DEPRECATED_SYMBOL_NAME (sym),
cu_header->addr_size,
TYPE_LENGTH (SYMBOL_TYPE
(sym)));
SYMBOL_VALUE_BYTES (sym) = (char *)
- obstack_alloc (&objfile->symbol_obstack, cu_header->addr_size);
- store_address (SYMBOL_VALUE_BYTES (sym), cu_header->addr_size,
- DW_ADDR (attr));
+ obstack_alloc (&objfile->objfile_obstack, cu_header->addr_size);
+ /* NOTE: cagney/2003-05-09: In-lined store_address call with
+ it's body - store_unsigned_integer. */
+ store_unsigned_integer (SYMBOL_VALUE_BYTES (sym), cu_header->addr_size,
+ DW_ADDR (attr));
SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
break;
case DW_FORM_block1:
case DW_FORM_block:
blk = DW_BLOCK (attr);
if (TYPE_LENGTH (SYMBOL_TYPE (sym)) != blk->size)
- dwarf2_const_value_length_mismatch_complaint (SYMBOL_NAME (sym),
+ dwarf2_const_value_length_mismatch_complaint (DEPRECATED_SYMBOL_NAME (sym),
blk->size,
TYPE_LENGTH (SYMBOL_TYPE
(sym)));
SYMBOL_VALUE_BYTES (sym) = (char *)
- obstack_alloc (&objfile->symbol_obstack, blk->size);
+ obstack_alloc (&objfile->objfile_obstack, blk->size);
memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size);
SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
break;
/* Return the type of the die in question using its DW_AT_type attribute. */
static struct type *
-die_type (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+die_type (struct die_info *die, struct dwarf2_cu *cu)
{
struct type *type;
struct attribute *type_attr;
struct die_info *type_die;
unsigned int ref;
- type_attr = dwarf_attr (die, DW_AT_type);
+ type_attr = dwarf2_attr (die, DW_AT_type, cu);
if (!type_attr)
{
/* A missing DW_AT_type represents a void type. */
- return dwarf2_fundamental_type (objfile, FT_VOID);
+ return dwarf2_fundamental_type (cu->objfile, FT_VOID, cu);
}
else
{
- ref = dwarf2_get_ref_die_offset (type_attr);
+ ref = dwarf2_get_ref_die_offset (type_attr, cu);
type_die = follow_die_ref (ref);
if (!type_die)
{
error ("Dwarf Error: Cannot find referent at offset %d [in module %s]",
- ref, objfile->name);
+ 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 [in module %s]",
- objfile->name);
+ 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;
struct die_info *type_die = NULL;
unsigned int ref;
- type_attr = dwarf_attr (die, DW_AT_containing_type);
+ type_attr = dwarf2_attr (die, DW_AT_containing_type, cu);
if (type_attr)
{
- ref = dwarf2_get_ref_die_offset (type_attr);
+ ref = dwarf2_get_ref_die_offset (type_attr, cu);
type_die = follow_die_ref (ref);
if (!type_die)
{
error ("Dwarf Error: Cannot find referent at offset %d [in module %s]", ref,
- objfile->name);
+ 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 [in module %s]",
- objfile->name);
+ 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 [in module %s]",
- objfile->name);
+ cu->objfile->name);
}
return die->type;
}
}
static void
-read_type_die (struct die_info *die, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+read_type_die (struct die_info *die, struct dwarf2_cu *cu)
{
+ char *prefix = determine_prefix (die, cu);
+ const char *old_prefix = processing_current_prefix;
+ struct cleanup *back_to = make_cleanup (xfree, prefix);
+ processing_current_prefix = prefix;
+
switch (die->tag)
{
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
- read_structure_scope (die, objfile, cu_header);
+ read_structure_type (die, cu);
break;
case DW_TAG_enumeration_type:
- read_enumeration (die, objfile, cu_header);
+ read_enumeration_type (die, cu);
break;
case DW_TAG_subprogram:
case DW_TAG_subroutine_type:
- read_subroutine_type (die, objfile, cu_header);
+ read_subroutine_type (die, cu);
break;
case DW_TAG_array_type:
- read_array_type (die, objfile, cu_header);
+ read_array_type (die, cu);
break;
case DW_TAG_pointer_type:
- read_tag_pointer_type (die, objfile, cu_header);
+ read_tag_pointer_type (die, cu);
break;
case DW_TAG_ptr_to_member_type:
- read_tag_ptr_to_member_type (die, objfile, cu_header);
+ read_tag_ptr_to_member_type (die, cu);
break;
case DW_TAG_reference_type:
- read_tag_reference_type (die, objfile, cu_header);
+ read_tag_reference_type (die, cu);
break;
case DW_TAG_const_type:
- read_tag_const_type (die, objfile, cu_header);
+ read_tag_const_type (die, cu);
break;
case DW_TAG_volatile_type:
- read_tag_volatile_type (die, objfile, cu_header);
+ read_tag_volatile_type (die, cu);
break;
case DW_TAG_string_type:
- read_tag_string_type (die, objfile);
+ read_tag_string_type (die, cu);
break;
case DW_TAG_typedef:
- read_typedef (die, objfile, cu_header);
+ read_typedef (die, cu);
+ break;
+ case DW_TAG_subrange_type:
+ read_subrange_type (die, cu);
break;
case DW_TAG_base_type:
- read_base_type (die, objfile);
+ read_base_type (die, cu);
break;
default:
complaint (&symfile_complaints, "unexepected tag in read_type_die: '%s'",
dwarf_tag_name (die->tag));
break;
}
+
+ processing_current_prefix = old_prefix;
+ do_cleanups (back_to);
+}
+
+/* Return the name of the namespace/class that DIE is defined within,
+ or "" if we can't tell. The caller should xfree the result. */
+
+/* NOTE: carlton/2004-01-23: See read_func_scope (and the comment
+ therein) for an example of how to use this function to deal with
+ DW_AT_specification. */
+
+static char *
+determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct die_info *parent;
+
+ if (cu->language != language_cplus)
+ return NULL;
+
+ parent = die->parent;
+
+ if (parent == NULL)
+ {
+ return xstrdup ("");
+ }
+ else
+ {
+ switch (parent->tag) {
+ case DW_TAG_namespace:
+ {
+ /* FIXME: carlton/2004-03-05: Should I follow extension dies
+ before doing this check? */
+ if (parent->type != NULL && TYPE_TAG_NAME (parent->type) != NULL)
+ {
+ return xstrdup (TYPE_TAG_NAME (parent->type));
+ }
+ else
+ {
+ int dummy;
+ char *parent_prefix = determine_prefix (parent, cu);
+ char *retval = typename_concat (parent_prefix,
+ namespace_name (parent, &dummy,
+ cu));
+ xfree (parent_prefix);
+ return retval;
+ }
+ }
+ break;
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ {
+ if (parent->type != NULL && TYPE_TAG_NAME (parent->type) != NULL)
+ {
+ return xstrdup (TYPE_TAG_NAME (parent->type));
+ }
+ else
+ {
+ const char *old_prefix = processing_current_prefix;
+ char *new_prefix = determine_prefix (parent, cu);
+ char *retval;
+
+ processing_current_prefix = new_prefix;
+ retval = determine_class_name (parent, cu);
+ processing_current_prefix = old_prefix;
+
+ xfree (new_prefix);
+ return retval;
+ }
+ }
+ default:
+ return determine_prefix (parent, cu);
+ }
+ }
+}
+
+/* Return a newly-allocated string formed by concatenating PREFIX,
+ "::", and SUFFIX, except that if PREFIX is NULL or the empty
+ string, just return a copy of SUFFIX. */
+
+static char *
+typename_concat (const char *prefix, const char *suffix)
+{
+ if (prefix == NULL || prefix[0] == '\0')
+ return xstrdup (suffix);
+ else
+ {
+ char *retval = xmalloc (strlen (prefix) + 2 + strlen (suffix) + 1);
+
+ strcpy (retval, prefix);
+ strcat (retval, "::");
+ strcat (retval, suffix);
+
+ return retval;
+ }
}
static struct type *
-dwarf_base_type (int encoding, int size, struct objfile *objfile)
+dwarf_base_type (int encoding, int size, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
+
/* FIXME - this should not produce a new (struct type *)
every time. It should cache base types. */
struct type *type;
switch (encoding)
{
case DW_ATE_address:
- type = dwarf2_fundamental_type (objfile, FT_VOID);
+ type = dwarf2_fundamental_type (objfile, FT_VOID, cu);
return type;
case DW_ATE_boolean:
- type = dwarf2_fundamental_type (objfile, FT_BOOLEAN);
+ type = dwarf2_fundamental_type (objfile, FT_BOOLEAN, cu);
return type;
case DW_ATE_complex_float:
if (size == 16)
{
- type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX);
+ type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_COMPLEX, cu);
}
else
{
- type = dwarf2_fundamental_type (objfile, FT_COMPLEX);
+ type = dwarf2_fundamental_type (objfile, FT_COMPLEX, cu);
}
return type;
case DW_ATE_float:
if (size == 8)
{
- type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT);
+ type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_FLOAT, cu);
}
else
{
- type = dwarf2_fundamental_type (objfile, FT_FLOAT);
+ type = dwarf2_fundamental_type (objfile, FT_FLOAT, cu);
}
return type;
case DW_ATE_signed:
switch (size)
{
case 1:
- type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR, cu);
break;
case 2:
- type = dwarf2_fundamental_type (objfile, FT_SIGNED_SHORT);
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_SHORT, cu);
break;
default:
case 4:
- type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER, cu);
break;
}
return type;
case DW_ATE_signed_char:
- type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR);
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_CHAR, cu);
return type;
case DW_ATE_unsigned:
switch (size)
{
case 1:
- type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
+ type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR, cu);
break;
case 2:
- type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_SHORT);
+ type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_SHORT, cu);
break;
default:
case 4:
- type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_INTEGER);
+ type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_INTEGER, cu);
break;
}
return type;
case DW_ATE_unsigned_char:
- type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR);
+ type = dwarf2_fundamental_type (objfile, FT_UNSIGNED_CHAR, cu);
return type;
default:
- type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER);
+ type = dwarf2_fundamental_type (objfile, FT_SIGNED_INTEGER, cu);
return type;
}
}
static struct die_info *
sibling_die (struct die_info *die)
{
- int nesting_level = 0;
-
- if (!die->has_children)
- {
- if (die->next && (die->next->tag == 0))
- {
- return NULL;
- }
- else
- {
- return die->next;
- }
- }
- else
- {
- do
- {
- if (die->has_children)
- {
- nesting_level++;
- }
- if (die->tag == 0)
- {
- nesting_level--;
- }
- die = die->next;
- }
- while (nesting_level);
- if (die && (die->tag == 0))
- {
- return NULL;
- }
- else
- {
- return die;
- }
- }
+ return die->sibling;
}
/* Get linkage name of a die, return NULL if not found. */
static char *
-dwarf2_linkage_name (struct die_info *die)
+dwarf2_linkage_name (struct die_info *die, struct dwarf2_cu *cu)
{
struct attribute *attr;
- attr = dwarf_attr (die, DW_AT_MIPS_linkage_name);
+ attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu);
+ if (attr && DW_STRING (attr))
+ return DW_STRING (attr);
+ attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
return DW_STRING (attr);
- attr = dwarf_attr (die, DW_AT_name);
+ return NULL;
+}
+
+/* Get name of a die, return NULL if not found. */
+
+static char *
+dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct attribute *attr;
+
+ attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr && DW_STRING (attr))
return DW_STRING (attr);
return NULL;
}
+/* Return the die that this die in an extension of, or NULL if there
+ is none. */
+
+static struct die_info *
+dwarf2_extension (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct attribute *attr;
+ struct die_info *extension_die;
+ unsigned int ref;
+
+ attr = dwarf2_attr (die, DW_AT_extension, cu);
+ if (attr == NULL)
+ return NULL;
+
+ ref = dwarf2_get_ref_die_offset (attr, cu);
+ extension_die = follow_die_ref (ref);
+ if (!extension_die)
+ {
+ error ("Dwarf Error: Cannot find referent at offset %d.", ref);
+ }
+
+ return extension_die;
+}
+
/* Convert a DIE tag into its string name. */
static char *
-dwarf_tag_name (register unsigned tag)
+dwarf_tag_name (unsigned tag)
{
switch (tag)
{
/* 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);
}
}
}
static unsigned int
-dwarf2_get_ref_die_offset (struct attribute *attr)
+dwarf2_get_ref_die_offset (struct attribute *attr, struct dwarf2_cu *cu)
{
unsigned int result = 0;
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
- result = cu_header_offset + DW_UNSND (attr);
+ result = cu->header.offset + DW_UNSND (attr);
break;
default:
complaint (&symfile_complaints,
return result;
}
+/* Return the constant value held by the given attribute. Return -1
+ if the value held by the attribute is not constant. */
+
+static int
+dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
+{
+ if (attr->form == DW_FORM_sdata)
+ return DW_SND (attr);
+ else if (attr->form == DW_FORM_udata
+ || attr->form == DW_FORM_data1
+ || attr->form == DW_FORM_data2
+ || attr->form == DW_FORM_data4
+ || attr->form == DW_FORM_data8)
+ return DW_UNSND (attr);
+ else
+ {
+ complaint (&symfile_complaints, "Attribute value is not a constant (%s)",
+ dwarf_form_name (attr->form));
+ return default_value;
+ }
+}
+
static struct die_info *
follow_die_ref (unsigned int offset)
{
}
static struct type *
-dwarf2_fundamental_type (struct objfile *objfile, int typeid)
+dwarf2_fundamental_type (struct objfile *objfile, int typeid,
+ struct dwarf2_cu *cu)
{
if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
{
one is not found, create and install one appropriate for the
current language and the current target machine. */
- if (ftypes[typeid] == NULL)
+ if (cu->ftypes[typeid] == NULL)
{
- ftypes[typeid] = cu_language_defn->la_fund_type (objfile, typeid);
+ cu->ftypes[typeid] = cu->language_defn->la_fund_type (objfile, typeid);
}
- return (ftypes[typeid]);
+ return (cu->ftypes[typeid]);
}
/* Decode simple location descriptions.
Given a pointer to a dwarf block that defines a location, compute
the location and return the value.
- FIXME: This is a kludge until we figure out a better
- way to handle the location descriptions.
- Gdb's design does not mesh well with the DWARF2 notion of a location
- computing interpreter, which is a shame because the flexibility goes unused.
- FIXME: Implement more operations as necessary.
+ NOTE drow/2003-11-18: This function is called in two situations
+ now: for the address of static or global variables (partial symbols
+ only) and for offsets into structures which are expected to be
+ (more or less) constant. The partial symbol case should go away,
+ and only the constant case should remain. That will let this
+ function complain more accurately. A few special modes are allowed
+ without complaint for global variables (for instance, global
+ register values and thread-local values).
A location description containing no operations indicates that the
- object is optimized out. The global optimized_out flag is set for
- those, the return value is meaningless.
+ object is optimized out. The return value is 0 for that case.
+ FIXME drow/2003-11-16: No callers check for this case any more; soon all
+ callers will only want a very basic result and this can become a
+ complaint.
When the result is a register number, the global isreg flag is set,
otherwise it is cleared.
- When the result is a base register offset, the global offreg flag is set
- and the register number is returned in basereg, otherwise it is cleared.
-
- When the DW_OP_fbreg operation is encountered without a corresponding
- DW_AT_frame_base attribute, the global islocal flag is set.
- Hopefully the machine dependent code knows how to set up a virtual
- frame pointer for the local references.
-
Note that stack[0] is unused except as a default error return.
Note that stack overflow is not yet handled. */
static CORE_ADDR
-decode_locdesc (struct dwarf_block *blk, struct objfile *objfile,
- const struct comp_unit_head *cu_header)
+decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
{
+ struct objfile *objfile = cu->objfile;
+ struct comp_unit_head *cu_header = &cu->header;
int i;
int size = blk->size;
char *data = blk->data;
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
- {
- complaint (&symfile_complaints,
- "DW_AT_frame_base missing for DW_OP_fbreg");
- 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)
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)
dwarf2_complex_location_expr_complaint ();
break;
/* memory allocation interface */
-/* ARGSUSED */
-static void
-dwarf2_free_tmp_obstack (void *ignore)
-{
- obstack_free (&dwarf2_tmp_obstack, NULL);
-}
-
static struct dwarf_block *
-dwarf_alloc_block (void)
+dwarf_alloc_block (struct dwarf2_cu *cu)
{
struct dwarf_block *blk;
blk = (struct dwarf_block *)
- obstack_alloc (&dwarf2_tmp_obstack, sizeof (struct dwarf_block));
+ obstack_alloc (&cu->comp_unit_obstack, sizeof (struct dwarf_block));
return (blk);
}
static struct abbrev_info *
-dwarf_alloc_abbrev (void)
+dwarf_alloc_abbrev (struct dwarf2_cu *cu)
{
struct abbrev_info *abbrev;
- abbrev = (struct abbrev_info *) xmalloc (sizeof (struct abbrev_info));
+ abbrev = (struct abbrev_info *)
+ obstack_alloc (&cu->abbrev_obstack, sizeof (struct abbrev_info));
memset (abbrev, 0, sizeof (struct abbrev_info));
return (abbrev);
}
/* We don't create a macro table for this compilation unit
at all until we actually get a filename. */
if (! pending_macros)
- pending_macros = new_macro_table (&objfile->symbol_obstack,
+ pending_macros = new_macro_table (&objfile->objfile_obstack,
objfile->macro_cache);
if (! current_file)
static void
dwarf_decode_macros (struct line_header *lh, unsigned int offset,
char *comp_dir, bfd *abfd,
- const struct comp_unit_head *cu_header,
- struct objfile *objfile)
+ struct dwarf2_cu *cu)
{
char *mac_ptr, *mac_end;
struct macro_source_file *current_file = 0;
- if (dwarf_macinfo_buffer == NULL)
+ if (dwarf2_per_objfile->macinfo_buffer == NULL)
{
complaint (&symfile_complaints, "missing .debug_macinfo section");
return;
}
- mac_ptr = dwarf_macinfo_buffer + offset;
- mac_end = dwarf_macinfo_buffer + dwarf_macinfo_size;
+ mac_ptr = dwarf2_per_objfile->macinfo_buffer + offset;
+ mac_end = dwarf2_per_objfile->macinfo_buffer
+ + dwarf2_per_objfile->macinfo_size;
for (;;)
{
current_file = macro_start_file (file, line,
current_file, comp_dir,
- lh, objfile);
+ lh, cu->objfile);
}
break;
|| attr->form == DW_FORM_block4
|| attr->form == DW_FORM_block);
}
+
+static void
+dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+ struct dwarf2_cu *cu)
+{
+ if (attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+ {
+ struct dwarf2_loclist_baton *baton;
+
+ baton = obstack_alloc (&cu->objfile->objfile_obstack,
+ sizeof (struct dwarf2_loclist_baton));
+ baton->objfile = cu->objfile;
+
+ /* We don't know how long the location list is, but make sure we
+ don't run off the edge of the section. */
+ baton->size = dwarf2_per_objfile->loc_size - DW_UNSND (attr);
+ baton->data = dwarf2_per_objfile->loc_buffer + DW_UNSND (attr);
+ baton->base_address = cu->header.base_address;
+ if (cu->header.base_known == 0)
+ complaint (&symfile_complaints,
+ "Location list used without specifying the CU base address.");
+
+ SYMBOL_OPS (sym) = &dwarf2_loclist_funcs;
+ SYMBOL_LOCATION_BATON (sym) = baton;
+ }
+ else
+ {
+ struct dwarf2_locexpr_baton *baton;
+
+ baton = obstack_alloc (&cu->objfile->objfile_obstack,
+ sizeof (struct dwarf2_locexpr_baton));
+ baton->objfile = cu->objfile;
+
+ if (attr_form_is_block (attr))
+ {
+ /* Note that we're just copying the block's data pointer
+ here, not the actual data. We're still pointing into the
+ info_buffer for SYM's objfile; right now we never release
+ that buffer, but when we do clean up properly this may
+ need to change. */
+ baton->size = DW_BLOCK (attr)->size;
+ baton->data = DW_BLOCK (attr)->data;
+ }
+ else
+ {
+ dwarf2_invalid_attrib_class_complaint ("location description",
+ SYMBOL_NATURAL_NAME (sym));
+ baton->size = 0;
+ baton->data = NULL;
+ }
+
+ SYMBOL_OPS (sym) = &dwarf2_locexpr_funcs;
+ SYMBOL_LOCATION_BATON (sym) = baton;
+ }
+}
+
+/* This cleanup function is passed the address of a dwarf2_cu on the stack
+ when we're finished with it. We can't free the pointer itself, but
+ release any associated storage.
+
+ Only used during partial symbol parsing. */
+
+static void
+free_stack_comp_unit (void *data)
+{
+ struct dwarf2_cu *cu = data;
+
+ obstack_free (&cu->comp_unit_obstack, NULL);
+ cu->partial_dies = NULL;
+}
+
+/* Allocation function for the libiberty hash table which uses an
+ obstack. */
+
+static void *
+hashtab_obstack_allocate (void *data, size_t size, size_t count)
+{
+ unsigned int total = size * count;
+ void *ptr = obstack_alloc ((struct obstack *) data, total);
+ memset (ptr, 0, total);
+ return ptr;
+}
+
+/* Trivial deallocation function for the libiberty splay tree and hash
+ table - don't deallocate anything. Rely on later deletion of the
+ obstack. */
+
+static void
+dummy_obstack_deallocate (void *object, void *data)
+{
+ return;
+}
+
+/* Trivial hash function for partial_die_info: the hash value of a DIE
+ is its offset in .debug_info for this objfile. */
+
+static hashval_t
+partial_die_hash (const void *item)
+{
+ const struct partial_die_info *part_die = item;
+ return part_die->offset;
+}
+
+/* Trivial comparison function for partial_die_info structures: two DIEs
+ are equal if they have the same offset. */
+
+static int
+partial_die_eq (const void *item_lhs, const void *item_rhs)
+{
+ const struct partial_die_info *part_die_lhs = item_lhs;
+ const struct partial_die_info *part_die_rhs = item_rhs;
+ return part_die_lhs->offset == part_die_rhs->offset;
+}
+
+void _initialize_dwarf2_read (void);
+
+void
+_initialize_dwarf2_read (void)
+{
+ dwarf2_objfile_data_key = register_objfile_data ();
+}