/* DWARF 2 debugging format support for GDB.
- Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004
- Free Software Foundation, Inc.
+
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
with the Ada Joint Program Office), and Silicon Graphics, Inc.
Initial contribution by Brent Benson, Harris Computer Systems, Inc.,
based on Fred Fish's (Cygnus Support) implementation of DWARF 1
- support in dwarfread.c
+ support.
This file is part of GDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or (at
- your option) any later version.
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "bfd.h"
#include "dwarf2expr.h"
#include "dwarf2loc.h"
#include "cp-support.h"
+#include "hashtab.h"
+#include "command.h"
+#include "gdbcmd.h"
#include <fcntl.h>
#include "gdb_string.h"
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
-
#if 0
/* .debug_info header for a compilation unit
Because of alignment constraints, this structure has padding and cannot
}
_STATEMENT_PROLOGUE;
-/* offsets and sizes of debugging sections */
+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. */
+ gdb_byte *info_buffer;
+ gdb_byte *abbrev_buffer;
+ gdb_byte *line_buffer;
+ gdb_byte *str_buffer;
+ gdb_byte *macinfo_buffer;
+ gdb_byte *ranges_buffer;
+ gdb_byte *loc_buffer;
+
+ /* A list of all the compilation units. This is used to locate
+ the target compilation unit of a particular reference. */
+ struct dwarf2_per_cu_data **all_comp_units;
+
+ /* The number of compilation units in ALL_COMP_UNITS. */
+ int n_comp_units;
+
+ /* A chain of compilation units that are currently read in, so that
+ they can be freed later. */
+ struct dwarf2_per_cu_data *read_in_chain;
+
+ /* A flag indicating wether this objfile has a section loaded at a
+ VMA of 0. */
+ int has_section_at_zero;
+};
-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 struct dwarf2_per_objfile *dwarf2_per_objfile;
static asection *dwarf_info_section;
static asection *dwarf_abbrev_section;
/* The data in a compilation unit header, after target2host
translation, looks like this. */
struct comp_unit_head
- {
- unsigned long length;
- short version;
- unsigned int abbrev_offset;
- unsigned char addr_size;
- unsigned char signed_addr_p;
- unsigned int offset_size; /* size of file offsets; either 4 or 8 */
- unsigned int initial_length_size; /* size of the length field; either
- 4 or 12 */
-
- /* Offset to the first byte of this compilation unit header in the
- * .debug_info section, for resolving relative reference dies. */
-
- unsigned int offset;
-
- /* Pointer to this compilation unit header in the .debug_info
- * section */
+{
+ unsigned long length;
+ short version;
+ unsigned int abbrev_offset;
+ unsigned char addr_size;
+ unsigned char signed_addr_p;
- char *cu_head_ptr;
+ /* Size of file offsets; either 4 or 8. */
+ unsigned int offset_size;
- /* Pointer to the first die of this compilatio unit. This will
- * be the first byte following the compilation unit header. */
+ /* Size of the length field; either 4 or 12. */
+ unsigned int initial_length_size;
- char *first_die_ptr;
+ /* Offset to the first byte of this compilation unit header in the
+ .debug_info section, for resolving relative reference dies. */
+ unsigned int offset;
- /* Pointer to the next compilation unit header in the program. */
+ /* Pointer to this compilation unit header in the .debug_info
+ section. */
+ gdb_byte *cu_head_ptr;
- struct comp_unit_head *next;
+ /* Pointer to the first die of this compilation unit. This will be
+ the first byte following the compilation unit header. */
+ gdb_byte *first_die_ptr;
- /* Base address of this compilation unit. */
+ /* Pointer to the next compilation unit header in the program. */
+ struct comp_unit_head *next;
- CORE_ADDR base_address;
+ /* Base address of this compilation unit. */
+ CORE_ADDR base_address;
- /* Non-zero if base_address has been set. */
+ /* Non-zero if base_address has been set. */
+ int base_known;
+};
- int base_known;
- };
+/* Fixed size for the DIE hash table. */
+#ifndef REF_HASH_SIZE
+#define REF_HASH_SIZE 1021
+#endif
/* Internal state when decoding a particular compilation unit. */
struct dwarf2_cu
enum language language;
const struct language_defn *language_defn;
+ const char *producer;
+
/* The generic symbol table building routines have separate lists for
file scope symbols and all all other scopes (local scopes). So
we need to select the right one to pass to add_symbol_to_list().
/* 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;
+
+ /* When multiple dwarf2_cu structures are living in memory, this field
+ chains them all together, so that they can be released efficiently.
+ We will probably also want a generation counter so that most-recently-used
+ compilation units are cached... */
+ struct dwarf2_per_cu_data *read_in_chain;
+
+ /* Backchain to our per_cu entry if the tree has been built. */
+ struct dwarf2_per_cu_data *per_cu;
+
+ /* How many compilation units ago was this CU last referenced? */
+ int last_used;
+
+ /* A hash table of die offsets for following references. */
+ struct die_info *die_ref_table[REF_HASH_SIZE];
+
+ /* Full DIEs if read in. */
+ struct die_info *dies;
+
+ /* A set of pointers to dwarf2_per_cu_data objects for compilation
+ units referenced by this one. Only set during full symbol processing;
+ partial symbol tables do not have dependencies. */
+ htab_t dependencies;
+
+ /* Header data from the line table, during full symbol processing. */
+ struct line_header *line_header;
+
+ /* Mark used when releasing cached dies. */
+ unsigned int mark : 1;
+
+ /* This flag will be set if this compilation unit might include
+ inter-compilation-unit references. */
+ unsigned int has_form_ref_addr : 1;
+
+ /* 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;
+};
+
+/* Persistent data held for a compilation unit, even when not
+ processing it. We put a pointer to this structure in the
+ read_symtab_private field of the psymtab. If we encounter
+ inter-compilation-unit references, we also maintain a sorted
+ list of all compilation units. */
+
+struct dwarf2_per_cu_data
+{
+ /* The start offset and length of this compilation unit. 2**30-1
+ bytes should suffice to store the length of any compilation unit
+ - if it doesn't, GDB will fall over anyway. */
+ unsigned long offset;
+ unsigned long length : 30;
+
+ /* Flag indicating this compilation unit will be read in before
+ any of the current compilation units are processed. */
+ unsigned long queued : 1;
+
+ /* This flag will be set if we need to load absolutely all DIEs
+ for this compilation unit, instead of just the ones we think
+ are interesting. It gets set if we look for a DIE in the
+ hash table and don't find it. */
+ unsigned int load_all_dies : 1;
+
+ /* Set iff currently read in. */
+ struct dwarf2_cu *cu;
+
+ /* If full symbols for this CU have been read in, then this field
+ holds a map of DIE offsets to types. It isn't always possible
+ to reconstruct this information later, so we have to preserve
+ it. */
+ htab_t type_hash;
+
+ /* The partial symbol table associated with this compilation unit,
+ or NULL for partial units (which do not have an associated
+ symtab). */
+ struct partial_symtab *psymtab;
};
/* The line number information for a compilation unit (found in the
unsigned int dir_index;
unsigned int mod_time;
unsigned int length;
+ int included_p; /* Non-zero if referenced by the Line Number Program. */
+ struct symtab *symtab; /* The associated symbol table, if any. */
} *file_names;
/* The start and end of the statement program following this
- header. These point into dwarf_line_buffer. */
- char *statement_program_start, *statement_program_end;
+ header. These point into dwarf2_per_objfile->line_buffer. */
+ gdb_byte *statement_program_start, *statement_program_end;
};
/* When we construct a partial symbol table entry we only
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;
+
+ /* Flag set if the DIE has a byte_size attribute. */
+ unsigned int has_byte_size : 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;
- char *sibling;
+
+ /* Pointer into the info_buffer pointing at the target of
+ DW_AT_sibling, if any. */
+ gdb_byte *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. */
struct dwarf_block
{
unsigned int size;
- char *data;
+ gdb_byte *data;
};
#ifndef ATTR_ALLOC_CHUNK
#define ATTR_ALLOC_CHUNK 4
#endif
-/* A hash table of die offsets for following references. */
-#ifndef REF_HASH_SIZE
-#define REF_HASH_SIZE 1021
-#endif
-
-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;
-
/* Allocate fields for structs, unions and enums in this size. */
#ifndef DW_FIELD_ALLOC_CHUNK
#define DW_FIELD_ALLOC_CHUNK 4
#endif
-/* 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;
-static char *dwarf_loc_buffer;
-
/* A zeroed version of a partial die for initialization purposes. */
static struct partial_die_info zeroed_partial_die;
-/* 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 isreg; /* Object lives in register.
- decode_locdesc's return value is
- the register number. */
-
-/* We put a pointer to this structure in the read_symtab_private field
- of the psymtab.
-
- 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 possible to have both dwarf2 and some other form
- of debug symbols in one object file. */
-
-struct dwarf2_pinfo
- {
- /* Pointer to start of dwarf info buffer for the objfile. */
-
- char *dwarf_info_buffer;
-
- /* Offset in dwarf_info_buffer for this compilation unit. */
-
- unsigned long dwarf_info_offset;
-
- /* Pointer to start of dwarf abbreviation buffer for the objfile. */
-
- char *dwarf_abbrev_buffer;
-
- /* Size of dwarf abbreviation section for the objfile. */
-
- unsigned int dwarf_abbrev_size;
-
- /* Pointer to start of dwarf line buffer for the objfile. */
-
- char *dwarf_line_buffer;
-
- /* Size of dwarf_line_buffer, in bytes. */
-
- unsigned int dwarf_line_size;
-
- /* Pointer to start of dwarf string buffer for the objfile. */
-
- char *dwarf_str_buffer;
-
- /* Size of dwarf string section for the objfile. */
-
- unsigned int dwarf_str_size;
-
- /* Pointer to start of dwarf macro buffer for the objfile. */
-
- char *dwarf_macinfo_buffer;
-
- /* Size of dwarf macinfo section for the objfile. */
-
- unsigned int dwarf_macinfo_size;
-
- /* Pointer to start of dwarf ranges buffer for the objfile. */
-
- char *dwarf_ranges_buffer;
-
- /* Size of dwarf ranges buffer for the objfile. */
-
- unsigned int dwarf_ranges_size;
-
- /* Pointer to start of dwarf locations buffer for the objfile. */
-
- char *dwarf_loc_buffer;
-
- /* Size of dwarf locations buffer for the objfile. */
-
- unsigned int dwarf_loc_size;
- };
-
-#define PST_PRIVATE(p) ((struct dwarf2_pinfo *)(p)->read_symtab_private)
-#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)
-#define DWARF_LOC_BUFFER(p) (PST_PRIVATE(p)->dwarf_loc_buffer)
-#define DWARF_LOC_SIZE(p) (PST_PRIVATE(p)->dwarf_loc_size)
-
/* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte,
but this would require a corresponding change in unpack_field_as_long
and friends. */
int nfnfields;
};
+/* One item on the queue of compilation units to read in full symbols
+ for. */
+struct dwarf2_queue_item
+{
+ struct dwarf2_per_cu_data *per_cu;
+ struct dwarf2_queue_item *next;
+};
+
+/* The current queue. */
+static struct dwarf2_queue_item *dwarf2_queue, *dwarf2_queue_tail;
+
+/* Loaded secondary compilation units are kept in memory until they
+ have not been referenced for the processing of this many
+ compilation units. Set this to zero to disable caching. Cache
+ sizes of up to at least twenty will improve startup time for
+ typical inter-CU-reference binaries, at an obvious memory cost. */
+static int dwarf2_max_cache_age = 5;
+static void
+show_dwarf2_max_cache_age (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ fprintf_filtered (file, _("\
+The upper bound on the age of cached dwarf2 compilation units is %s.\n"),
+ value);
+}
+
+
/* Various complaints about symbol reading that don't abort the process */
static void
dwarf2_statement_list_fits_in_line_number_section_complaint (void)
{
complaint (&symfile_complaints,
- "statement list doesn't fit in .debug_line section");
+ _("statement list doesn't fit in .debug_line section"));
+}
+
+static void
+dwarf2_debug_line_missing_file_complaint (void)
+{
+ complaint (&symfile_complaints,
+ _(".debug_line section has line data without a file"));
}
static void
dwarf2_complex_location_expr_complaint (void)
{
- complaint (&symfile_complaints, "location expression too complex");
+ complaint (&symfile_complaints, _("location expression too complex"));
}
static void
int arg3)
{
complaint (&symfile_complaints,
- "const value length mismatch for '%s', got %d, expected %d", arg1,
+ _("const value length mismatch for '%s', got %d, expected %d"), arg1,
arg2, arg3);
}
dwarf2_macros_too_long_complaint (void)
{
complaint (&symfile_complaints,
- "macro info runs off end of `.debug_macinfo' section");
+ _("macro info runs off end of `.debug_macinfo' section"));
}
static void
dwarf2_macro_malformed_definition_complaint (const char *arg1)
{
complaint (&symfile_complaints,
- "macro debug info contains a malformed macro definition:\n`%s'",
+ _("macro debug info contains a malformed macro definition:\n`%s'"),
arg1);
}
dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
{
complaint (&symfile_complaints,
- "invalid attribute class or form for '%s' in '%s'", arg1, arg2);
+ _("invalid attribute class or form for '%s' in '%s'"), arg1, arg2);
}
/* local function prototypes */
static void dwarf2_build_psymtabs_easy (struct objfile *, int);
#endif
-static void dwarf2_build_psymtabs_hard (struct objfile *, int);
+static void dwarf2_create_include_psymtab (char *, struct partial_symtab *,
+ struct objfile *);
-static char *scan_partial_symbols (char *, CORE_ADDR *, CORE_ADDR *,
- struct dwarf2_cu *,
- const char *namespace);
+static void dwarf2_build_include_psymtabs (struct dwarf2_cu *,
+ struct partial_die_info *,
+ struct partial_symtab *);
-static void add_partial_symbol (struct partial_die_info *, struct dwarf2_cu *,
- const char *namespace);
+static void dwarf2_build_psymtabs_hard (struct objfile *, int);
+
+static void scan_partial_symbols (struct partial_die_info *,
+ CORE_ADDR *, CORE_ADDR *,
+ struct dwarf2_cu *);
-static int pdi_needs_namespace (enum dwarf_tag tag, const char *namespace);
+static void add_partial_symbol (struct partial_die_info *,
+ struct dwarf2_cu *);
-static char *add_partial_namespace (struct partial_die_info *pdi,
- char *info_ptr,
- CORE_ADDR *lowpc, CORE_ADDR *highpc,
- struct dwarf2_cu *cu,
- const char *namespace);
+static int pdi_needs_namespace (enum dwarf_tag tag);
-static char *add_partial_structure (struct partial_die_info *struct_pdi,
- char *info_ptr,
- struct dwarf2_cu *cu,
- const char *namespace);
+static void add_partial_namespace (struct partial_die_info *pdi,
+ CORE_ADDR *lowpc, CORE_ADDR *highpc,
+ struct dwarf2_cu *cu);
-static char *add_partial_enumeration (struct partial_die_info *enum_pdi,
- char *info_ptr,
- struct dwarf2_cu *cu,
- const char *namespace);
+static void add_partial_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 gdb_byte *locate_pdi_sibling (struct partial_die_info *orig_pdi,
+ gdb_byte *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 *, asection *);
+gdb_byte *dwarf2_read_section (struct objfile *, asection *);
static void dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu);
static void dwarf2_free_abbrev_table (void *);
+static struct abbrev_info *peek_die_abbrev (gdb_byte *, unsigned int *,
+ struct dwarf2_cu *);
+
static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int,
struct dwarf2_cu *);
-static char *read_partial_die (struct partial_die_info *,
- bfd *, char *, struct dwarf2_cu *);
+static struct partial_die_info *load_partial_dies (bfd *, gdb_byte *, int,
+ struct dwarf2_cu *);
+
+static gdb_byte *read_partial_die (struct partial_die_info *,
+ struct abbrev_info *abbrev, unsigned int,
+ bfd *, gdb_byte *, struct dwarf2_cu *);
+
+static struct partial_die_info *find_partial_die (unsigned long,
+ struct dwarf2_cu *);
-static char *read_full_die (struct die_info **, bfd *, char *,
- struct dwarf2_cu *, int *);
+static void fixup_partial_die (struct partial_die_info *,
+ struct dwarf2_cu *);
-static char *read_attribute (struct attribute *, struct attr_abbrev *,
- bfd *, char *, struct dwarf2_cu *);
+static gdb_byte *read_full_die (struct die_info **, bfd *, gdb_byte *,
+ struct dwarf2_cu *, int *);
-static char *read_attribute_value (struct attribute *, unsigned,
- bfd *, char *, struct dwarf2_cu *);
+static gdb_byte *read_attribute (struct attribute *, struct attr_abbrev *,
+ bfd *, gdb_byte *, struct dwarf2_cu *);
-static unsigned int read_1_byte (bfd *, char *);
+static gdb_byte *read_attribute_value (struct attribute *, unsigned,
+ bfd *, gdb_byte *, struct dwarf2_cu *);
-static int read_1_signed_byte (bfd *, char *);
+static unsigned int read_1_byte (bfd *, gdb_byte *);
-static unsigned int read_2_bytes (bfd *, char *);
+static int read_1_signed_byte (bfd *, gdb_byte *);
-static unsigned int read_4_bytes (bfd *, char *);
+static unsigned int read_2_bytes (bfd *, gdb_byte *);
-static unsigned long read_8_bytes (bfd *, char *);
+static unsigned int read_4_bytes (bfd *, gdb_byte *);
-static CORE_ADDR read_address (bfd *, char *ptr, struct dwarf2_cu *,
- int *bytes_read);
+static unsigned long read_8_bytes (bfd *, gdb_byte *);
-static LONGEST read_initial_length (bfd *, char *,
- struct comp_unit_head *, int *bytes_read);
+static CORE_ADDR read_address (bfd *, gdb_byte *ptr, struct dwarf2_cu *,
+ unsigned int *);
-static LONGEST read_offset (bfd *, char *, const struct comp_unit_head *,
- int *bytes_read);
+static LONGEST read_initial_length (bfd *, gdb_byte *,
+ struct comp_unit_head *, unsigned int *);
-static char *read_n_bytes (bfd *, char *, unsigned int);
+static LONGEST read_offset (bfd *, gdb_byte *, const struct comp_unit_head *,
+ unsigned int *);
-static char *read_string (bfd *, char *, unsigned int *);
+static gdb_byte *read_n_bytes (bfd *, gdb_byte *, unsigned int);
-static char *read_indirect_string (bfd *, char *, const struct comp_unit_head *,
- unsigned int *);
+static char *read_string (bfd *, gdb_byte *, unsigned int *);
-static unsigned long read_unsigned_leb128 (bfd *, char *, unsigned int *);
+static char *read_indirect_string (bfd *, gdb_byte *,
+ const struct comp_unit_head *,
+ unsigned int *);
-static long read_signed_leb128 (bfd *, char *, unsigned int *);
+static unsigned long read_unsigned_leb128 (bfd *, gdb_byte *, unsigned int *);
-static char *skip_leb128 (bfd *, char *);
+static long read_signed_leb128 (bfd *, gdb_byte *, unsigned int *);
+
+static gdb_byte *skip_leb128 (bfd *, gdb_byte *);
static void set_cu_language (unsigned int, struct dwarf2_cu *);
static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
struct dwarf2_cu *);
+static int dwarf2_flag_true_p (struct die_info *die, unsigned name,
+ struct dwarf2_cu *cu);
+
static int die_is_declaration (struct die_info *, struct dwarf2_cu *cu);
static struct die_info *die_specification (struct die_info *die,
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, struct dwarf2_cu *cu));
static void dwarf_decode_lines (struct line_header *, char *, bfd *,
- struct dwarf2_cu *);
+ struct dwarf2_cu *, struct partial_symtab *);
-static void dwarf2_start_subfile (char *, char *);
+static void dwarf2_start_subfile (char *, char *, char *);
static struct symbol *new_symbol (struct die_info *, struct type *,
struct dwarf2_cu *);
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 dwarf2_cu *);
static void read_type_die (struct die_info *, struct dwarf2_cu *);
static char *determine_prefix (struct die_info *die, struct dwarf2_cu *);
-static char *typename_concat (const char *prefix, const char *suffix);
+static char *typename_concat (struct obstack *,
+ const char *prefix,
+ const char *suffix,
+ struct dwarf2_cu *);
static void read_typedef (struct die_info *, struct dwarf2_cu *);
static void read_array_type (struct die_info *, struct dwarf2_cu *);
+static enum dwarf_array_dim_ordering read_array_order (struct die_info *,
+ struct dwarf2_cu *);
+
static void read_tag_pointer_type (struct die_info *, struct dwarf2_cu *);
static void read_tag_ptr_to_member_type (struct die_info *,
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_comp_unit (gdb_byte *, bfd *, struct dwarf2_cu *);
-static struct die_info *read_die_and_children (char *info_ptr, bfd *abfd,
+static struct die_info *read_die_and_children (gdb_byte *info_ptr, bfd *abfd,
struct dwarf2_cu *,
- char **new_info_ptr,
+ gdb_byte **new_info_ptr,
struct die_info *parent);
-static struct die_info *read_die_and_siblings (char *info_ptr, bfd *abfd,
+static struct die_info *read_die_and_siblings (gdb_byte *info_ptr, bfd *abfd,
struct dwarf2_cu *,
- char **new_info_ptr,
+ gdb_byte **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 dwarf2_cu *);
static char *dwarf2_linkage_name (struct die_info *, struct dwarf2_cu *);
static void dump_die_list (struct die_info *);
-static void store_in_ref_table (unsigned int, struct die_info *);
-
-static void dwarf2_empty_hash_tables (void);
+static void store_in_ref_table (unsigned int, struct die_info *,
+ struct dwarf2_cu *);
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 die_info *follow_die_ref (struct die_info *,
+ struct attribute *,
+ struct dwarf2_cu *);
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 (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 void dwarf2_symbol_mark_computed (struct attribute *attr,
+ struct symbol *sym,
+ struct dwarf2_cu *cu);
+
+static gdb_byte *skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev,
+ struct dwarf2_cu *cu);
+
+static void free_stack_comp_unit (void *);
+
+static hashval_t partial_die_hash (const void *item);
+
+static int partial_die_eq (const void *item_lhs, const void *item_rhs);
+
+static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
+ (unsigned long offset, struct objfile *objfile);
+
+static struct dwarf2_per_cu_data *dwarf2_find_comp_unit
+ (unsigned long offset, struct objfile *objfile);
+
+static void free_one_comp_unit (void *);
+
+static void free_cached_comp_units (void *);
+
+static void age_cached_comp_units (void);
+
+static void free_one_cached_comp_unit (void *);
+
+static void set_die_type (struct die_info *, struct type *,
+ struct dwarf2_cu *);
+
+static void reset_die_and_siblings_types (struct die_info *,
+ struct dwarf2_cu *);
+
+static void create_all_comp_units (struct objfile *);
+
+static struct dwarf2_cu *load_full_comp_unit (struct dwarf2_per_cu_data *,
+ struct objfile *);
+
+static void process_full_comp_unit (struct dwarf2_per_cu_data *);
+
+static void dwarf2_add_dependence (struct dwarf2_cu *,
+ struct dwarf2_per_cu_data *);
+
+static void dwarf2_mark (struct dwarf2_cu *);
+
+static void dwarf2_clear_marks (struct dwarf2_per_cu_data *);
+
+static void read_set_type (struct die_info *, struct dwarf2_cu *);
-static char *skip_one_die (char *info_ptr, struct abbrev_info *abbrev,
- struct dwarf2_cu *cu);
/* Try to locate the sections we need for DWARF 2 debugging
information and return true if we have enough to do something. */
int
-dwarf2_has_info (bfd *abfd)
+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_ranges_section = 0;
dwarf_loc_section = 0;
- bfd_map_over_sections (abfd, dwarf2_locate_sections, NULL);
+ bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL);
return (dwarf_info_section != NULL && dwarf_abbrev_section != NULL);
}
in. */
static void
-dwarf2_locate_sections (bfd *ignore_abfd, asection *sectp, void *ignore_ptr)
+dwarf2_locate_sections (bfd *abfd, asection *sectp, void *ignore_ptr)
{
if (strcmp (sectp->name, INFO_SECTION) == 0)
{
- dwarf_info_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->info_size = bfd_get_section_size (sectp);
dwarf_info_section = sectp;
}
else if (strcmp (sectp->name, ABBREV_SECTION) == 0)
{
- dwarf_abbrev_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->abbrev_size = bfd_get_section_size (sectp);
dwarf_abbrev_section = sectp;
}
else if (strcmp (sectp->name, LINE_SECTION) == 0)
{
- dwarf_line_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->line_size = bfd_get_section_size (sectp);
dwarf_line_section = sectp;
}
else if (strcmp (sectp->name, PUBNAMES_SECTION) == 0)
{
- dwarf_pubnames_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->pubnames_size = bfd_get_section_size (sectp);
dwarf_pubnames_section = sectp;
}
else if (strcmp (sectp->name, ARANGES_SECTION) == 0)
{
- dwarf_aranges_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->aranges_size = bfd_get_section_size (sectp);
dwarf_aranges_section = sectp;
}
else if (strcmp (sectp->name, LOC_SECTION) == 0)
{
- dwarf_loc_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->loc_size = bfd_get_section_size (sectp);
dwarf_loc_section = sectp;
}
else if (strcmp (sectp->name, MACINFO_SECTION) == 0)
{
- dwarf_macinfo_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->macinfo_size = bfd_get_section_size (sectp);
dwarf_macinfo_section = sectp;
}
else if (strcmp (sectp->name, STR_SECTION) == 0)
{
- dwarf_str_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->str_size = bfd_get_section_size (sectp);
dwarf_str_section = sectp;
}
else if (strcmp (sectp->name, FRAME_SECTION) == 0)
{
- dwarf_frame_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->frame_size = bfd_get_section_size (sectp);
dwarf_frame_section = sectp;
}
else if (strcmp (sectp->name, EH_FRAME_SECTION) == 0)
flagword aflag = bfd_get_section_flags (ignore_abfd, sectp);
if (aflag & SEC_HAS_CONTENTS)
{
- dwarf_eh_frame_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->eh_frame_size = bfd_get_section_size (sectp);
dwarf_eh_frame_section = sectp;
}
}
else if (strcmp (sectp->name, RANGES_SECTION) == 0)
{
- dwarf_ranges_size = bfd_get_section_size_before_reloc (sectp);
+ dwarf2_per_objfile->ranges_size = bfd_get_section_size (sectp);
dwarf_ranges_section = sectp;
}
+
+ if ((bfd_get_section_flags (abfd, sectp) & SEC_LOAD)
+ && bfd_section_vma (abfd, sectp) == 0)
+ dwarf2_per_objfile->has_section_at_zero = 1;
}
/* Build a partial symbol table. */
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_section);
- dwarf_abbrev_buffer = dwarf2_read_section (objfile, dwarf_abbrev_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)
- dwarf_line_buffer = dwarf2_read_section (objfile, 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_section)
- dwarf_str_buffer = dwarf2_read_section (objfile, 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_section)
- dwarf_macinfo_buffer = dwarf2_read_section (objfile,
+ 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_section)
- dwarf_ranges_buffer = dwarf2_read_section (objfile, 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)
- dwarf_loc_buffer = dwarf2_read_section (objfile, dwarf_loc_section);
+ dwarf2_per_objfile->loc_buffer = dwarf2_read_section (objfile, dwarf_loc_section);
else
- dwarf_loc_buffer = NULL;
+ dwarf2_per_objfile->loc_buffer = NULL;
if (mainline
|| (objfile->global_psymbols.size == 0
pubnames_buffer = dwarf2_read_section (objfile,
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;
+ unsigned int bytes_read;
entry_length = read_initial_length (abfd, pubnames_ptr, &cu_header,
- &bytes_read);
+ &bytes_read);
pubnames_ptr += bytes_read;
version = read_1_byte (abfd, pubnames_ptr);
pubnames_ptr += 1;
#endif
/* Read in the comp unit header information from the debug_info at
- info_ptr. */
+ info_ptr. */
-static char *
+static gdb_byte *
read_comp_unit_head (struct comp_unit_head *cu_header,
- char *info_ptr, bfd *abfd)
+ gdb_byte *info_ptr, bfd *abfd)
{
int signed_addr;
- int bytes_read;
+ unsigned int bytes_read;
cu_header->length = read_initial_length (abfd, info_ptr, cu_header,
&bytes_read);
info_ptr += bytes_read;
signed_addr = bfd_get_sign_extend_vma (abfd);
if (signed_addr < 0)
internal_error (__FILE__, __LINE__,
- "read_comp_unit_head: dwarf from non elf file");
+ _("read_comp_unit_head: dwarf from non elf file"));
cu_header->signed_addr_p = signed_addr;
return info_ptr;
}
+static gdb_byte *
+partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr,
+ bfd *abfd)
+{
+ gdb_byte *beg_of_comp_unit = info_ptr;
+
+ info_ptr = read_comp_unit_head (header, info_ptr, abfd);
+
+ if (header->version != 2 && header->version != 3)
+ 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. */
+ 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 *beg_of_comp_unit;
+ gdb_byte *info_ptr;
+ gdb_byte *beg_of_comp_unit;
struct partial_die_info comp_unit_die;
struct partial_symtab *pst;
struct cleanup *back_to;
CORE_ADDR lowpc, highpc, baseaddr;
- info_ptr = dwarf_info_buffer;
- abbrev_ptr = dwarf_abbrev_buffer;
-
- /* We use dwarf2_tmp_obstack for objects that don't need to survive
- the partial symbol scan, like attribute values.
-
- We could reduce our peak memory consumption during partial symbol
- table construction by freeing stuff from this obstack more often
- --- say, after processing each compilation unit, or each die ---
- but it turns out that this saves almost nothing. For an
- executable with 11Mb of Dwarf 2 data, I found about 64k allocated
- on dwarf2_tmp_obstack. Some investigation showed:
-
- 1) 69% of the attributes used forms DW_FORM_addr, DW_FORM_data*,
- DW_FORM_flag, DW_FORM_[su]data, and DW_FORM_ref*. These are
- all fixed-length values not requiring dynamic allocation.
-
- 2) 30% of the attributes used the form DW_FORM_string. For
- DW_FORM_string, read_attribute simply hands back a pointer to
- the null-terminated string in dwarf_info_buffer, so no dynamic
- allocation is needed there either.
-
- 3) The remaining 1% of the attributes all used DW_FORM_block1.
- 75% of those were DW_AT_frame_base location lists for
- functions; the rest were DW_AT_location attributes, probably
- for the global variables.
+ info_ptr = dwarf2_per_objfile->info_buffer;
- 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. */
+ /* Any cached compilation units will be linked by the per-objfile
+ read_in_chain. Make sure to free them when we're done. */
+ back_to = make_cleanup (free_cached_comp_units, NULL);
- obstack_init (&dwarf2_tmp_obstack);
- back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
+ create_all_comp_units (objfile);
- /* 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 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;
+ 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 = read_comp_unit_head (&cu.header, info_ptr, abfd);
+ info_ptr = partial_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;
- }
/* Complete the cu_header */
- cu.header.offset = beg_of_comp_unit - dwarf_info_buffer;
+ 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;
/* Read the abbrevs for this compilation unit into a table */
dwarf2_read_abbrevs (abfd, &cu);
- back_to_inner = make_cleanup (dwarf2_free_abbrev_table, &cu);
+ make_cleanup (dwarf2_free_abbrev_table, &cu);
+
+ this_cu = dwarf2_find_comp_unit (cu.header.offset, objfile);
/* Read the compilation unit die */
- info_ptr = read_partial_die (&comp_unit_die, abfd, info_ptr,
- &cu);
+ abbrev = peek_die_abbrev (info_ptr, &bytes_read, &cu);
+ info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read,
+ abfd, info_ptr, &cu);
+
+ if (comp_unit_die.tag == DW_TAG_partial_unit)
+ {
+ info_ptr = (beg_of_comp_unit + cu.header.length
+ + cu.header.initial_length_size);
+ do_cleanups (back_to_inner);
+ continue;
+ }
/* Set the language we're debugging */
set_cu_language (comp_unit_die.language, &cu);
objfile->global_psymbols.next,
objfile->static_psymbols.next);
- pst->read_symtab_private = (char *)
- obstack_alloc (&objfile->objfile_obstack, sizeof (struct dwarf2_pinfo));
- 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;
- DWARF_LOC_BUFFER (pst) = dwarf_loc_buffer;
- DWARF_LOC_SIZE (pst) = dwarf_loc_size;
+ if (comp_unit_die.dirname)
+ pst->dirname = xstrdup (comp_unit_die.dirname);
+
+ pst->read_symtab_private = (char *) this_cu;
+
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
/* Store the function that reads in the rest of the symbol table */
pst->read_symtab = dwarf2_psymtab_to_symtab;
+ /* If this compilation unit was already read in, free the
+ cached copy in order to read it in again. This is
+ necessary because we skipped some symbols when we first
+ read in the compilation unit (see load_partial_dies).
+ This problem could be avoided, but the benefit is
+ unclear. */
+ if (this_cu->cu != NULL)
+ free_one_cached_comp_unit (this_cu->cu);
+
+ cu.per_cu = this_cu;
+
+ /* Note that this is a pointer to our stack frame, being
+ added to a global data structure. It will be cleaned up
+ in free_stack_comp_unit when we finish with this
+ compilation unit. */
+ this_cu->cu = &cu;
+
+ this_cu->psymtab = pst;
+
/* Check if comp unit has_children.
If so, read the rest of the partial symbols from this comp unit.
If not, there's no more debug_info for this comp unit. */
if (comp_unit_die.has_children)
{
+ struct partial_die_info *first_die;
+
lowpc = ((CORE_ADDR) -1);
highpc = ((CORE_ADDR) 0);
- info_ptr = scan_partial_symbols (info_ptr, &lowpc, &highpc,
- &cu, NULL);
+ 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. */
if (! comp_unit_die.has_pc_info)
also happen.) This happens in VxWorks. */
free_named_symtabs (pst->filename);
- info_ptr = beg_of_comp_unit + cu.header.length
+ 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);
+ }
+
do_cleanups (back_to_inner);
}
do_cleanups (back_to);
}
-/* Read in all interesting dies to the end of the compilation unit or
- to the end of the current namespace. NAMESPACE is NULL if we
- haven't yet encountered any DW_TAG_namespace entries; otherwise,
- it's the name of the current namespace. In particular, it's the
- empty string if we're currently in the global namespace but have
- previously encountered a DW_TAG_namespace. */
+/* Load the DIEs for a secondary CU into memory. */
-static char *
-scan_partial_symbols (char *info_ptr, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, struct dwarf2_cu *cu,
- const char *namespace)
+static void
+load_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile)
+{
+ bfd *abfd = objfile->obfd;
+ gdb_byte *info_ptr, *beg_of_comp_unit;
+ struct partial_die_info comp_unit_die;
+ struct dwarf2_cu *cu;
+ struct abbrev_info *abbrev;
+ unsigned int bytes_read;
+ struct cleanup *back_to;
+
+ info_ptr = dwarf2_per_objfile->info_buffer + this_cu->offset;
+ beg_of_comp_unit = info_ptr;
+
+ cu = xmalloc (sizeof (struct dwarf2_cu));
+ memset (cu, 0, sizeof (struct dwarf2_cu));
+
+ obstack_init (&cu->comp_unit_obstack);
+
+ 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 - dwarf2_per_objfile->info_buffer;
+ cu->header.first_die_ptr = info_ptr;
+ cu->header.cu_head_ptr = beg_of_comp_unit;
+
+ /* Read the abbrevs for this compilation unit into a table. */
+ dwarf2_read_abbrevs (abfd, cu);
+ back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
+
+ /* Read the compilation unit die. */
+ 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, cu);
+
+ /* Link this compilation unit into the compilation unit tree. */
+ this_cu->cu = cu;
+ cu->per_cu = this_cu;
+
+ /* Check if comp unit has_children.
+ If so, read the rest of the partial symbols from this comp unit.
+ If not, there's no more debug_info for this comp unit. */
+ if (comp_unit_die.has_children)
+ load_partial_dies (abfd, info_ptr, 0, cu);
+
+ do_cleanups (back_to);
+}
+
+/* Create a list of all compilation units in OBJFILE. We do this only
+ if an inter-comp-unit reference is found; presumably if there is one,
+ there will be many, and one will occur early in the .debug_info section.
+ So there's no point in building this list incrementally. */
+
+static void
+create_all_comp_units (struct objfile *objfile)
+{
+ int n_allocated;
+ int n_comp_units;
+ struct dwarf2_per_cu_data **all_comp_units;
+ gdb_byte *info_ptr = dwarf2_per_objfile->info_buffer;
+
+ n_comp_units = 0;
+ n_allocated = 10;
+ all_comp_units = xmalloc (n_allocated
+ * sizeof (struct dwarf2_per_cu_data *));
+
+ while (info_ptr < dwarf2_per_objfile->info_buffer + dwarf2_per_objfile->info_size)
+ {
+ struct comp_unit_head cu_header;
+ gdb_byte *beg_of_comp_unit;
+ struct dwarf2_per_cu_data *this_cu;
+ unsigned long offset;
+ unsigned int bytes_read;
+
+ offset = info_ptr - dwarf2_per_objfile->info_buffer;
+
+ /* Read just enough information to find out where the next
+ compilation unit is. */
+ cu_header.initial_length_size = 0;
+ cu_header.length = read_initial_length (objfile->obfd, info_ptr,
+ &cu_header, &bytes_read);
+
+ /* Save the compilation unit for later lookup. */
+ this_cu = obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct dwarf2_per_cu_data));
+ memset (this_cu, 0, sizeof (*this_cu));
+ this_cu->offset = offset;
+ this_cu->length = cu_header.length + cu_header.initial_length_size;
+
+ if (n_comp_units == n_allocated)
+ {
+ n_allocated *= 2;
+ all_comp_units = xrealloc (all_comp_units,
+ n_allocated
+ * sizeof (struct dwarf2_per_cu_data *));
+ }
+ all_comp_units[n_comp_units++] = this_cu;
+
+ info_ptr = info_ptr + this_cu->length;
+ }
+
+ dwarf2_per_objfile->all_comp_units
+ = obstack_alloc (&objfile->objfile_obstack,
+ n_comp_units * sizeof (struct dwarf2_per_cu_data *));
+ memcpy (dwarf2_per_objfile->all_comp_units, all_comp_units,
+ n_comp_units * sizeof (struct dwarf2_per_cu_data *));
+ xfree (all_comp_units);
+ dwarf2_per_objfile->n_comp_units = n_comp_units;
+}
+
+/* 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 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;
/* Now, march along the PDI's, descending into ones which have
interesting children but skipping the children of the other ones,
until we reach the end of the compilation unit. */
- while (1)
- {
- /* This flag tells whether or not info_ptr has gotten updated
- inside the loop. */
- int info_ptr_updated = 0;
+ pdi = first_die;
- info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu);
+ while (pdi != NULL)
+ {
+ fixup_partial_die (pdi, cu);
/* Anonymous namespaces have no name but have interesting
children, so we need to look at them. Ditto for anonymous
enums. */
- if (pdi.name != NULL || pdi.tag == DW_TAG_namespace
- || pdi.tag == DW_TAG_enumeration_type)
+ 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_declaration)
+ if (!pdi->is_declaration)
{
- add_partial_symbol (&pdi, cu, namespace);
+ add_partial_symbol (pdi, cu);
}
}
break;
case DW_TAG_variable:
case DW_TAG_typedef:
case DW_TAG_union_type:
- if (!pdi.is_declaration)
+ if (!pdi->is_declaration)
{
- add_partial_symbol (&pdi, cu, namespace);
+ add_partial_symbol (pdi, cu);
}
break;
case DW_TAG_class_type:
case DW_TAG_structure_type:
- if (!pdi.is_declaration)
+ if (!pdi->is_declaration)
{
- info_ptr = add_partial_structure (&pdi, info_ptr, cu,
- namespace);
- info_ptr_updated = 1;
+ add_partial_symbol (pdi, cu);
}
break;
case DW_TAG_enumeration_type:
- if (!pdi.is_declaration)
- {
- info_ptr = add_partial_enumeration (&pdi, info_ptr, cu,
- namespace);
- info_ptr_updated = 1;
- }
+ 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. */
- add_partial_symbol (&pdi, cu, namespace);
+ add_partial_symbol (pdi, cu);
break;
case DW_TAG_namespace:
- /* We've hit a DW_TAG_namespace entry, so we know this
- file has been compiled using a compiler that
- generates them; update NAMESPACE to reflect that. */
- if (namespace == NULL)
- namespace = "";
- info_ptr = add_partial_namespace (&pdi, info_ptr, lowpc, highpc,
- cu, namespace);
- info_ptr_updated = 1;
+ add_partial_namespace (pdi, lowpc, highpc, cu);
break;
default:
break;
}
}
- if (pdi.tag == 0)
- break;
+ /* If the die has a sibling, skip to the sibling. */
+
+ pdi = pdi->die_sibling;
+ }
+}
+
+/* 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. For
+ Java, the same thing occurs except that "." is used instead of "::".
+ 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;
- /* If the die has a sibling, skip to the sibling, unless another
- function has already updated info_ptr for us. */
+ /* We need to look at our parent DIE; if we have a DW_AT_specification,
+ then this means the parent of the specification DIE. */
- /* NOTE: carlton/2003-06-16: This is a bit hackish, but whether
- or not we want to update this depends on enough stuff (not
- only pdi.tag but also whether or not pdi.name is NULL) that
- this seems like the easiest way to handle the issue. */
+ real_pdi = pdi;
+ while (real_pdi->has_specification)
+ real_pdi = find_partial_die (real_pdi->spec_offset, cu);
- if (!info_ptr_updated)
- info_ptr = locate_pdi_sibling (&pdi, info_ptr, abfd, 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, 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 = typename_concat (&cu->comp_unit_obstack, grandparent_scope,
+ parent->name, cu);
+ }
+ 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;
}
- return info_ptr;
+ 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 typename_concat (NULL, parent_scope, pdi->name, cu);
}
static void
-add_partial_symbol (struct partial_die_info *pdi,
- struct dwarf2_cu *cu, const char *namespace)
+add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
CORE_ADDR addr = 0;
- char *actual_name = pdi->name;
+ char *actual_name = NULL;
+ 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));
- /* If we're not in the global namespace and if the namespace name
- isn't encoded in a mangled actual_name, add it. */
-
- if (pdi_needs_namespace (pdi->tag, namespace))
+ if (pdi_needs_namespace (pdi->tag))
{
- actual_name = alloca (strlen (pdi->name) + 2 + strlen (namespace) + 1);
- strcpy (actual_name, namespace);
- strcat (actual_name, "::");
- strcat (actual_name, pdi->name);
+ 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:
{
/* Static Variable. Skip symbols without location descriptors. */
if (pdi->locdesc == NULL)
- return;
+ {
+ if (built_actual_name)
+ xfree (actual_name);
+ return;
+ }
addr = decode_locdesc (pdi->locdesc, cu);
/*prim_record_minimal_symbol (actual_name, addr + baseaddr,
mst_file_data, objfile); */
&objfile->static_psymbols,
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_union_type:
case DW_TAG_enumeration_type:
- /* Skip aggregate types without children, these are external
- references. */
+ /* Skip external references. The DWARF standard says in the section
+ about "Structure, Union, and Class Type Entries": "An incomplete
+ structure, union or class type is represented by a structure,
+ union or class entry that does not have a byte size attribute
+ and that has a DW_AT_declaration attribute." */
+ if (!pdi->has_byte_size && pdi->is_declaration)
+ {
+ if (built_actual_name)
+ xfree (actual_name);
+ return;
+ }
+
/* NOTE: carlton/2003-10-07: See comment in new_symbol about
static vs. global. */
- if (pdi->has_children == 0)
- return;
add_psymbol_to_list (actual_name, strlen (actual_name),
STRUCT_DOMAIN, LOC_TYPEDEF,
- cu->language == language_cplus
+ (cu->language == language_cplus
+ || cu->language == language_java)
? &objfile->global_psymbols
: &objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
- if (cu->language == language_cplus)
+ if (cu->language == language_cplus
+ || cu->language == language_java
+ || cu->language == language_ada)
{
- /* For C++, these implicitly act as typedefs as well. */
+ /* For C++ and Java, these implicitly act as typedefs as well. */
add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->global_psymbols,
case DW_TAG_enumerator:
add_psymbol_to_list (actual_name, strlen (actual_name),
VAR_DOMAIN, LOC_CONST,
- cu->language == language_cplus
+ (cu->language == language_cplus
+ || cu->language == language_java)
? &objfile->global_psymbols
: &objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
(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
- && namespace == NULL
+ && 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 the C++ namespace
- NAMESPACE needs to have the name of the namespace prepended to the
+/* 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, const char *namespace)
+pdi_needs_namespace (enum dwarf_tag tag)
{
- if (namespace == NULL || namespace[0] == '\0')
- return 0;
-
switch (tag)
{
+ case DW_TAG_namespace:
case DW_TAG_typedef:
case DW_TAG_class_type:
case DW_TAG_structure_type:
corresponding to that namespace to the symbol table. NAMESPACE is
the name of the enclosing namespace. */
-static char *
-add_partial_namespace (struct partial_die_info *pdi, char *info_ptr,
+static void
+add_partial_namespace (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- struct dwarf2_cu *cu, const char *namespace)
+ struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
- const char *new_name = pdi->name;
- char *full_name;
-
- /* Calculate the full name of the namespace that we just entered. */
- if (new_name == NULL)
- new_name = "(anonymous namespace)";
- full_name = alloca (strlen (namespace) + 2 + strlen (new_name) + 1);
- strcpy (full_name, namespace);
- if (*namespace != '\0')
- strcat (full_name, "::");
- strcat (full_name, new_name);
+ /* Add a symbol for the namespace. */
- /* FIXME: carlton/2003-10-07: We can't just replace this by a call
- to add_partial_symbol, because we don't have a way to pass in the
- full name to that function; that might be a flaw in
- add_partial_symbol's interface. */
-
- add_psymbol_to_list (full_name, strlen (full_name),
- VAR_DOMAIN, LOC_TYPEDEF,
- &objfile->global_psymbols,
- 0, 0, cu->language, objfile);
+ add_partial_symbol (pdi, cu);
/* Now scan partial symbols in that namespace. */
if (pdi->has_children)
- info_ptr = scan_partial_symbols (info_ptr, lowpc, highpc, cu, full_name);
-
- return info_ptr;
+ scan_partial_symbols (pdi->die_child, lowpc, highpc, cu);
}
-/* Read a partial die corresponding to a class or structure. */
+/* 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 char *
-add_partial_structure (struct partial_die_info *struct_pdi, char *info_ptr,
- struct dwarf2_cu *cu,
- const char *namespace)
+static void
+guess_structure_name (struct partial_die_info *struct_pdi,
+ struct dwarf2_cu *cu)
{
- bfd *abfd = cu->objfile->obfd;
- char *actual_class_name = NULL;
-
- if (cu->language == language_cplus
- && (namespace == NULL || namespace[0] == '\0')
- && struct_pdi->name != NULL
+ if ((cu->language == language_cplus
+ || cu->language == language_java)
+ && cu->has_namespace_info == 0
&& struct_pdi->has_children)
{
- /* See if we can figure out if the class lives in a namespace
- (or is nested within another class.) We do this by looking
- for a member function; its demangled name will contain
- namespace info, if there is any. */
-
/* 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). */
- /* FIXME: carlton/2004-01-23: If NAMESPACE equals "", we have
- the appropriate debug information, so it would be nice to be
- able to avoid this hack. But NAMESPACE may not be the
- namespace where this class was defined: NAMESPACE reflects
- where STRUCT_PDI occurs in the tree of dies, but because of
- DW_AT_specification, that may not actually tell us where the
- class is defined. (See the comment in read_func_scope for an
- example of how this could occur.)
+ struct partial_die_info *child_pdi = struct_pdi->die_child;
+ struct partial_die_info *real_pdi;
- Unfortunately, our current partial symtab data structures are
- completely unable to deal with DW_AT_specification. So, for
- now, the best thing to do is to get nesting information from
- places other than the tree structure of dies if there's any
- chance that a DW_AT_specification is involved. :-( */
+ /* 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. */
- char *next_child = info_ptr;
+ real_pdi = struct_pdi;
+ while (real_pdi->has_specification)
+ real_pdi = find_partial_die (real_pdi->spec_offset, cu);
- while (1)
- {
- struct partial_die_info child_pdi;
+ if (real_pdi->die_parent != NULL)
+ return;
- next_child = read_partial_die (&child_pdi, abfd, next_child,
- cu);
- if (!child_pdi.tag)
- break;
- if (child_pdi.tag == DW_TAG_subprogram)
+ while (child_pdi != NULL)
+ {
+ if (child_pdi->tag == DW_TAG_subprogram)
{
- actual_class_name = class_name_from_physname (child_pdi.name);
+ char *actual_class_name
+ = language_class_name_from_physname (cu->language_defn,
+ child_pdi->name);
if (actual_class_name != NULL)
- struct_pdi->name = actual_class_name;
+ {
+ struct_pdi->name
+ = obsavestring (actual_class_name,
+ strlen (actual_class_name),
+ &cu->comp_unit_obstack);
+ xfree (actual_class_name);
+ }
break;
}
- else
- {
- next_child = locate_pdi_sibling (&child_pdi, next_child,
- abfd, cu);
- }
+
+ child_pdi = child_pdi->die_sibling;
}
}
-
- add_partial_symbol (struct_pdi, cu, namespace);
- xfree (actual_class_name);
-
- return locate_pdi_sibling (struct_pdi, info_ptr, abfd, cu);
}
/* Read a partial die corresponding to an enumeration type. */
-static char *
-add_partial_enumeration (struct partial_die_info *enum_pdi, char *info_ptr,
- struct dwarf2_cu *cu, const char *namespace)
+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;
+ struct partial_die_info *pdi;
if (enum_pdi->name != NULL)
- add_partial_symbol (enum_pdi, cu, namespace);
-
- while (1)
+ add_partial_symbol (enum_pdi, cu);
+
+ pdi = enum_pdi->die_child;
+ while (pdi)
{
- info_ptr = read_partial_die (&pdi, abfd, info_ptr, cu);
- if (pdi.tag == 0)
- break;
- if (pdi.tag != DW_TAG_enumerator || pdi.name == NULL)
- complaint (&symfile_complaints, "malformed enumerator DIE ignored");
+ if (pdi->tag != DW_TAG_enumerator || pdi->name == NULL)
+ complaint (&symfile_complaints, _("malformed enumerator DIE ignored"));
else
- add_partial_symbol (&pdi, cu, namespace);
+ add_partial_symbol (pdi, cu);
+ pdi = pdi->die_sibling;
}
-
- return info_ptr;
}
/* Read the initial uleb128 in the die at INFO_PTR in compilation unit CU.
the initial number. */
static struct abbrev_info *
-peek_die_abbrev (char *info_ptr, int *bytes_read, struct dwarf2_cu *cu)
+peek_die_abbrev (gdb_byte *info_ptr, unsigned int *bytes_read,
+ struct dwarf2_cu *cu)
{
bfd *abfd = cu->objfile->obfd;
unsigned int abbrev_number;
abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
if (!abbrev)
{
- error ("Dwarf Error: Could not find abbrev number %d [in module %s]", abbrev_number,
+ error (_("Dwarf Error: Could not find abbrev number %d [in module %s]"), abbrev_number,
bfd_get_filename (abfd));
}
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)
+static gdb_byte *
+skip_children (gdb_byte *info_ptr, struct dwarf2_cu *cu)
{
struct abbrev_info *abbrev;
unsigned int bytes_read;
ABBREV. Returns a pointer to this DIE's sibling, skipping any
children. */
-static char *
-skip_one_die (char *info_ptr, struct abbrev_info *abbrev,
+static gdb_byte *
+skip_one_die (gdb_byte *info_ptr, struct abbrev_info *abbrev,
struct dwarf2_cu *cu)
{
unsigned int bytes_read;
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");
+ complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling"));
else
- return dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr, cu);
+ return dwarf2_per_objfile->info_buffer
+ + dwarf2_get_ref_die_offset (&attr, cu);
}
/* If it isn't DW_AT_sibling, skip this attribute. */
goto skip_attribute;
default:
- error ("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]",
+ error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"),
dwarf_form_name (form),
bfd_get_filename (abfd));
}
/* 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,
+static gdb_byte *
+locate_pdi_sibling (struct partial_die_info *orig_pdi, gdb_byte *info_ptr,
bfd *abfd, struct dwarf2_cu *cu)
{
/* Do we know the sibling already? */
-
+
if (orig_pdi->sibling)
return orig_pdi->sibling;
{
if (pst->readin)
{
- warning ("bug: psymtab for %s is already read in.", pst->filename);
+ warning (_("bug: psymtab for %s is already read in."), pst->filename);
}
else
{
if (info_verbose)
{
- printf_filtered ("Reading in symbols for %s...", pst->filename);
+ printf_filtered (_("Reading in symbols for %s..."), pst->filename);
gdb_flush (gdb_stdout);
}
+ /* Restore our global data. */
+ dwarf2_per_objfile = objfile_data (pst->objfile,
+ dwarf2_objfile_data_key);
+
psymtab_to_symtab_1 (pst);
/* Finish up the debug error message. */
if (info_verbose)
- printf_filtered ("done.\n");
+ printf_filtered (_("done.\n"));
+ }
+ }
+}
+
+/* Add PER_CU to the queue. */
+
+static void
+queue_comp_unit (struct dwarf2_per_cu_data *per_cu)
+{
+ struct dwarf2_queue_item *item;
+
+ per_cu->queued = 1;
+ item = xmalloc (sizeof (*item));
+ item->per_cu = per_cu;
+ item->next = NULL;
+
+ if (dwarf2_queue == NULL)
+ dwarf2_queue = item;
+ else
+ dwarf2_queue_tail->next = item;
+
+ dwarf2_queue_tail = item;
+}
+
+/* Process the queue. */
+
+static void
+process_queue (struct objfile *objfile)
+{
+ struct dwarf2_queue_item *item, *next_item;
+
+ /* Initially, there is just one item on the queue. Load its DIEs,
+ and the DIEs of any other compilation units it requires,
+ transitively. */
+
+ for (item = dwarf2_queue; item != NULL; item = item->next)
+ {
+ /* Read in this compilation unit. This may add new items to
+ the end of the queue. */
+ load_full_comp_unit (item->per_cu, objfile);
+
+ item->per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+ dwarf2_per_objfile->read_in_chain = item->per_cu;
+
+ /* If this compilation unit has already had full symbols created,
+ reset the TYPE fields in each DIE. */
+ if (item->per_cu->type_hash)
+ reset_die_and_siblings_types (item->per_cu->cu->dies,
+ item->per_cu->cu);
+ }
+
+ /* Now everything left on the queue needs to be read in. Process
+ them, one at a time, removing from the queue as we finish. */
+ for (item = dwarf2_queue; item != NULL; dwarf2_queue = item = next_item)
+ {
+ if (item->per_cu->psymtab && !item->per_cu->psymtab->readin)
+ process_full_comp_unit (item->per_cu);
+
+ item->per_cu->queued = 0;
+ next_item = item->next;
+ xfree (item);
+ }
+
+ dwarf2_queue_tail = NULL;
+}
+
+/* Free all allocated queue entries. This function only releases anything if
+ an error was thrown; if the queue was processed then it would have been
+ freed as we went along. */
+
+static void
+dwarf2_release_queue (void *dummy)
+{
+ struct dwarf2_queue_item *item, *last;
+
+ item = dwarf2_queue;
+ while (item)
+ {
+ /* Anything still marked queued is likely to be in an
+ inconsistent state, so discard it. */
+ if (item->per_cu->queued)
+ {
+ if (item->per_cu->cu != NULL)
+ free_one_cached_comp_unit (item->per_cu->cu);
+ item->per_cu->queued = 0;
}
+
+ last = item;
+ item = item->next;
+ xfree (last);
}
+
+ dwarf2_queue = dwarf2_queue_tail = NULL;
}
+/* Read in full symbols for PST, and anything it depends on. */
+
static void
psymtab_to_symtab_1 (struct partial_symtab *pst)
{
- struct objfile *objfile = pst->objfile;
+ struct dwarf2_per_cu_data *per_cu;
+ struct cleanup *back_to;
+ 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)
+ {
+ /* FIXME: i18n: Need to make this a single string. */
+ 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]);
+ }
+
+ per_cu = (struct dwarf2_per_cu_data *) pst->read_symtab_private;
+
+ if (per_cu == NULL)
+ {
+ /* It's an include file, no symbols to read for it.
+ Everything is in the parent symtab. */
+ pst->readin = 1;
+ return;
+ }
+
+ back_to = make_cleanup (dwarf2_release_queue, NULL);
+
+ queue_comp_unit (per_cu);
+
+ process_queue (pst->objfile);
+
+ /* Age the cache, releasing compilation units that have not
+ been used recently. */
+ age_cached_comp_units ();
+
+ do_cleanups (back_to);
+}
+
+/* Load the DIEs associated with PST and PER_CU into memory. */
+
+static struct dwarf2_cu *
+load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
+{
bfd *abfd = objfile->obfd;
- struct dwarf2_cu cu;
- struct die_info *dies;
+ struct dwarf2_cu *cu;
unsigned long offset;
- CORE_ADDR lowpc, highpc;
- struct die_info *child_die;
- char *info_ptr;
- struct symtab *symtab;
- struct cleanup *back_to;
+ gdb_byte *info_ptr;
+ struct cleanup *back_to, *free_cu_cleanup;
struct attribute *attr;
CORE_ADDR baseaddr;
/* 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);
- dwarf_loc_buffer = DWARF_LOC_BUFFER (pst);
- dwarf_loc_size = DWARF_LOC_SIZE (pst);
- info_ptr = dwarf_info_buffer + offset;
- baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+ offset = per_cu->offset;
- /* We're in the global namespace. */
- processing_current_prefix = "";
+ info_ptr = dwarf2_per_objfile->info_buffer + offset;
- obstack_init (&dwarf2_tmp_obstack);
- back_to = make_cleanup (dwarf2_free_tmp_obstack, NULL);
+ cu = xmalloc (sizeof (struct dwarf2_cu));
+ memset (cu, 0, sizeof (struct dwarf2_cu));
- buildsym_init ();
- make_cleanup (really_free_pendings, NULL);
+ /* If an error occurs while loading, release our storage. */
+ free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
- cu.objfile = objfile;
+ 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);
- make_cleanup (dwarf2_free_abbrev_table, &cu);
+ dwarf2_read_abbrevs (abfd, cu);
+ back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
+
+ cu->header.offset = offset;
- cu.header.offset = offset;
+ cu->per_cu = per_cu;
+ per_cu->cu = cu;
- cu.list_in_scope = &file_symbols;
+ /* We use this obstack for block values in dwarf_alloc_block. */
+ obstack_init (&cu->comp_unit_obstack);
- dies = read_comp_unit (info_ptr, abfd, &cu);
+ cu->dies = read_comp_unit (info_ptr, abfd, cu);
- make_cleanup_free_die_list (dies);
+ /* We try not to read any attributes in this function, because not
+ all objfiles needed for references have been loaded yet, and symbol
+ table processing isn't initialized. But we have to set the CU language,
+ or we won't be able to build types correctly. */
+ attr = dwarf2_attr (cu->dies, DW_AT_language, cu);
+ if (attr)
+ set_cu_language (DW_UNSND (attr), cu);
+ else
+ set_cu_language (language_minimal, cu);
+
+ do_cleanups (back_to);
+
+ /* We've successfully allocated this compilation unit. Let our caller
+ clean it up when finished with it. */
+ discard_cleanups (free_cu_cleanup);
+
+ return cu;
+}
+
+/* Generate full symbol information for PST and CU, whose DIEs have
+ already been loaded into memory. */
+
+static void
+process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
+{
+ struct partial_symtab *pst = per_cu->psymtab;
+ struct dwarf2_cu *cu = per_cu->cu;
+ struct objfile *objfile = pst->objfile;
+ bfd *abfd = objfile->obfd;
+ CORE_ADDR lowpc, highpc;
+ struct symtab *symtab;
+ struct cleanup *back_to;
+ struct attribute *attr;
+ CORE_ADDR baseaddr;
+
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+ /* We're in the global namespace. */
+ processing_current_prefix = "";
+
+ buildsym_init ();
+ back_to = make_cleanup (really_free_pendings, NULL);
+
+ cu->list_in_scope = &file_symbols;
/* Find the base address of the compilation unit for range lists and
location lists. It will normally be specified by DW_AT_low_pc.
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;
+ cu->header.base_known = 0;
+ cu->header.base_address = 0;
- attr = dwarf2_attr (dies, DW_AT_entry_pc, &cu);
+ attr = dwarf2_attr (cu->dies, DW_AT_entry_pc, cu);
if (attr)
{
- cu.header.base_address = DW_ADDR (attr);
- cu.header.base_known = 1;
+ cu->header.base_address = DW_ADDR (attr);
+ cu->header.base_known = 1;
}
else
{
- attr = dwarf2_attr (dies, DW_AT_low_pc, &cu);
+ attr = dwarf2_attr (cu->dies, DW_AT_low_pc, cu);
if (attr)
{
- cu.header.base_address = DW_ADDR (attr);
- cu.header.base_known = 1;
+ cu->header.base_address = DW_ADDR (attr);
+ cu->header.base_known = 1;
}
}
/* Do line number decoding in read_file_scope () */
- process_die (dies, &cu);
+ process_die (cu->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);
+ get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);
symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
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;
case DW_TAG_subroutine_type:
read_subroutine_type (die, cu);
break;
+ case DW_TAG_set_type:
+ read_set_type (die, cu);
+ break;
case DW_TAG_array_type:
read_array_type (die, cu);
break;
cu->first_fn = cu->last_fn = cu->cached_fn = NULL;
}
+static void
+free_cu_line_header (void *arg)
+{
+ struct dwarf2_cu *cu = arg;
+
+ free_line_header (cu->line_header);
+ cu->line_header = NULL;
+}
+
static void
read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
{
CORE_ADDR lowpc = ((CORE_ADDR) -1);
CORE_ADDR highpc = ((CORE_ADDR) 0);
struct attribute *attr;
- char *name = "<unknown>";
+ char *name = NULL;
char *comp_dir = NULL;
struct die_info *child_die;
bfd *abfd = objfile->obfd;
lowpc += baseaddr;
highpc += baseaddr;
+ /* Find the filename. Do not use dwarf2_name here, since the filename
+ is not a source language identifier. */
attr = dwarf2_attr (die, DW_AT_name, cu);
if (attr)
{
name = DW_STRING (attr);
}
+
attr = dwarf2_attr (die, DW_AT_comp_dir, cu);
if (attr)
+ comp_dir = DW_STRING (attr);
+ else if (name != NULL && IS_ABSOLUTE_PATH (name))
{
- comp_dir = DW_STRING (attr);
- if (comp_dir)
- {
- /* Irix 6.2 native cc prepends <machine>.: to the compilation
- directory, get rid of it. */
- char *cp = strchr (comp_dir, ':');
-
- if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
- comp_dir = cp + 1;
- }
+ comp_dir = ldirname (name);
+ if (comp_dir != NULL)
+ make_cleanup (xfree, comp_dir);
}
-
- if (objfile->ei.entry_point >= lowpc &&
- objfile->ei.entry_point < highpc)
+ if (comp_dir != NULL)
{
- objfile->ei.deprecated_entry_file_lowpc = lowpc;
- objfile->ei.deprecated_entry_file_highpc = highpc;
+ /* Irix 6.2 native cc prepends <machine>.: to the compilation
+ directory, get rid of it. */
+ char *cp = strchr (comp_dir, ':');
+
+ if (cp && cp != comp_dir && cp[-1] == '.' && cp[1] == '/')
+ comp_dir = cp + 1;
}
+ if (name == NULL)
+ name = "<unknown>";
+
attr = dwarf2_attr (die, DW_AT_language, cu);
if (attr)
{
set_cu_language (DW_UNSND (attr), cu);
}
+ attr = dwarf2_attr (die, DW_AT_producer, cu);
+ if (attr)
+ cu->producer = DW_STRING (attr);
+
/* We assume that we're processing GCC output. */
processing_gcc_compilation = 2;
-#if 0
- /* FIXME:Do something here. */
- if (dip->at_producer != NULL)
- {
- handle_producer (dip->at_producer);
- }
-#endif
/* The compilation unit may be in a different language or objfile,
zero out all remembered fundamental types. */
start_symtab (name, comp_dir, lowpc);
record_debugformat ("DWARF 2");
+ record_producer (cu->producer);
initialize_cu_func_list (cu);
+ /* Decode line number information if present. We do this before
+ processing child DIEs, so that the line header table is available
+ for DW_AT_decl_file. */
+ 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);
+ if (line_header)
+ {
+ cu->line_header = line_header;
+ make_cleanup (free_cu_line_header, cu);
+ dwarf_decode_lines (line_header, comp_dir, abfd, cu, NULL);
+ }
+ }
+
/* Process all dies in compilation unit. */
if (die->child != NULL)
{
}
}
- /* Decode line number information if present. */
- 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);
- if (line_header)
- {
- make_cleanup ((make_cleanup_ftype *) free_line_header,
- (void *) line_header);
- dwarf_decode_lines (line_header, comp_dir, abfd, cu);
- }
- }
-
/* Decode macro information, if present. Dwarf 2 macro information
refers to information in the line number info statement program
header, so we can only read it if we've read the header
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;
if (name == NULL || !dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu))
return;
- if (cu->language == language_cplus)
+ if (cu->language == language_cplus
+ || cu->language == language_java)
{
struct die_info *spec_die = die_specification (die, cu);
/* Record the function range for dwarf_decode_lines. */
add_to_cu_func_list (name, lowpc, highpc, cu);
- if (objfile->ei.entry_point >= lowpc &&
- objfile->ei.entry_point < highpc)
- {
- objfile->ei.entry_func_lowpc = lowpc;
- objfile->ei.entry_func_highpc = highpc;
- }
-
new = push_context (0, lowpc);
new->name = new_symbol (die, die->type, cu);
/* Base address selection entry. */
CORE_ADDR base;
int found_base;
- int dummy;
- char *buffer;
+ unsigned int dummy;
+ gdb_byte *buffer;
CORE_ADDR marker;
int low_set;
found_base = cu_header->base_known;
base = cu_header->base_address;
- if (offset >= dwarf_ranges_size)
+ if (offset >= dwarf2_per_objfile->ranges_size)
{
complaint (&symfile_complaints,
- "Offset %d out of bounds for DW_AT_ranges attribute",
+ _("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, &dummy);
/* We have no valid base address for the ranges
data. */
complaint (&symfile_complaints,
- "Invalid .debug_ranges data (no base address)");
+ _("Invalid .debug_ranges data (no base address)"));
return 0;
}
labels are not in the output, so the relocs get a value of 0.
If this is a discarded function, mark the pc bounds as invalid,
so that GDB will ignore it. */
- if (low == 0 && (bfd_get_file_flags (obfd) & HAS_RELOC) == 0)
+ if (low == 0 && !dwarf2_per_objfile->has_section_at_zero)
return 0;
*lowpc = low;
}
/* Get name of field. */
- attr = dwarf2_attr (die, DW_AT_name, cu);
- if (attr && DW_STRING (attr))
- fieldname = DW_STRING (attr);
+ fieldname = dwarf2_name (die, cu);
+ if (fieldname == NULL)
+ fieldname = "";
/* The name is already allocated along with this objfile, so we don't
need to duplicate it for the type. */
char *physname;
/* Get name of field. */
- attr = dwarf2_attr (die, DW_AT_name, cu);
- if (attr && DW_STRING (attr))
- fieldname = DW_STRING (attr);
- else
+ fieldname = dwarf2_name (die, cu);
+ if (fieldname == NULL)
return;
/* Get physical name. */
if (fip->nbaseclasses)
{
int num_bytes = B_BYTES (fip->nbaseclasses);
- char *pointer;
+ unsigned char *pointer;
ALLOCATE_CPLUS_STRUCT_TYPE (type);
- pointer = (char *) TYPE_ALLOC (type, num_bytes);
- TYPE_FIELD_VIRTUAL_BITS (type) = (B_TYPE *) pointer;
+ pointer = TYPE_ALLOC (type, num_bytes);
+ TYPE_FIELD_VIRTUAL_BITS (type) = pointer;
B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses);
TYPE_N_BASECLASSES (type) = fip->nbaseclasses;
}
default:
/* Unknown accessibility. Complain and treat it as public. */
{
- complaint (&symfile_complaints, "unsupported accessibility %d",
+ complaint (&symfile_complaints, _("unsupported accessibility %d"),
fip->fields->accessibility);
}
break;
struct nextfnfield *new_fnfield;
/* Get name of member function. */
- attr = dwarf2_attr (die, DW_AT_name, cu);
- if (attr && DW_STRING (attr))
- fieldname = DW_STRING (attr);
- else
+ fieldname = dwarf2_name (die, cu);
+ if (fieldname == NULL)
return;
/* Get the mangled name. */
fnp->voffset = VOFFSET_STATIC;
}
else
- complaint (&symfile_complaints, "member function type missing for '%s'",
+ complaint (&symfile_complaints, _("member function type missing for '%s'"),
physname);
/* Get fcontext from DW_AT_containing_type if present. */
TYPE_NFN_FIELDS_TOTAL (type) = total_length;
}
+/* Returns non-zero if NAME is the name of a vtable member in CU's
+ language, zero otherwise. */
+static int
+is_vtable_name (const char *name, struct dwarf2_cu *cu)
+{
+ static const char vptr[] = "_vptr";
+ static const char vtable[] = "vtable";
+
+ /* Look for the C++ and Java forms of the vtable. */
+ if ((cu->language == language_java
+ && strncmp (name, vtable, sizeof (vtable) - 1) == 0)
+ || (strncmp (name, vptr, sizeof (vptr) - 1) == 0
+ && is_cplus_marker (name[sizeof (vptr) - 1])))
+ return 1;
+
+ return 0;
+}
+
+/* GCC outputs unnamed structures that are really pointers to member
+ functions, with the ABI-specified layout. If DIE (from CU) describes
+ such a structure, set its type, and return nonzero. Otherwise return
+ zero.
+
+ GCC shouldn't do this; it should just output pointer to member DIEs.
+ This is GCC PR debug/28767. */
+
+static int
+quirk_gcc_member_function_pointer (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+ struct type *type;
+ struct die_info *pfn_die, *delta_die;
+ struct attribute *pfn_name, *delta_name;
+ struct type *pfn_type, *domain_type;
+
+ /* Check for a structure with no name and two children. */
+ if (die->tag != DW_TAG_structure_type
+ || dwarf2_attr (die, DW_AT_name, cu) != NULL
+ || die->child == NULL
+ || die->child->sibling == NULL
+ || (die->child->sibling->sibling != NULL
+ && die->child->sibling->sibling->tag != DW_TAG_padding))
+ return 0;
+
+ /* Check for __pfn and __delta members. */
+ pfn_die = die->child;
+ pfn_name = dwarf2_attr (pfn_die, DW_AT_name, cu);
+ if (pfn_die->tag != DW_TAG_member
+ || pfn_name == NULL
+ || DW_STRING (pfn_name) == NULL
+ || strcmp ("__pfn", DW_STRING (pfn_name)) != 0)
+ return 0;
+
+ delta_die = pfn_die->sibling;
+ delta_name = dwarf2_attr (delta_die, DW_AT_name, cu);
+ if (delta_die->tag != DW_TAG_member
+ || delta_name == NULL
+ || DW_STRING (delta_name) == NULL
+ || strcmp ("__delta", DW_STRING (delta_name)) != 0)
+ return 0;
+
+ /* Find the type of the method. */
+ pfn_type = die_type (pfn_die, cu);
+ if (pfn_type == NULL
+ || TYPE_CODE (pfn_type) != TYPE_CODE_PTR
+ || TYPE_CODE (TYPE_TARGET_TYPE (pfn_type)) != TYPE_CODE_FUNC)
+ return 0;
+
+ /* Look for the "this" argument. */
+ pfn_type = TYPE_TARGET_TYPE (pfn_type);
+ if (TYPE_NFIELDS (pfn_type) == 0
+ || TYPE_CODE (TYPE_FIELD_TYPE (pfn_type, 0)) != TYPE_CODE_PTR)
+ return 0;
+
+ domain_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (pfn_type, 0));
+ type = alloc_type (objfile);
+ smash_to_method_type (type, domain_type, TYPE_TARGET_TYPE (pfn_type),
+ TYPE_FIELDS (pfn_type), TYPE_NFIELDS (pfn_type),
+ TYPE_VARARGS (pfn_type));
+ type = lookup_methodptr_type (type);
+ set_die_type (die, type, cu);
+
+ return 1;
+}
+
/* Called when we find the DIE that starts a structure or union scope
(definition) to process all dies that define the members of the
structure or union.
struct attribute *attr;
const char *previous_prefix = processing_current_prefix;
struct cleanup *back_to = NULL;
+ char *name;
if (die->type)
return;
- type = alloc_type (objfile);
+ if (quirk_gcc_member_function_pointer (die, cu))
+ return;
+ type = alloc_type (objfile);
INIT_CPLUS_SPECIFIC (type);
- attr = dwarf2_attr (die, DW_AT_name, cu);
- if (attr && DW_STRING (attr))
+ name = dwarf2_name (die, cu);
+ if (name != NULL)
{
- if (cu->language == language_cplus)
+ if (cu->language == language_cplus
+ || cu->language == language_java)
{
char *new_prefix = determine_class_name (die, cu);
TYPE_TAG_NAME (type) = obsavestring (new_prefix,
{
/* 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);
+ TYPE_TAG_NAME (type) = name;
}
}
TYPE_LENGTH (type) = 0;
}
+ TYPE_FLAGS (type) |= TYPE_FLAG_STUB_SUPPORTED;
+ 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;
+ set_die_type (die, type, cu);
if (die->child != NULL && ! die_is_declaration (die, cu))
{
TYPE_VPTR_BASETYPE (type) = t;
if (type == t)
{
- static const char vptr_name[] =
- {'_', 'v', 'p', 't', 'r', '\0'};
int i;
/* Our own class provides vtbl ptr. */
{
char *fieldname = TYPE_FIELD_NAME (t, i);
- if ((strncmp (fieldname, vptr_name,
- strlen (vptr_name) - 1)
- == 0)
- && is_cplus_marker (fieldname[strlen (vptr_name)]))
+ if (is_vtable_name (fieldname, cu))
{
TYPE_VPTR_FIELDNO (type) = i;
break;
/* Complain if virtual function table field not found. */
if (i < TYPE_N_BASECLASSES (t))
complaint (&symfile_complaints,
- "virtual function table pointer not found when defining class '%s'",
+ _("virtual function table pointer not found when defining class '%s'"),
TYPE_TAG_NAME (type) ? TYPE_TAG_NAME (type) :
"");
}
TYPE_VPTR_FIELDNO (type) = TYPE_VPTR_FIELDNO (t);
}
}
+ else if (cu->producer
+ && strncmp (cu->producer,
+ "IBM(R) XL C/C++ Advanced Edition", 32) == 0)
+ {
+ /* The IBM XLC compiler does not provide direct indication
+ of the containing type, but the vtable pointer is
+ always named __vfp. */
+
+ int i;
+
+ for (i = TYPE_NFIELDS (type) - 1;
+ i >= TYPE_N_BASECLASSES (type);
+ --i)
+ {
+ if (strcmp (TYPE_FIELD_NAME (type, i), "__vfp") == 0)
+ {
+ TYPE_VPTR_FIELDNO (type) = i;
+ TYPE_VPTR_BASETYPE (type) = type;
+ break;
+ }
+ }
+ }
}
do_cleanups (back_to);
}
- else
- {
- /* No children, must be stub. */
- TYPE_FLAGS (type) |= TYPE_FLAG_STUB;
- }
processing_current_prefix = previous_prefix;
if (back_to != NULL)
child_die = sibling_die (child_die);
}
- if (die->child != NULL && ! die_is_declaration (die, cu))
+ /* Do not consider external references. According to the DWARF standard,
+ these DIEs are identified by the fact that they have no byte_size
+ attribute, and a declaration attribute. */
+ if (dwarf2_attr (die, DW_AT_byte_size, cu) != NULL
+ || !die_is_declaration (die, cu))
new_symbol (die, die->type, cu);
processing_current_prefix = previous_prefix;
struct objfile *objfile = cu->objfile;
struct type *type;
struct attribute *attr;
+ char *name;
if (die->type)
return;
type = alloc_type (objfile);
TYPE_CODE (type) = TYPE_CODE_ENUM;
- attr = dwarf2_attr (die, DW_AT_name, cu);
- if (attr && DW_STRING (attr))
+ name = dwarf2_name (die, cu);
+ if (name != NULL)
{
- 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);
+ TYPE_TAG_NAME (type) = typename_concat (&objfile->objfile_obstack,
+ processing_current_prefix,
+ name, cu);
}
else
{
TYPE_LENGTH (type) = 0;
}
- die->type = type;
+ set_die_type (die, type, cu);
}
/* Determine the name of the type represented by DIE, which should be
- a named C++ compound type. Return the name in question; the caller
+ a named C++ or Java compound type. Return the name in question; the caller
is responsible for xfree()'ing it. */
static char *
/* If we don't have namespace debug info, guess the name by trying
to demangle the names of members, just like we did in
- add_partial_structure. */
+ guess_structure_name. */
if (!processing_has_namespace_info)
{
struct die_info *child;
{
if (child->tag == DW_TAG_subprogram)
{
- new_prefix = class_name_from_physname (dwarf2_linkage_name
+ new_prefix
+ = language_class_name_from_physname (cu->language_defn,
+ dwarf2_linkage_name
(child, cu));
if (new_prefix != NULL)
if (new_prefix == NULL)
{
const char *name = dwarf2_name (die, cu);
- new_prefix = typename_concat (processing_current_prefix,
- name ? name : "<<anonymous>>");
+ new_prefix = typename_concat (NULL, processing_current_prefix,
+ name ? name : "<<anonymous>>",
+ cu);
}
if (back_to != NULL)
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;
+ char *name;
num_fields = 0;
fields = NULL;
}
else
{
- attr = dwarf2_attr (child_die, DW_AT_name, cu);
- if (attr)
+ name = dwarf2_name (child_die, cu);
+ if (name)
{
sym = new_symbol (child_die, die->type, cu);
if (SYMBOL_VALUE (sym) < 0)
struct attribute *attr;
int ndim = 0;
struct cleanup *back_to;
+ char *name;
/* Return if we've already decoded this type. */
if (die->type)
{
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);
+ set_die_type (die, create_array_type (NULL, element_type, range_type),
+ cu);
return;
}
/* Dwarf2 dimensions are output from left to right, create the
necessary array types in backwards order. */
+
type = element_type;
- while (ndim-- > 0)
- type = create_array_type (NULL, type, range_types[ndim]);
+
+ if (read_array_order (die, cu) == DW_ORD_col_major)
+ {
+ int i = 0;
+ while (i < ndim)
+ type = create_array_type (NULL, type, range_types[i++]);
+ }
+ else
+ {
+ while (ndim-- > 0)
+ type = create_array_type (NULL, type, range_types[ndim]);
+ }
/* Understand Dwarf2 support for vector types (like they occur on
the PowerPC w/ AltiVec). Gcc just adds another attribute to the
to functions. */
attr = dwarf2_attr (die, DW_AT_GNU_vector, cu);
if (attr)
- TYPE_FLAGS (type) |= TYPE_FLAG_VECTOR;
+ make_vector_type (type);
+ name = dwarf2_name (die, cu);
+ if (name)
+ TYPE_NAME (type) = name;
+
do_cleanups (back_to);
/* Install the type in the die. */
- die->type = type;
+ set_die_type (die, type, cu);
+}
+
+static enum dwarf_array_dim_ordering
+read_array_order (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct attribute *attr;
+
+ attr = dwarf2_attr (die, DW_AT_ordering, cu);
+
+ if (attr) return DW_SND (attr);
+
+ /*
+ GNU F77 is a special case, as at 08/2004 array type info is the
+ opposite order to the dwarf2 specification, but data is still
+ laid out as per normal fortran.
+
+ FIXME: dsl/2004-8-20: If G77 is ever fixed, this will also need
+ version checking.
+ */
+
+ if (cu->language == language_fortran &&
+ cu->producer && strstr (cu->producer, "GNU F77"))
+ {
+ return DW_ORD_row_major;
+ }
+
+ switch (cu->language_defn->la_array_ordering)
+ {
+ case array_column_major:
+ return DW_ORD_col_major;
+ case array_row_major:
+ default:
+ return DW_ORD_row_major;
+ };
+}
+
+/* Extract all information from a DW_TAG_set_type DIE and put it in
+ the DIE's type field. */
+
+static void
+read_set_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+ if (die->type == NULL)
+ die->type = create_set_type ((struct type *) NULL, die_type (die, cu));
}
/* First cut: install each common block member as a global variable. */
const char *name;
int is_anonymous;
struct die_info *current_die;
+ struct cleanup *back_to = make_cleanup (null_cleanup, 0);
name = namespace_name (die, &is_anonymous, cu);
}
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);
-
+ char *temp_name = typename_concat (NULL, previous_prefix, name, cu);
+ make_cleanup (xfree, temp_name);
processing_current_prefix = temp_name;
}
TYPE_TAG_NAME (type) = TYPE_NAME (type);
new_symbol (die, type, cu);
- die->type = type;
+ set_die_type (die, type, cu);
if (is_anonymous)
cp_add_using_directive (processing_current_prefix,
}
processing_current_prefix = previous_prefix;
+ do_cleanups (back_to);
}
/* Return the name of the namespace represented by DIE. Set
length accordingly. */
if (TYPE_LENGTH (type) != byte_size || addr_class != DW_ADDR_none)
{
- if (ADDRESS_CLASS_TYPE_FLAGS_P ())
+ if (gdbarch_address_class_type_flags_p (current_gdbarch))
{
int type_flags;
- type_flags = ADDRESS_CLASS_TYPE_FLAGS (byte_size, addr_class);
+ type_flags = gdbarch_address_class_type_flags
+ (current_gdbarch, byte_size, addr_class);
gdb_assert ((type_flags & ~TYPE_FLAG_ADDRESS_CLASS_ALL) == 0);
type = make_type_with_address_space (type, type_flags);
}
else if (TYPE_LENGTH (type) != byte_size)
{
- complaint (&symfile_complaints, "invalid pointer size %d", byte_size);
+ complaint (&symfile_complaints, _("invalid pointer size %d"), byte_size);
}
else {
/* Should we also complain about unhandled address classes? */
}
TYPE_LENGTH (type) = byte_size;
- die->type = type;
+ set_die_type (die, type, cu);
}
/* Extract all information from a DW_TAG_ptr_to_member_type DIE and add to
return;
}
- type = alloc_type (objfile);
to_type = die_type (die, cu);
domain = die_containing_type (die, cu);
- smash_to_member_type (type, domain, to_type);
- die->type = type;
+ if (TYPE_CODE (check_typedef (to_type)) == TYPE_CODE_METHOD)
+ type = lookup_methodptr_type (to_type);
+ else
+ type = lookup_memberptr_type (to_type, domain);
+
+ set_die_type (die, type, cu);
}
/* Extract all information from a DW_TAG_reference_type DIE and add to
{
TYPE_LENGTH (type) = cu_header->addr_size;
}
- die->type = type;
+ set_die_type (die, type, cu);
}
static void
}
base_type = die_type (die, cu);
- die->type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
+ set_die_type (die, make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0),
+ cu);
}
static void
}
base_type = die_type (die, cu);
- die->type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
+ set_die_type (die, make_cv_type (TYPE_CONST (base_type), 1, base_type, 0),
+ cu);
}
/* Extract all information from a DW_TAG_string_type DIE and add to
char_type = dwarf2_fundamental_type (objfile, FT_CHAR, cu);
type = create_string_type (char_type, range_type);
}
- die->type = type;
+ set_die_type (die, type, cu);
}
/* Handle DIES due to C code like:
return;
}
type = die_type (die, cu);
- ftype = lookup_function_type (type);
+ ftype = make_function_type (type, (struct type **) 0);
- /* All functions in C++ have prototypes. */
+ /* All functions in C++, Pascal and Java have prototypes. */
attr = dwarf2_attr (die, DW_AT_prototyped, cu);
if ((attr && (DW_UNSND (attr) != 0))
- || cu->language == language_cplus)
+ || cu->language == language_cplus
+ || cu->language == language_java
+ || cu->language == language_pascal)
TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED;
if (die->child != NULL)
/* Allocate storage for parameters and fill them in. */
TYPE_NFIELDS (ftype) = nparams;
TYPE_FIELDS (ftype) = (struct field *)
- TYPE_ALLOC (ftype, nparams * sizeof (struct field));
+ TYPE_ZALLOC (ftype, nparams * sizeof (struct field));
child_die = die->child;
while (child_die && child_die->tag)
}
}
- die->type = ftype;
+ set_die_type (die, ftype, cu);
}
static void
if (!die->type)
{
- 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);
+ name = dwarf2_name (die, cu);
+ set_die_type (die, init_type (TYPE_CODE_TYPEDEF, 0,
+ TYPE_FLAG_TARGET_STUB, name, objfile),
+ cu);
TYPE_TARGET_TYPE (die->type) = die_type (die, cu);
}
}
struct type *type;
struct attribute *attr;
int encoding = 0, size = 0;
+ char *name;
/* If we've already decoded this die, this is a no-op. */
if (die->type)
{
size = DW_UNSND (attr);
}
- attr = dwarf2_attr (die, DW_AT_name, cu);
- if (attr && DW_STRING (attr))
+ name = dwarf2_name (die, cu);
+ if (name)
{
enum type_code code = TYPE_CODE_INT;
int type_flags = 0;
case DW_ATE_complex_float:
code = TYPE_CODE_COMPLEX;
break;
+ case DW_ATE_decimal_float:
+ code = TYPE_CODE_DECFLOAT;
+ break;
case DW_ATE_float:
code = TYPE_CODE_FLT;
break;
case DW_ATE_signed:
- case DW_ATE_signed_char:
break;
case DW_ATE_unsigned:
- case DW_ATE_unsigned_char:
+ type_flags |= TYPE_FLAG_UNSIGNED;
+ break;
+ case DW_ATE_signed_char:
+ if (cu->language == language_m2)
+ code = TYPE_CODE_CHAR;
+ break;
+ case DW_ATE_unsigned_char:
+ if (cu->language == language_m2)
+ code = TYPE_CODE_CHAR;
type_flags |= TYPE_FLAG_UNSIGNED;
break;
default:
- complaint (&symfile_complaints, "unsupported DW_AT_encoding: '%s'",
+ complaint (&symfile_complaints, _("unsupported DW_AT_encoding: '%s'"),
dwarf_type_encoding_name (encoding));
break;
}
- type = init_type (code, size, type_flags, DW_STRING (attr), objfile);
+ type = init_type (code, size, type_flags, name, objfile);
if (encoding == DW_ATE_address)
TYPE_TARGET_TYPE (type) = dwarf2_fundamental_type (objfile, FT_VOID,
cu);
{
type = dwarf_base_type (encoding, size, cu);
}
- die->type = type;
+ set_die_type (die, type, cu);
}
/* Read the given DW_AT_subrange DIE. */
struct attribute *attr;
int low = 0;
int high = -1;
+ char *name;
/* 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)
+ if (TYPE_CODE (base_type) == TYPE_CODE_VOID)
{
complaint (&symfile_complaints,
- "DW_AT_type missing from DW_TAG_subrange_type");
- return;
+ _("DW_AT_type missing from DW_TAG_subrange_type"));
+ base_type
+ = dwarf_base_type (DW_ATE_signed,
+ gdbarch_addr_bit (current_gdbarch) / 8, cu);
}
- 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;
}
+ /* FIXME: For variable sized arrays either of these could be
+ a variable rather than a constant value. We'll allow it,
+ but we don't know how to handle it. */
attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
if (attr)
low = dwarf2_get_attr_constant_value (attr, 0);
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);
+ name = dwarf2_name (die, cu);
+ if (name)
+ TYPE_NAME (range_type) = name;
attr = dwarf2_attr (die, DW_AT_byte_size, cu);
if (attr)
TYPE_LENGTH (range_type) = DW_UNSND (attr);
- die->type = range_type;
+ set_die_type (die, range_type, cu);
}
+static void
+read_unspecified_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct type *type;
+
+ if (die->type)
+ return;
+
+ /* For now, we only support the C meaning of an unspecified type: void. */
+
+ type = init_type (TYPE_CODE_VOID, 0, 0, dwarf2_name (die, cu),
+ cu->objfile);
+
+ set_die_type (die, type, cu);
+}
/* Read a whole compilation unit into a linked list of dies. */
static struct die_info *
-read_comp_unit (char *info_ptr, bfd *abfd, struct dwarf2_cu *cu)
+read_comp_unit (gdb_byte *info_ptr, bfd *abfd, struct dwarf2_cu *cu)
{
- /* 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);
}
is the parent of the die in question. */
static struct die_info *
-read_die_and_children (char *info_ptr, bfd *abfd,
+read_die_and_children (gdb_byte *info_ptr, bfd *abfd,
struct dwarf2_cu *cu,
- char **new_info_ptr,
+ gdb_byte **new_info_ptr,
struct die_info *parent)
{
struct die_info *die;
- char *cur_ptr;
+ gdb_byte *cur_ptr;
int has_children;
cur_ptr = read_full_die (&die, abfd, info_ptr, cu, &has_children);
- store_in_ref_table (die->offset, die);
+ store_in_ref_table (die->offset, die, cu);
if (has_children)
{
in read_die_and_children. */
static struct die_info *
-read_die_and_siblings (char *info_ptr, bfd *abfd,
+read_die_and_siblings (gdb_byte *info_ptr, bfd *abfd,
struct dwarf2_cu *cu,
- char **new_info_ptr,
+ gdb_byte **new_info_ptr,
struct die_info *parent)
{
struct die_info *first_die, *last_sibling;
- char *cur_ptr;
+ gdb_byte *cur_ptr;
cur_ptr = info_ptr;
first_die = last_sibling = NULL;
}
}
-static void
-do_free_die_list_cleanup (void *dies)
-{
- free_die_list (dies);
-}
-
-static struct cleanup *
-make_cleanup_free_die_list (struct die_info *dies)
-{
- return make_cleanup (do_free_die_list_cleanup, dies);
-}
-
-
/* Read the contents of the section at OFFSET and of size SIZE from the
object file specified by OBJFILE into the objfile_obstack and return it. */
-char *
+gdb_byte *
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);
+ gdb_byte *buf, *retbuf;
+ bfd_size_type size = bfd_get_section_size (sectp);
if (size == 0)
return NULL;
- buf = (char *) obstack_alloc (&objfile->objfile_obstack, size);
- retbuf
- = (char *) symfile_relocate_debug_section (abfd, sectp, (bfd_byte *) buf);
+ buf = obstack_alloc (&objfile->objfile_obstack, size);
+ retbuf = symfile_relocate_debug_section (abfd, sectp, buf);
if (retbuf != NULL)
return retbuf;
if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
|| bfd_bread (buf, size, abfd) != size)
- error ("Dwarf Error: Can't read DWARF data from '%s'",
+ 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 dwarf2_cu *cu)
{
struct comp_unit_head *cu_header = &cu->header;
- char *abbrev_ptr;
+ gdb_byte *abbrev_ptr;
struct abbrev_info *cur_abbrev;
unsigned int abbrev_number, bytes_read, abbrev_name;
unsigned int abbrev_form, hash_number;
memset (cu->dwarf2_abbrevs, 0,
ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
- abbrev_ptr = dwarf_abbrev_buffer + cu_header->abbrev_offset;
+ 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;
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;
= xrealloc (cur_attrs, (allocated_attrs
* sizeof (struct attr_abbrev)));
}
+
+ /* Record whether this compilation unit might have
+ inter-compilation-unit references. If we don't know what form
+ this attribute will have, then it might potentially be a
+ DW_FORM_ref_addr, so we conservatively expect inter-CU
+ references. */
+
+ if (abbrev_form == DW_FORM_ref_addr
+ || abbrev_form == DW_FORM_indirect)
+ cu->has_form_ref_addr = 1;
+
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);
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;
cu->dwarf2_abbrevs = NULL;
}
-/* Lookup an abbrev_info structure in the abbrev hash table. */
+/* Lookup an abbrev_info structure in the abbrev hash table. */
+
+static struct abbrev_info *
+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->dwarf2_abbrevs[hash_number];
+
+ while (abbrev)
+ {
+ if (abbrev->number == number)
+ return abbrev;
+ else
+ abbrev = abbrev->next;
+ }
+ 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, gdb_byte *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;
+ unsigned int load_all = 0;
+
+ int nesting_level = 1;
+
+ parent_die = NULL;
+ last_die = NULL;
+
+ if (cu->per_cu && cu->per_cu->load_all_dies)
+ load_all = 1;
+
+ 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. Normally
+ we would not be interested in members here, but there may be
+ later variables referencing them via DW_AT_specification (for
+ static members). */
+ if (!load_all
+ && !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
+ && abbrev->tag != DW_TAG_member)
+ {
+ /* 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->language == language_java)
+ ? &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
+ wasted time in find_partial_die, when we reread the compilation
+ unit with load_all_dies set. */
+
+ if (load_all
+ || abbrev->tag == DW_TAG_subprogram
+ || abbrev->tag == DW_TAG_variable
+ || abbrev->tag == DW_TAG_namespace
+ || part_die->is_declaration)
+ {
+ void **slot;
-static struct abbrev_info *
-dwarf2_lookup_abbrev (unsigned int number, struct dwarf2_cu *cu)
-{
- unsigned int hash_number;
- struct abbrev_info *abbrev;
+ slot = htab_find_slot_with_hash (cu->partial_dies, part_die,
+ part_die->offset, INSERT);
+ *slot = part_die;
+ }
- hash_number = number % ABBREV_HASH_SIZE;
- abbrev = cu->dwarf2_abbrevs[hash_number];
+ 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
+ && (load_all
+ || 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;
+ }
- while (abbrev)
- {
- if (abbrev->number == number)
- return abbrev;
- else
- abbrev = abbrev->next;
+ /* 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. */
}
- return NULL;
}
/* 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, struct dwarf2_cu *cu)
+static gdb_byte *
+read_partial_die (struct partial_die_info *part_die,
+ struct abbrev_info *abbrev,
+ unsigned int abbrev_len, bfd *abfd,
+ gdb_byte *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);
- 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)
{
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
the current compile unit. */
if (attr.form == DW_FORM_ref_addr)
- complaint (&symfile_complaints, "ignoring absolute DW_AT_sibling");
+ complaint (&symfile_complaints, _("ignoring absolute DW_AT_sibling"));
else
- part_die->sibling =
- dwarf_info_buffer + dwarf2_get_ref_die_offset (&attr, cu);
+ 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;
+ case DW_AT_byte_size:
+ part_die->has_byte_size = 1;
+ 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;
-
- spec_ptr = dwarf_info_buffer
- + dwarf2_get_ref_die_offset (&spec_attr, cu);
- read_partial_die (&spec_die, abfd, spec_ptr, 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;
- }
- }
-
/* 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.
if (has_low_pc_attr && has_high_pc_attr
&& part_die->lowpc < part_die->highpc
&& (part_die->lowpc != 0
- || (bfd_get_file_flags (abfd) & HAS_RELOC)))
+ || dwarf2_per_objfile->has_section_at_zero))
part_die->has_pc_info = 1;
return info_ptr;
}
+/* 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);
+
+ 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_per_cu_data *per_cu = NULL;
+ struct partial_die_info *pd = NULL;
+
+ if (offset >= cu->header.offset
+ && offset < cu->header.offset + cu->header.length)
+ {
+ pd = find_partial_die_in_comp_unit (offset, cu);
+ if (pd != NULL)
+ return pd;
+ }
+
+ per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
+
+ if (per_cu->cu == NULL)
+ {
+ load_comp_unit (per_cu, cu->objfile);
+ per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+ dwarf2_per_objfile->read_in_chain = per_cu;
+ }
+
+ per_cu->cu->last_used = 0;
+ pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
+
+ if (pd == NULL && per_cu->load_all_dies == 0)
+ {
+ struct cleanup *back_to;
+ struct partial_die_info comp_unit_die;
+ struct abbrev_info *abbrev;
+ unsigned int bytes_read;
+ char *info_ptr;
+
+ per_cu->load_all_dies = 1;
+
+ /* Re-read the DIEs. */
+ back_to = make_cleanup (null_cleanup, 0);
+ if (per_cu->cu->dwarf2_abbrevs == NULL)
+ {
+ dwarf2_read_abbrevs (per_cu->cu->objfile->obfd, per_cu->cu);
+ back_to = make_cleanup (dwarf2_free_abbrev_table, per_cu->cu);
+ }
+ info_ptr = per_cu->cu->header.first_die_ptr;
+ abbrev = peek_die_abbrev (info_ptr, &bytes_read, per_cu->cu);
+ info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read,
+ per_cu->cu->objfile->obfd, info_ptr,
+ per_cu->cu);
+ if (comp_unit_die.has_children)
+ load_partial_dies (per_cu->cu->objfile->obfd, info_ptr, 0, per_cu->cu);
+ do_cleanups (back_to);
+
+ pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
+ }
+
+ if (pd == NULL)
+ internal_error (__FILE__, __LINE__,
+ _("could not find partial DIE 0x%lx in cache [from module %s]\n"),
+ offset, bfd_get_filename (cu->objfile->obfd));
+ return pd;
+}
+
+/* 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;
+
+ spec_die = find_partial_die (part_die->spec_offset, cu);
+
+ fixup_partial_die (spec_die, 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,
+static gdb_byte *
+read_full_die (struct die_info **diep, bfd *abfd, gdb_byte *info_ptr,
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)
abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
if (!abbrev)
{
- error ("Dwarf Error: could not find abbrev number %d [in module %s]",
- abbrev_number,
+ error (_("Dwarf Error: could not find abbrev number %d [in module %s]"),
+ abbrev_number,
bfd_get_filename (abfd));
}
die = dwarf_alloc_die ();
{
info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
abfd, info_ptr, cu);
+
+ /* If this attribute is an absolute reference to a different
+ compilation unit, make sure that compilation unit is loaded
+ also. */
+ if (die->attrs[i].form == DW_FORM_ref_addr
+ && (DW_ADDR (&die->attrs[i]) < cu->header.offset
+ || (DW_ADDR (&die->attrs[i])
+ >= cu->header.offset + cu->header.length)))
+ {
+ struct dwarf2_per_cu_data *per_cu;
+ per_cu = dwarf2_find_containing_comp_unit (DW_ADDR (&die->attrs[i]),
+ cu->objfile);
+
+ /* Mark the dependence relation so that we don't flush PER_CU
+ too early. */
+ dwarf2_add_dependence (cu, per_cu);
+
+ /* If it's already on the queue, we have nothing to do. */
+ if (per_cu->queued)
+ continue;
+
+ /* If the compilation unit is already loaded, just mark it as
+ used. */
+ if (per_cu->cu != NULL)
+ {
+ per_cu->cu->last_used = 0;
+ continue;
+ }
+
+ /* Add it to the queue. */
+ queue_comp_unit (per_cu);
+ }
}
*diep = die;
/* Read an attribute value described by an attribute form. */
-static char *
+static gdb_byte *
read_attribute_value (struct attribute *attr, unsigned form,
- bfd *abfd, char *info_ptr,
+ bfd *abfd, gdb_byte *info_ptr,
struct dwarf2_cu *cu)
{
struct comp_unit_head *cu_header = &cu->header;
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);
info_ptr += bytes_read;
break;
case DW_FORM_ref1:
- DW_UNSND (attr) = read_1_byte (abfd, info_ptr);
+ DW_ADDR (attr) = cu->header.offset + read_1_byte (abfd, info_ptr);
info_ptr += 1;
break;
case DW_FORM_ref2:
- DW_UNSND (attr) = read_2_bytes (abfd, info_ptr);
+ DW_ADDR (attr) = cu->header.offset + read_2_bytes (abfd, info_ptr);
info_ptr += 2;
break;
case DW_FORM_ref4:
- DW_UNSND (attr) = read_4_bytes (abfd, info_ptr);
+ DW_ADDR (attr) = cu->header.offset + read_4_bytes (abfd, info_ptr);
info_ptr += 4;
break;
case DW_FORM_ref8:
- DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
+ DW_ADDR (attr) = cu->header.offset + read_8_bytes (abfd, info_ptr);
info_ptr += 8;
break;
case DW_FORM_ref_udata:
- DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+ DW_ADDR (attr) = (cu->header.offset
+ + read_unsigned_leb128 (abfd, info_ptr, &bytes_read));
info_ptr += bytes_read;
break;
case DW_FORM_indirect:
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]",
+ error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"),
dwarf_form_name (form),
bfd_get_filename (abfd));
}
/* Read an attribute described by an abbreviated attribute. */
-static char *
+static gdb_byte *
read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
- bfd *abfd, char *info_ptr, struct dwarf2_cu *cu)
+ bfd *abfd, gdb_byte *info_ptr, struct dwarf2_cu *cu)
{
attr->name = abbrev->name;
return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu);
/* read dwarf information from a buffer */
static unsigned int
-read_1_byte (bfd *abfd, char *buf)
+read_1_byte (bfd *abfd, gdb_byte *buf)
{
- return bfd_get_8 (abfd, (bfd_byte *) buf);
+ return bfd_get_8 (abfd, buf);
}
static int
-read_1_signed_byte (bfd *abfd, char *buf)
+read_1_signed_byte (bfd *abfd, gdb_byte *buf)
{
- return bfd_get_signed_8 (abfd, (bfd_byte *) buf);
+ return bfd_get_signed_8 (abfd, buf);
}
static unsigned int
-read_2_bytes (bfd *abfd, char *buf)
+read_2_bytes (bfd *abfd, gdb_byte *buf)
{
- return bfd_get_16 (abfd, (bfd_byte *) buf);
+ return bfd_get_16 (abfd, buf);
}
static int
-read_2_signed_bytes (bfd *abfd, char *buf)
+read_2_signed_bytes (bfd *abfd, gdb_byte *buf)
{
- return bfd_get_signed_16 (abfd, (bfd_byte *) buf);
+ return bfd_get_signed_16 (abfd, buf);
}
static unsigned int
-read_4_bytes (bfd *abfd, char *buf)
+read_4_bytes (bfd *abfd, gdb_byte *buf)
{
- return bfd_get_32 (abfd, (bfd_byte *) buf);
+ return bfd_get_32 (abfd, buf);
}
static int
-read_4_signed_bytes (bfd *abfd, char *buf)
+read_4_signed_bytes (bfd *abfd, gdb_byte *buf)
{
- return bfd_get_signed_32 (abfd, (bfd_byte *) buf);
+ return bfd_get_signed_32 (abfd, buf);
}
static unsigned long
-read_8_bytes (bfd *abfd, char *buf)
+read_8_bytes (bfd *abfd, gdb_byte *buf)
{
- return bfd_get_64 (abfd, (bfd_byte *) buf);
+ return bfd_get_64 (abfd, buf);
}
static CORE_ADDR
-read_address (bfd *abfd, char *buf, struct dwarf2_cu *cu, int *bytes_read)
+read_address (bfd *abfd, gdb_byte *buf, struct dwarf2_cu *cu,
+ unsigned int *bytes_read)
{
struct comp_unit_head *cu_header = &cu->header;
CORE_ADDR retval = 0;
switch (cu_header->addr_size)
{
case 2:
- retval = bfd_get_signed_16 (abfd, (bfd_byte *) buf);
+ retval = bfd_get_signed_16 (abfd, buf);
break;
case 4:
- retval = bfd_get_signed_32 (abfd, (bfd_byte *) buf);
+ retval = bfd_get_signed_32 (abfd, buf);
break;
case 8:
- retval = bfd_get_signed_64 (abfd, (bfd_byte *) buf);
+ retval = bfd_get_signed_64 (abfd, buf);
break;
default:
internal_error (__FILE__, __LINE__,
- "read_address: bad switch, signed [in module %s]",
+ _("read_address: bad switch, signed [in module %s]"),
bfd_get_filename (abfd));
}
}
switch (cu_header->addr_size)
{
case 2:
- retval = bfd_get_16 (abfd, (bfd_byte *) buf);
+ retval = bfd_get_16 (abfd, buf);
break;
case 4:
- retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+ retval = bfd_get_32 (abfd, buf);
break;
case 8:
- retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ retval = bfd_get_64 (abfd, buf);
break;
default:
internal_error (__FILE__, __LINE__,
- "read_address: bad switch, unsigned [in module %s]",
+ _("read_address: bad switch, unsigned [in module %s]"),
bfd_get_filename (abfd));
}
}
sense for the 32-bit format, this initial zero can be considered to
be an escape value which indicates the presence of the older 64-bit
format. As written, the code can't detect (old format) lengths
- greater than 4GB. If it becomes necessary to handle lengths somewhat
- larger than 4GB, we could allow other small values (such as the
- non-sensical values of 1, 2, and 3) to also be used as escape values
- indicating the presence of the old format.
+ greater than 4GB. If it becomes necessary to handle lengths
+ somewhat larger than 4GB, we could allow other small values (such
+ as the non-sensical values of 1, 2, and 3) to also be used as
+ escape values indicating the presence of the old format.
- The value returned via bytes_read should be used to increment
- the relevant pointer after calling read_initial_length().
+ The value returned via bytes_read should be used to increment the
+ relevant pointer after calling read_initial_length().
As a side effect, this function sets the fields initial_length_size
and offset_size in cu_header to the values appropriate for the
length field. (The format of the initial length field determines
- the width of file offsets to be fetched later with fetch_offset().)
+ the width of file offsets to be fetched later with read_offset().)
[ Note: read_initial_length() and read_offset() are based on the
document entitled "DWARF Debugging Information Format", revision
This document is only a draft and is subject to change. (So beware.)
Details regarding the older, non-standard 64-bit format were
- determined empirically by examining 64-bit ELF files produced
- by the SGI toolchain on an IRIX 6.5 machine.
+ determined empirically by examining 64-bit ELF files produced by
+ the SGI toolchain on an IRIX 6.5 machine.
- Kevin, July 16, 2002
] */
static LONGEST
-read_initial_length (bfd *abfd, char *buf, struct comp_unit_head *cu_header,
- int *bytes_read)
+read_initial_length (bfd *abfd, gdb_byte *buf, struct comp_unit_head *cu_header,
+ unsigned int *bytes_read)
{
- LONGEST retval = 0;
+ LONGEST length = bfd_get_32 (abfd, buf);
- retval = bfd_get_32 (abfd, (bfd_byte *) buf);
-
- if (retval == 0xffffffff)
+ if (length == 0xffffffff)
{
- retval = bfd_get_64 (abfd, (bfd_byte *) buf + 4);
+ length = bfd_get_64 (abfd, buf + 4);
*bytes_read = 12;
- if (cu_header != NULL)
- {
- cu_header->initial_length_size = 12;
- cu_header->offset_size = 8;
- }
}
- else if (retval == 0)
+ else if (length == 0)
{
- /* Handle (non-standard) 64-bit DWARF2 formats such as that used
- by IRIX. */
- retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ /* Handle the (non-standard) 64-bit DWARF2 format used by IRIX. */
+ length = bfd_get_64 (abfd, buf);
*bytes_read = 8;
- if (cu_header != NULL)
- {
- cu_header->initial_length_size = 8;
- cu_header->offset_size = 8;
- }
}
else
{
*bytes_read = 4;
- if (cu_header != NULL)
- {
- cu_header->initial_length_size = 4;
- cu_header->offset_size = 4;
- }
}
- return retval;
+ if (cu_header)
+ {
+ gdb_assert (cu_header->initial_length_size == 0
+ || cu_header->initial_length_size == 4
+ || cu_header->initial_length_size == 8
+ || cu_header->initial_length_size == 12);
+
+ if (cu_header->initial_length_size != 0
+ && cu_header->initial_length_size != *bytes_read)
+ complaint (&symfile_complaints,
+ _("intermixed 32-bit and 64-bit DWARF sections"));
+
+ cu_header->initial_length_size = *bytes_read;
+ cu_header->offset_size = (*bytes_read == 4) ? 4 : 8;
+ }
+
+ return length;
}
/* Read an offset from the data stream. The size of the offset is
- given by cu_header->offset_size. */
+ given by cu_header->offset_size. */
static LONGEST
-read_offset (bfd *abfd, char *buf, const struct comp_unit_head *cu_header,
- int *bytes_read)
+read_offset (bfd *abfd, gdb_byte *buf, const struct comp_unit_head *cu_header,
+ unsigned int *bytes_read)
{
LONGEST retval = 0;
switch (cu_header->offset_size)
{
case 4:
- retval = bfd_get_32 (abfd, (bfd_byte *) buf);
+ retval = bfd_get_32 (abfd, buf);
*bytes_read = 4;
break;
case 8:
- retval = bfd_get_64 (abfd, (bfd_byte *) buf);
+ retval = bfd_get_64 (abfd, buf);
*bytes_read = 8;
break;
default:
internal_error (__FILE__, __LINE__,
- "read_offset: bad switch [in module %s]",
+ _("read_offset: bad switch [in module %s]"),
bfd_get_filename (abfd));
}
- return retval;
+ return retval;
}
-static char *
-read_n_bytes (bfd *abfd, char *buf, unsigned int size)
+static gdb_byte *
+read_n_bytes (bfd *abfd, gdb_byte *buf, unsigned int size)
{
/* If the size of a host char is 8 bits, we can return a pointer
to the buffer, otherwise we have to copy the data to a buffer
}
static char *
-read_string (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
+read_string (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
{
/* If the size of a host char is 8 bits, we can return a pointer
to the string, otherwise we have to copy the string to a buffer
*bytes_read_ptr = 1;
return NULL;
}
- *bytes_read_ptr = strlen (buf) + 1;
- return buf;
+ *bytes_read_ptr = strlen ((char *) buf) + 1;
+ return (char *) buf;
}
static char *
-read_indirect_string (bfd *abfd, char *buf,
+read_indirect_string (bfd *abfd, gdb_byte *buf,
const struct comp_unit_head *cu_header,
unsigned int *bytes_read_ptr)
{
LONGEST str_offset = read_offset (abfd, buf, cu_header,
- (int *) bytes_read_ptr);
+ 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]",
+ 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]",
+ 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 (char *) (dwarf2_per_objfile->str_buffer + str_offset);
}
static unsigned long
-read_unsigned_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
+read_unsigned_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
{
unsigned long result;
unsigned int num_read;
i = 0;
while (1)
{
- byte = bfd_get_8 (abfd, (bfd_byte *) buf);
+ byte = bfd_get_8 (abfd, buf);
buf++;
num_read++;
result |= ((unsigned long)(byte & 127) << shift);
}
static long
-read_signed_leb128 (bfd *abfd, char *buf, unsigned int *bytes_read_ptr)
+read_signed_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
{
long result;
- int i, shift, size, num_read;
+ int i, shift, num_read;
unsigned char byte;
result = 0;
shift = 0;
- size = 32;
num_read = 0;
i = 0;
while (1)
{
- byte = bfd_get_8 (abfd, (bfd_byte *) buf);
+ byte = bfd_get_8 (abfd, buf);
buf++;
num_read++;
result |= ((long)(byte & 127) << shift);
break;
}
}
- if ((shift < size) && (byte & 0x40))
- {
- result |= -(1 << shift);
- }
+ if ((shift < 8 * sizeof (result)) && (byte & 0x40))
+ result |= -(((long)1) << shift);
*bytes_read_ptr = num_read;
return result;
}
/* Return a pointer to just past the end of an LEB128 number in BUF. */
-static char *
-skip_leb128 (bfd *abfd, char *buf)
+static gdb_byte *
+skip_leb128 (bfd *abfd, gdb_byte *buf)
{
int byte;
while (1)
{
- byte = bfd_get_8 (abfd, (bfd_byte *) buf);
+ byte = bfd_get_8 (abfd, buf);
buf++;
if ((byte & 128) == 0)
return buf;
break;
case DW_LANG_Ada83:
case DW_LANG_Ada95:
+ cu->language = language_ada;
+ break;
+ case DW_LANG_Modula2:
+ cu->language = language_m2;
+ break;
+ case DW_LANG_Pascal83:
+ cu->language = language_pascal;
+ break;
case DW_LANG_Cobol74:
case DW_LANG_Cobol85:
- case DW_LANG_Pascal83:
- case DW_LANG_Modula2:
default:
cu->language = language_minimal;
break;
for (i = 0; i < die->num_attrs; ++i)
{
if (die->attrs[i].name == name)
- {
- return &die->attrs[i];
- }
+ return &die->attrs[i];
if (die->attrs[i].name == DW_AT_specification
|| die->attrs[i].name == DW_AT_abstract_origin)
spec = &die->attrs[i];
}
- if (spec)
- {
- struct die_info *ref_die =
- follow_die_ref (dwarf2_get_ref_die_offset (spec, cu));
- if (ref_die)
- return dwarf2_attr (ref_die, name, cu);
- }
+ if (spec)
+ return dwarf2_attr (follow_die_ref (die, spec, cu), 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, struct dwarf2_cu *cu)
{
- return (dwarf2_attr (die, DW_AT_declaration, cu)
- && ! dwarf2_attr (die, DW_AT_specification, cu));
+ /* A DIE is a declaration if it has a DW_AT_declaration attribute
+ which value is non-zero. However, we have to be careful with
+ DIEs having a DW_AT_specification attribute, because dwarf2_attr()
+ (via dwarf2_flag_true_p) follows this attribute. So we may
+ end up accidently finding a declaration attribute that belongs
+ to a different DIE referenced by the specification attribute,
+ even though the given DIE does not have a declaration attribute. */
+ return (dwarf2_flag_true_p (die, DW_AT_declaration, cu)
+ && dwarf2_attr (die, DW_AT_specification, cu) == NULL);
}
/* Return the die giving the specification for DIE, if there is
if (spec_attr == NULL)
return NULL;
else
- return follow_die_ref (dwarf2_get_ref_die_offset (spec_attr, cu));
+ return follow_die_ref (die, spec_attr, cu);
}
/* Free the line_header structure *LH, and any arrays and strings it
fe->dir_index = dir_index;
fe->mod_time = mod_time;
fe->length = length;
+ fe->included_p = 0;
+ fe->symtab = NULL;
}
/* 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
{
struct cleanup *back_to;
struct line_header *lh;
- char *line_ptr;
- int bytes_read;
+ gdb_byte *line_ptr;
+ unsigned int bytes_read;
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");
+ 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)
+ /* 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 >= 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);
+ /* Read in the header. */
+ lh->total_length =
+ read_initial_length (abfd, line_ptr, &cu->header, &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->opcode_base = read_1_byte (abfd, line_ptr);
line_ptr += 1;
lh->standard_opcode_lengths
- = (unsigned char *) xmalloc (lh->opcode_base * sizeof (unsigned char));
+ = xmalloc (lh->opcode_base * sizeof (lh->standard_opcode_lengths[0]));
lh->standard_opcode_lengths[0] = 1; /* This should never be used anyway. */
for (i = 1; i < lh->opcode_base; ++i)
line_ptr += 1;
}
- /* Read directory table */
+ /* Read directory table. */
while ((cur_dir = read_string (abfd, line_ptr, &bytes_read)) != NULL)
{
line_ptr += bytes_read;
}
line_ptr += bytes_read;
- /* Read file name table */
+ /* Read file name table. */
while ((cur_file = read_string (abfd, line_ptr, &bytes_read)) != NULL)
{
unsigned int dir_index, mod_time, length;
line_ptr += bytes_read;
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");
+ _("line number info header doesn't fit in `.debug_line' section"));
discard_cleanups (back_to);
return lh;
return address;
if (address != fn->lowpc)
complaint (&symfile_complaints,
- "misplaced first line number at 0x%lx for '%s'",
+ _("misplaced first line number at 0x%lx for '%s'"),
(unsigned long) address, fn->name);
fn->seen_line = 1;
return fn->lowpc;
}
-/* Decode the line number information for the compilation unit whose
- line number info is at OFFSET in the .debug_line section.
- The compilation directory of the file is passed in COMP_DIR. */
+/* Decode the Line Number Program (LNP) for the given line_header
+ structure and CU. The actual information extracted and the type
+ of structures created from the LNP depends on the value of PST.
+
+ 1. If PST is NULL, then this procedure uses the data from the program
+ to create all necessary symbol tables, and their linetables.
+ The compilation directory of the file is passed in COMP_DIR,
+ and must not be NULL.
+
+ 2. If PST is not NULL, this procedure reads the program to determine
+ the list of files included by the unit represented by PST, and
+ builds all the associated partial symbol tables. In this case,
+ the value of COMP_DIR is ignored, and can thus be NULL (the COMP_DIR
+ is not used to compute the full name of the symtab, and therefore
+ omitting it when building the partial symtab does not introduce
+ the potential for inconsistency - a partial symtab and its associated
+ symbtab having a different fullname -). */
static void
dwarf_decode_lines (struct line_header *lh, char *comp_dir, bfd *abfd,
- struct dwarf2_cu *cu)
+ struct dwarf2_cu *cu, struct partial_symtab *pst)
{
- char *line_ptr;
- char *line_end;
- unsigned int bytes_read;
+ gdb_byte *line_ptr, *extended_end;
+ gdb_byte *line_end;
+ unsigned int bytes_read, extended_len;
unsigned char op_code, extended_op, adj_opcode;
CORE_ADDR baseaddr;
struct objfile *objfile = cu->objfile;
+ const int decode_for_pst_p = (pst != NULL);
+ struct subfile *last_subfile = NULL, *first_subfile = current_subfile;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
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. */
struct file_entry *fe = &lh->file_names[file - 1];
- char *dir;
+ char *dir = NULL;
+
if (fe->dir_index)
dir = lh->include_dirs[fe->dir_index - 1];
- else
- dir = comp_dir;
- dwarf2_start_subfile (fe->name, dir);
+
+ dwarf2_start_subfile (fe->name, dir, comp_dir);
}
- /* Decode the table. */
+ /* Decode the table. */
while (!end_sequence)
{
op_code = read_1_byte (abfd, line_ptr);
line_ptr += 1;
if (op_code >= lh->opcode_base)
- { /* Special operand. */
+ {
+ /* Special operand. */
adj_opcode = op_code - lh->opcode_base;
address += (adj_opcode / lh->line_range)
* lh->minimum_instruction_length;
line += lh->line_base + (adj_opcode % lh->line_range);
- /* append row to matrix using current values */
- record_line (current_subfile, line,
- check_cu_functions (address, cu));
+ if (lh->num_file_names < file)
+ dwarf2_debug_line_missing_file_complaint ();
+ else
+ {
+ lh->file_names[file - 1].included_p = 1;
+ if (!decode_for_pst_p)
+ {
+ if (last_subfile != current_subfile)
+ {
+ if (last_subfile)
+ record_line (last_subfile, 0, address);
+ last_subfile = current_subfile;
+ }
+ /* Append row to matrix using current values. */
+ record_line (current_subfile, line,
+ check_cu_functions (address, cu));
+ }
+ }
basic_block = 1;
}
else switch (op_code)
{
case DW_LNS_extended_op:
- line_ptr += 1; /* ignore length */
+ extended_len = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ extended_end = line_ptr + extended_len;
extended_op = read_1_byte (abfd, line_ptr);
line_ptr += 1;
switch (extended_op)
{
case DW_LNE_end_sequence:
end_sequence = 1;
- record_line (current_subfile, 0, address);
+
+ if (lh->num_file_names < file)
+ dwarf2_debug_line_missing_file_complaint ();
+ else
+ {
+ lh->file_names[file - 1].included_p = 1;
+ if (!decode_for_pst_p)
+ record_line (current_subfile, 0, address);
+ }
break;
case DW_LNE_set_address:
address = read_address (abfd, line_ptr, cu, &bytes_read);
break;
default:
complaint (&symfile_complaints,
- "mangled .debug_line section");
+ _("mangled .debug_line section"));
+ return;
+ }
+ /* Make sure that we parsed the extended op correctly. If e.g.
+ we expected a different address size than the producer used,
+ we may have read the wrong number of bytes. */
+ if (line_ptr != extended_end)
+ {
+ complaint (&symfile_complaints,
+ _("mangled .debug_line section"));
return;
}
break;
case DW_LNS_copy:
- record_line (current_subfile, line,
- check_cu_functions (address, cu));
+ if (lh->num_file_names < file)
+ dwarf2_debug_line_missing_file_complaint ();
+ else
+ {
+ lh->file_names[file - 1].included_p = 1;
+ if (!decode_for_pst_p)
+ {
+ if (last_subfile != current_subfile)
+ {
+ if (last_subfile)
+ record_line (last_subfile, 0, address);
+ last_subfile = current_subfile;
+ }
+ record_line (current_subfile, line,
+ check_cu_functions (address, cu));
+ }
+ }
basic_block = 0;
break;
case DW_LNS_advance_pc:
break;
case DW_LNS_set_file:
{
- /* lh->include_dirs and lh->file_names are 0-based,
- but the directory and file name numbers in the
- statement program are 1-based. */
+ /* The arrays lh->include_dirs and lh->file_names are
+ 0-based, but the directory and file name numbers in
+ the statement program are 1-based. */
struct file_entry *fe;
- char *dir;
+ char *dir = NULL;
+
file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
- fe = &lh->file_names[file - 1];
- if (fe->dir_index)
- dir = lh->include_dirs[fe->dir_index - 1];
+ if (lh->num_file_names < file)
+ dwarf2_debug_line_missing_file_complaint ();
else
- dir = comp_dir;
- dwarf2_start_subfile (fe->name, dir);
+ {
+ fe = &lh->file_names[file - 1];
+ if (fe->dir_index)
+ dir = lh->include_dirs[fe->dir_index - 1];
+ if (!decode_for_pst_p)
+ {
+ last_subfile = current_subfile;
+ dwarf2_start_subfile (fe->name, dir, comp_dir);
+ }
+ }
}
break;
case DW_LNS_set_column:
break;
/* Add to the address register of the state machine the
address increment value corresponding to special opcode
- 255. Ie, this value is scaled by the minimum instruction
- length since special opcode 255 would have scaled the
- the increment. */
+ 255. I.e., this value is scaled by the minimum
+ instruction length since special opcode 255 would have
+ scaled the the increment. */
case DW_LNS_const_add_pc:
address += (lh->minimum_instruction_length
* ((255 - lh->opcode_base) / lh->line_range));
line_ptr += 2;
break;
default:
- { /* Unknown standard opcode, ignore it. */
+ {
+ /* Unknown standard opcode, ignore it. */
int i;
+
for (i = 0; i < lh->standard_opcode_lengths[op_code]; i++)
{
(void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
}
}
}
+
+ 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)
+ {
+ const struct file_entry fe = lh->file_names [file_index];
+ char *include_name = fe.name;
+ char *dir_name = NULL;
+ char *pst_filename = pst->filename;
+
+ if (fe.dir_index)
+ dir_name = lh->include_dirs[fe.dir_index - 1];
+
+ if (!IS_ABSOLUTE_PATH (include_name) && dir_name != NULL)
+ {
+ include_name = concat (dir_name, SLASH_STRING,
+ include_name, (char *)NULL);
+ make_cleanup (xfree, include_name);
+ }
+
+ if (!IS_ABSOLUTE_PATH (pst_filename) && pst->dirname != NULL)
+ {
+ pst_filename = concat (pst->dirname, SLASH_STRING,
+ pst_filename, (char *)NULL);
+ make_cleanup (xfree, pst_filename);
+ }
+
+ if (strcmp (include_name, pst_filename) != 0)
+ dwarf2_create_include_psymtab (include_name, pst, objfile);
+ }
+ }
+ else
+ {
+ /* Make sure a symtab is created for every file, even files
+ which contain only variables (i.e. no code with associated
+ line numbers). */
+
+ int i;
+ struct file_entry *fe;
+
+ for (i = 0; i < lh->num_file_names; i++)
+ {
+ char *dir = NULL;
+ fe = &lh->file_names[i];
+ if (fe->dir_index)
+ dir = lh->include_dirs[fe->dir_index - 1];
+ dwarf2_start_subfile (fe->name, dir, comp_dir);
+
+ /* Skip the main file; we don't need it, and it must be
+ allocated last, so that it will show up before the
+ non-primary symtabs in the objfile's symtab list. */
+ if (current_subfile == first_subfile)
+ continue;
+
+ if (current_subfile->symtab == NULL)
+ current_subfile->symtab = allocate_symtab (current_subfile->name,
+ cu->objfile);
+ fe->symtab = current_subfile->symtab;
+ }
+ }
}
/* Start a subfile for DWARF. FILENAME is the name of the file and
DIRNAME the name of the source directory which contains FILENAME
- or NULL if not known.
+ or NULL if not known. COMP_DIR is the compilation directory for the
+ linetable's compilation unit or NULL if not known.
This routine tries to keep line numbers from identical absolute and
relative file names in a common subfile.
files.files[1].dir: /srcdir
The line number information for list0.c has to end up in a single
- subfile, so that `break /srcdir/list0.c:1' works as expected. */
+ subfile, so that `break /srcdir/list0.c:1' works as expected.
+ start_subfile will ensure that this happens provided that we pass the
+ concatenation of files.files[1].dir and files.files[1].name as the
+ subfile's name. */
static void
-dwarf2_start_subfile (char *filename, char *dirname)
+dwarf2_start_subfile (char *filename, char *dirname, char *comp_dir)
{
- /* If the filename isn't absolute, try to match an existing subfile
- with the full pathname. */
+ char *fullname;
+
+ /* While reading the DIEs, we call start_symtab(DW_AT_name, DW_AT_comp_dir).
+ `start_symtab' will always pass the contents of DW_AT_comp_dir as
+ second argument to start_subfile. To be consistent, we do the
+ same here. In order not to lose the line information directory,
+ we concatenate it to the filename when it makes sense.
+ Note that the Dwarf3 standard says (speaking of filenames in line
+ information): ``The directory index is ignored for file names
+ that represent full path names''. Thus ignoring dirname in the
+ `else' branch below isn't an issue. */
if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL)
- {
- struct subfile *subfile;
- char *fullname = concat (dirname, "/", filename, NULL);
+ fullname = concat (dirname, SLASH_STRING, filename, (char *)NULL);
+ else
+ fullname = filename;
- for (subfile = subfiles; subfile; subfile = subfile->next)
- {
- if (FILENAME_CMP (subfile->name, fullname) == 0)
- {
- current_subfile = subfile;
- xfree (fullname);
- return;
- }
- }
- xfree (fullname);
- }
- start_subfile (filename, dirname);
+ start_subfile (fullname, comp_dir);
+
+ if (fullname != filename)
+ xfree (fullname);
}
static void
&& DW_BLOCK (attr)->size == 1 + cu_header->addr_size
&& DW_BLOCK (attr)->data[0] == DW_OP_addr)
{
- int dummy;
+ unsigned int dummy;
SYMBOL_VALUE_ADDRESS (sym) =
read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu, &dummy);
/* Default assumptions.
Use the passed type or decode it from the die. */
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
- SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
if (type != NULL)
SYMBOL_TYPE (sym) = type;
else
{
SYMBOL_LINE (sym) = DW_UNSND (attr);
}
+
+ attr = dwarf2_attr (die, DW_AT_decl_file, cu);
+ if (attr)
+ {
+ int file_index = DW_UNSND (attr);
+ if (cu->line_header == NULL
+ || file_index > cu->line_header->num_file_names)
+ complaint (&symfile_complaints,
+ _("file index out of range"));
+ else if (file_index > 0)
+ {
+ struct file_entry *fe;
+ fe = &cu->line_header->file_names[file_index - 1];
+ SYMBOL_SYMTAB (sym) = fe->symtab;
+ }
+ }
+
switch (die->tag)
{
case DW_TAG_label:
with missing type entries. Change the misleading `void' type
to something sensible. */
if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID)
- SYMBOL_TYPE (sym) = init_type (TYPE_CODE_INT,
- TARGET_INT_BIT / HOST_CHAR_BIT, 0,
- "<variable, no debug info>",
- objfile);
+ SYMBOL_TYPE (sym)
+ = builtin_type (current_gdbarch)->nodebug_data_symbol;
+
attr = dwarf2_attr (die, DW_AT_const_value, cu);
if (attr)
{
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
+ case DW_TAG_set_type:
case DW_TAG_enumeration_type:
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
read_structure_type, and the correct name is saved in
the type. */
- if (cu->language == language_cplus)
+ if (cu->language == language_cplus
+ || cu->language == language_java)
{
struct type *type = SYMBOL_TYPE (sym);
}
{
- /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't
+ /* NOTE: carlton/2003-11-10: C++ and Java 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
struct pending **list_to_add;
list_to_add = (cu->list_in_scope == &file_symbols
- && cu->language == language_cplus
+ && (cu->language == language_cplus
+ || cu->language == language_java)
? &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)
+ defines a typedef for "foo". A Java class declaration also
+ defines a typedef for the class. Synthesize a typedef symbol
+ so that "ptype foo" works as expected. */
+ if (cu->language == language_cplus
+ || cu->language == language_java
+ || cu->language == language_ada)
{
struct symbol *typedef_sym = (struct symbol *)
obstack_alloc (&objfile->objfile_obstack,
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);
+ TYPE_NAME (SYMBOL_TYPE (sym)) = SYMBOL_SEARCH_NAME (sym);
add_symbol_to_list (typedef_sym, list_to_add);
}
}
if (processing_has_namespace_info
&& processing_current_prefix[0] != '\0')
{
- SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->objfile_obstack,
- processing_current_prefix,
- "::",
- name);
+ SYMBOL_LINKAGE_NAME (sym) = typename_concat (&objfile->objfile_obstack,
+ processing_current_prefix,
+ name, cu);
}
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
if (processing_has_namespace_info
&& processing_current_prefix[0] != '\0')
{
- SYMBOL_LINKAGE_NAME (sym) = obconcat (&objfile->objfile_obstack,
- processing_current_prefix,
- "::",
- name);
+ SYMBOL_LINKAGE_NAME (sym) = typename_concat (&objfile->objfile_obstack,
+ processing_current_prefix,
+ name, cu);
}
attr = dwarf2_attr (die, DW_AT_const_value, cu);
if (attr)
struct pending **list_to_add;
list_to_add = (cu->list_in_scope == &file_symbols
- && cu->language == language_cplus
+ && (cu->language == language_cplus
+ || cu->language == language_java)
? &global_symbols : cu->list_in_scope);
add_symbol_to_list (sym, list_to_add);
trash data, but since we must specifically ignore things
we don't recognize, there is nothing else we should do at
this point. */
- complaint (&symfile_complaints, "unsupported tag: '%s'",
+ complaint (&symfile_complaints, _("unsupported tag: '%s'"),
dwarf_tag_name (die->tag));
break;
}
cu_header->addr_size,
TYPE_LENGTH (SYMBOL_TYPE
(sym)));
- SYMBOL_VALUE_BYTES (sym) = (char *)
+ SYMBOL_VALUE_BYTES (sym) =
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. */
blk->size,
TYPE_LENGTH (SYMBOL_TYPE
(sym)));
- SYMBOL_VALUE_BYTES (sym) = (char *)
+ SYMBOL_VALUE_BYTES (sym) =
obstack_alloc (&objfile->objfile_obstack, blk->size);
memcpy (SYMBOL_VALUE_BYTES (sym), blk->data, blk->size);
SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
default:
complaint (&symfile_complaints,
- "unsupported const value attribute form: '%s'",
+ _("unsupported const value attribute form: '%s'"),
dwarf_form_name (attr->form));
SYMBOL_VALUE (sym) = 0;
SYMBOL_CLASS (sym) = LOC_CONST;
struct type *type;
struct attribute *type_attr;
struct die_info *type_die;
- unsigned int ref;
type_attr = dwarf2_attr (die, DW_AT_type, cu);
if (!type_attr)
return dwarf2_fundamental_type (cu->objfile, FT_VOID, cu);
}
else
- {
- 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, cu->objfile->name);
- return NULL;
- }
- }
+ type_die = follow_die_ref (die, type_attr, cu);
+
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]",
+ error (_("Dwarf Error: Problem turning type die at offset into gdb type [in module %s]"),
cu->objfile->name);
}
return type;
struct type *type = NULL;
struct attribute *type_attr;
struct die_info *type_die = NULL;
- unsigned int ref;
type_attr = dwarf2_attr (die, DW_AT_containing_type, cu);
if (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,
- cu->objfile->name);
- return NULL;
- }
+ type_die = follow_die_ref (die, type_attr, cu);
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]",
+ error (_("Dwarf Error: Problem turning containing type into gdb type [in module %s]"),
cu->objfile->name);
}
return type;
}
-#if 0
-static struct type *
-type_at_offset (unsigned int offset, struct dwarf2_cu *cu)
-{
- struct die_info *die;
- struct type *type;
-
- die = follow_die_ref (offset);
- if (!die)
- {
- error ("Dwarf Error: Cannot find type referent at offset %d.", offset);
- return NULL;
- }
- type = tag_type_to_type (die, cu);
- return type;
-}
-#endif
-
static struct type *
tag_type_to_type (struct die_info *die, struct dwarf2_cu *cu)
{
if (!die->type)
{
dump_die (die);
- error ("Dwarf Error: Cannot find type of die [in module %s]",
+ error (_("Dwarf Error: Cannot find type of die [in module %s]"),
cu->objfile->name);
}
return die->type;
case DW_TAG_array_type:
read_array_type (die, cu);
break;
+ case DW_TAG_set_type:
+ read_set_type (die, cu);
+ break;
case DW_TAG_pointer_type:
read_tag_pointer_type (die, cu);
break;
case DW_TAG_base_type:
read_base_type (die, cu);
break;
+ case DW_TAG_unspecified_type:
+ read_unspecified_type (die, cu);
+ break;
default:
- complaint (&symfile_complaints, "unexepected tag in read_type_die: '%s'",
+ complaint (&symfile_complaints, _("unexpected tag in read_type_die: '%s'"),
dwarf_tag_name (die->tag));
break;
}
{
struct die_info *parent;
- if (cu->language != language_cplus)
+ if (cu->language != language_cplus
+ && cu->language != language_java)
return NULL;
parent = die->parent;
{
int dummy;
char *parent_prefix = determine_prefix (parent, cu);
- char *retval = typename_concat (parent_prefix,
+ char *retval = typename_concat (NULL, parent_prefix,
namespace_name (parent, &dummy,
- cu));
+ cu),
+ cu);
xfree (parent_prefix);
return retval;
}
}
}
-/* 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. */
+/* Return a newly-allocated string formed by concatenating PREFIX and
+ SUFFIX with appropriate separator. If PREFIX or SUFFIX is NULL or empty, then
+ simply copy the SUFFIX or PREFIX, respectively. If OBS is non-null,
+ perform an obconcat, otherwise allocate storage for the result. The CU argument
+ is used to determine the language and hence, the appropriate separator. */
+
+#define MAX_SEP_LEN 2 /* sizeof ("::") */
static char *
-typename_concat (const char *prefix, const char *suffix)
+typename_concat (struct obstack *obs, const char *prefix, const char *suffix,
+ struct dwarf2_cu *cu)
{
- if (prefix == NULL || prefix[0] == '\0')
- return xstrdup (suffix);
+ char *sep;
+
+ if (suffix == NULL || suffix[0] == '\0' || prefix == NULL || prefix[0] == '\0')
+ sep = "";
+ else if (cu->language == language_java)
+ sep = ".";
+ else
+ sep = "::";
+
+ if (obs == NULL)
+ {
+ char *retval = xmalloc (strlen (prefix) + MAX_SEP_LEN + strlen (suffix) + 1);
+ retval[0] = '\0';
+
+ if (prefix)
+ {
+ strcpy (retval, prefix);
+ strcat (retval, sep);
+ }
+ if (suffix)
+ strcat (retval, suffix);
+
+ return retval;
+ }
else
{
- char *retval = xmalloc (strlen (prefix) + 2 + strlen (suffix) + 1);
-
- strcpy (retval, prefix);
- strcat (retval, "::");
- strcat (retval, suffix);
-
- return retval;
+ /* We have an obstack. */
+ return obconcat (obs, prefix, sep, suffix);
}
}
type = dwarf2_fundamental_type (objfile, FT_FLOAT, cu);
}
return type;
+ case DW_ATE_decimal_float:
+ if (size == 16)
+ type = dwarf2_fundamental_type (objfile, FT_DBL_PREC_DECFLOAT, cu);
+ else if (size == 8)
+ type = dwarf2_fundamental_type (objfile, FT_EXT_PREC_DECFLOAT, cu);
+ else
+ type = dwarf2_fundamental_type (objfile, FT_DECFLOAT, cu);
+ return type;
case DW_ATE_signed:
switch (size)
{
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;
+ return follow_die_ref (die, attr, cu);
}
/* Convert a DIE tag into its string name. */
return "DW_TAG_partial_unit";
case DW_TAG_imported_unit:
return "DW_TAG_imported_unit";
+ case DW_TAG_condition:
+ return "DW_TAG_condition";
+ case DW_TAG_shared_type:
+ return "DW_TAG_shared_type";
case DW_TAG_MIPS_loop:
return "DW_TAG_MIPS_loop";
+ case DW_TAG_HP_array_descriptor:
+ return "DW_TAG_HP_array_descriptor";
case DW_TAG_format_label:
return "DW_TAG_format_label";
case DW_TAG_function_template:
return "DW_TAG_function_template";
case DW_TAG_class_template:
return "DW_TAG_class_template";
+ case DW_TAG_GNU_BINCL:
+ return "DW_TAG_GNU_BINCL";
+ case DW_TAG_GNU_EINCL:
+ return "DW_TAG_GNU_EINCL";
+ case DW_TAG_upc_shared_type:
+ return "DW_TAG_upc_shared_type";
+ case DW_TAG_upc_strict_type:
+ return "DW_TAG_upc_strict_type";
+ case DW_TAG_upc_relaxed_type:
+ return "DW_TAG_upc_relaxed_type";
+ case DW_TAG_PGI_kanji_type:
+ return "DW_TAG_PGI_kanji_type";
+ case DW_TAG_PGI_interface_block:
+ return "DW_TAG_PGI_interface_block";
default:
return "DW_TAG_<unknown>";
}
return "DW_AT_virtuality";
case DW_AT_vtable_elem_location:
return "DW_AT_vtable_elem_location";
+ /* DWARF 3 values. */
case DW_AT_allocated:
return "DW_AT_allocated";
case DW_AT_associated:
return "DW_AT_call_file";
case DW_AT_call_line:
return "DW_AT_call_line";
+ case DW_AT_description:
+ return "DW_AT_description";
+ case DW_AT_binary_scale:
+ return "DW_AT_binary_scale";
+ case DW_AT_decimal_scale:
+ return "DW_AT_decimal_scale";
+ case DW_AT_small:
+ return "DW_AT_small";
+ case DW_AT_decimal_sign:
+ return "DW_AT_decimal_sign";
+ case DW_AT_digit_count:
+ return "DW_AT_digit_count";
+ case DW_AT_picture_string:
+ return "DW_AT_picture_string";
+ case DW_AT_mutable:
+ return "DW_AT_mutable";
+ case DW_AT_threads_scaled:
+ return "DW_AT_threads_scaled";
+ case DW_AT_explicit:
+ return "DW_AT_explicit";
+ case DW_AT_object_pointer:
+ return "DW_AT_object_pointer";
+ case DW_AT_endianity:
+ return "DW_AT_endianity";
+ case DW_AT_elemental:
+ return "DW_AT_elemental";
+ case DW_AT_pure:
+ return "DW_AT_pure";
+ case DW_AT_recursive:
+ return "DW_AT_recursive";
#ifdef MIPS
+ /* SGI/MIPS extensions. */
case DW_AT_MIPS_fde:
return "DW_AT_MIPS_fde";
case DW_AT_MIPS_loop_begin:
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";
-
+ case DW_AT_MIPS_stride:
+ return "DW_AT_MIPS_stride";
+ case DW_AT_MIPS_abstract_name:
+ return "DW_AT_MIPS_abstract_name";
+ case DW_AT_MIPS_clone_origin:
+ return "DW_AT_MIPS_clone_origin";
+ case DW_AT_MIPS_has_inlines:
+ return "DW_AT_MIPS_has_inlines";
+#endif
+ /* HP extensions. */
+ case DW_AT_HP_block_index:
+ return "DW_AT_HP_block_index";
+ case DW_AT_HP_unmodifiable:
+ return "DW_AT_HP_unmodifiable";
+ case DW_AT_HP_actuals_stmt_list:
+ return "DW_AT_HP_actuals_stmt_list";
+ case DW_AT_HP_proc_per_section:
+ return "DW_AT_HP_proc_per_section";
+ case DW_AT_HP_raw_data_ptr:
+ return "DW_AT_HP_raw_data_ptr";
+ case DW_AT_HP_pass_by_reference:
+ return "DW_AT_HP_pass_by_reference";
+ case DW_AT_HP_opt_level:
+ return "DW_AT_HP_opt_level";
+ case DW_AT_HP_prof_version_id:
+ return "DW_AT_HP_prof_version_id";
+ case DW_AT_HP_opt_flags:
+ return "DW_AT_HP_opt_flags";
+ case DW_AT_HP_cold_region_low_pc:
+ return "DW_AT_HP_cold_region_low_pc";
+ case DW_AT_HP_cold_region_high_pc:
+ return "DW_AT_HP_cold_region_high_pc";
+ case DW_AT_HP_all_variables_modifiable:
+ return "DW_AT_HP_all_variables_modifiable";
+ case DW_AT_HP_linkage_name:
+ return "DW_AT_HP_linkage_name";
+ case DW_AT_HP_prof_flags:
+ return "DW_AT_HP_prof_flags";
+ /* GNU extensions. */
case DW_AT_sf_names:
return "DW_AT_sf_names";
case DW_AT_src_info:
return "DW_AT_body_end";
case DW_AT_GNU_vector:
return "DW_AT_GNU_vector";
+ /* VMS extensions. */
+ case DW_AT_VMS_rtnbeg_pd_address:
+ return "DW_AT_VMS_rtnbeg_pd_address";
+ /* UPC extension. */
+ case DW_AT_upc_threads_scaled:
+ return "DW_AT_upc_threads_scaled";
+ /* PGI (STMicroelectronics) extensions. */
+ case DW_AT_PGI_lbase:
+ return "DW_AT_PGI_lbase";
+ case DW_AT_PGI_soffset:
+ return "DW_AT_PGI_soffset";
+ case DW_AT_PGI_lstride:
+ return "DW_AT_PGI_lstride";
default:
return "DW_AT_<unknown>";
}
return "DW_OP_xderef_size";
case DW_OP_nop:
return "DW_OP_nop";
- /* DWARF 3 extensions. */
+ /* DWARF 3 extensions. */
case DW_OP_push_object_address:
return "DW_OP_push_object_address";
case DW_OP_call2:
return "DW_OP_call4";
case DW_OP_call_ref:
return "DW_OP_call_ref";
- /* GNU extensions. */
+ /* GNU extensions. */
+ case DW_OP_form_tls_address:
+ return "DW_OP_form_tls_address";
+ case DW_OP_call_frame_cfa:
+ return "DW_OP_call_frame_cfa";
+ case DW_OP_bit_piece:
+ return "DW_OP_bit_piece";
case DW_OP_GNU_push_tls_address:
return "DW_OP_GNU_push_tls_address";
+ case DW_OP_GNU_uninit:
+ return "DW_OP_GNU_uninit";
+ /* HP extensions. */
+ case DW_OP_HP_is_value:
+ return "DW_OP_HP_is_value";
+ case DW_OP_HP_fltconst4:
+ return "DW_OP_HP_fltconst4";
+ case DW_OP_HP_fltconst8:
+ return "DW_OP_HP_fltconst8";
+ case DW_OP_HP_mod_range:
+ return "DW_OP_HP_mod_range";
+ case DW_OP_HP_unmod_range:
+ return "DW_OP_HP_unmod_range";
+ case DW_OP_HP_tls:
+ return "DW_OP_HP_tls";
default:
return "OP_<unknown>";
}
{
switch (enc)
{
+ case DW_ATE_void:
+ return "DW_ATE_void";
case DW_ATE_address:
return "DW_ATE_address";
case DW_ATE_boolean:
return "DW_ATE_unsigned";
case DW_ATE_unsigned_char:
return "DW_ATE_unsigned_char";
+ /* DWARF 3. */
case DW_ATE_imaginary_float:
return "DW_ATE_imaginary_float";
+ case DW_ATE_packed_decimal:
+ return "DW_ATE_packed_decimal";
+ case DW_ATE_numeric_string:
+ return "DW_ATE_numeric_string";
+ case DW_ATE_edited:
+ return "DW_ATE_edited";
+ case DW_ATE_signed_fixed:
+ return "DW_ATE_signed_fixed";
+ case DW_ATE_unsigned_fixed:
+ return "DW_ATE_unsigned_fixed";
+ case DW_ATE_decimal_float:
+ return "DW_ATE_decimal_float";
+ /* HP extensions. */
+ case DW_ATE_HP_float80:
+ return "DW_ATE_HP_float80";
+ case DW_ATE_HP_complex_float80:
+ return "DW_ATE_HP_complex_float80";
+ case DW_ATE_HP_float128:
+ return "DW_ATE_HP_float128";
+ case DW_ATE_HP_complex_float128:
+ return "DW_ATE_HP_complex_float128";
+ case DW_ATE_HP_floathpintel:
+ return "DW_ATE_HP_floathpintel";
+ case DW_ATE_HP_imaginary_float80:
+ return "DW_ATE_HP_imaginary_float80";
+ case DW_ATE_HP_imaginary_float128:
+ return "DW_ATE_HP_imaginary_float128";
default:
return "DW_ATE_<unknown>";
}
return "DW_CFA_def_cfa_register";
case DW_CFA_def_cfa_offset:
return "DW_CFA_def_cfa_offset";
-
- /* DWARF 3 */
+ /* DWARF 3. */
case DW_CFA_def_cfa_expression:
return "DW_CFA_def_cfa_expression";
case DW_CFA_expression:
return "DW_CFA_def_cfa_sf";
case DW_CFA_def_cfa_offset_sf:
return "DW_CFA_def_cfa_offset_sf";
-
- /* SGI/MIPS specific */
+ case DW_CFA_val_offset:
+ return "DW_CFA_val_offset";
+ case DW_CFA_val_offset_sf:
+ return "DW_CFA_val_offset_sf";
+ case DW_CFA_val_expression:
+ return "DW_CFA_val_expression";
+ /* SGI/MIPS specific. */
case DW_CFA_MIPS_advance_loc8:
return "DW_CFA_MIPS_advance_loc8";
-
- /* GNU extensions */
+ /* GNU extensions. */
case DW_CFA_GNU_window_save:
return "DW_CFA_GNU_window_save";
case DW_CFA_GNU_args_size:
return "DW_CFA_GNU_args_size";
case DW_CFA_GNU_negative_offset_extended:
return "DW_CFA_GNU_negative_offset_extended";
-
default:
return "DW_CFA_<unknown>";
}
case DW_FORM_ref_addr:
case DW_FORM_addr:
fprintf_unfiltered (gdb_stderr, "address: ");
- print_address_numeric (DW_ADDR (&die->attrs[i]), 1, gdb_stderr);
+ deprecated_print_address_numeric (DW_ADDR (&die->attrs[i]), 1, gdb_stderr);
break;
case DW_FORM_block2:
case DW_FORM_block4:
case DW_FORM_block1:
fprintf_unfiltered (gdb_stderr, "block: size %d", DW_BLOCK (&die->attrs[i])->size);
break;
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ fprintf_unfiltered (gdb_stderr, "constant ref: %ld (adjusted)",
+ (long) (DW_ADDR (&die->attrs[i])));
+ break;
case DW_FORM_data1:
case DW_FORM_data2:
case DW_FORM_data4:
case DW_FORM_data8:
- case DW_FORM_ref1:
- case DW_FORM_ref2:
- case DW_FORM_ref4:
case DW_FORM_udata:
case DW_FORM_sdata:
fprintf_unfiltered (gdb_stderr, "constant: %ld", DW_UNSND (&die->attrs[i]));
}
static void
-store_in_ref_table (unsigned int offset, struct die_info *die)
+store_in_ref_table (unsigned int offset, struct die_info *die,
+ struct dwarf2_cu *cu)
{
int h;
struct die_info *old;
h = (offset % REF_HASH_SIZE);
- old = die_ref_table[h];
+ old = cu->die_ref_table[h];
die->next_ref = old;
- die_ref_table[h] = die;
-}
-
-
-static void
-dwarf2_empty_hash_tables (void)
-{
- memset (die_ref_table, 0, sizeof (die_ref_table));
+ cu->die_ref_table[h] = die;
}
static unsigned int
switch (attr->form)
{
case DW_FORM_ref_addr:
- result = DW_ADDR (attr);
- break;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
- result = cu->header.offset + DW_UNSND (attr);
+ result = DW_ADDR (attr);
break;
default:
complaint (&symfile_complaints,
- "unsupported die ref attribute form: '%s'",
+ _("unsupported die ref attribute form: '%s'"),
dwarf_form_name (attr->form));
}
return result;
return DW_UNSND (attr);
else
{
- complaint (&symfile_complaints, "Attribute value is not a constant (%s)",
+ 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)
+follow_die_ref (struct die_info *src_die, struct attribute *attr,
+ struct dwarf2_cu *cu)
{
struct die_info *die;
+ unsigned int offset;
int h;
+ struct die_info temp_die;
+ struct dwarf2_cu *target_cu;
+
+ offset = dwarf2_get_ref_die_offset (attr, cu);
+
+ if (DW_ADDR (attr) < cu->header.offset
+ || DW_ADDR (attr) >= cu->header.offset + cu->header.length)
+ {
+ struct dwarf2_per_cu_data *per_cu;
+ per_cu = dwarf2_find_containing_comp_unit (DW_ADDR (attr),
+ cu->objfile);
+ target_cu = per_cu->cu;
+ }
+ else
+ target_cu = cu;
h = (offset % REF_HASH_SIZE);
- die = die_ref_table[h];
+ die = target_cu->die_ref_table[h];
while (die)
{
if (die->offset == offset)
- {
- return die;
- }
+ return die;
die = die->next_ref;
}
+
+ error (_("Dwarf Error: Cannot find DIE at 0x%lx referenced from DIE "
+ "at 0x%lx [in module %s]"),
+ (long) src_die->offset, (long) offset, cu->objfile->name);
+
return NULL;
}
{
if (typeid < 0 || typeid >= FT_NUM_MEMBERS)
{
- error ("Dwarf Error: internal error - invalid fundamental type id %d [in module %s]",
+ error (_("Dwarf Error: internal error - invalid fundamental type id %d [in module %s]"),
typeid, objfile->name);
}
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.
-
Note that stack[0] is unused except as a default error return.
Note that stack overflow is not yet handled. */
struct comp_unit_head *cu_header = &cu->header;
int i;
int size = blk->size;
- char *data = blk->data;
+ gdb_byte *data = blk->data;
CORE_ADDR stack[64];
int stacki;
unsigned int bytes_read, unsnd;
- unsigned char op;
+ gdb_byte op;
i = 0;
stacki = 0;
stack[stacki] = 0;
- isreg = 0;
while (i < size)
{
case DW_OP_reg29:
case DW_OP_reg30:
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:
- isreg = 1;
unsnd = read_unsigned_leb128 (NULL, (data + i), &bytes_read);
i += bytes_read;
stack[++stacki] = unsnd;
dwarf2_complex_location_expr_complaint ();
break;
+ case DW_OP_GNU_uninit:
+ break;
+
default:
- complaint (&symfile_complaints, "unsupported stack op: '%s'",
+ complaint (&symfile_complaints, _("unsupported stack op: '%s'"),
dwarf_stack_op_name (op));
return (stack[stacki]);
}
/* memory allocation interface */
-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 char *
file_full_name (int file, struct line_header *lh, const char *comp_dir)
{
- struct file_entry *fe = &lh->file_names[file - 1];
+ /* Is the file number a valid index into the line header's file name
+ table? Remember that file numbers start with one, not zero. */
+ if (1 <= file && file <= lh->num_file_names)
+ {
+ struct file_entry *fe = &lh->file_names[file - 1];
- if (IS_ABSOLUTE_PATH (fe->name))
- return xstrdup (fe->name);
+ if (IS_ABSOLUTE_PATH (fe->name))
+ return xstrdup (fe->name);
+ else
+ {
+ const char *dir;
+ int dir_len;
+ char *full_name;
+
+ if (fe->dir_index)
+ dir = lh->include_dirs[fe->dir_index - 1];
+ else
+ dir = comp_dir;
+
+ if (dir)
+ {
+ dir_len = strlen (dir);
+ full_name = xmalloc (dir_len + 1 + strlen (fe->name) + 1);
+ strcpy (full_name, dir);
+ full_name[dir_len] = '/';
+ strcpy (full_name + dir_len + 1, fe->name);
+ return full_name;
+ }
+ else
+ return xstrdup (fe->name);
+ }
+ }
else
{
- const char *dir;
- int dir_len;
- char *full_name;
+ /* The compiler produced a bogus file number. We can at least
+ record the macro definitions made in the file, even if we
+ won't be able to find the file by name. */
+ char fake_name[80];
+ sprintf (fake_name, "<bad macro file number %d>", file);
- if (fe->dir_index)
- dir = lh->include_dirs[fe->dir_index - 1];
- else
- dir = comp_dir;
+ complaint (&symfile_complaints,
+ _("bad file number in macro information (%d)"),
+ file);
- if (dir)
- {
- dir_len = strlen (dir);
- full_name = xmalloc (dir_len + 1 + strlen (fe->name) + 1);
- strcpy (full_name, dir);
- full_name[dir_len] = '/';
- strcpy (full_name + dir_len + 1, fe->name);
- return full_name;
- }
- else
- return xstrdup (fe->name);
+ return xstrdup (fake_name);
}
}
if (*p == ' ')
{
complaint (&symfile_complaints,
- "macro definition contains spaces in formal argument list:\n`%s'",
+ _("macro definition contains spaces in formal argument list:\n`%s'"),
body);
while (*p == ' ')
char *comp_dir, bfd *abfd,
struct dwarf2_cu *cu)
{
- char *mac_ptr, *mac_end;
+ gdb_byte *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");
+ 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 (;;)
{
case DW_MACINFO_define:
case DW_MACINFO_undef:
{
- int bytes_read;
+ unsigned int bytes_read;
int line;
char *body;
if (! current_file)
complaint (&symfile_complaints,
- "debug info gives macro %s outside of any file: %s",
+ _("debug info gives macro %s outside of any file: %s"),
macinfo_type ==
DW_MACINFO_define ? "definition" : macinfo_type ==
DW_MACINFO_undef ? "undefinition" :
case DW_MACINFO_start_file:
{
- int bytes_read;
+ unsigned int bytes_read;
int line, file;
line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
case DW_MACINFO_end_file:
if (! current_file)
complaint (&symfile_complaints,
- "macro debug info has an unmatched `close_file' directive");
+ _("macro debug info has an unmatched `close_file' directive"));
else
{
current_file = current_file->included_by;
next_type = read_1_byte (abfd, mac_ptr);
if (next_type != 0)
complaint (&symfile_complaints,
- "no terminating 0-type entry for macros in `.debug_macinfo' section");
+ _("no terminating 0-type entry for macros in `.debug_macinfo' section"));
return;
}
case DW_MACINFO_vendor_ext:
{
- int bytes_read;
+ unsigned int bytes_read;
int constant;
char *string;
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 objfile *objfile = cu->objfile;
+
+ /* Save the master objfile, so that we can report and look up the
+ correct file containing this variable. */
+ if (objfile->separate_debug_objfile_backlink)
+ objfile = objfile->separate_debug_objfile_backlink;
+
+ if ((attr->form == DW_FORM_data4 || attr->form == DW_FORM_data8)
+ /* ".debug_loc" may not exist at all, or the offset may be outside
+ the section. If so, fall through to the complaint in the
+ other branch. */
+ && DW_UNSND (attr) < dwarf2_per_objfile->loc_size)
{
struct dwarf2_loclist_baton *baton;
baton = obstack_alloc (&cu->objfile->objfile_obstack,
sizeof (struct dwarf2_loclist_baton));
- baton->objfile = cu->objfile;
+ baton->objfile = objfile;
/* We don't know how long the location list is, but make sure we
don't run off the edge of the section. */
- baton->size = dwarf_loc_size - DW_UNSND (attr);
- baton->data = dwarf_loc_buffer + DW_UNSND (attr);
+ baton->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.");
+ _("Location list used without specifying the CU base address."));
SYMBOL_OPS (sym) = &dwarf2_loclist_funcs;
SYMBOL_LOCATION_BATON (sym) = baton;
baton = obstack_alloc (&cu->objfile->objfile_obstack,
sizeof (struct dwarf2_locexpr_baton));
- baton->objfile = cu->objfile;
+ baton->objfile = objfile;
if (attr_form_is_block (attr))
{
/* Note that we're just copying the block's data pointer
here, not the actual data. We're still pointing into the
- dwarf_info_buffer for SYM's objfile; right now we never
- release that buffer, but when we do clean up properly
- this may need to change. */
+ 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;
}
SYMBOL_LOCATION_BATON (sym) = baton;
}
}
+
+/* Locate the compilation unit from CU's objfile which contains the
+ DIE at OFFSET. Raises an error on failure. */
+
+static struct dwarf2_per_cu_data *
+dwarf2_find_containing_comp_unit (unsigned long offset,
+ struct objfile *objfile)
+{
+ struct dwarf2_per_cu_data *this_cu;
+ int low, high;
+
+ low = 0;
+ high = dwarf2_per_objfile->n_comp_units - 1;
+ while (high > low)
+ {
+ int mid = low + (high - low) / 2;
+ if (dwarf2_per_objfile->all_comp_units[mid]->offset >= offset)
+ high = mid;
+ else
+ low = mid + 1;
+ }
+ gdb_assert (low == high);
+ if (dwarf2_per_objfile->all_comp_units[low]->offset > offset)
+ {
+ if (low == 0)
+ error (_("Dwarf Error: could not find partial DIE containing "
+ "offset 0x%lx [in module %s]"),
+ (long) offset, bfd_get_filename (objfile->obfd));
+
+ gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->offset <= offset);
+ return dwarf2_per_objfile->all_comp_units[low-1];
+ }
+ else
+ {
+ this_cu = dwarf2_per_objfile->all_comp_units[low];
+ if (low == dwarf2_per_objfile->n_comp_units - 1
+ && offset >= this_cu->offset + this_cu->length)
+ error (_("invalid dwarf2 offset %ld"), offset);
+ gdb_assert (offset < this_cu->offset + this_cu->length);
+ return this_cu;
+ }
+}
+
+/* Locate the compilation unit from OBJFILE which is located at exactly
+ OFFSET. Raises an error on failure. */
+
+static struct dwarf2_per_cu_data *
+dwarf2_find_comp_unit (unsigned long offset, struct objfile *objfile)
+{
+ struct dwarf2_per_cu_data *this_cu;
+ this_cu = dwarf2_find_containing_comp_unit (offset, objfile);
+ if (this_cu->offset != offset)
+ error (_("no compilation unit with offset %ld."), offset);
+ return this_cu;
+}
+
+/* Release one cached compilation unit, CU. We unlink it from the tree
+ of compilation units, but we don't remove it from the read_in_chain;
+ the caller is responsible for that. */
+
+static void
+free_one_comp_unit (void *data)
+{
+ struct dwarf2_cu *cu = data;
+
+ if (cu->per_cu != NULL)
+ cu->per_cu->cu = NULL;
+ cu->per_cu = NULL;
+
+ obstack_free (&cu->comp_unit_obstack, NULL);
+ if (cu->dies)
+ free_die_list (cu->dies);
+
+ xfree (cu);
+}
+
+/* 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 be
+ sure to unlink it from the cache. Also release any associated storage
+ and perform cache maintenance.
+
+ 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;
+
+ if (cu->per_cu != NULL)
+ {
+ /* This compilation unit is on the stack in our caller, so we
+ should not xfree it. Just unlink it. */
+ cu->per_cu->cu = NULL;
+ cu->per_cu = NULL;
+
+ /* If we had a per-cu pointer, then we may have other compilation
+ units loaded, so age them now. */
+ age_cached_comp_units ();
+ }
+}
+
+/* Free all cached compilation units. */
+
+static void
+free_cached_comp_units (void *data)
+{
+ struct dwarf2_per_cu_data *per_cu, **last_chain;
+
+ per_cu = dwarf2_per_objfile->read_in_chain;
+ last_chain = &dwarf2_per_objfile->read_in_chain;
+ while (per_cu != NULL)
+ {
+ struct dwarf2_per_cu_data *next_cu;
+
+ next_cu = per_cu->cu->read_in_chain;
+
+ free_one_comp_unit (per_cu->cu);
+ *last_chain = next_cu;
+
+ per_cu = next_cu;
+ }
+}
+
+/* Increase the age counter on each cached compilation unit, and free
+ any that are too old. */
+
+static void
+age_cached_comp_units (void)
+{
+ struct dwarf2_per_cu_data *per_cu, **last_chain;
+
+ dwarf2_clear_marks (dwarf2_per_objfile->read_in_chain);
+ per_cu = dwarf2_per_objfile->read_in_chain;
+ while (per_cu != NULL)
+ {
+ per_cu->cu->last_used ++;
+ if (per_cu->cu->last_used <= dwarf2_max_cache_age)
+ dwarf2_mark (per_cu->cu);
+ per_cu = per_cu->cu->read_in_chain;
+ }
+
+ per_cu = dwarf2_per_objfile->read_in_chain;
+ last_chain = &dwarf2_per_objfile->read_in_chain;
+ while (per_cu != NULL)
+ {
+ struct dwarf2_per_cu_data *next_cu;
+
+ next_cu = per_cu->cu->read_in_chain;
+
+ if (!per_cu->cu->mark)
+ {
+ free_one_comp_unit (per_cu->cu);
+ *last_chain = next_cu;
+ }
+ else
+ last_chain = &per_cu->cu->read_in_chain;
+
+ per_cu = next_cu;
+ }
+}
+
+/* Remove a single compilation unit from the cache. */
+
+static void
+free_one_cached_comp_unit (void *target_cu)
+{
+ struct dwarf2_per_cu_data *per_cu, **last_chain;
+
+ per_cu = dwarf2_per_objfile->read_in_chain;
+ last_chain = &dwarf2_per_objfile->read_in_chain;
+ while (per_cu != NULL)
+ {
+ struct dwarf2_per_cu_data *next_cu;
+
+ next_cu = per_cu->cu->read_in_chain;
+
+ if (per_cu->cu == target_cu)
+ {
+ free_one_comp_unit (per_cu->cu);
+ *last_chain = next_cu;
+ break;
+ }
+ else
+ last_chain = &per_cu->cu->read_in_chain;
+
+ per_cu = next_cu;
+ }
+}
+
+/* Release all extra memory associated with OBJFILE. */
+
+void
+dwarf2_free_objfile (struct objfile *objfile)
+{
+ dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
+
+ if (dwarf2_per_objfile == NULL)
+ return;
+
+ /* Cached DIE trees use xmalloc and the comp_unit_obstack. */
+ free_cached_comp_units (NULL);
+
+ /* Everything else should be on the objfile obstack. */
+}
+
+/* A pair of DIE offset and GDB type pointer. We store these
+ in a hash table separate from the DIEs, and preserve them
+ when the DIEs are flushed out of cache. */
+
+struct dwarf2_offset_and_type
+{
+ unsigned int offset;
+ struct type *type;
+};
+
+/* Hash function for a dwarf2_offset_and_type. */
+
+static hashval_t
+offset_and_type_hash (const void *item)
+{
+ const struct dwarf2_offset_and_type *ofs = item;
+ return ofs->offset;
+}
+
+/* Equality function for a dwarf2_offset_and_type. */
+
+static int
+offset_and_type_eq (const void *item_lhs, const void *item_rhs)
+{
+ const struct dwarf2_offset_and_type *ofs_lhs = item_lhs;
+ const struct dwarf2_offset_and_type *ofs_rhs = item_rhs;
+ return ofs_lhs->offset == ofs_rhs->offset;
+}
+
+/* Set the type associated with DIE to TYPE. Save it in CU's hash
+ table if necessary. */
+
+static void
+set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
+{
+ struct dwarf2_offset_and_type **slot, ofs;
+
+ die->type = type;
+
+ if (cu->per_cu == NULL)
+ return;
+
+ if (cu->per_cu->type_hash == NULL)
+ cu->per_cu->type_hash
+ = htab_create_alloc_ex (cu->header.length / 24,
+ offset_and_type_hash,
+ offset_and_type_eq,
+ NULL,
+ &cu->objfile->objfile_obstack,
+ hashtab_obstack_allocate,
+ dummy_obstack_deallocate);
+
+ ofs.offset = die->offset;
+ ofs.type = type;
+ slot = (struct dwarf2_offset_and_type **)
+ htab_find_slot_with_hash (cu->per_cu->type_hash, &ofs, ofs.offset, INSERT);
+ *slot = obstack_alloc (&cu->objfile->objfile_obstack, sizeof (**slot));
+ **slot = ofs;
+}
+
+/* Find the type for DIE in TYPE_HASH, or return NULL if DIE does not
+ have a saved type. */
+
+static struct type *
+get_die_type (struct die_info *die, htab_t type_hash)
+{
+ struct dwarf2_offset_and_type *slot, ofs;
+
+ ofs.offset = die->offset;
+ slot = htab_find_with_hash (type_hash, &ofs, ofs.offset);
+ if (slot)
+ return slot->type;
+ else
+ return NULL;
+}
+
+/* Restore the types of the DIE tree starting at START_DIE from the hash
+ table saved in CU. */
+
+static void
+reset_die_and_siblings_types (struct die_info *start_die, struct dwarf2_cu *cu)
+{
+ struct die_info *die;
+
+ if (cu->per_cu->type_hash == NULL)
+ return;
+
+ for (die = start_die; die != NULL; die = die->sibling)
+ {
+ die->type = get_die_type (die, cu->per_cu->type_hash);
+ if (die->child != NULL)
+ reset_die_and_siblings_types (die->child, cu);
+ }
+}
+
+/* Set the mark field in CU and in every other compilation unit in the
+ cache that we must keep because we are keeping CU. */
+
+/* Add a dependence relationship from CU to REF_PER_CU. */
+
+static void
+dwarf2_add_dependence (struct dwarf2_cu *cu,
+ struct dwarf2_per_cu_data *ref_per_cu)
+{
+ void **slot;
+
+ if (cu->dependencies == NULL)
+ cu->dependencies
+ = htab_create_alloc_ex (5, htab_hash_pointer, htab_eq_pointer,
+ NULL, &cu->comp_unit_obstack,
+ hashtab_obstack_allocate,
+ dummy_obstack_deallocate);
+
+ slot = htab_find_slot (cu->dependencies, ref_per_cu, INSERT);
+ if (*slot == NULL)
+ *slot = ref_per_cu;
+}
+
+/* Set the mark field in CU and in every other compilation unit in the
+ cache that we must keep because we are keeping CU. */
+
+static int
+dwarf2_mark_helper (void **slot, void *data)
+{
+ struct dwarf2_per_cu_data *per_cu;
+
+ per_cu = (struct dwarf2_per_cu_data *) *slot;
+ if (per_cu->cu->mark)
+ return 1;
+ per_cu->cu->mark = 1;
+
+ if (per_cu->cu->dependencies != NULL)
+ htab_traverse (per_cu->cu->dependencies, dwarf2_mark_helper, NULL);
+
+ return 1;
+}
+
+static void
+dwarf2_mark (struct dwarf2_cu *cu)
+{
+ if (cu->mark)
+ return;
+ cu->mark = 1;
+ if (cu->dependencies != NULL)
+ htab_traverse (cu->dependencies, dwarf2_mark_helper, NULL);
+}
+
+static void
+dwarf2_clear_marks (struct dwarf2_per_cu_data *per_cu)
+{
+ while (per_cu)
+ {
+ per_cu->cu->mark = 0;
+ per_cu = per_cu->cu->read_in_chain;
+ }
+}
+
+/* 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;
+}
+
+static struct cmd_list_element *set_dwarf2_cmdlist;
+static struct cmd_list_element *show_dwarf2_cmdlist;
+
+static void
+set_dwarf2_cmd (char *args, int from_tty)
+{
+ help_list (set_dwarf2_cmdlist, "maintenance set dwarf2 ", -1, gdb_stdout);
+}
+
+static void
+show_dwarf2_cmd (char *args, int from_tty)
+{
+ cmd_show_list (show_dwarf2_cmdlist, from_tty, "");
+}
+
+void _initialize_dwarf2_read (void);
+
+void
+_initialize_dwarf2_read (void)
+{
+ dwarf2_objfile_data_key = register_objfile_data ();
+
+ add_prefix_cmd ("dwarf2", class_maintenance, set_dwarf2_cmd, _("\
+Set DWARF 2 specific variables.\n\
+Configure DWARF 2 variables such as the cache size"),
+ &set_dwarf2_cmdlist, "maintenance set dwarf2 ",
+ 0/*allow-unknown*/, &maintenance_set_cmdlist);
+
+ add_prefix_cmd ("dwarf2", class_maintenance, show_dwarf2_cmd, _("\
+Show DWARF 2 specific variables\n\
+Show DWARF 2 variables such as the cache size"),
+ &show_dwarf2_cmdlist, "maintenance show dwarf2 ",
+ 0/*allow-unknown*/, &maintenance_show_cmdlist);
+
+ add_setshow_zinteger_cmd ("max-cache-age", class_obscure,
+ &dwarf2_max_cache_age, _("\
+Set the upper bound on the age of cached dwarf2 compilation units."), _("\
+Show the upper bound on the age of cached dwarf2 compilation units."), _("\
+A higher limit means that cached compilation units will be stored\n\
+in memory longer, and more total memory will be used. Zero disables\n\
+caching, which can slow down startup."),
+ NULL,
+ show_dwarf2_max_cache_age,
+ &set_dwarf2_cmdlist,
+ &show_dwarf2_cmdlist);
+}