#include "c-lang.h"
#include "go-lang.h"
#include "valprint.h"
+#include "gdbcore.h" /* for gnutarget */
#include <ctype.h>
#include <fcntl.h>
const char *constant_pool;
};
+typedef struct dwarf2_per_cu_data *dwarf2_per_cu_ptr;
+DEF_VEC_P (dwarf2_per_cu_ptr);
+
/* Collection of data recorded per objfile.
This hangs off of dwarf2_objfile_data_key. */
struct dwarf2_section_info macro;
struct dwarf2_section_info str;
struct dwarf2_section_info ranges;
+ struct dwarf2_section_info addr;
struct dwarf2_section_info frame;
struct dwarf2_section_info eh_frame;
struct dwarf2_section_info gdb_index;
This is NULL if the .debug_types section hasn't been read in yet. */
htab_t signatured_types;
+ /* A table mapping DW_AT_dwo_name values to struct dwo_file objects.
+ This is NULL if the table hasn't been allocated yet. */
+ htab_t dwo_files;
+
/* A flag indicating wether this objfile has a section loaded at a
VMA of 0. */
int has_section_at_zero;
This is NULL if not allocated yet.
The mapping is done via (CU/TU signature + DIE offset) -> type. */
htab_t die_type_hash;
+
+ /* The CUs we recently read. */
+ VEC (dwarf2_per_cu_ptr) *just_read_cus;
};
static struct dwarf2_per_objfile *dwarf2_per_objfile;
{ ".debug_str", ".zdebug_str" },
{ ".debug_ranges", ".zdebug_ranges" },
{ ".debug_types", ".zdebug_types" },
+ { ".debug_addr", ".zdebug_addr" },
{ ".debug_frame", ".zdebug_frame" },
{ ".eh_frame", NULL },
{ ".gdb_index", ".zgdb_index" },
23
};
+/* List of DWO sections. */
+
+static const struct dwo_section_names
+{
+ struct dwarf2_section_names abbrev_dwo;
+ struct dwarf2_section_names info_dwo;
+ struct dwarf2_section_names line_dwo;
+ struct dwarf2_section_names loc_dwo;
+ struct dwarf2_section_names str_dwo;
+ struct dwarf2_section_names str_offsets_dwo;
+ struct dwarf2_section_names types_dwo;
+}
+dwo_section_names =
+{
+ { ".debug_abbrev.dwo", ".zdebug_abbrev.dwo" },
+ { ".debug_info.dwo", ".zdebug_info.dwo" },
+ { ".debug_line.dwo", ".zdebug_line.dwo" },
+ { ".debug_loc.dwo", ".zdebug_loc.dwo" },
+ { ".debug_str.dwo", ".zdebug_str.dwo" },
+ { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo" },
+ { ".debug_types.dwo", ".zdebug_types.dwo" },
+};
+
/* local data types */
/* We hold several abbreviation tables in memory at the same time. */
/* To be copied to symtab->call_site_htab. */
htab_t call_site_htab;
+ /* Non-NULL if this CU came from a DWO file. */
+ struct dwo_unit *dwo_unit;
+
+ /* The DW_AT_addr_base attribute if present, zero otherwise
+ (zero is a valid value though).
+ Note this value comes from the stub CU/TU's DIE. */
+ ULONGEST addr_base;
+
/* Mark used when releasing cached dies. */
unsigned int mark : 1;
excessive time spent in producer_is_gxx_lt_4_6. */
unsigned int checked_producer : 1;
unsigned int producer_is_gxx_lt_4_6 : 1;
+
+ /* Non-zero if DW_AT_addr_base was found.
+ Used when processing DWO files. */
+ unsigned int have_addr_base : 1;
};
/* Persistent data held for a compilation unit, even when not
bytes should suffice to store the length of any compilation unit
- if it doesn't, GDB will fall over anyway.
NOTE: Unlike comp_unit_head.length, this length includes
- initial_length_size. */
+ initial_length_size.
+ If the DIE refers to a DWO file, this is always of the original die,
+ not the DWO file. */
sect_offset offset;
unsigned int length : 29;
hash table and don't find it. */
unsigned int load_all_dies : 1;
- /* Non-null if this CU is from .debug_types; in which case it points
- to the section. Otherwise it's from .debug_info. */
- struct dwarf2_section_info *debug_types_section;
+ /* Non-zero if this CU is from .debug_types. */
+ unsigned int is_debug_types : 1;
+
+ /* The section this CU/TU lives in.
+ If the DIE refers to a DWO file, this is always the original die,
+ not the DWO file. */
+ struct dwarf2_section_info *info_or_types_section;
/* Set to non-NULL iff this CU is currently loaded. When it gets freed out
of the CU cache it gets reset to NULL again. */
union
{
/* The partial symbol table associated with this compilation unit,
- or NULL for partial units (which do not have an associated
- symtab). */
+ or NULL for unread partial units. */
struct partial_symtab *psymtab;
/* Data needed by the "quick" functions. */
struct dwarf2_per_cu_quick_data *quick;
} v;
+
+ /* The CUs we import using DW_TAG_imported_unit. This is filled in
+ while reading psymtabs, used to compute the psymtab dependencies,
+ and then cleared. Then it is filled in again while reading full
+ symbols, and only deleted when the objfile is destroyed. */
+ VEC (dwarf2_per_cu_ptr) *imported_symtabs;
};
/* Entry in the signatured_types hash table. */
struct signatured_type
{
+ /* The type's signature. */
ULONGEST signature;
- /* Offset in this TU of the type defined by this TU. */
- cu_offset type_offset;
+ /* Offset in the TU of the type's DIE, as read from the TU header.
+ If the definition lives in a DWO file, this value is unusable. */
+ cu_offset type_offset_in_tu;
+
+ /* Offset in the section of the type's DIE.
+ If the definition lives in a DWO file, this is the offset in the
+ .debug_types.dwo section.
+ The value is zero until the actual value is known.
+ Zero is otherwise not a valid section offset. */
+ sect_offset type_offset_in_section;
/* The CU(/TU) of this type. */
struct dwarf2_per_cu_data per_cu;
};
+/* These sections are what may appear in a "dwo" file. */
+
+struct dwo_sections
+{
+ struct dwarf2_section_info abbrev;
+ struct dwarf2_section_info info;
+ struct dwarf2_section_info line;
+ struct dwarf2_section_info loc;
+ struct dwarf2_section_info str;
+ struct dwarf2_section_info str_offsets;
+ VEC (dwarf2_section_info_def) *types;
+};
+
+/* Common bits of DWO CUs/TUs. */
+
+struct dwo_unit
+{
+ /* Backlink to the containing struct dwo_file. */
+ struct dwo_file *dwo_file;
+
+ /* The "id" that distinguishes this CU/TU.
+ .debug_info calls this "dwo_id", .debug_types calls this "signature".
+ Since signatures came first, we stick with it for consistency. */
+ ULONGEST signature;
+
+ /* The section this CU/TU lives in, in the DWO file. */
+ struct dwarf2_section_info *info_or_types_section;
+
+ /* Same as dwarf2_per_cu_data:{offset,length} but for the DWO section. */
+ sect_offset offset;
+ unsigned int length;
+
+ /* For types, offset in the type's DIE of the type defined by this TU. */
+ cu_offset type_offset_in_tu;
+};
+
+/* Data for one DWO file. */
+
+struct dwo_file
+{
+ /* The DW_AT_GNU_dwo_name attribute.
+ We don't manage space for this, it's an attribute. */
+ const char *dwo_name;
+
+ /* The bfd, when the file is open. Otherwise this is NULL. */
+ bfd *dwo_bfd;
+
+ /* Section info for this file. */
+ struct dwo_sections sections;
+
+ /* Table of CUs in the file.
+ Each element is a struct dwo_unit. */
+ htab_t cus;
+
+ /* Table of TUs in the file.
+ Each element is a struct dwo_unit. */
+ htab_t tus;
+};
+
/* Struct used to pass misc. parameters to read_die_and_children, et
al. which are used for both .debug_info and .debug_types dies.
All parameters here are unchanging for the life of the call. This
/* The CU of the DIE we are parsing. */
struct dwarf2_cu *cu;
+ /* Non-NULL if reading a DWO file. */
+ struct dwo_file *dwo_file;
+
/* The section the die comes from.
- This is either .debug_info or .debug_types. */
+ This is either .debug_info or .debug_types, or the .dwo variants. */
struct dwarf2_section_info *die_section;
/* die_section->buffer. */
gdb_byte *buffer;
};
-/* Type of function passed to init_cu_and_read_dies, et.al. */
+/* Type of function passed to init_cutu_and_read_dies, et.al. */
typedef void (die_reader_func_ftype) (const struct die_reader_specs *reader,
gdb_byte *info_ptr,
struct die_info *comp_unit_die,
when this compilation unit leaves the cache. */
char *scope;
- /* The location description associated with this DIE, if any. */
- struct dwarf_block *locdesc;
+ /* Some data associated with the partial DIE. The tag determines
+ which field is live. */
+ union
+ {
+ /* The location description associated with this DIE, if any. */
+ struct dwarf_block *locdesc;
+ /* The offset of an import, for DW_TAG_imported_unit. */
+ sect_offset offset;
+ } d;
/* If HAS_PC_INFO, the PC range associated with this DIE. */
CORE_ADDR lowpc;
struct dwarf2_queue_item
{
struct dwarf2_per_cu_data *per_cu;
+ enum language pretend_language;
struct dwarf2_queue_item *next;
};
static LONGEST read_signed_leb128 (bfd *, gdb_byte *, unsigned int *);
+static CORE_ADDR read_addr_index_from_leb128 (struct dwarf2_cu *, gdb_byte *,
+ unsigned int *);
+
+static char *read_str_index (const struct die_reader_specs *reader,
+ struct dwarf2_cu *cu, ULONGEST str_index);
+
static gdb_byte *skip_leb128 (bfd *, gdb_byte *);
static void set_cu_language (unsigned int, struct dwarf2_cu *);
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 struct line_header *dwarf_decode_line_header (unsigned int offset,
+ struct dwarf2_cu *cu);
static void dwarf_decode_lines (struct line_header *, const char *,
struct dwarf2_cu *, struct partial_symtab *,
gdb_byte **new_info_ptr,
struct die_info *parent);
+static gdb_byte *read_full_die_1 (const struct die_reader_specs *,
+ struct die_info **, gdb_byte *, int *, int);
+
static gdb_byte *read_full_die (const struct die_reader_specs *,
struct die_info **, gdb_byte *, int *);
static struct die_info *dwarf2_extension (struct die_info *die,
struct dwarf2_cu **);
-static char *dwarf_tag_name (unsigned int);
+static const char *dwarf_tag_name (unsigned int);
-static char *dwarf_attr_name (unsigned int);
+static const char *dwarf_attr_name (unsigned int);
-static char *dwarf_form_name (unsigned int);
+static const char *dwarf_form_name (unsigned int);
static char *dwarf_bool_name (unsigned int);
-static char *dwarf_type_encoding_name (unsigned int);
-
-#if 0
-static char *dwarf_cfi_name (unsigned int);
-#endif
+static const char *dwarf_type_encoding_name (unsigned int);
static struct die_info *sibling_die (struct die_info *);
static void dwarf_decode_macros (struct line_header *, unsigned int,
char *, bfd *, struct dwarf2_cu *,
struct dwarf2_section_info *,
- int);
+ int, const char *);
static int attr_form_is_block (struct attribute *);
struct dwarf2_per_cu_data *per_cu);
static void prepare_one_comp_unit (struct dwarf2_cu *cu,
- struct die_info *comp_unit_die);
+ struct die_info *comp_unit_die,
+ enum language pretend_language);
static void free_heap_comp_unit (void *);
static int create_all_type_units (struct objfile *);
-static void load_full_comp_unit (struct dwarf2_per_cu_data *);
+static void load_full_comp_unit (struct dwarf2_per_cu_data *,
+ enum language);
-static void process_full_comp_unit (struct dwarf2_per_cu_data *);
+static void process_full_comp_unit (struct dwarf2_per_cu_data *,
+ enum language);
static void dwarf2_add_dependence (struct dwarf2_cu *,
struct dwarf2_per_cu_data *);
static void dwarf2_release_queue (void *dummy);
-static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu);
+static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu,
+ enum language pretend_language);
+
+static int maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
+ struct dwarf2_per_cu_data *per_cu,
+ enum language pretend_language);
static void process_queue (void);
struct dwarf2_section_info *section, gdb_byte *info_ptr,
int is_debug_types_section);
+static void init_cutu_and_read_dies
+ (struct dwarf2_per_cu_data *this_cu, int use_existing_cu, int keep,
+ die_reader_func_ftype *die_reader_func, void *data);
+
static void init_cutu_and_read_dies_simple
(struct dwarf2_per_cu_data *this_cu,
die_reader_func_ftype *die_reader_func, void *data);
static htab_t allocate_signatured_type_table (struct objfile *objfile);
-static void process_psymtab_comp_unit (struct dwarf2_per_cu_data *);
+static void process_psymtab_comp_unit (struct dwarf2_per_cu_data *, int);
+
+static htab_t allocate_dwo_unit_table (struct objfile *objfile);
+
+static struct dwo_unit *lookup_dwo_comp_unit
+ (struct dwarf2_per_cu_data *, char *, const char *, ULONGEST);
+
+static struct dwo_unit *lookup_dwo_type_unit
+ (struct signatured_type *, char *, const char *);
+
+static void free_dwo_file_cleanup (void *);
+
+static void munmap_section_buffer (struct dwarf2_section_info *);
+
+static void process_cu_includes (void);
#if WORDS_BIGENDIAN
dwarf2_per_objfile->str.asection = sectp;
dwarf2_per_objfile->str.size = bfd_get_section_size (sectp);
}
+ else if (section_is_p (sectp->name, &names->addr))
+ {
+ dwarf2_per_objfile->addr.asection = sectp;
+ dwarf2_per_objfile->addr.size = bfd_get_section_size (sectp);
+ }
else if (section_is_p (sectp->name, &names->frame))
{
dwarf2_per_objfile->frame.asection = sectp;
}
else if (section_is_p (sectp->name, &names->eh_frame))
{
- flagword aflag = bfd_get_section_flags (ignore_abfd, sectp);
+ flagword aflag = bfd_get_section_flags (abfd, sectp);
if (aflag & SEC_HAS_CONTENTS)
{
zlib_decompress_section (struct objfile *objfile, asection *sectp,
gdb_byte **outbuf, bfd_size_type *outsize)
{
- bfd *abfd = objfile->obfd;
+ bfd *abfd = sectp->owner;
#ifndef HAVE_ZLIB_H
error (_("Support for zlib-compressed DWARF data (from '%s') "
"is disabled in this copy of GDB"),
#endif
}
-/* A helper function that decides whether a section is empty. */
+/* A helper function that decides whether a section is empty,
+ or not present. */
static int
dwarf2_section_empty_p (struct dwarf2_section_info *info)
return info->asection == NULL || info->size == 0;
}
-/* Read the contents of the section INFO from object file specified by
- OBJFILE, store info about the section into INFO.
+/* Read the contents of the section INFO.
+ OBJFILE is the main object file, but not necessarily the file where
+ the section comes from. E.g., for DWO files INFO->asection->owner
+ is the bfd of the DWO file.
If the section is compressed, uncompress it before returning. */
static void
dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
{
- bfd *abfd = objfile->obfd;
asection *sectp = info->asection;
+ bfd *abfd;
gdb_byte *buf, *retbuf;
unsigned char header[4];
if (dwarf2_section_empty_p (info))
return;
+ /* Note that ABFD may not be from OBJFILE, e.g. a DWO section. */
+ abfd = sectp->owner;
+
/* Check if the file has a 4-byte header indicating compression. */
if (info->size > sizeof (header)
&& bfd_seek (abfd, sectp->filepos, SEEK_SET) == 0
static void
load_cu (struct dwarf2_per_cu_data *per_cu)
{
- if (per_cu->debug_types_section)
+ if (per_cu->is_debug_types)
load_full_type_unit (per_cu);
else
- load_full_comp_unit (per_cu);
+ load_full_comp_unit (per_cu, language_minimal);
gdb_assert (per_cu->cu != NULL);
back_to = make_cleanup (dwarf2_release_queue, NULL);
- queue_comp_unit (per_cu);
-
- load_cu (per_cu);
+ if (dwarf2_per_objfile->using_index
+ ? per_cu->v.quick->symtab == NULL
+ : (per_cu->v.psymtab == NULL || !per_cu->v.psymtab->readin))
+ {
+ queue_comp_unit (per_cu, language_minimal);
+ load_cu (per_cu);
+ }
process_queue ();
static struct symtab *
dw2_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
{
+ gdb_assert (dwarf2_per_objfile->using_index);
if (!per_cu->v.quick->symtab)
{
struct cleanup *back_to = make_cleanup (free_cached_comp_units, NULL);
increment_reading_symtab ();
dw2_do_instantiate_symtab (per_cu);
+ process_cu_includes ();
do_cleanups (back_to);
}
return per_cu->v.quick->symtab;
the_cu->offset.sect_off = offset;
the_cu->length = length;
the_cu->objfile = objfile;
+ the_cu->info_or_types_section = &dwarf2_per_objfile->info;
the_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
struct dwarf2_per_cu_quick_data);
dwarf2_per_objfile->all_comp_units[i / 2] = the_cu;
sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
struct signatured_type);
sig_type->signature = signature;
- sig_type->type_offset.cu_off = type_offset_in_tu;
- sig_type->per_cu.debug_types_section = section;
+ sig_type->type_offset_in_tu.cu_off = type_offset_in_tu;
+ sig_type->per_cu.is_debug_types = 1;
+ sig_type->per_cu.info_or_types_section = section;
sig_type->per_cu.offset.sect_off = offset;
sig_type->per_cu.objfile = objfile;
sig_type->per_cu.v.quick
struct dwarf2_cu *cu = reader->cu;
struct dwarf2_per_cu_data *this_cu = cu->per_cu;
struct objfile *objfile = dwarf2_per_objfile->objfile;
- bfd *abfd = objfile->obfd;
struct line_header *lh;
struct attribute *attr;
int i;
- unsigned int bytes_read;
char *name, *comp_dir;
void **slot;
struct quick_file_names *qfn;
return;
}
- lh = dwarf_decode_line_header (line_offset, abfd, cu);
+ lh = dwarf_decode_line_header (line_offset, cu);
}
if (lh == NULL)
{
if (this_cu->v.quick->no_file_data)
return NULL;
- init_cutu_and_read_dies_simple (this_cu, dw2_get_file_names_reader, NULL);
+ /* If DWO files are in use, we can still find the DW_AT_stmt_list attribute
+ in the stub for CUs, there's is no need to lookup the DWO file.
+ However, that's not the case for TUs where DW_AT_stmt_list lives in the
+ DWO file. */
+ if (this_cu->is_debug_types)
+ init_cutu_and_read_dies (this_cu, 0, 0, dw2_get_file_names_reader, NULL);
+ else
+ init_cutu_and_read_dies_simple (this_cu, dw2_get_file_names_reader, NULL);
if (this_cu->v.quick->no_file_data)
return NULL;
per_cu = dw2_get_cu (MAYBE_SWAP (vec[1]));
file_data = dw2_get_file_names (objfile, per_cu);
- if (file_data == NULL)
+ if (file_data == NULL
+ || file_data->num_file_names == 0)
return NULL;
return file_data->file_names[file_data->num_file_names - 1];
}
}
+/* A helper for dw2_find_pc_sect_symtab which finds the most specific
+ symtab. */
+
+static struct symtab *
+recursively_find_pc_sect_symtab (struct symtab *symtab, CORE_ADDR pc)
+{
+ int i;
+
+ if (BLOCKVECTOR (symtab) != NULL
+ && blockvector_contains_pc (BLOCKVECTOR (symtab), pc))
+ return symtab;
+
+ for (i = 0; symtab->includes[i]; ++i)
+ {
+ struct symtab *s;
+
+ s = recursively_find_pc_sect_symtab (s, pc);
+ if (s != NULL)
+ return s;
+ }
+
+ return NULL;
+}
+
static struct symtab *
dw2_find_pc_sect_symtab (struct objfile *objfile,
struct minimal_symbol *msymbol,
int warn_if_readin)
{
struct dwarf2_per_cu_data *data;
+ struct symtab *result;
dw2_setup (objfile);
warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
paddress (get_objfile_arch (objfile), pc));
- return dw2_instantiate_symtab (data);
+ result = recursively_find_pc_sect_symtab (dw2_instantiate_symtab (data), pc);
+ gdb_assert (result != NULL);
+ return result;
}
static void
struct die_info *die,
struct partial_symtab *pst)
{
- struct objfile *objfile = cu->objfile;
- bfd *abfd = objfile->obfd;
struct line_header *lh = NULL;
struct attribute *attr;
attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
if (attr)
- {
- unsigned int line_offset = DW_UNSND (attr);
-
- lh = dwarf_decode_line_header (line_offset, abfd, cu);
- }
+ lh = dwarf_decode_line_header (DW_UNSND (attr), cu);
if (lh == NULL)
return; /* No linetable, so no includes. */
return 1;
}
-/* Create the hash table of all entries in the .debug_types section(s).
- The result is zero if there are no .debug_types sections,
- otherwise non-zero. */
+/* Create the hash table of all entries in the .debug_types section.
+ DWO_FILE is a pointer to the DWO file for .debug_types.dwo, NULL otherwise.
+ The result is a pointer to the hash table or NULL if there are
+ no types. */
-static int
-create_all_type_units (struct objfile *objfile)
+static htab_t
+create_debug_types_hash_table (struct dwo_file *dwo_file,
+ VEC (dwarf2_section_info_def) *types)
{
- struct bfd *abfd = objfile->obfd;
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
htab_t types_htab = NULL;
- struct dwarf2_per_cu_data **iter;
int ix;
struct dwarf2_section_info *section;
- if (VEC_empty (dwarf2_section_info_def, dwarf2_per_objfile->types))
- {
- dwarf2_per_objfile->signatured_types = NULL;
- return 0;
- }
+ if (VEC_empty (dwarf2_section_info_def, types))
+ return NULL;
for (ix = 0;
- VEC_iterate (dwarf2_section_info_def, dwarf2_per_objfile->types,
- ix, section);
+ VEC_iterate (dwarf2_section_info_def, types, ix, section);
++ix)
{
+ bfd *abfd;
gdb_byte *info_ptr, *end_ptr;
dwarf2_read_section (objfile, section);
if (info_ptr == NULL)
continue;
+ /* We can't set abfd until now because the section may be empty or
+ not present, in which case section->asection will be NULL. */
+ abfd = section->asection->owner;
+
if (types_htab == NULL)
- types_htab = allocate_signatured_type_table (objfile);
+ {
+ if (dwo_file)
+ types_htab = allocate_dwo_unit_table (objfile);
+ else
+ types_htab = allocate_signatured_type_table (objfile);
+ }
if (dwarf2_die_debug)
fprintf_unfiltered (gdb_stdlog, "Reading signatured types for %s:\n",
while (info_ptr < end_ptr)
{
sect_offset offset;
- cu_offset type_offset;
+ cu_offset type_offset_in_tu;
ULONGEST signature;
struct signatured_type *sig_type;
+ struct dwo_unit *dwo_tu;
void **slot;
gdb_byte *ptr = info_ptr;
struct comp_unit_head header;
table, but we don't need anything else just yet. */
ptr = read_and_check_type_unit_head (&header, section, ptr,
- &signature, &type_offset);
+ &signature, &type_offset_in_tu);
length = header.initial_length_size + header.length;
continue;
}
- sig_type = obstack_alloc (&objfile->objfile_obstack, sizeof (*sig_type));
- memset (sig_type, 0, sizeof (*sig_type));
- sig_type->signature = signature;
- sig_type->type_offset = type_offset;
- sig_type->per_cu.objfile = objfile;
- sig_type->per_cu.debug_types_section = section;
- sig_type->per_cu.offset = offset;
+ if (dwo_file)
+ {
+ sig_type = NULL;
+ dwo_tu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwo_unit);
+ dwo_tu->dwo_file = dwo_file;
+ dwo_tu->signature = signature;
+ dwo_tu->type_offset_in_tu = type_offset_in_tu;
+ dwo_tu->info_or_types_section = section;
+ dwo_tu->offset = offset;
+ dwo_tu->length = length;
+ }
+ else
+ {
+ /* N.B.: type_offset is not usable if this type uses a DWO file.
+ The real type_offset is in the DWO file. */
+ dwo_tu = NULL;
+ sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct signatured_type);
+ sig_type->signature = signature;
+ sig_type->type_offset_in_tu = type_offset_in_tu;
+ sig_type->per_cu.objfile = objfile;
+ sig_type->per_cu.is_debug_types = 1;
+ sig_type->per_cu.info_or_types_section = section;
+ sig_type->per_cu.offset = offset;
+ sig_type->per_cu.length = length;
+ }
- slot = htab_find_slot (types_htab, sig_type, INSERT);
+ slot = htab_find_slot (types_htab,
+ dwo_file ? (void*) dwo_tu : (void *) sig_type,
+ INSERT);
gdb_assert (slot != NULL);
if (*slot != NULL)
{
- const struct signatured_type *dup_sig = *slot;
+ sect_offset dup_offset;
+
+ if (dwo_file)
+ {
+ const struct dwo_unit *dup_tu = *slot;
+
+ dup_offset = dup_tu->offset;
+ }
+ else
+ {
+ const struct signatured_type *dup_tu = *slot;
+
+ dup_offset = dup_tu->per_cu.offset;
+ }
complaint (&symfile_complaints,
_("debug type entry at offset 0x%x is duplicate to the "
"entry at offset 0x%x, signature 0x%s"),
- offset.sect_off, dup_sig->per_cu.offset.sect_off,
+ offset.sect_off, dup_offset.sect_off,
phex (signature, sizeof (signature)));
- gdb_assert (signature == dup_sig->signature);
}
- *slot = sig_type;
+ *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
if (dwarf2_die_debug)
fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature 0x%s\n",
}
}
+ return types_htab;
+}
+
+/* Create the hash table of all entries in the .debug_types section,
+ and initialize all_type_units.
+ The result is zero if there is an error (e.g. missing .debug_types section),
+ otherwise non-zero. */
+
+static int
+create_all_type_units (struct objfile *objfile)
+{
+ htab_t types_htab;
+ struct dwarf2_per_cu_data **iter;
+
+ types_htab = create_debug_types_hash_table (NULL, dwarf2_per_objfile->types);
+ if (types_htab == NULL)
+ {
+ dwarf2_per_objfile->signatured_types = NULL;
+ return 0;
+ }
+
dwarf2_per_objfile->signatured_types = types_htab;
dwarf2_per_objfile->n_type_units = htab_elements (types_htab);
static void
init_cu_die_reader (struct die_reader_specs *reader,
struct dwarf2_cu *cu,
- struct dwarf2_section_info *section)
+ struct dwarf2_section_info *section,
+ struct dwo_file *dwo_file)
{
- gdb_assert (section->readin);
+ gdb_assert (section->readin && section->buffer != NULL);
reader->abfd = section->asection->owner;
reader->cu = cu;
+ reader->dwo_file = dwo_file;
reader->die_section = section;
reader->buffer = section->buffer;
}
}
}
-/* Subroutine of init_{cu,tu}_and_read_dies.
- Do all the work necessary to initialize THIS_CU->cu and read in its DIE(s).
+/* Initialize a CU (or TU) and read its DIEs.
+ If the CU defers to a DWO file, read the DWO file as well.
If USE_EXISTING_CU is non-zero, and THIS_CU->cu is non-NULL, then use it.
Otherwise, a new CU is allocated with xmalloc.
read_in_chain. Otherwise the dwarf2_cu data is freed at the end.
WARNING: If THIS_CU is a "dummy CU" (used as filler by the incremental
- linker) then DIE_READER_FUNC will not get called.
-
- FIXME: As an implementation detail between our callers and us,
- USE_EXISTING_CU and KEEP are OK. But bubbling them up into their callers
- isn't as clean as I'd like. Having more callers with good names
- may be the way to go. */
+ linker) then DIE_READER_FUNC will not get called. */
static void
-init_and_read_dies_worker (struct dwarf2_per_cu_data *this_cu,
- int use_existing_cu, int keep,
- die_reader_func_ftype *die_reader_func,
- void *data)
+init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
+ int use_existing_cu, int keep,
+ die_reader_func_ftype *die_reader_func,
+ void *data)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
- struct dwarf2_section_info *section;
- bfd *abfd;
+ struct dwarf2_section_info *section = this_cu->info_or_types_section;
+ bfd *abfd = section->asection->owner;
struct dwarf2_cu *cu;
gdb_byte *begin_info_ptr, *info_ptr;
struct die_reader_specs reader;
if (use_existing_cu)
gdb_assert (keep);
- if (this_cu->debug_types_section)
- gdb_assert (! use_existing_cu);
-
- if (this_cu->debug_types_section)
- section = this_cu->debug_types_section;
- else
- section = &dwarf2_per_objfile->info;
- abfd = section->asection->owner;
cleanups = make_cleanup (null_cleanup, NULL);
/* If an error occurs while loading, release our storage. */
free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
- if (this_cu->debug_types_section)
+ if (this_cu->is_debug_types)
{
ULONGEST signature;
/* LENGTH has not been set yet for type units. */
this_cu->length = cu->header.length + cu->header.initial_length_size;
+
+ /* Establish the type offset that can be used to lookup the type. */
+ sig_type->type_offset_in_section.sect_off =
+ this_cu->offset.sect_off + sig_type->type_offset_in_tu.cu_off;
}
else
{
}
/* Read the top level CU/TU die. */
- init_cu_die_reader (&reader, cu, section);
+ init_cu_die_reader (&reader, cu, section, NULL);
info_ptr = read_full_die (&reader, &comp_unit_die, info_ptr, &has_children);
+ /* If we have a DWO stub, process it and then read in the DWO file.
+ Note that if USE_EXISTING_OK != 0, and THIS_CU->cu already contains
+ a DWO CU, that this test will fail. */
+ attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_name, cu);
+ if (attr)
+ {
+ char *dwo_name = DW_STRING (attr);
+ const char *comp_dir;
+ struct dwo_unit *dwo_unit;
+ ULONGEST signature; /* Or dwo_id. */
+ struct attribute *stmt_list, *low_pc, *high_pc, *ranges;
+ int i,num_extra_attrs;
+
+ if (has_children)
+ error (_("Dwarf Error: compilation unit with DW_AT_GNU_dwo_name"
+ " has children (offset 0x%x) [in module %s]"),
+ this_cu->offset.sect_off, bfd_get_filename (abfd));
+
+ /* These attributes aren't processed until later:
+ DW_AT_stmt_list, DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges.
+ However, the attribute is found in the stub which we won't have later.
+ In order to not impose this complication on the rest of the code,
+ we read them here and copy them to the DWO CU/TU die. */
+ stmt_list = low_pc = high_pc = ranges = NULL;
+
+ /* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
+ DWO file. */
+ if (! this_cu->is_debug_types)
+ stmt_list = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, cu);
+ low_pc = dwarf2_attr (comp_unit_die, DW_AT_low_pc, cu);
+ high_pc = dwarf2_attr (comp_unit_die, DW_AT_high_pc, cu);
+ ranges = dwarf2_attr (comp_unit_die, DW_AT_ranges, cu);
+
+ /* There should be a DW_AT_addr_base attribute here (if needed).
+ We need the value before we can process DW_FORM_GNU_addr_index. */
+ cu->addr_base = 0;
+ cu->have_addr_base = 0;
+ attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_addr_base, cu);
+ if (attr)
+ {
+ cu->addr_base = DW_UNSND (attr);
+ cu->have_addr_base = 1;
+ }
+
+ if (this_cu->is_debug_types)
+ {
+ gdb_assert (sig_type != NULL);
+ signature = sig_type->signature;
+ }
+ else
+ {
+ attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_id, cu);
+ if (! attr)
+ error (_("Dwarf Error: missing dwo_id [in module %s]"),
+ dwo_name);
+ signature = DW_UNSND (attr);
+ }
+
+ /* We may need the comp_dir in order to find the DWO file. */
+ comp_dir = NULL;
+ attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, cu);
+ if (attr)
+ comp_dir = DW_STRING (attr);
+
+ if (this_cu->is_debug_types)
+ dwo_unit = lookup_dwo_type_unit (sig_type, dwo_name, comp_dir);
+ else
+ dwo_unit = lookup_dwo_comp_unit (this_cu, dwo_name, comp_dir,
+ signature);
+
+ if (dwo_unit == NULL)
+ {
+ error (_("Dwarf Error: CU at offset 0x%x references unknown DWO"
+ " with ID %s [in module %s]"),
+ this_cu->offset.sect_off,
+ phex (signature, sizeof (signature)),
+ objfile->name);
+ }
+
+ /* Set up for reading the DWO CU/TU. */
+ cu->dwo_unit = dwo_unit;
+ section = dwo_unit->info_or_types_section;
+ begin_info_ptr = info_ptr = section->buffer + dwo_unit->offset.sect_off;
+ init_cu_die_reader (&reader, cu, section, dwo_unit->dwo_file);
+
+ if (this_cu->is_debug_types)
+ {
+ ULONGEST signature;
+
+ info_ptr = read_and_check_type_unit_head (&cu->header,
+ section, info_ptr,
+ &signature, NULL);
+ gdb_assert (sig_type->signature == signature);
+ gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
+ gdb_assert (dwo_unit->length
+ == cu->header.length + cu->header.initial_length_size);
+
+ /* Establish the type offset that can be used to lookup the type.
+ For DWO files, we don't know it until now. */
+ sig_type->type_offset_in_section.sect_off =
+ dwo_unit->offset.sect_off + dwo_unit->type_offset_in_tu.cu_off;
+ }
+ else
+ {
+ info_ptr = read_and_check_comp_unit_head (&cu->header,
+ section, info_ptr, 0);
+ gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
+ gdb_assert (dwo_unit->length
+ == cu->header.length + cu->header.initial_length_size);
+ }
+
+ /* Discard the original CU's abbrev table, and read the DWO's. */
+ dwarf2_free_abbrev_table (cu);
+ dwarf2_read_abbrevs (cu, &dwo_unit->dwo_file->sections.abbrev);
+
+ /* Read in the die, but leave space to copy over the attributes
+ from the stub. This has the benefit of simplifying the rest of
+ the code - all the real work is done here. */
+ num_extra_attrs = ((stmt_list != NULL)
+ + (low_pc != NULL)
+ + (high_pc != NULL)
+ + (ranges != NULL));
+ info_ptr = read_full_die_1 (&reader, &comp_unit_die, info_ptr,
+ &has_children, num_extra_attrs);
+
+ /* Copy over the attributes from the stub to the DWO die. */
+ i = comp_unit_die->num_attrs;
+ if (stmt_list != NULL)
+ comp_unit_die->attrs[i++] = *stmt_list;
+ if (low_pc != NULL)
+ comp_unit_die->attrs[i++] = *low_pc;
+ if (high_pc != NULL)
+ comp_unit_die->attrs[i++] = *high_pc;
+ if (ranges != NULL)
+ comp_unit_die->attrs[i++] = *ranges;
+ comp_unit_die->num_attrs += num_extra_attrs;
+
+ /* Skip dummy compilation units. */
+ if (info_ptr >= begin_info_ptr + dwo_unit->length
+ || peek_abbrev_code (abfd, info_ptr) == 0)
+ {
+ do_cleanups (cleanups);
+ return;
+ }
+ }
+
die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
if (free_cu_cleanup != NULL)
do_cleanups (cleanups);
}
-/* Main entry point for reading a CU.
- Do all the work necessary to initialize THIS_CU->cu and read in its DIE(s).
-
- If USE_EXISTING_CU is non-zero, and THIS_CU->cu is non-NULL, then use it.
- Otherwise, a new CU is allocated with xmalloc.
-
- If KEEP is non-zero, then if we allocated a dwarf2_cu we add it to
- read_in_chain. Otherwise the dwarf2_cu data is freed at the end. */
-
-static void
-init_cu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
- int use_existing_cu, int keep,
- die_reader_func_ftype *die_reader_func,
- void *data)
-{
- init_and_read_dies_worker (this_cu, use_existing_cu, keep,
- die_reader_func, data);
-}
-
-/* Main entry point for reading a TU.
- Do all the work necessary to initialize THIS_CU->cu and read in its DIE(s).
-
- If KEEP is non-zero, then if we allocated a dwarf2_cu we add it to
- read_in_chain. Otherwise the dwarf2_cu data is freed at the end. */
-
-static void
-init_tu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
- int keep,
- die_reader_func_ftype *die_reader_func,
- void *data)
-{
- gdb_assert (this_cu->debug_types_section);
- init_and_read_dies_worker (this_cu, 0, keep, die_reader_func, data);
-}
-
-/* Read the CU/TU at OFFSET in section SECTION.
+/* Read CU/TU THIS_CU in section SECTION,
+ but do not follow DW_AT_GNU_dwo_name if present.
+ DWO_FILE, if non-NULL, is the DWO file to read (the caller is assumed to
+ have already done the lookup to find the DWO file).
The caller is required to fill in THIS_CU->section, THIS_CU->offset, and
- THIS_CU->debug_types_section, but nothing else.
+ THIS_CU->is_debug_types, but nothing else.
We fill in THIS_CU->length.
linker) then DIE_READER_FUNC will not get called.
THIS_CU->cu is always freed when done.
- [This is done for Fission reasons, to be specified.] */
+ This is done in order to not leave THIS_CU->cu in a state where we have
+ to care whether it refers to the "main" CU or the DWO CU. */
static void
init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
struct dwarf2_section_info *abbrev_section,
+ struct dwo_file *dwo_file,
die_reader_func_ftype *die_reader_func,
void *data)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
- struct dwarf2_section_info *section;
- bfd *abfd;
+ struct dwarf2_section_info *section = this_cu->info_or_types_section;
+ bfd *abfd = section->asection->owner;
struct dwarf2_cu cu;
gdb_byte *begin_info_ptr, *info_ptr;
struct die_reader_specs reader;
gdb_assert (this_cu->cu == NULL);
- if (this_cu->debug_types_section)
- section = this_cu->debug_types_section;
- else
- section = &dwarf2_per_objfile->info;
- abfd = section->asection->owner;
-
/* This is cheap if the section is already read in. */
dwarf2_read_section (objfile, section);
begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
info_ptr = read_and_check_comp_unit_head (&cu.header, section, info_ptr,
- this_cu->debug_types_section != NULL);
+ this_cu->is_debug_types);
this_cu->length = cu.header.length + cu.header.initial_length_size;
dwarf2_read_abbrevs (&cu, abbrev_section);
make_cleanup (dwarf2_free_abbrev_table, &cu);
- init_cu_die_reader (&reader, &cu, section);
+ init_cu_die_reader (&reader, &cu, section, dwo_file);
info_ptr = read_full_die (&reader, &comp_unit_die, info_ptr, &has_children);
die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
do_cleanups (cleanups);
}
-/* Read a CU/TU.
- [This is a separate routine for Fission, to be specified.]
+/* Read a CU/TU, except that this does not look for DW_AT_GNU_dwo_name and
+ does not lookup the specified DWO file.
+ This cannot be used to read DWO files.
THIS_CU->cu is always freed when done.
- [This is done for Fission reasons, to be specified.] */
+ This is done in order to not leave THIS_CU->cu in a state where we have
+ to care whether it refers to the "main" CU or the DWO CU.
+ We can revisit this if the data shows there's a performance issue. */
static void
init_cutu_and_read_dies_simple (struct dwarf2_per_cu_data *this_cu,
{
init_cutu_and_read_dies_no_follow (this_cu,
&dwarf2_per_objfile->abbrev,
+ NULL,
die_reader_func, data);
}
struct dwarf2_cu *cu = reader->cu;
struct objfile *objfile = cu->objfile;
struct dwarf2_per_cu_data *per_cu = cu->per_cu;
- bfd *abfd = objfile->obfd;
struct attribute *attr;
CORE_ADDR baseaddr;
CORE_ADDR best_lowpc = 0, best_highpc = 0;
struct partial_symtab *pst;
int has_pc_info;
const char *filename;
+ int *want_partial_unit_ptr = data;
- if (comp_unit_die->tag == DW_TAG_partial_unit)
+ if (comp_unit_die->tag == DW_TAG_partial_unit
+ && (want_partial_unit_ptr == NULL
+ || !*want_partial_unit_ptr))
return;
- prepare_one_comp_unit (cu, comp_unit_die);
+ prepare_one_comp_unit (cu, comp_unit_die, language_minimal);
cu->list_in_scope = &file_symbols;
(objfile->static_psymbols.list + pst->statics_offset);
sort_pst_symbols (pst);
- if (per_cu->debug_types_section)
+ if (!VEC_empty (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs))
+ {
+ int i;
+ int len = VEC_length (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs);
+ struct dwarf2_per_cu_data *iter;
+
+ /* Fill in 'dependencies' here; we fill in 'users' in a
+ post-pass. */
+ pst->number_of_dependencies = len;
+ pst->dependencies = obstack_alloc (&objfile->objfile_obstack,
+ len * sizeof (struct symtab *));
+ for (i = 0;
+ VEC_iterate (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
+ i, iter);
+ ++i)
+ pst->dependencies[i] = iter->v.psymtab;
+
+ VEC_free (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs);
+ }
+
+ if (per_cu->is_debug_types)
{
/* It's not clear we want to do anything with stmt lists here.
Waiting to see what gcc ultimately does. */
Process compilation unit THIS_CU for a psymtab. */
static void
-process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu)
+process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
+ int want_partial_unit)
{
/* If this compilation unit was already read in, free the
cached copy in order to read it in again. This is
if (this_cu->cu != NULL)
free_one_cached_comp_unit (this_cu);
- gdb_assert (! this_cu->debug_types_section);
- init_cu_and_read_dies (this_cu, 0, 0, process_psymtab_comp_unit_reader,
- NULL);
+ gdb_assert (! this_cu->is_debug_types);
+ init_cutu_and_read_dies (this_cu, 0, 0, process_psymtab_comp_unit_reader,
+ &want_partial_unit);
/* Age out any secondary CUs. */
age_cached_comp_units ();
struct signatured_type *sig_type = (struct signatured_type *) *slot;
struct dwarf2_per_cu_data *per_cu = &sig_type->per_cu;
+ gdb_assert (per_cu->is_debug_types);
gdb_assert (info == NULL);
/* If this compilation unit was already read in, free the
if (per_cu->cu != NULL)
free_one_cached_comp_unit (per_cu);
- gdb_assert (per_cu->debug_types_section);
- init_tu_and_read_dies (per_cu, 0, process_psymtab_comp_unit_reader, NULL);
+ init_cutu_and_read_dies (per_cu, 0, 0, process_psymtab_comp_unit_reader,
+ NULL);
/* Age out any secondary CUs. */
age_cached_comp_units ();
objfile->psymtabs_addrmap = NULL;
}
+/* Compute the 'user' field for each psymtab in OBJFILE. */
+
+static void
+set_partial_user (struct objfile *objfile)
+{
+ int i;
+
+ for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
+ {
+ struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
+ struct partial_symtab *pst = per_cu->v.psymtab;
+ int j;
+
+ for (j = 0; j < pst->number_of_dependencies; ++j)
+ {
+ /* Set the 'user' field only if it is not already set. */
+ if (pst->dependencies[j]->user == NULL)
+ pst->dependencies[j]->user = pst;
+ }
+ }
+}
+
/* Build the partial symbol table by doing a quick pass through the
.debug_info and .debug_abbrev sections. */
{
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
- process_psymtab_comp_unit (per_cu);
+ process_psymtab_comp_unit (per_cu, 0);
}
+ set_partial_user (objfile);
+
objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
&objfile->objfile_obstack);
discard_cleanups (addrmap_cleanup);
do_cleanups (back_to);
}
-/* Load the partial DIEs for a secondary CU into memory. */
+/* die_reader_func for load_partial_comp_unit. */
static void
load_partial_comp_unit_reader (const struct die_reader_specs *reader,
{
struct dwarf2_cu *cu = reader->cu;
- prepare_one_comp_unit (cu, comp_unit_die);
+ prepare_one_comp_unit (cu, comp_unit_die, language_minimal);
/* Check if comp unit has_children.
If so, read the rest of the partial symbols from this comp unit.
static void
load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu)
{
- if (this_cu->debug_types_section)
- init_tu_and_read_dies (this_cu, 1, load_partial_comp_unit_reader, NULL);
- else
- init_cu_and_read_dies (this_cu, 0, 1, load_partial_comp_unit_reader, NULL);
+ init_cutu_and_read_dies (this_cu, 1, 1, load_partial_comp_unit_reader, NULL);
}
/* Create a list of all compilation units in OBJFILE.
this_cu->offset = offset;
this_cu->length = length + initial_length_size;
this_cu->objfile = objfile;
+ this_cu->info_or_types_section = &dwarf2_per_objfile->info;
if (n_comp_units == n_allocated)
{
enums. */
if (pdi->name != NULL || pdi->tag == DW_TAG_namespace
- || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type)
+ || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type
+ || pdi->tag == DW_TAG_imported_unit)
{
switch (pdi->tag)
{
case DW_TAG_module:
add_partial_module (pdi, lowpc, highpc, need_pc, cu);
break;
+ case DW_TAG_imported_unit:
+ {
+ struct dwarf2_per_cu_data *per_cu;
+
+ per_cu = dwarf2_find_containing_comp_unit (pdi->d.offset,
+ cu->objfile);
+
+ /* Go read the partial unit, if needed. */
+ if (per_cu->v.psymtab == NULL)
+ process_psymtab_comp_unit (per_cu, 1);
+
+ VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
+ per_cu);
+ }
+ break;
default:
break;
}
}
break;
case DW_TAG_variable:
- if (pdi->locdesc)
- addr = decode_locdesc (pdi->locdesc, cu);
+ if (pdi->d.locdesc)
+ addr = decode_locdesc (pdi->d.locdesc, cu);
- if (pdi->locdesc
+ if (pdi->d.locdesc
&& addr == 0
&& !dwarf2_per_objfile->has_section_at_zero)
{
used by GDB, but it comes in handy for debugging partial symbol
table building. */
- if (pdi->locdesc || pdi->has_type)
+ if (pdi->d.locdesc || pdi->has_type)
add_psymbol_to_list (actual_name, strlen (actual_name),
built_actual_name,
VAR_DOMAIN, LOC_STATIC,
else
{
/* Static Variable. Skip symbols without location descriptors. */
- if (pdi->locdesc == NULL)
+ if (pdi->d.locdesc == NULL)
{
if (built_actual_name)
xfree (actual_name);
case DW_FORM_sdata:
case DW_FORM_udata:
case DW_FORM_ref_udata:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index:
info_ptr = skip_leb128 (abfd, info_ptr);
break;
case DW_FORM_indirect:
printf_filtered (_("done.\n"));
}
}
+
+ process_cu_includes ();
}
\f
/* Reading in full CUs. */
/* Add PER_CU to the queue. */
static void
-queue_comp_unit (struct dwarf2_per_cu_data *per_cu)
+queue_comp_unit (struct dwarf2_per_cu_data *per_cu,
+ enum language pretend_language)
{
struct dwarf2_queue_item *item;
per_cu->queued = 1;
item = xmalloc (sizeof (*item));
item->per_cu = per_cu;
+ item->pretend_language = pretend_language;
item->next = NULL;
if (dwarf2_queue == NULL)
if (dwarf2_per_objfile->using_index
? !item->per_cu->v.quick->symtab
: (item->per_cu->v.psymtab && !item->per_cu->v.psymtab->readin))
- process_full_comp_unit (item->per_cu);
+ process_full_comp_unit (item->per_cu, item->pretend_language);
item->per_cu->queued = 0;
next_item = item->next;
psymtab_to_symtab_1 (struct partial_symtab *pst)
{
struct dwarf2_per_cu_data *per_cu;
- struct cleanup *back_to;
int i;
+ if (pst->readin)
+ return;
+
for (i = 0; i < pst->number_of_dependencies; i++)
- if (!pst->dependencies[i]->readin)
+ if (!pst->dependencies[i]->readin
+ && pst->dependencies[i]->user == NULL)
{
/* Inform about additional files that need to be read in. */
if (info_verbose)
void *data)
{
struct dwarf2_cu *cu = reader->cu;
- struct attribute *attr;
+ enum language *language_ptr = data;
gdb_assert (cu->die_hash == NULL);
cu->die_hash =
or we won't be able to build types correctly.
Similarly, if we do not read the producer, we can not apply
producer-specific interpretation. */
- prepare_one_comp_unit (cu, cu->dies);
+ prepare_one_comp_unit (cu, cu->dies, *language_ptr);
}
/* Load the DIEs associated with PER_CU into memory. */
static void
-load_full_comp_unit (struct dwarf2_per_cu_data *this_cu)
+load_full_comp_unit (struct dwarf2_per_cu_data *this_cu,
+ enum language pretend_language)
{
- gdb_assert (! this_cu->debug_types_section);
+ gdb_assert (! this_cu->is_debug_types);
- init_cu_and_read_dies (this_cu, 1, 1, load_full_comp_unit_reader, NULL);
+ init_cutu_and_read_dies (this_cu, 1, 1, load_full_comp_unit_reader,
+ &pretend_language);
}
/* Add a DIE to the delayed physname list. */
}
}
-/* Generate full symbol information for PER_CU, whose DIEs have
- already been loaded into memory. */
+static void compute_symtab_includes (struct dwarf2_per_cu_data *per_cu);
-static void
-process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
+/* Return the symtab for PER_CU. This works properly regardless of
+ whether we're using the index or psymtabs. */
+
+static struct symtab *
+get_symtab (struct dwarf2_per_cu_data *per_cu)
{
- struct dwarf2_cu *cu = per_cu->cu;
- struct objfile *objfile = per_cu->objfile;
+ return (dwarf2_per_objfile->using_index
+ ? per_cu->v.quick->symtab
+ : per_cu->v.psymtab->symtab);
+}
+
+/* A helper function for computing the list of all symbol tables
+ included by PER_CU. */
+
+static void
+recursively_compute_inclusions (VEC (dwarf2_per_cu_ptr) **result,
+ htab_t all_children,
+ struct dwarf2_per_cu_data *per_cu)
+{
+ void **slot;
+ int ix;
+ struct dwarf2_per_cu_data *iter;
+
+ slot = htab_find_slot (all_children, per_cu, INSERT);
+ if (*slot != NULL)
+ {
+ /* This inclusion and its children have been processed. */
+ return;
+ }
+
+ *slot = per_cu;
+ /* Only add a CU if it has a symbol table. */
+ if (get_symtab (per_cu) != NULL)
+ VEC_safe_push (dwarf2_per_cu_ptr, *result, per_cu);
+
+ for (ix = 0;
+ VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs, ix, iter);
+ ++ix)
+ recursively_compute_inclusions (result, all_children, iter);
+}
+
+/* Compute the symtab 'includes' fields for the symtab related to
+ PER_CU. */
+
+static void
+compute_symtab_includes (struct dwarf2_per_cu_data *per_cu)
+{
+ if (!VEC_empty (dwarf2_per_cu_ptr, per_cu->imported_symtabs))
+ {
+ int ix, len;
+ struct dwarf2_per_cu_data *iter;
+ VEC (dwarf2_per_cu_ptr) *result_children = NULL;
+ htab_t all_children;
+ struct symtab *symtab = get_symtab (per_cu);
+
+ /* If we don't have a symtab, we can just skip this case. */
+ if (symtab == NULL)
+ return;
+
+ all_children = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer,
+ NULL, xcalloc, xfree);
+
+ for (ix = 0;
+ VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs,
+ ix, iter);
+ ++ix)
+ recursively_compute_inclusions (&result_children, all_children, iter);
+
+ /* Now we have a transitive closure of all the included CUs, so
+ we can convert it to a list of symtabs. */
+ len = VEC_length (dwarf2_per_cu_ptr, result_children);
+ symtab->includes
+ = obstack_alloc (&dwarf2_per_objfile->objfile->objfile_obstack,
+ (len + 1) * sizeof (struct symtab *));
+ for (ix = 0;
+ VEC_iterate (dwarf2_per_cu_ptr, result_children, ix, iter);
+ ++ix)
+ symtab->includes[ix] = get_symtab (iter);
+ symtab->includes[len] = NULL;
+
+ VEC_free (dwarf2_per_cu_ptr, result_children);
+ htab_delete (all_children);
+ }
+}
+
+/* Compute the 'includes' field for the symtabs of all the CUs we just
+ read. */
+
+static void
+process_cu_includes (void)
+{
+ int ix;
+ struct dwarf2_per_cu_data *iter;
+
+ for (ix = 0;
+ VEC_iterate (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus,
+ ix, iter);
+ ++ix)
+ compute_symtab_includes (iter);
+
+ VEC_free (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus);
+}
+
+/* Generate full symbol information for PER_CU, whose DIEs have
+ already been loaded into memory. */
+
+static void
+process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
+ enum language pretend_language)
+{
+ struct dwarf2_cu *cu = per_cu->cu;
+ struct objfile *objfile = per_cu->objfile;
CORE_ADDR lowpc, highpc;
struct symtab *symtab;
struct cleanup *back_to, *delayed_list_cleanup;
cu->list_in_scope = &file_symbols;
+ cu->language = pretend_language;
+ cu->language_defn = language_def (cu->language);
+
/* Do line number decoding in read_file_scope () */
process_die (cu->dies, cu);
pst->readin = 1;
}
+ /* Push it for inclusion processing later. */
+ VEC_safe_push (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus, per_cu);
+
do_cleanups (back_to);
}
+/* Process an imported unit DIE. */
+
+static void
+process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct attribute *attr;
+
+ attr = dwarf2_attr (die, DW_AT_import, cu);
+ if (attr != NULL)
+ {
+ struct dwarf2_per_cu_data *per_cu;
+ struct symtab *imported_symtab;
+ sect_offset offset;
+
+ offset = dwarf2_get_ref_die_offset (attr);
+ per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
+
+ /* Queue the unit, if needed. */
+ if (maybe_queue_comp_unit (cu, per_cu, cu->language))
+ load_full_comp_unit (per_cu, cu->language);
+
+ VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
+ per_cu);
+ }
+}
+
/* Process a die and its children. */
static void
case DW_TAG_padding:
break;
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
read_file_scope (die, cu);
break;
case DW_TAG_type_unit:
dwarf_tag_name (die->tag));
read_import_statement (die, cu);
break;
+
+ case DW_TAG_imported_unit:
+ process_imported_unit_die (die, cu);
+ break;
+
default:
new_symbol (die, NULL, cu);
break;
const char *comp_dir, int want_line_info)
{
struct attribute *attr;
- struct objfile *objfile = cu->objfile;
- bfd *abfd = objfile->obfd;
attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
if (attr)
{
unsigned int line_offset = DW_UNSND (attr);
struct line_header *line_header
- = dwarf_decode_line_header (line_offset, abfd, cu);
+ = dwarf_decode_line_header (line_offset, cu);
if (line_header)
{
}
}
-/* Process DW_TAG_compile_unit. */
+/* Process DW_TAG_compile_unit or DW_TAG_partial_unit. */
static void
read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
find_file_and_directory (die, cu, &name, &comp_dir);
- prepare_one_comp_unit (cu, die);
+ prepare_one_comp_unit (cu, die, cu->language);
/* The XLCL doesn't generate DW_LANG_OpenCL because this attribute is not
standardised yet. As a workaround for the language detection we fall
dwarf_decode_macros (cu->line_header, DW_UNSND (attr),
comp_dir, abfd, cu,
- &dwarf2_per_objfile->macro, 1);
+ &dwarf2_per_objfile->macro, 1,
+ ".debug_macro");
}
else
{
dwarf_decode_macros (cu->line_header, macro_offset,
comp_dir, abfd, cu,
- &dwarf2_per_objfile->macinfo, 0);
+ &dwarf2_per_objfile->macinfo, 0,
+ ".debug_macinfo");
}
}
if (name == NULL)
name = "<unknown>";
- prepare_one_comp_unit (cu, die);
+ prepare_one_comp_unit (cu, die, language_minimal);
/* We assume that we're processing GCC output. */
processing_gcc_compilation = 2;
do_cleanups (back_to);
}
+\f
+/* DWO files. */
+
+static hashval_t
+hash_dwo_file (const void *item)
+{
+ const struct dwo_file *dwo_file = item;
+
+ return htab_hash_string (dwo_file->dwo_name);
+}
+
+static int
+eq_dwo_file (const void *item_lhs, const void *item_rhs)
+{
+ const struct dwo_file *lhs = item_lhs;
+ const struct dwo_file *rhs = item_rhs;
+
+ return strcmp (lhs->dwo_name, rhs->dwo_name) == 0;
+}
+
+/* Allocate a hash table for DWO files. */
+
+static htab_t
+allocate_dwo_file_hash_table (void)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+
+ return htab_create_alloc_ex (41,
+ hash_dwo_file,
+ eq_dwo_file,
+ NULL,
+ &objfile->objfile_obstack,
+ hashtab_obstack_allocate,
+ dummy_obstack_deallocate);
+}
+
+static hashval_t
+hash_dwo_unit (const void *item)
+{
+ const struct dwo_unit *dwo_unit = item;
+
+ /* This drops the top 32 bits of the id, but is ok for a hash. */
+ return dwo_unit->signature;
+}
+
+static int
+eq_dwo_unit (const void *item_lhs, const void *item_rhs)
+{
+ const struct dwo_unit *lhs = item_lhs;
+ const struct dwo_unit *rhs = item_rhs;
+
+ /* The signature is assumed to be unique within the DWO file.
+ So while object file CU dwo_id's always have the value zero,
+ that's OK, assuming each object file DWO file has only one CU,
+ and that's the rule for now. */
+ return lhs->signature == rhs->signature;
+}
+
+/* Allocate a hash table for DWO CUs,TUs.
+ There is one of these tables for each of CUs,TUs for each DWO file. */
+
+static htab_t
+allocate_dwo_unit_table (struct objfile *objfile)
+{
+ /* Start out with a pretty small number.
+ Generally DWO files contain only one CU and maybe some TUs. */
+ return htab_create_alloc_ex (3,
+ hash_dwo_unit,
+ eq_dwo_unit,
+ NULL,
+ &objfile->objfile_obstack,
+ hashtab_obstack_allocate,
+ dummy_obstack_deallocate);
+}
+
+/* This function is mapped across the sections and remembers the offset and
+ size of each of the DWO debugging sections we are interested in. */
+
+static void
+dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp, void *dwo_file_ptr)
+{
+ struct dwo_file *dwo_file = dwo_file_ptr;
+ const struct dwo_section_names *names = &dwo_section_names;
+
+ if (section_is_p (sectp->name, &names->abbrev_dwo))
+ {
+ dwo_file->sections.abbrev.asection = sectp;
+ dwo_file->sections.abbrev.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->info_dwo))
+ {
+ dwo_file->sections.info.asection = sectp;
+ dwo_file->sections.info.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->line_dwo))
+ {
+ dwo_file->sections.line.asection = sectp;
+ dwo_file->sections.line.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->loc_dwo))
+ {
+ dwo_file->sections.loc.asection = sectp;
+ dwo_file->sections.loc.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->str_dwo))
+ {
+ dwo_file->sections.str.asection = sectp;
+ dwo_file->sections.str.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->str_offsets_dwo))
+ {
+ dwo_file->sections.str_offsets.asection = sectp;
+ dwo_file->sections.str_offsets.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->types_dwo))
+ {
+ struct dwarf2_section_info type_section;
+
+ memset (&type_section, 0, sizeof (type_section));
+ type_section.asection = sectp;
+ type_section.size = bfd_get_section_size (sectp);
+ VEC_safe_push (dwarf2_section_info_def, dwo_file->sections.types,
+ &type_section);
+ }
+}
+
+/* Structure used to pass data to create_debug_info_hash_table_reader. */
+
+struct create_dwo_info_table_data
+{
+ struct dwo_file *dwo_file;
+ htab_t cu_htab;
+};
+
+/* die_reader_func for create_debug_info_hash_table. */
+
+static void
+create_debug_info_hash_table_reader (const struct die_reader_specs *reader,
+ gdb_byte *info_ptr,
+ struct die_info *comp_unit_die,
+ int has_children,
+ void *datap)
+{
+ struct dwarf2_cu *cu = reader->cu;
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ sect_offset offset = cu->per_cu->offset;
+ struct dwarf2_section_info *section = cu->per_cu->info_or_types_section;
+ struct create_dwo_info_table_data *data = datap;
+ struct dwo_file *dwo_file = data->dwo_file;
+ htab_t cu_htab = data->cu_htab;
+ void **slot;
+ struct attribute *attr;
+ struct dwo_unit *dwo_unit;
+
+ attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_id, cu);
+ if (attr == NULL)
+ {
+ error (_("Dwarf Error: debug entry at offset 0x%x is missing"
+ " its dwo_id [in module %s]"),
+ offset.sect_off, dwo_file->dwo_name);
+ return;
+ }
+
+ dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
+ dwo_unit->dwo_file = dwo_file;
+ dwo_unit->signature = DW_UNSND (attr);
+ dwo_unit->info_or_types_section = section;
+ dwo_unit->offset = offset;
+ dwo_unit->length = cu->per_cu->length;
+
+ slot = htab_find_slot (cu_htab, dwo_unit, INSERT);
+ gdb_assert (slot != NULL);
+ if (*slot != NULL)
+ {
+ const struct dwo_unit *dup_dwo_unit = *slot;
+
+ complaint (&symfile_complaints,
+ _("debug entry at offset 0x%x is duplicate to the entry at"
+ " offset 0x%x, dwo_id 0x%s [in module %s]"),
+ offset.sect_off, dup_dwo_unit->offset.sect_off,
+ phex (dwo_unit->signature, sizeof (dwo_unit->signature)),
+ dwo_file->dwo_name);
+ }
+ else
+ *slot = dwo_unit;
+
+ if (dwarf2_die_debug)
+ fprintf_unfiltered (gdb_stdlog, " offset 0x%x, dwo_id 0x%s\n",
+ offset.sect_off,
+ phex (dwo_unit->signature,
+ sizeof (dwo_unit->signature)));
+}
+
+/* Create a hash table to map DWO IDs to their CU entry in .debug_info.dwo. */
+
+static htab_t
+create_debug_info_hash_table (struct dwo_file *dwo_file)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct dwarf2_section_info *section = &dwo_file->sections.info;
+ bfd *abfd;
+ htab_t cu_htab;
+ gdb_byte *info_ptr, *end_ptr;
+ struct create_dwo_info_table_data create_dwo_info_table_data;
+
+ dwarf2_read_section (objfile, section);
+ info_ptr = section->buffer;
+
+ if (info_ptr == NULL)
+ return NULL;
+
+ /* We can't set abfd until now because the section may be empty or
+ not present, in which case section->asection will be NULL. */
+ abfd = section->asection->owner;
+
+ if (dwarf2_die_debug)
+ fprintf_unfiltered (gdb_stdlog, "Reading .debug_info.dwo for %s:\n",
+ bfd_get_filename (abfd));
+
+ cu_htab = allocate_dwo_unit_table (objfile);
+
+ create_dwo_info_table_data.dwo_file = dwo_file;
+ create_dwo_info_table_data.cu_htab = cu_htab;
+
+ end_ptr = info_ptr + section->size;
+ while (info_ptr < end_ptr)
+ {
+ struct dwarf2_per_cu_data per_cu;
+
+ memset (&per_cu, 0, sizeof (per_cu));
+ per_cu.objfile = objfile;
+ per_cu.is_debug_types = 0;
+ per_cu.offset.sect_off = info_ptr - section->buffer;
+ per_cu.info_or_types_section = section;
+
+ init_cutu_and_read_dies_no_follow (&per_cu,
+ &dwo_file->sections.abbrev,
+ dwo_file,
+ create_debug_info_hash_table_reader,
+ &create_dwo_info_table_data);
+
+ info_ptr += per_cu.length;
+ }
+
+ return cu_htab;
+}
+
+/* Subroutine of open_dwo_file to simplify it.
+ Open the file specified by FILE_NAME and hand it off to BFD for
+ preliminary analysis. Return a newly initialized bfd *, which
+ includes a canonicalized copy of FILE_NAME.
+ In case of trouble, return NULL.
+ NOTE: This function is derived from symfile_bfd_open. */
+
+static bfd *
+try_open_dwo_file (const char *file_name)
+{
+ bfd *sym_bfd;
+ int desc;
+ char *absolute_name;
+
+ desc = openp (debug_file_directory, OPF_TRY_CWD_FIRST, file_name,
+ O_RDONLY | O_BINARY, &absolute_name);
+ if (desc < 0)
+ return NULL;
+
+ sym_bfd = bfd_fopen (absolute_name, gnutarget, FOPEN_RB, desc);
+ if (!sym_bfd)
+ {
+ close (desc);
+ xfree (absolute_name);
+ return NULL;
+ }
+ bfd_set_cacheable (sym_bfd, 1);
+
+ if (!bfd_check_format (sym_bfd, bfd_object))
+ {
+ bfd_close (sym_bfd); /* This also closes desc. */
+ xfree (absolute_name);
+ return NULL;
+ }
+
+ /* bfd_usrdata exists for applications and libbfd must not touch it. */
+ gdb_assert (bfd_usrdata (sym_bfd) == NULL);
+
+ return sym_bfd;
+}
+
+/* Try to open DWO file DWO_NAME.
+ COMP_DIR is the DW_AT_comp_dir attribute.
+ The result is the bfd handle of the file.
+ If there is a problem finding or opening the file, return NULL.
+ Upon success, the canonicalized path of the file is stored in the bfd,
+ same as symfile_bfd_open. */
+
+static bfd *
+open_dwo_file (const char *dwo_name, const char *comp_dir)
+{
+ bfd *abfd;
+
+ if (IS_ABSOLUTE_PATH (dwo_name))
+ return try_open_dwo_file (dwo_name);
+
+ /* Before trying the search path, try DWO_NAME in COMP_DIR. */
+
+ if (comp_dir != NULL)
+ {
+ char *path_to_try = concat (comp_dir, SLASH_STRING, dwo_name, NULL);
+
+ /* NOTE: If comp_dir is a relative path, this will also try the
+ search path, which seems useful. */
+ abfd = try_open_dwo_file (path_to_try);
+ xfree (path_to_try);
+ if (abfd != NULL)
+ return abfd;
+ }
+
+ /* That didn't work, try debug-file-directory, which, despite its name,
+ is a list of paths. */
+
+ if (*debug_file_directory == '\0')
+ return NULL;
+
+ return try_open_dwo_file (dwo_name);
+}
+
+/* Initialize the use of the DWO file specified by DWO_NAME. */
+
+static struct dwo_file *
+init_dwo_file (const char *dwo_name, const char *comp_dir)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct dwo_file *dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwo_file);
+ bfd *abfd;
+ struct cleanup *cleanups;
+
+ if (dwarf2_die_debug)
+ fprintf_unfiltered (gdb_stdlog, "Reading DWO file %s:\n", dwo_name);
+
+ abfd = open_dwo_file (dwo_name, comp_dir);
+ if (abfd == NULL)
+ return NULL;
+ dwo_file->dwo_name = dwo_name;
+ dwo_file->dwo_bfd = abfd;
+
+ cleanups = make_cleanup (free_dwo_file_cleanup, dwo_file);
+
+ bfd_map_over_sections (abfd, dwarf2_locate_dwo_sections, dwo_file);
+
+ dwo_file->cus = create_debug_info_hash_table (dwo_file);
+
+ dwo_file->tus = create_debug_types_hash_table (dwo_file,
+ dwo_file->sections.types);
+
+ discard_cleanups (cleanups);
+
+ return dwo_file;
+}
+
+/* Lookup DWO file DWO_NAME. */
+
+static struct dwo_file *
+lookup_dwo_file (char *dwo_name, const char *comp_dir)
+{
+ struct dwo_file *dwo_file;
+ struct dwo_file find_entry;
+ void **slot;
+
+ if (dwarf2_per_objfile->dwo_files == NULL)
+ dwarf2_per_objfile->dwo_files = allocate_dwo_file_hash_table ();
+
+ /* Have we already seen this DWO file? */
+ find_entry.dwo_name = dwo_name;
+ slot = htab_find_slot (dwarf2_per_objfile->dwo_files, &find_entry, INSERT);
+
+ /* If not, read it in and build a table of the DWOs it contains. */
+ if (*slot == NULL)
+ *slot = init_dwo_file (dwo_name, comp_dir);
+
+ /* NOTE: This will be NULL if unable to open the file. */
+ dwo_file = *slot;
+
+ return dwo_file;
+}
+
+/* Lookup the DWO CU referenced from THIS_CU in DWO file DWO_NAME.
+ If non-NULL, comp_dir is the DW_AT_comp_dir attribute.
+ SIGNATURE is the "dwo_id" of the CU (for consistency we use the same
+ nomenclature as TUs).
+ The result is the DWO CU or NULL if we didn't find it
+ (dwo_id mismatch or couldn't find the DWO file). */
+
+static struct dwo_unit *
+lookup_dwo_comp_unit (struct dwarf2_per_cu_data *this_cu,
+ char *dwo_name, const char *comp_dir,
+ ULONGEST signature)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct dwo_file *dwo_file;
+
+ dwo_file = lookup_dwo_file (dwo_name, comp_dir);
+ if (dwo_file == NULL)
+ return NULL;
+
+ /* Look up the DWO using its signature(dwo_id). */
+
+ if (dwo_file->cus != NULL)
+ {
+ struct dwo_unit find_dwo_cu, *dwo_cu;
+
+ find_dwo_cu.signature = signature;
+ dwo_cu = htab_find (dwo_file->cus, &find_dwo_cu);
+
+ if (dwo_cu != NULL)
+ return dwo_cu;
+ }
+
+ /* We didn't find it. This must mean a dwo_id mismatch. */
+
+ complaint (&symfile_complaints,
+ _("Could not find DWO CU referenced by CU at offset 0x%x"
+ " [in module %s]"),
+ this_cu->offset.sect_off, objfile->name);
+ return NULL;
+}
+
+/* Lookup the DWO TU referenced from THIS_TU in DWO file DWO_NAME.
+ If non-NULL, comp_dir is the DW_AT_comp_dir attribute.
+ The result is the DWO CU or NULL if we didn't find it
+ (dwo_id mismatch or couldn't find the DWO file). */
+
+static struct dwo_unit *
+lookup_dwo_type_unit (struct signatured_type *this_tu,
+ char *dwo_name, const char *comp_dir)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct dwo_file *dwo_file;
+
+ dwo_file = lookup_dwo_file (dwo_name, comp_dir);
+ if (dwo_file == NULL)
+ return NULL;
+
+ /* Look up the DWO using its signature(dwo_id). */
+
+ if (dwo_file->tus != NULL)
+ {
+ struct dwo_unit find_dwo_tu, *dwo_tu;
+
+ find_dwo_tu.signature = this_tu->signature;
+ dwo_tu = htab_find (dwo_file->tus, &find_dwo_tu);
+
+ if (dwo_tu != NULL)
+ return dwo_tu;
+ }
+
+ /* We didn't find it. This must mean a dwo_id mismatch. */
+
+ complaint (&symfile_complaints,
+ _("Could not find DWO TU referenced by TU at offset 0x%x"
+ " [in module %s]"),
+ this_tu->per_cu.offset.sect_off, objfile->name);
+ return NULL;
+}
+
+/* Free all resources associated with DWO_FILE.
+ Close the DWO file and munmap the sections.
+ All memory should be on the objfile obstack. */
+
+static void
+free_dwo_file (struct dwo_file *dwo_file, struct objfile *objfile)
+{
+ int ix;
+ struct dwarf2_section_info *section;
+
+ gdb_assert (dwo_file->dwo_bfd != objfile->obfd);
+ bfd_close (dwo_file->dwo_bfd);
+
+ munmap_section_buffer (&dwo_file->sections.abbrev);
+ munmap_section_buffer (&dwo_file->sections.info);
+ munmap_section_buffer (&dwo_file->sections.line);
+ munmap_section_buffer (&dwo_file->sections.loc);
+ munmap_section_buffer (&dwo_file->sections.str);
+ munmap_section_buffer (&dwo_file->sections.str_offsets);
+
+ for (ix = 0;
+ VEC_iterate (dwarf2_section_info_def, dwo_file->sections.types,
+ ix, section);
+ ++ix)
+ munmap_section_buffer (section);
+
+ VEC_free (dwarf2_section_info_def, dwo_file->sections.types);
+}
+
+/* Wrapper for free_dwo_file for use in cleanups. */
+
+static void
+free_dwo_file_cleanup (void *arg)
+{
+ struct dwo_file *dwo_file = (struct dwo_file *) arg;
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+
+ free_dwo_file (dwo_file, objfile);
+}
+
+/* Traversal function for free_dwo_files. */
+
+static int
+free_dwo_file_from_slot (void **slot, void *info)
+{
+ struct dwo_file *dwo_file = (struct dwo_file *) *slot;
+ struct objfile *objfile = (struct objfile *) info;
+
+ free_dwo_file (dwo_file, objfile);
+
+ return 1;
+}
+
+/* Free all resources associated with DWO_FILES. */
+
+static void
+free_dwo_files (htab_t dwo_files, struct objfile *objfile)
+{
+ htab_traverse_noresize (dwo_files, free_dwo_file_from_slot, objfile);
+}
+\f
+/* Read in various DIEs. */
/* qsort helper for inherit_abstract_dies. */
child_die && child_die->tag;
child_die = sibling_die (child_die))
{
- struct dwarf2_locexpr_baton *dlbaton;
struct call_site_parameter *parameter;
if (child_die->tag != DW_TAG_GNU_call_site_parameter)
if (attr)
{
low = DW_ADDR (attr);
- if (attr_high->form == DW_FORM_addr)
+ if (attr_high->form == DW_FORM_addr
+ || attr_high->form == DW_FORM_GNU_addr_index)
high = DW_ADDR (attr_high);
else
high = low + DW_UNSND (attr_high);
{
CORE_ADDR low = DW_ADDR (attr);
CORE_ADDR high;
- if (attr_high->form == DW_FORM_addr)
+ if (attr_high->form == DW_FORM_addr
+ || attr_high->form == DW_FORM_GNU_addr_index)
high = DW_ADDR (attr_high);
else
high = low + DW_UNSND (attr_high);
actually available. Note that we do not want to do this for all
enums which are just declarations, because C++0x allows forward
enum declarations. */
- if (cu->per_cu->debug_types_section
+ if (cu->per_cu->is_debug_types
&& die_is_declaration (die, cu))
{
struct signatured_type *sig_type;
sig_type
= lookup_signatured_type_at_offset (dwarf2_per_objfile->objfile,
- cu->per_cu->debug_types_section,
+ cu->per_cu->info_or_types_section,
cu->per_cu->offset);
- if (sig_type->per_cu.offset.sect_off + sig_type->type_offset.cu_off
- != die->offset.sect_off)
+ gdb_assert (sig_type->type_offset_in_section.sect_off != 0);
+ if (sig_type->type_offset_in_section.sect_off != die->offset.sect_off)
return;
}
}
}
-/* 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. */
+/* Read a die and all its attributes, leave space for NUM_EXTRA_ATTRS
+ attributes.
+ The caller is responsible for filling in the extra attributes
+ and updating (*DIEP)->num_attrs.
+ 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 gdb_byte *
-read_full_die (const struct die_reader_specs *reader,
- struct die_info **diep, gdb_byte *info_ptr,
- int *has_children)
+read_full_die_1 (const struct die_reader_specs *reader,
+ struct die_info **diep, gdb_byte *info_ptr,
+ int *has_children, int num_extra_attrs)
{
unsigned int abbrev_number, bytes_read, i;
sect_offset offset;
abbrev_number,
bfd_get_filename (abfd));
- die = dwarf_alloc_die (cu, abbrev->num_attrs);
+ die = dwarf_alloc_die (cu, abbrev->num_attrs + num_extra_attrs);
die->offset = offset;
die->tag = abbrev->tag;
die->abbrev = abbrev_number;
+ /* Make the result usable.
+ The caller needs to update num_attrs after adding the extra
+ attributes. */
die->num_attrs = abbrev->num_attrs;
for (i = 0; i < abbrev->num_attrs; ++i)
return info_ptr;
}
+/* Read a die and all its attributes.
+ 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 gdb_byte *
+read_full_die (const struct die_reader_specs *reader,
+ struct die_info **diep, gdb_byte *info_ptr,
+ int *has_children)
+{
+ return read_full_die_1 (reader, diep, info_ptr, has_children, 0);
+}
+
/* 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
&& abbrev->tag != DW_TAG_variable
&& abbrev->tag != DW_TAG_namespace
&& abbrev->tag != DW_TAG_module
- && abbrev->tag != DW_TAG_member)
+ && abbrev->tag != DW_TAG_member
+ && abbrev->tag != DW_TAG_imported_unit)
{
/* Otherwise we skip to the next sibling, if any. */
info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
switch (part_die->tag)
{
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
case DW_TAG_type_unit:
/* Compilation units have a DW_AT_name that is a filename, not
a source language identifier. */
break;
case DW_AT_high_pc:
has_high_pc_attr = 1;
- if (attr.form == DW_FORM_addr)
+ if (attr.form == DW_FORM_addr
+ || attr.form == DW_FORM_GNU_addr_index)
part_die->highpc = DW_ADDR (&attr);
else
{
/* Support the .debug_loc offsets. */
if (attr_form_is_block (&attr))
{
- part_die->locdesc = DW_BLOCK (&attr);
+ part_die->d.locdesc = DW_BLOCK (&attr);
}
else if (attr_form_is_section_offset (&attr))
{
|| DW_UNSND (&attr) == DW_INL_declared_inlined)
part_die->may_be_inlined = 1;
break;
+
+ case DW_AT_import:
+ if (part_die->tag == DW_TAG_imported_unit)
+ part_die->d.offset = dwarf2_get_ref_die_offset (&attr);
+ break;
+
default:
break;
}
else
{
/* TUs don't reference other CUs/TUs (except via type signatures). */
- if (cu->per_cu->debug_types_section)
+ if (cu->per_cu->is_debug_types)
{
error (_("Dwarf Error: Type Unit at offset 0x%lx contains"
" external reference to offset 0x%lx [in module %s].\n"),
if (pd == NULL && per_cu->load_all_dies == 0)
{
- /* FIXME: The testsuite doesn't trigger this code path.
- http://sourceware.org/bugzilla/show_bug.cgi?id=13961 */
-
- free_one_cached_comp_unit (per_cu);
per_cu->load_all_dies = 1;
+
+ /* This is nasty. When we reread the DIEs, somewhere up the call chain
+ THIS_CU->cu may already be in use. So we can't just free it and
+ replace its DIEs with the ones we read in. Instead, we leave those
+ DIEs alone (which can still be in use, e.g. in scan_partial_symbols),
+ and clobber THIS_CU->cu->partial_dies with the hash table for the new
+ set. */
load_partial_comp_unit (per_cu);
pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
info_ptr += bytes_read;
info_ptr = read_attribute_value (reader, attr, form, info_ptr);
break;
+ case DW_FORM_GNU_addr_index:
+ if (reader->dwo_file == NULL)
+ {
+ /* For now flag a hard error.
+ Later we can turn this into a complaint. */
+ error (_("Dwarf Error: %s found in non-DWO CU [in module %s]"),
+ dwarf_form_name (form),
+ bfd_get_filename (abfd));
+ }
+ DW_ADDR (attr) = read_addr_index_from_leb128 (cu, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ break;
+ case DW_FORM_GNU_str_index:
+ if (reader->dwo_file == NULL)
+ {
+ /* For now flag a hard error.
+ Later we can turn this into a complaint if warranted. */
+ error (_("Dwarf Error: %s found in non-DWO CU [in module %s]"),
+ dwarf_form_name (form),
+ bfd_get_filename (abfd));
+ }
+ {
+ ULONGEST str_index =
+ read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
+
+ DW_STRING (attr) = read_str_index (reader, cu, str_index);
+ DW_STRING_IS_CANONICAL (attr) = 0;
+ info_ptr += bytes_read;
+ }
+ break;
default:
error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"),
dwarf_form_name (form),
return result;
}
+/* Given index ADDR_INDEX in .debug_addr, fetch the value.
+ ADDR_BASE is the DW_AT_GNU_addr_base attribute or zero.
+ ADDR_SIZE is the size of addresses from the CU header. */
+
+static CORE_ADDR
+read_addr_index_1 (unsigned int addr_index, ULONGEST addr_base, int addr_size)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ bfd *abfd = objfile->obfd;
+ const gdb_byte *info_ptr;
+
+ dwarf2_read_section (objfile, &dwarf2_per_objfile->addr);
+ if (dwarf2_per_objfile->addr.buffer == NULL)
+ error (_("DW_FORM_addr_index used without .debug_addr section [in module %s]"),
+ objfile->name);
+ if (addr_base + addr_index * addr_size >= dwarf2_per_objfile->addr.size)
+ error (_("DW_FORM_addr_index pointing outside of "
+ ".debug_addr section [in module %s]"),
+ objfile->name);
+ info_ptr = (dwarf2_per_objfile->addr.buffer
+ + addr_base + addr_index * addr_size);
+ if (addr_size == 4)
+ return bfd_get_32 (abfd, info_ptr);
+ else
+ return bfd_get_64 (abfd, info_ptr);
+}
+
+/* Given index ADDR_INDEX in .debug_addr, fetch the value. */
+
+static CORE_ADDR
+read_addr_index (struct dwarf2_cu *cu, unsigned int addr_index)
+{
+ return read_addr_index_1 (addr_index, cu->addr_base, cu->header.addr_size);
+}
+
+/* Given a pointer to an leb128 value, fetch the value from .debug_addr. */
+
+static CORE_ADDR
+read_addr_index_from_leb128 (struct dwarf2_cu *cu, gdb_byte *info_ptr,
+ unsigned int *bytes_read)
+{
+ bfd *abfd = cu->objfile->obfd;
+ unsigned int addr_index = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
+
+ return read_addr_index (cu, addr_index);
+}
+
+/* Data structure to pass results from dwarf2_read_addr_index_reader
+ back to dwarf2_read_addr_index. */
+
+struct dwarf2_read_addr_index_data
+{
+ ULONGEST addr_base;
+ int addr_size;
+};
+
+/* die_reader_func for dwarf2_read_addr_index. */
+
+static void
+dwarf2_read_addr_index_reader (const struct die_reader_specs *reader,
+ gdb_byte *info_ptr,
+ struct die_info *comp_unit_die,
+ int has_children,
+ void *data)
+{
+ struct dwarf2_cu *cu = reader->cu;
+ struct dwarf2_read_addr_index_data *aidata =
+ (struct dwarf2_read_addr_index_data *) data;
+
+ aidata->addr_base = cu->addr_base;
+ aidata->addr_size = cu->header.addr_size;
+}
+
+/* Given an index in .debug_addr, fetch the value.
+ NOTE: This can be called during dwarf expression evaluation,
+ long after the debug information has been read, and thus per_cu->cu
+ may no longer exist. */
+
+CORE_ADDR
+dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
+ unsigned int addr_index)
+{
+ struct objfile *objfile = per_cu->objfile;
+ struct dwarf2_cu *cu = per_cu->cu;
+ ULONGEST addr_base;
+ int addr_size;
+
+ /* This is intended to be called from outside this file. */
+ dw2_setup (objfile);
+
+ /* We need addr_base and addr_size.
+ If we don't have PER_CU->cu, we have to get it.
+ Nasty, but the alternative is storing the needed info in PER_CU,
+ which at this point doesn't seem justified: it's not clear how frequently
+ it would get used and it would increase the size of every PER_CU.
+ Entry points like dwarf2_per_cu_addr_size do a similar thing
+ so we're not in uncharted territory here.
+ Alas we need to be a bit more complicated as addr_base is contained
+ in the DIE.
+
+ We don't need to read the entire CU(/TU).
+ We just need the header and top level die.
+ IWBN to use the aging mechanism to let us lazily later discard the CU.
+ See however init_cutu_and_read_dies_simple. */
+
+ if (cu != NULL)
+ {
+ addr_base = cu->addr_base;
+ addr_size = cu->header.addr_size;
+ }
+ else
+ {
+ struct dwarf2_read_addr_index_data aidata;
+
+ init_cutu_and_read_dies_simple (per_cu, dwarf2_read_addr_index_reader,
+ &aidata);
+ addr_base = aidata.addr_base;
+ addr_size = aidata.addr_size;
+ }
+
+ return read_addr_index_1 (addr_index, addr_base, addr_size);
+}
+
+/* Given a DW_AT_str_index, fetch the string. */
+
+static char *
+read_str_index (const struct die_reader_specs *reader,
+ struct dwarf2_cu *cu, ULONGEST str_index)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ const char *dwo_name = objfile->name;
+ bfd *abfd = objfile->obfd;
+ struct dwo_sections *sections = &reader->dwo_file->sections;
+ gdb_byte *info_ptr;
+ ULONGEST str_offset;
+
+ dwarf2_read_section (objfile, §ions->str);
+ dwarf2_read_section (objfile, §ions->str_offsets);
+ if (sections->str.buffer == NULL)
+ error (_("DW_FORM_str_index used without .debug_str.dwo section"
+ " in CU at offset 0x%lx [in module %s]"),
+ (long) cu->header.offset.sect_off, dwo_name);
+ if (sections->str_offsets.buffer == NULL)
+ error (_("DW_FORM_str_index used without .debug_str_offsets.dwo section"
+ " in CU at offset 0x%lx [in module %s]"),
+ (long) cu->header.offset.sect_off, dwo_name);
+ if (str_index * cu->header.offset_size >= sections->str_offsets.size)
+ error (_("DW_FORM_str_index pointing outside of .debug_str_offsets.dwo"
+ " section in CU at offset 0x%lx [in module %s]"),
+ (long) cu->header.offset.sect_off, dwo_name);
+ info_ptr = (sections->str_offsets.buffer
+ + str_index * cu->header.offset_size);
+ if (cu->header.offset_size == 4)
+ str_offset = bfd_get_32 (abfd, info_ptr);
+ else
+ str_offset = bfd_get_64 (abfd, info_ptr);
+ if (str_offset >= sections->str.size)
+ error (_("Offset from DW_FORM_str_index pointing outside of"
+ " .debug_str.dwo section in CU at offset 0x%lx [in module %s]"),
+ (long) cu->header.offset.sect_off, dwo_name);
+ return (char *) (sections->str.buffer + str_offset);
+}
+
/* Return a pointer to just past the end of an LEB128 number in BUF. */
static gdb_byte *
}
}
+/* Return the length of an LEB128 number in BUF. */
+
+static int
+leb128_size (const gdb_byte *buf)
+{
+ const gdb_byte *begin = buf;
+ gdb_byte byte;
+
+ while (1)
+ {
+ byte = *buf++;
+ if ((byte & 128) == 0)
+ return buf - begin;
+ }
+}
+
static void
set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
{
}
/* Read the statement program header starting at OFFSET in
- .debug_line, according to the endianness of ABFD. Return a pointer
+ .debug_line, or .debug_line.dwo. Return a pointer
to a struct line_header, allocated using xmalloc.
NOTE: the strings in the include directory and file name tables of
- the returned object point into debug_line_buffer, and must not be
- freed. */
+ the returned object point into the dwarf line section buffer,
+ and must not be freed. */
static struct line_header *
-dwarf_decode_line_header (unsigned int offset, bfd *abfd,
- struct dwarf2_cu *cu)
+dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
{
struct cleanup *back_to;
struct line_header *lh;
unsigned int bytes_read, offset_size;
int i;
char *cur_dir, *cur_file;
+ struct dwarf2_section_info *section;
+ bfd *abfd;
+
+ /* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
+ DWO file. */
+ if (cu->dwo_unit && cu->per_cu->is_debug_types)
+ section = &cu->dwo_unit->dwo_file->sections.line;
+ else
+ section = &dwarf2_per_objfile->line;
- dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->line);
- if (dwarf2_per_objfile->line.buffer == NULL)
+ dwarf2_read_section (dwarf2_per_objfile->objfile, section);
+ if (section->buffer == NULL)
{
- complaint (&symfile_complaints, _("missing .debug_line section"));
+ if (cu->dwo_unit && cu->per_cu->is_debug_types)
+ complaint (&symfile_complaints, _("missing .debug_line.dwo section"));
+ else
+ complaint (&symfile_complaints, _("missing .debug_line section"));
return 0;
}
+ /* We can't do this until we know the section is non-empty.
+ Only then do we know we have such a section. */
+ abfd = section->asection->owner;
+
/* 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)
+ if (offset + 4 >= section->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 = dwarf2_per_objfile->line.buffer + offset;
+ line_ptr = section->buffer + offset;
/* Read in the header. */
lh->total_length =
read_checked_initial_length_and_offset (abfd, line_ptr, &cu->header,
&bytes_read, &offset_size);
line_ptr += bytes_read;
- if (line_ptr + lh->total_length > (dwarf2_per_objfile->line.buffer
- + dwarf2_per_objfile->line.size))
+ if (line_ptr + lh->total_length > (section->buffer + section->size))
{
dwarf2_statement_list_fits_in_line_number_section_complaint ();
return 0;
line_ptr += bytes_read;
lh->statement_program_start = line_ptr;
- if (line_ptr > (dwarf2_per_objfile->line.buffer
- + dwarf2_per_objfile->line.size))
+ if (line_ptr > (section->buffer + section->size))
complaint (&symfile_complaints,
_("line number info header doesn't "
"fit in `.debug_line' section"));
/* Handle one degenerate form of location expression specially, to
preserve GDB's previous behavior when section offsets are
- specified. If this is just a DW_OP_addr then mark this symbol
- as LOC_STATIC. */
+ specified. If this is just a DW_OP_addr or DW_OP_GNU_addr_index
+ then mark this symbol as LOC_STATIC. */
if (attr_form_is_block (attr)
- && DW_BLOCK (attr)->size == 1 + cu_header->addr_size
- && DW_BLOCK (attr)->data[0] == DW_OP_addr)
+ && ((DW_BLOCK (attr)->data[0] == DW_OP_addr
+ && DW_BLOCK (attr)->size == 1 + cu_header->addr_size)
+ || (DW_BLOCK (attr)->data[0] == DW_OP_GNU_addr_index
+ && (DW_BLOCK (attr)->size
+ == 1 + leb128_size (&DW_BLOCK (attr)->data[1])))))
{
unsigned int dummy;
- SYMBOL_VALUE_ADDRESS (sym) =
- read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu, &dummy);
+ if (DW_BLOCK (attr)->data[0] == DW_OP_addr)
+ SYMBOL_VALUE_ADDRESS (sym) =
+ read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu, &dummy);
+ else
+ SYMBOL_VALUE_ADDRESS (sym) =
+ read_addr_index_from_leb128 (cu, DW_BLOCK (attr)->data + 1, &dummy);
SYMBOL_CLASS (sym) = LOC_STATIC;
fixup_symbol_section (sym, objfile);
SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets,
switch (attr->form)
{
case DW_FORM_addr:
+ case DW_FORM_GNU_addr_index:
{
gdb_byte *data;
break;
case DW_FORM_string:
case DW_FORM_strp:
+ case DW_FORM_GNU_str_index:
/* DW_STRING is already allocated on the objfile obstack, point
directly to it. */
*bytes = (gdb_byte *) DW_STRING (attr);
else if (attr->form == DW_FORM_ref_sig8)
{
struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr);
- sect_offset offset;
/* sig_type will be NULL if the signatured type is missing from
the debug info. */
"at 0x%x [in module %s]"),
die->offset.sect_off, objfile->name);
- gdb_assert (sig_type->per_cu.debug_types_section);
- offset.sect_off = (sig_type->per_cu.offset.sect_off
- + sig_type->type_offset.cu_off);
- this_type = get_die_type_at_offset (offset, &sig_type->per_cu);
+ gdb_assert (sig_type->per_cu.is_debug_types);
+ /* If we haven't filled in type_offset_in_section yet, then we
+ haven't read the type in yet. */
+ this_type = NULL;
+ if (sig_type->type_offset_in_section.sect_off != 0)
+ {
+ this_type =
+ get_die_type_at_offset (sig_type->type_offset_in_section,
+ &sig_type->per_cu);
+ }
}
else
{
struct dwarf2_cu *type_cu = cu;
type_die = follow_die_ref_or_sig (die, attr, &type_cu);
- /* If the type is cached, we should have found it above. */
- gdb_assert (get_die_type (type_die, type_cu) == NULL);
- this_type = read_type_die_1 (type_die, type_cu);
+ /* If we found the type now, it's probably because the type came
+ from an inter-CU reference and the type's CU got expanded before
+ ours. */
+ this_type = get_die_type (type_die, type_cu);
+ if (this_type == NULL)
+ this_type = read_type_die_1 (type_die, type_cu);
}
/* If we still don't have a type use an error marker. */
So it does not need a prefix. */
return "";
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
/* gcc-4.5 -gdwarf-4 can drop the enclosing namespace. Cope. */
if (cu->language == language_cplus
&& !VEC_empty (dwarf2_section_info_def, dwarf2_per_objfile->types)
switch (die->tag)
{
case DW_TAG_compile_unit:
+ case DW_TAG_partial_unit:
/* Compilation units have a DW_AT_name that is a filename, not
a source language identifier. */
case DW_TAG_enumeration_type:
if (die->tag == DW_TAG_class_type)
return dwarf2_name (die, cu);
}
- while (die->tag != DW_TAG_compile_unit);
+ while (die->tag != DW_TAG_compile_unit
+ && die->tag != DW_TAG_partial_unit);
}
break;
/* Convert a DIE tag into its string name. */
-static char *
+static const char *
dwarf_tag_name (unsigned tag)
{
- switch (tag)
- {
- case DW_TAG_padding:
- return "DW_TAG_padding";
- case DW_TAG_array_type:
- return "DW_TAG_array_type";
- case DW_TAG_class_type:
- return "DW_TAG_class_type";
- case DW_TAG_entry_point:
- return "DW_TAG_entry_point";
- case DW_TAG_enumeration_type:
- return "DW_TAG_enumeration_type";
- case DW_TAG_formal_parameter:
- return "DW_TAG_formal_parameter";
- case DW_TAG_imported_declaration:
- return "DW_TAG_imported_declaration";
- case DW_TAG_label:
- return "DW_TAG_label";
- case DW_TAG_lexical_block:
- return "DW_TAG_lexical_block";
- case DW_TAG_member:
- return "DW_TAG_member";
- case DW_TAG_pointer_type:
- return "DW_TAG_pointer_type";
- case DW_TAG_reference_type:
- return "DW_TAG_reference_type";
- case DW_TAG_compile_unit:
- return "DW_TAG_compile_unit";
- case DW_TAG_string_type:
- return "DW_TAG_string_type";
- case DW_TAG_structure_type:
- return "DW_TAG_structure_type";
- case DW_TAG_subroutine_type:
- return "DW_TAG_subroutine_type";
- case DW_TAG_typedef:
- return "DW_TAG_typedef";
- case DW_TAG_union_type:
- return "DW_TAG_union_type";
- case DW_TAG_unspecified_parameters:
- return "DW_TAG_unspecified_parameters";
- case DW_TAG_variant:
- return "DW_TAG_variant";
- case DW_TAG_common_block:
- return "DW_TAG_common_block";
- case DW_TAG_common_inclusion:
- return "DW_TAG_common_inclusion";
- case DW_TAG_inheritance:
- return "DW_TAG_inheritance";
- case DW_TAG_inlined_subroutine:
- return "DW_TAG_inlined_subroutine";
- case DW_TAG_module:
- return "DW_TAG_module";
- case DW_TAG_ptr_to_member_type:
- return "DW_TAG_ptr_to_member_type";
- case DW_TAG_set_type:
- return "DW_TAG_set_type";
- case DW_TAG_subrange_type:
- return "DW_TAG_subrange_type";
- case DW_TAG_with_stmt:
- return "DW_TAG_with_stmt";
- case DW_TAG_access_declaration:
- return "DW_TAG_access_declaration";
- case DW_TAG_base_type:
- return "DW_TAG_base_type";
- case DW_TAG_catch_block:
- return "DW_TAG_catch_block";
- case DW_TAG_const_type:
- return "DW_TAG_const_type";
- case DW_TAG_constant:
- return "DW_TAG_constant";
- case DW_TAG_enumerator:
- return "DW_TAG_enumerator";
- case DW_TAG_file_type:
- return "DW_TAG_file_type";
- case DW_TAG_friend:
- return "DW_TAG_friend";
- case DW_TAG_namelist:
- return "DW_TAG_namelist";
- case DW_TAG_namelist_item:
- return "DW_TAG_namelist_item";
- case DW_TAG_packed_type:
- return "DW_TAG_packed_type";
- case DW_TAG_subprogram:
- return "DW_TAG_subprogram";
- case DW_TAG_template_type_param:
- return "DW_TAG_template_type_param";
- case DW_TAG_template_value_param:
- return "DW_TAG_template_value_param";
- case DW_TAG_thrown_type:
- return "DW_TAG_thrown_type";
- case DW_TAG_try_block:
- return "DW_TAG_try_block";
- case DW_TAG_variant_part:
- return "DW_TAG_variant_part";
- case DW_TAG_variable:
- return "DW_TAG_variable";
- case DW_TAG_volatile_type:
- return "DW_TAG_volatile_type";
- case DW_TAG_dwarf_procedure:
- return "DW_TAG_dwarf_procedure";
- case DW_TAG_restrict_type:
- return "DW_TAG_restrict_type";
- case DW_TAG_interface_type:
- return "DW_TAG_interface_type";
- case DW_TAG_namespace:
- return "DW_TAG_namespace";
- case DW_TAG_imported_module:
- return "DW_TAG_imported_module";
- case DW_TAG_unspecified_type:
- return "DW_TAG_unspecified_type";
- case DW_TAG_partial_unit:
- return "DW_TAG_partial_unit";
- case DW_TAG_imported_unit:
- return "DW_TAG_imported_unit";
- case DW_TAG_condition:
- return "DW_TAG_condition";
- case DW_TAG_shared_type:
- return "DW_TAG_shared_type";
- case DW_TAG_type_unit:
- return "DW_TAG_type_unit";
- 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";
- case DW_TAG_GNU_call_site:
- return "DW_TAG_GNU_call_site";
- default:
- return "DW_TAG_<unknown>";
- }
+ const char *name = get_DW_TAG_name (tag);
+
+ if (name == NULL)
+ return "DW_TAG_<unknown>";
+
+ return name;
}
/* Convert a DWARF attribute code into its string name. */
-static char *
+static const char *
dwarf_attr_name (unsigned attr)
{
- switch (attr)
- {
- case DW_AT_sibling:
- return "DW_AT_sibling";
- case DW_AT_location:
- return "DW_AT_location";
- case DW_AT_name:
- return "DW_AT_name";
- case DW_AT_ordering:
- return "DW_AT_ordering";
- case DW_AT_subscr_data:
- return "DW_AT_subscr_data";
- case DW_AT_byte_size:
- return "DW_AT_byte_size";
- case DW_AT_bit_offset:
- return "DW_AT_bit_offset";
- case DW_AT_bit_size:
- return "DW_AT_bit_size";
- case DW_AT_element_list:
- return "DW_AT_element_list";
- case DW_AT_stmt_list:
- return "DW_AT_stmt_list";
- case DW_AT_low_pc:
- return "DW_AT_low_pc";
- case DW_AT_high_pc:
- return "DW_AT_high_pc";
- case DW_AT_language:
- return "DW_AT_language";
- case DW_AT_member:
- return "DW_AT_member";
- case DW_AT_discr:
- return "DW_AT_discr";
- case DW_AT_discr_value:
- return "DW_AT_discr_value";
- case DW_AT_visibility:
- return "DW_AT_visibility";
- case DW_AT_import:
- return "DW_AT_import";
- case DW_AT_string_length:
- return "DW_AT_string_length";
- case DW_AT_common_reference:
- return "DW_AT_common_reference";
- case DW_AT_comp_dir:
- return "DW_AT_comp_dir";
- case DW_AT_const_value:
- return "DW_AT_const_value";
- case DW_AT_containing_type:
- return "DW_AT_containing_type";
- case DW_AT_default_value:
- return "DW_AT_default_value";
- case DW_AT_inline:
- return "DW_AT_inline";
- case DW_AT_is_optional:
- return "DW_AT_is_optional";
- case DW_AT_lower_bound:
- return "DW_AT_lower_bound";
- case DW_AT_producer:
- return "DW_AT_producer";
- case DW_AT_prototyped:
- return "DW_AT_prototyped";
- case DW_AT_return_addr:
- return "DW_AT_return_addr";
- case DW_AT_start_scope:
- return "DW_AT_start_scope";
- case DW_AT_bit_stride:
- return "DW_AT_bit_stride";
- case DW_AT_upper_bound:
- return "DW_AT_upper_bound";
- case DW_AT_abstract_origin:
- return "DW_AT_abstract_origin";
- case DW_AT_accessibility:
- return "DW_AT_accessibility";
- case DW_AT_address_class:
- return "DW_AT_address_class";
- case DW_AT_artificial:
- return "DW_AT_artificial";
- case DW_AT_base_types:
- return "DW_AT_base_types";
- case DW_AT_calling_convention:
- return "DW_AT_calling_convention";
- case DW_AT_count:
- return "DW_AT_count";
- case DW_AT_data_member_location:
- return "DW_AT_data_member_location";
- case DW_AT_decl_column:
- return "DW_AT_decl_column";
- case DW_AT_decl_file:
- return "DW_AT_decl_file";
- case DW_AT_decl_line:
- return "DW_AT_decl_line";
- case DW_AT_declaration:
- return "DW_AT_declaration";
- case DW_AT_discr_list:
- return "DW_AT_discr_list";
- case DW_AT_encoding:
- return "DW_AT_encoding";
- case DW_AT_external:
- return "DW_AT_external";
- case DW_AT_frame_base:
- return "DW_AT_frame_base";
- case DW_AT_friend:
- return "DW_AT_friend";
- case DW_AT_identifier_case:
- return "DW_AT_identifier_case";
- case DW_AT_macro_info:
- return "DW_AT_macro_info";
- case DW_AT_namelist_items:
- return "DW_AT_namelist_items";
- case DW_AT_priority:
- return "DW_AT_priority";
- case DW_AT_segment:
- return "DW_AT_segment";
- case DW_AT_specification:
- return "DW_AT_specification";
- case DW_AT_static_link:
- return "DW_AT_static_link";
- case DW_AT_type:
- return "DW_AT_type";
- case DW_AT_use_location:
- return "DW_AT_use_location";
- case DW_AT_variable_parameter:
- return "DW_AT_variable_parameter";
- case DW_AT_virtuality:
- 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_associated";
- case DW_AT_data_location:
- return "DW_AT_data_location";
- case DW_AT_byte_stride:
- return "DW_AT_byte_stride";
- case DW_AT_entry_pc:
- return "DW_AT_entry_pc";
- case DW_AT_use_UTF8:
- return "DW_AT_use_UTF8";
- case DW_AT_extension:
- return "DW_AT_extension";
- case DW_AT_ranges:
- return "DW_AT_ranges";
- case DW_AT_trampoline:
- return "DW_AT_trampoline";
- case DW_AT_call_column:
- return "DW_AT_call_column";
- case DW_AT_call_file:
- return "DW_AT_call_file";
- case DW_AT_call_line:
- return "DW_AT_call_line";
- 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";
- /* DWARF 4 values. */
- case DW_AT_signature:
- return "DW_AT_signature";
- case DW_AT_linkage_name:
- return "DW_AT_linkage_name";
- /* SGI/MIPS extensions. */
+ const char *name;
+
#ifdef MIPS /* collides with DW_AT_HP_block_index */
- case DW_AT_MIPS_fde:
- return "DW_AT_MIPS_fde";
-#endif
- case DW_AT_MIPS_loop_begin:
- return "DW_AT_MIPS_loop_begin";
- case DW_AT_MIPS_tail_loop_begin:
- return "DW_AT_MIPS_tail_loop_begin";
- case DW_AT_MIPS_epilog_begin:
- return "DW_AT_MIPS_epilog_begin";
- case DW_AT_MIPS_loop_unroll_factor:
- return "DW_AT_MIPS_loop_unroll_factor";
- case DW_AT_MIPS_software_pipeline_depth:
- return "DW_AT_MIPS_software_pipeline_depth";
- 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";
- /* HP extensions. */
-#ifndef MIPS /* collides with DW_AT_MIPS_fde */
- case DW_AT_HP_block_index:
- return "DW_AT_HP_block_index";
+ if (attr == DW_AT_MIPS_fde)
+ return "DW_AT_MIPS_fde";
+#else
+ if (attr == DW_AT_HP_block_index)
+ return "DW_AT_HP_block_index";
#endif
- 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_src_info";
- case DW_AT_mac_info:
- return "DW_AT_mac_info";
- case DW_AT_src_coords:
- return "DW_AT_src_coords";
- case DW_AT_body_begin:
- return "DW_AT_body_begin";
- case DW_AT_body_end:
- return "DW_AT_body_end";
- case DW_AT_GNU_vector:
- return "DW_AT_GNU_vector";
- case DW_AT_GNU_odr_signature:
- return "DW_AT_GNU_odr_signature";
- /* 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>";
- }
+
+ name = get_DW_AT_name (attr);
+
+ if (name == NULL)
+ return "DW_AT_<unknown>";
+
+ return name;
}
/* Convert a DWARF value form code into its string name. */
-static char *
+static const char *
dwarf_form_name (unsigned form)
{
- switch (form)
- {
- case DW_FORM_addr:
- return "DW_FORM_addr";
- case DW_FORM_block2:
- return "DW_FORM_block2";
- case DW_FORM_block4:
- return "DW_FORM_block4";
- case DW_FORM_data2:
- return "DW_FORM_data2";
- case DW_FORM_data4:
- return "DW_FORM_data4";
- case DW_FORM_data8:
- return "DW_FORM_data8";
- case DW_FORM_string:
- return "DW_FORM_string";
- case DW_FORM_block:
- return "DW_FORM_block";
- case DW_FORM_block1:
- return "DW_FORM_block1";
- case DW_FORM_data1:
- return "DW_FORM_data1";
- case DW_FORM_flag:
- return "DW_FORM_flag";
- case DW_FORM_sdata:
- return "DW_FORM_sdata";
- case DW_FORM_strp:
- return "DW_FORM_strp";
- case DW_FORM_udata:
- return "DW_FORM_udata";
- case DW_FORM_ref_addr:
- return "DW_FORM_ref_addr";
- case DW_FORM_ref1:
- return "DW_FORM_ref1";
- case DW_FORM_ref2:
- return "DW_FORM_ref2";
- case DW_FORM_ref4:
- return "DW_FORM_ref4";
- case DW_FORM_ref8:
- return "DW_FORM_ref8";
- case DW_FORM_ref_udata:
- return "DW_FORM_ref_udata";
- case DW_FORM_indirect:
- return "DW_FORM_indirect";
- case DW_FORM_sec_offset:
- return "DW_FORM_sec_offset";
- case DW_FORM_exprloc:
- return "DW_FORM_exprloc";
- case DW_FORM_flag_present:
- return "DW_FORM_flag_present";
- case DW_FORM_ref_sig8:
- return "DW_FORM_ref_sig8";
- default:
- return "DW_FORM_<unknown>";
- }
-}
-
-/* Convert a DWARF stack opcode into its string name. */
-
-const char *
-dwarf_stack_op_name (unsigned op)
-{
- switch (op)
- {
- case DW_OP_addr:
- return "DW_OP_addr";
- case DW_OP_deref:
- return "DW_OP_deref";
- case DW_OP_const1u:
- return "DW_OP_const1u";
- case DW_OP_const1s:
- return "DW_OP_const1s";
- case DW_OP_const2u:
- return "DW_OP_const2u";
- case DW_OP_const2s:
- return "DW_OP_const2s";
- case DW_OP_const4u:
- return "DW_OP_const4u";
- case DW_OP_const4s:
- return "DW_OP_const4s";
- case DW_OP_const8u:
- return "DW_OP_const8u";
- case DW_OP_const8s:
- return "DW_OP_const8s";
- case DW_OP_constu:
- return "DW_OP_constu";
- case DW_OP_consts:
- return "DW_OP_consts";
- case DW_OP_dup:
- return "DW_OP_dup";
- case DW_OP_drop:
- return "DW_OP_drop";
- case DW_OP_over:
- return "DW_OP_over";
- case DW_OP_pick:
- return "DW_OP_pick";
- case DW_OP_swap:
- return "DW_OP_swap";
- case DW_OP_rot:
- return "DW_OP_rot";
- case DW_OP_xderef:
- return "DW_OP_xderef";
- case DW_OP_abs:
- return "DW_OP_abs";
- case DW_OP_and:
- return "DW_OP_and";
- case DW_OP_div:
- return "DW_OP_div";
- case DW_OP_minus:
- return "DW_OP_minus";
- case DW_OP_mod:
- return "DW_OP_mod";
- case DW_OP_mul:
- return "DW_OP_mul";
- case DW_OP_neg:
- return "DW_OP_neg";
- case DW_OP_not:
- return "DW_OP_not";
- case DW_OP_or:
- return "DW_OP_or";
- case DW_OP_plus:
- return "DW_OP_plus";
- case DW_OP_plus_uconst:
- return "DW_OP_plus_uconst";
- case DW_OP_shl:
- return "DW_OP_shl";
- case DW_OP_shr:
- return "DW_OP_shr";
- case DW_OP_shra:
- return "DW_OP_shra";
- case DW_OP_xor:
- return "DW_OP_xor";
- case DW_OP_bra:
- return "DW_OP_bra";
- case DW_OP_eq:
- return "DW_OP_eq";
- case DW_OP_ge:
- return "DW_OP_ge";
- case DW_OP_gt:
- return "DW_OP_gt";
- case DW_OP_le:
- return "DW_OP_le";
- case DW_OP_lt:
- return "DW_OP_lt";
- case DW_OP_ne:
- return "DW_OP_ne";
- case DW_OP_skip:
- return "DW_OP_skip";
- case DW_OP_lit0:
- return "DW_OP_lit0";
- case DW_OP_lit1:
- return "DW_OP_lit1";
- case DW_OP_lit2:
- return "DW_OP_lit2";
- case DW_OP_lit3:
- return "DW_OP_lit3";
- case DW_OP_lit4:
- return "DW_OP_lit4";
- case DW_OP_lit5:
- return "DW_OP_lit5";
- case DW_OP_lit6:
- return "DW_OP_lit6";
- case DW_OP_lit7:
- return "DW_OP_lit7";
- case DW_OP_lit8:
- return "DW_OP_lit8";
- case DW_OP_lit9:
- return "DW_OP_lit9";
- case DW_OP_lit10:
- return "DW_OP_lit10";
- case DW_OP_lit11:
- return "DW_OP_lit11";
- case DW_OP_lit12:
- return "DW_OP_lit12";
- case DW_OP_lit13:
- return "DW_OP_lit13";
- case DW_OP_lit14:
- return "DW_OP_lit14";
- case DW_OP_lit15:
- return "DW_OP_lit15";
- case DW_OP_lit16:
- return "DW_OP_lit16";
- case DW_OP_lit17:
- return "DW_OP_lit17";
- case DW_OP_lit18:
- return "DW_OP_lit18";
- case DW_OP_lit19:
- return "DW_OP_lit19";
- case DW_OP_lit20:
- return "DW_OP_lit20";
- case DW_OP_lit21:
- return "DW_OP_lit21";
- case DW_OP_lit22:
- return "DW_OP_lit22";
- case DW_OP_lit23:
- return "DW_OP_lit23";
- case DW_OP_lit24:
- return "DW_OP_lit24";
- case DW_OP_lit25:
- return "DW_OP_lit25";
- case DW_OP_lit26:
- return "DW_OP_lit26";
- case DW_OP_lit27:
- return "DW_OP_lit27";
- case DW_OP_lit28:
- return "DW_OP_lit28";
- case DW_OP_lit29:
- return "DW_OP_lit29";
- case DW_OP_lit30:
- return "DW_OP_lit30";
- case DW_OP_lit31:
- return "DW_OP_lit31";
- case DW_OP_reg0:
- return "DW_OP_reg0";
- case DW_OP_reg1:
- return "DW_OP_reg1";
- case DW_OP_reg2:
- return "DW_OP_reg2";
- case DW_OP_reg3:
- return "DW_OP_reg3";
- case DW_OP_reg4:
- return "DW_OP_reg4";
- case DW_OP_reg5:
- return "DW_OP_reg5";
- case DW_OP_reg6:
- return "DW_OP_reg6";
- case DW_OP_reg7:
- return "DW_OP_reg7";
- case DW_OP_reg8:
- return "DW_OP_reg8";
- case DW_OP_reg9:
- return "DW_OP_reg9";
- case DW_OP_reg10:
- return "DW_OP_reg10";
- case DW_OP_reg11:
- return "DW_OP_reg11";
- case DW_OP_reg12:
- return "DW_OP_reg12";
- case DW_OP_reg13:
- return "DW_OP_reg13";
- case DW_OP_reg14:
- return "DW_OP_reg14";
- case DW_OP_reg15:
- return "DW_OP_reg15";
- case DW_OP_reg16:
- return "DW_OP_reg16";
- case DW_OP_reg17:
- return "DW_OP_reg17";
- case DW_OP_reg18:
- return "DW_OP_reg18";
- case DW_OP_reg19:
- return "DW_OP_reg19";
- case DW_OP_reg20:
- return "DW_OP_reg20";
- case DW_OP_reg21:
- return "DW_OP_reg21";
- case DW_OP_reg22:
- return "DW_OP_reg22";
- case DW_OP_reg23:
- return "DW_OP_reg23";
- case DW_OP_reg24:
- return "DW_OP_reg24";
- case DW_OP_reg25:
- return "DW_OP_reg25";
- case DW_OP_reg26:
- return "DW_OP_reg26";
- case DW_OP_reg27:
- return "DW_OP_reg27";
- case DW_OP_reg28:
- return "DW_OP_reg28";
- case DW_OP_reg29:
- return "DW_OP_reg29";
- case DW_OP_reg30:
- return "DW_OP_reg30";
- case DW_OP_reg31:
- return "DW_OP_reg31";
- case DW_OP_breg0:
- return "DW_OP_breg0";
- case DW_OP_breg1:
- return "DW_OP_breg1";
- case DW_OP_breg2:
- return "DW_OP_breg2";
- case DW_OP_breg3:
- return "DW_OP_breg3";
- case DW_OP_breg4:
- return "DW_OP_breg4";
- case DW_OP_breg5:
- return "DW_OP_breg5";
- case DW_OP_breg6:
- return "DW_OP_breg6";
- case DW_OP_breg7:
- return "DW_OP_breg7";
- case DW_OP_breg8:
- return "DW_OP_breg8";
- case DW_OP_breg9:
- return "DW_OP_breg9";
- case DW_OP_breg10:
- return "DW_OP_breg10";
- case DW_OP_breg11:
- return "DW_OP_breg11";
- case DW_OP_breg12:
- return "DW_OP_breg12";
- case DW_OP_breg13:
- return "DW_OP_breg13";
- case DW_OP_breg14:
- return "DW_OP_breg14";
- case DW_OP_breg15:
- return "DW_OP_breg15";
- case DW_OP_breg16:
- return "DW_OP_breg16";
- case DW_OP_breg17:
- return "DW_OP_breg17";
- case DW_OP_breg18:
- return "DW_OP_breg18";
- case DW_OP_breg19:
- return "DW_OP_breg19";
- case DW_OP_breg20:
- return "DW_OP_breg20";
- case DW_OP_breg21:
- return "DW_OP_breg21";
- case DW_OP_breg22:
- return "DW_OP_breg22";
- case DW_OP_breg23:
- return "DW_OP_breg23";
- case DW_OP_breg24:
- return "DW_OP_breg24";
- case DW_OP_breg25:
- return "DW_OP_breg25";
- case DW_OP_breg26:
- return "DW_OP_breg26";
- case DW_OP_breg27:
- return "DW_OP_breg27";
- case DW_OP_breg28:
- return "DW_OP_breg28";
- case DW_OP_breg29:
- return "DW_OP_breg29";
- case DW_OP_breg30:
- return "DW_OP_breg30";
- case DW_OP_breg31:
- return "DW_OP_breg31";
- case DW_OP_regx:
- return "DW_OP_regx";
- case DW_OP_fbreg:
- return "DW_OP_fbreg";
- case DW_OP_bregx:
- return "DW_OP_bregx";
- case DW_OP_piece:
- return "DW_OP_piece";
- case DW_OP_deref_size:
- return "DW_OP_deref_size";
- case DW_OP_xderef_size:
- return "DW_OP_xderef_size";
- case DW_OP_nop:
- return "DW_OP_nop";
- /* DWARF 3 extensions. */
- case DW_OP_push_object_address:
- return "DW_OP_push_object_address";
- case DW_OP_call2:
- return "DW_OP_call2";
- case DW_OP_call4:
- return "DW_OP_call4";
- case DW_OP_call_ref:
- return "DW_OP_call_ref";
- 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";
- /* DWARF 4 extensions. */
- case DW_OP_implicit_value:
- return "DW_OP_implicit_value";
- case DW_OP_stack_value:
- return "DW_OP_stack_value";
- /* GNU extensions. */
- case DW_OP_GNU_push_tls_address:
- return "DW_OP_GNU_push_tls_address";
- case DW_OP_GNU_uninit:
- return "DW_OP_GNU_uninit";
- case DW_OP_GNU_encoded_addr:
- return "DW_OP_GNU_encoded_addr";
- case DW_OP_GNU_implicit_pointer:
- return "DW_OP_GNU_implicit_pointer";
- case DW_OP_GNU_entry_value:
- return "DW_OP_GNU_entry_value";
- case DW_OP_GNU_const_type:
- return "DW_OP_GNU_const_type";
- case DW_OP_GNU_regval_type:
- return "DW_OP_GNU_regval_type";
- case DW_OP_GNU_deref_type:
- return "DW_OP_GNU_deref_type";
- case DW_OP_GNU_convert:
- return "DW_OP_GNU_convert";
- case DW_OP_GNU_reinterpret:
- return "DW_OP_GNU_reinterpret";
- case DW_OP_GNU_parameter_ref:
- return "DW_OP_GNU_parameter_ref";
- default:
- return NULL;
- }
+ const char *name = get_DW_FORM_name (form);
+
+ if (name == NULL)
+ return "DW_FORM_<unknown>";
+
+ return name;
}
static char *
/* Convert a DWARF type code into its string name. */
-static char *
+static const char *
dwarf_type_encoding_name (unsigned enc)
{
- 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_boolean";
- case DW_ATE_complex_float:
- return "DW_ATE_complex_float";
- case DW_ATE_float:
- return "DW_ATE_float";
- case DW_ATE_signed:
- return "DW_ATE_signed";
- case DW_ATE_signed_char:
- return "DW_ATE_signed_char";
- case DW_ATE_unsigned:
- 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";
- /* DWARF 4. */
- case DW_ATE_UTF:
- return "DW_ATE_UTF";
- /* 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>";
- }
-}
+ const char *name = get_DW_ATE_name (enc);
-/* Convert a DWARF call frame info operation to its string name. */
+ if (name == NULL)
+ return "DW_ATE_<unknown>";
-#if 0
-static char *
-dwarf_cfi_name (unsigned cfi_opc)
-{
- switch (cfi_opc)
- {
- case DW_CFA_advance_loc:
- return "DW_CFA_advance_loc";
- case DW_CFA_offset:
- return "DW_CFA_offset";
- case DW_CFA_restore:
- return "DW_CFA_restore";
- case DW_CFA_nop:
- return "DW_CFA_nop";
- case DW_CFA_set_loc:
- return "DW_CFA_set_loc";
- case DW_CFA_advance_loc1:
- return "DW_CFA_advance_loc1";
- case DW_CFA_advance_loc2:
- return "DW_CFA_advance_loc2";
- case DW_CFA_advance_loc4:
- return "DW_CFA_advance_loc4";
- case DW_CFA_offset_extended:
- return "DW_CFA_offset_extended";
- case DW_CFA_restore_extended:
- return "DW_CFA_restore_extended";
- case DW_CFA_undefined:
- return "DW_CFA_undefined";
- case DW_CFA_same_value:
- return "DW_CFA_same_value";
- case DW_CFA_register:
- return "DW_CFA_register";
- case DW_CFA_remember_state:
- return "DW_CFA_remember_state";
- case DW_CFA_restore_state:
- return "DW_CFA_restore_state";
- case DW_CFA_def_cfa:
- return "DW_CFA_def_cfa";
- case DW_CFA_def_cfa_register:
- return "DW_CFA_def_cfa_register";
- case DW_CFA_def_cfa_offset:
- return "DW_CFA_def_cfa_offset";
- /* DWARF 3. */
- case DW_CFA_def_cfa_expression:
- return "DW_CFA_def_cfa_expression";
- case DW_CFA_expression:
- return "DW_CFA_expression";
- case DW_CFA_offset_extended_sf:
- return "DW_CFA_offset_extended_sf";
- case DW_CFA_def_cfa_sf:
- return "DW_CFA_def_cfa_sf";
- case DW_CFA_def_cfa_offset_sf:
- return "DW_CFA_def_cfa_offset_sf";
- 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. */
- 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>";
- }
+ return name;
}
-#endif
static void
dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
switch (die->attrs[i].form)
{
case DW_FORM_addr:
+ case DW_FORM_GNU_addr_index:
fprintf_unfiltered (f, "address: ");
fputs_filtered (hex_string (DW_ADDR (&die->attrs[i])), f);
break;
break;
case DW_FORM_string:
case DW_FORM_strp:
+ case DW_FORM_GNU_str_index:
fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
DW_STRING (&die->attrs[i])
? DW_STRING (&die->attrs[i]) : "",
static int
maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
- struct dwarf2_per_cu_data *per_cu)
+ struct dwarf2_per_cu_data *per_cu,
+ enum language pretend_language)
{
/* We may arrive here during partial symbol reading, if we need full
DIEs to process an unusual case (e.g. template arguments). Do
}
/* Add it to the queue. */
- queue_comp_unit (per_cu);
+ queue_comp_unit (per_cu, pretend_language);
return 1;
}
target_cu = cu;
- if (cu->per_cu->debug_types_section)
+ if (cu->per_cu->is_debug_types)
{
/* .debug_types CUs cannot reference anything outside their CU.
If they need to, they have to reference a signatured type via
per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
/* If necessary, add it to the queue and load its DIEs. */
- if (maybe_queue_comp_unit (cu, per_cu))
- load_full_comp_unit (per_cu);
+ if (maybe_queue_comp_unit (cu, per_cu, cu->language))
+ load_full_comp_unit (per_cu, cu->language);
target_cu = per_cu->cu;
}
{
/* We're loading full DIEs during partial symbol reading. */
gdb_assert (dwarf2_per_objfile->reading_partial_symbols);
- load_full_comp_unit (cu->per_cu);
+ load_full_comp_unit (cu->per_cu, language_minimal);
}
*ref_cu = target_cu;
/* If necessary, add it to the queue and load its DIEs. */
- if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu))
+ if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu, language_minimal))
read_signatured_type (sig_type);
gdb_assert (sig_type->per_cu.cu != NULL);
sig_cu = sig_type->per_cu.cu;
- temp_die.offset.sect_off = (sig_type->per_cu.offset.sect_off
- + sig_type->type_offset.cu_off);
+ gdb_assert (sig_type->type_offset_in_section.sect_off != 0);
+ temp_die.offset = sig_type->type_offset_in_section;
die = htab_find_with_hash (sig_cu->die_hash, &temp_die,
temp_die.offset.sect_off);
if (die)
load_full_type_unit (struct dwarf2_per_cu_data *per_cu)
{
struct objfile *objfile = per_cu->objfile;
- struct dwarf2_section_info *sect = per_cu->debug_types_section;
+ struct dwarf2_section_info *sect = per_cu->info_or_types_section;
sect_offset offset = per_cu->offset;
struct signatured_type *sig_type;
void *data)
{
struct dwarf2_cu *cu = reader->cu;
- struct attribute *attr;
gdb_assert (cu->die_hash == NULL);
cu->die_hash =
or we won't be able to build types correctly.
Similarly, if we do not read the producer, we can not apply
producer-specific interpretation. */
- prepare_one_comp_unit (cu, cu->dies);
+ prepare_one_comp_unit (cu, cu->dies, language_minimal);
}
-/* Read in a signatured type and build its CU and DIEs. */
+/* Read in a signatured type and build its CU and DIEs.
+ If the type is a stub for the real type in a DWO file,
+ read in the real type from the DWO file as well. */
static void
read_signatured_type (struct signatured_type *sig_type)
{
struct dwarf2_per_cu_data *per_cu = &sig_type->per_cu;
- gdb_assert (per_cu->debug_types_section);
+ gdb_assert (per_cu->is_debug_types);
gdb_assert (per_cu->cu == NULL);
- init_tu_and_read_dies (per_cu, 1, read_signatured_type_reader, NULL);
+ init_cutu_and_read_dies (per_cu, 0, 1, read_signatured_type_reader, NULL);
}
/* Decode simple location descriptions.
case DW_OP_GNU_uninit:
break;
+ case DW_OP_GNU_addr_index:
+ stack[++stacki] = read_addr_index_from_leb128 (cu, &data[i],
+ &bytes_read);
+ i += bytes_read;
+ break;
+
default:
{
- const char *name = dwarf_stack_op_name (op);
+ const char *name = get_DW_OP_name (op);
if (name)
complaint (&symfile_complaints, _("unsupported stack op: '%s'"),
objfile->macro_cache);
if (! current_file)
- /* If we have no current file, then this must be the start_file
- directive for the compilation unit's main source file. */
- current_file = macro_set_main (pending_macros, full_name);
+ {
+ /* If we have no current file, then this must be the start_file
+ directive for the compilation unit's main source file. */
+ current_file = macro_set_main (pending_macros, full_name);
+ macro_define_special (pending_macros);
+ }
else
current_file = macro_include (current_file, line, full_name);
case DW_FORM_sdata:
case DW_FORM_udata:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index:
bytes = skip_leb128 (abfd, bytes);
break;
char *comp_dir, bfd *abfd,
struct dwarf2_cu *cu,
struct dwarf2_section_info *section,
- int section_is_gnu)
+ int section_is_gnu, const char *section_name)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
gdb_byte *mac_ptr, *mac_end;
dwarf2_read_section (objfile, section);
if (section->buffer == NULL)
{
- complaint (&symfile_complaints, _("missing %s section"),
- section->asection->name);
+ complaint (&symfile_complaints, _("missing %s section"), section_name);
return;
}
}
}
+/* Return the .debug_loc section to use for CU.
+ For DWO files use .debug_loc.dwo. */
+
+static struct dwarf2_section_info *
+cu_debug_loc_section (struct dwarf2_cu *cu)
+{
+ if (cu->dwo_unit)
+ return &cu->dwo_unit->dwo_file->sections.loc;
+ return &dwarf2_per_objfile->loc;
+}
+
/* A helper function that fills in a dwarf2_loclist_baton. */
static void
struct dwarf2_loclist_baton *baton,
struct attribute *attr)
{
- dwarf2_read_section (dwarf2_per_objfile->objfile,
- &dwarf2_per_objfile->loc);
+ struct dwarf2_section_info *section = cu_debug_loc_section (cu);
+
+ dwarf2_read_section (dwarf2_per_objfile->objfile, section);
baton->per_cu = cu->per_cu;
gdb_assert (baton->per_cu);
/* We don't know how long the location list is, but make sure we
don't run off the edge of the section. */
- baton->size = dwarf2_per_objfile->loc.size - DW_UNSND (attr);
- baton->data = dwarf2_per_objfile->loc.buffer + DW_UNSND (attr);
+ baton->size = section->size - DW_UNSND (attr);
+ baton->data = section->buffer + DW_UNSND (attr);
baton->base_address = cu->base_address;
}
struct dwarf2_cu *cu)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct dwarf2_section_info *section = cu_debug_loc_section (cu);
if (attr_form_is_section_offset (attr)
- /* ".debug_loc" may not exist at all, or the offset may be outside
+ /* .debug_loc{,.dwo} 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_section_size (objfile,
- &dwarf2_per_objfile->loc))
+ && DW_UNSND (attr) < dwarf2_section_size (objfile, section))
{
struct dwarf2_loclist_baton *baton;
/* Initialize basic fields of dwarf_cu CU according to DIE COMP_UNIT_DIE. */
static void
-prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die)
+prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die,
+ enum language pretend_language)
{
struct attribute *attr;
set_cu_language (DW_UNSND (attr), cu);
else
{
- cu->language = language_minimal;
+ cu->language = pretend_language;
cu->language_defn = language_def (cu->language);
}
when the DIEs are flushed out of cache.
The CU "per_cu" pointer is needed because offset alone is not enough to
- uniquely identify the type. A file may have multiple .debug_types sections.
- We have to use something in dwarf2_per_cu_data (or the pointer to it)
- because we can enter the lookup routine, get_die_type_at_offset, from
- outside this file, and thus won't necessarily have PER_CU->cu.
- Fortunately, PER_CU is stable for the life of the objfile. */
+ uniquely identify the type. A file may have multiple .debug_types sections,
+ or the type may come from a DWO file. We have to use something in
+ dwarf2_per_cu_data (or the pointer to it) because we can enter the lookup
+ routine, get_die_type_at_offset, from outside this file, and thus won't
+ necessarily have PER_CU->cu. Fortunately, PER_CU is stable for the life
+ of the objfile. */
struct dwarf2_per_cu_offset_and_type
{
munmap_section_buffer (&data->macro);
munmap_section_buffer (&data->str);
munmap_section_buffer (&data->ranges);
+ munmap_section_buffer (&data->addr);
munmap_section_buffer (&data->frame);
munmap_section_buffer (&data->eh_frame);
munmap_section_buffer (&data->gdb_index);
++ix)
munmap_section_buffer (section);
+ for (ix = 0; ix < dwarf2_per_objfile->n_comp_units; ++ix)
+ VEC_free (dwarf2_per_cu_ptr,
+ dwarf2_per_objfile->all_comp_units[ix]->imported_symtabs);
+
VEC_free (dwarf2_section_info_def, data->types);
+
+ if (data->dwo_files)
+ free_dwo_files (data->dwo_files, objfile);
}
\f
{
struct addrmap_index_data *data = datap;
struct partial_symtab *pst = obj;
- offset_type cu_index;
- void **slot;
if (data->previous_valid)
add_address_entry (data->objfile, data->addr_obstack,
store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
entry->per_cu.offset.sect_off);
obstack_grow (info->types_list, val, 8);
- store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->type_offset.cu_off);
+ store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
+ entry->type_offset_in_tu.cu_off);
obstack_grow (info->types_list, val, 8);
store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->signature);
obstack_grow (info->types_list, val, 8);
return 1;
}
+/* Recurse into all "included" dependencies and write their symbols as
+ if they appeared in this psymtab. */
+
+static void
+recursively_write_psymbols (struct objfile *objfile,
+ struct partial_symtab *psymtab,
+ struct mapped_symtab *symtab,
+ htab_t psyms_seen,
+ offset_type cu_index)
+{
+ int i;
+
+ for (i = 0; i < psymtab->number_of_dependencies; ++i)
+ if (psymtab->dependencies[i]->user != NULL)
+ recursively_write_psymbols (objfile, psymtab->dependencies[i],
+ symtab, psyms_seen, cu_index);
+
+ write_psymbols (symtab,
+ psyms_seen,
+ objfile->global_psymbols.list + psymtab->globals_offset,
+ psymtab->n_global_syms, cu_index,
+ 0);
+ write_psymbols (symtab,
+ psyms_seen,
+ objfile->static_psymbols.list + psymtab->statics_offset,
+ psymtab->n_static_syms, cu_index,
+ 1);
+}
+
/* Create an index file for OBJFILE in the directory DIR. */
static void
struct mapped_symtab *symtab;
offset_type val, size_of_contents, total_len;
struct stat st;
- char buf[8];
htab_t psyms_seen;
htab_t cu_index_htab;
struct psymtab_cu_index_map *psymtab_cu_index_map;
struct psymtab_cu_index_map *map;
void **slot;
- write_psymbols (symtab,
- psyms_seen,
- objfile->global_psymbols.list + psymtab->globals_offset,
- psymtab->n_global_syms, i,
- 0);
- write_psymbols (symtab,
- psyms_seen,
- objfile->static_psymbols.list + psymtab->statics_offset,
- psymtab->n_static_syms, i,
- 1);
+ if (psymtab->user == NULL)
+ recursively_write_psymbols (objfile, psymtab, symtab, psyms_seen, i);
map = &psymtab_cu_index_map[i];
map->psymtab = psymtab;