/* DWARF 2 debugging format support for GDB.
- Copyright (C) 1994-2013 Free Software Foundation, Inc.
+ Copyright (C) 1994-2014 Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
#include "jv-lang.h"
#include "psympriv.h"
#include "exceptions.h"
-#include "gdb_stat.h"
+#include <sys/stat.h>
#include "completer.h"
#include "vec.h"
#include "c-lang.h"
#include "gdb_bfd.h"
#include "f-lang.h"
#include "source.h"
+#include "filestuff.h"
+#include "build-id.h"
#include <fcntl.h>
-#include "gdb_string.h"
+#include <string.h>
#include "gdb_assert.h"
#include <sys/types.h>
typedef struct symbol *symbolp;
DEF_VEC_P (symbolp);
-/* When non-zero, print basic high level tracing messages.
+/* When == 1, print basic high level tracing messages.
+ When > 1, be more verbose.
This is in contrast to the low level DIE reading of dwarf2_die_debug. */
-static int dwarf2_read_debug = 0;
+static unsigned int dwarf2_read_debug = 0;
/* When non-zero, dump DIEs after they are read in. */
static unsigned int dwarf2_die_debug = 0;
static int dwarf2_locexpr_block_index;
static int dwarf2_loclist_block_index;
+/* A descriptor for dwarf sections.
+
+ S.ASECTION, SIZE are typically initialized when the objfile is first
+ scanned. BUFFER, READIN are filled in later when the section is read.
+ If the section contained compressed data then SIZE is updated to record
+ the uncompressed size of the section.
+
+ DWP file format V2 introduces a wrinkle that is easiest to handle by
+ creating the concept of virtual sections contained within a real section.
+ In DWP V2 the sections of the input DWO files are concatenated together
+ into one section, but section offsets are kept relative to the original
+ input section.
+ If this is a virtual dwp-v2 section, S.CONTAINING_SECTION is a backlink to
+ the real section this "virtual" section is contained in, and BUFFER,SIZE
+ describe the virtual section. */
+
struct dwarf2_section_info
{
- asection *asection;
+ union
+ {
+ /* If this is a real section, the bfd section. */
+ asection *asection;
+ /* If this is a virtual section, pointer to the containing ("real")
+ section. */
+ struct dwarf2_section_info *containing_section;
+ } s;
+ /* Pointer to section data, only valid if readin. */
const gdb_byte *buffer;
+ /* The size of the section, real or virtual. */
bfd_size_type size;
+ /* If this is a virtual section, the offset in the real section.
+ Only valid if is_virtual. */
+ bfd_size_type virtual_offset;
/* True if we have tried to read this section. */
- int readin;
+ char readin;
+ /* True if this is a virtual section, False otherwise.
+ This specifies which of s.asection and s.containing_section to use. */
+ char is_virtual;
};
typedef struct dwarf2_section_info dwarf2_section_info_def;
/* The number of .debug_types-related CUs. */
int n_type_units;
- /* The .debug_types-related CUs (TUs). */
+ /* The .debug_types-related CUs (TUs).
+ This is stored in malloc space because we may realloc it. */
struct signatured_type **all_type_units;
/* The number of entries in all_type_unit_groups. */
compilation units are cached... */
struct dwarf2_per_cu_data *read_in_chain;
- /* Backchain to our per_cu entry if the tree has been built. */
+ /* Backlink to our per_cu entry. */
struct dwarf2_per_cu_data *per_cu;
/* How many compilation units ago was this CU last referenced? */
/* Non-zero if this CU is from the .dwz file. */
unsigned int is_dwz : 1;
+ /* Non-zero if reading a TU directly from a DWO file, bypassing the stub.
+ This flag is only valid if is_debug_types is true.
+ We can't read a CU directly from a DWO file: There are required
+ attributes in the stub. */
+ unsigned int reading_dwo_directly : 1;
+
+ /* Non-zero if the TU has been read.
+ This is used to assist the "Stay in DWO Optimization" for Fission:
+ When reading a DWO, it's faster to read TUs from the DWO instead of
+ fetching them from random other DWOs (due to comdat folding).
+ If the TU has already been read, the optimization is unnecessary
+ (and unwise - we don't want to change where gdb thinks the TU lives
+ "midflight").
+ This flag is only valid if is_debug_types is true. */
+ unsigned int tu_read : 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. */
DW_TAG_imported_unit, so we just use the same mechanism: For
.gdb_index version <=7 this also records the TUs that the CU referred
to. Concurrently with this change gdb was modified to emit version 8
- indices so we only pay a price for gold generated indices. */
+ indices so we only pay a price for gold generated indices.
+ http://sourceware.org/bugzilla/show_bug.cgi?id=15021. */
VEC (dwarf2_per_cu_ptr) *imported_symtabs;
};
The first time we encounter this type we fully read it in and install it
in the symbol tables. Subsequent times we only need the type. */
struct type *type;
+
+ /* Containing DWO unit.
+ This field is valid iff per_cu.reading_dwo_directly. */
+ struct dwo_unit *dwo_unit;
};
typedef struct signatured_type *sig_type_ptr;
struct symtab **symtabs;
};
-/* These sections are what may appear in a DWO file. */
+/* These sections are what may appear in a (real or virtual) DWO file. */
struct dwo_sections
{
/* The section this CU/TU lives in, in the DWO file. */
struct dwarf2_section_info *section;
- /* Same as dwarf2_per_cu_data:{offset,length} but for the DWO section. */
+ /* Same as dwarf2_per_cu_data:{offset,length} but in the DWO section. */
sect_offset offset;
unsigned int length;
cu_offset type_offset_in_tu;
};
+/* include/dwarf2.h defines the DWP section codes.
+ It defines a max value but it doesn't define a min value, which we
+ use for error checking, so provide one. */
+
+enum dwp_v2_section_ids
+{
+ DW_SECT_MIN = 1
+};
+
/* Data for one DWO file.
- This includes virtual DWO files that have been packaged into a
- DWP file. */
+
+ This includes virtual DWO files (a virtual DWO file is a DWO file as it
+ appears in a DWP file). DWP files don't really have DWO files per se -
+ comdat folding of types "loses" the DWO file they came from, and from
+ a high level view DWP files appear to contain a mass of random types.
+ However, to maintain consistency with the non-DWP case we pretend DWP
+ files contain virtual DWO files, and we assign each TU with one virtual
+ DWO file (generally based on the line and abbrev section offsets -
+ a heuristic that seems to work in practice). */
struct dwo_file
{
This is unused(NULL) for virtual DWO files where we use dwp_file.dbfd. */
bfd *dbfd;
- /* Section info for this file. */
+ /* The sections that make up this DWO file.
+ Remember that for virtual DWO files in DWP V2, these are virtual
+ sections (for lack of a better name). */
struct dwo_sections sections;
/* The CU in the file.
struct dwp_sections
{
+ /* These are used by both DWP version 1 and 2. */
struct dwarf2_section_info str;
struct dwarf2_section_info cu_index;
struct dwarf2_section_info tu_index;
- /* The .debug_info.dwo, .debug_types.dwo, and other sections are referenced
- by section number. We don't need to record them here. */
+
+ /* These are only used by DWP version 2 files.
+ In DWP version 1 the .debug_info.dwo, .debug_types.dwo, and other
+ sections are referenced by section number, and are not recorded here.
+ In DWP version 2 there is at most one copy of all these sections, each
+ section being (effectively) comprised of the concatenation of all of the
+ individual sections that exist in the version 1 format.
+ To keep the code simple we treat each of these concatenated pieces as a
+ section itself (a virtual section?). */
+ struct dwarf2_section_info abbrev;
+ struct dwarf2_section_info info;
+ struct dwarf2_section_info line;
+ struct dwarf2_section_info loc;
+ struct dwarf2_section_info macinfo;
+ struct dwarf2_section_info macro;
+ struct dwarf2_section_info str_offsets;
+ struct dwarf2_section_info types;
};
-/* These sections are what may appear in a virtual DWO file. */
+/* These sections are what may appear in a virtual DWO file in DWP version 1.
+ A virtual DWO file is a DWO file as it appears in a DWP file. */
-struct virtual_dwo_sections
+struct virtual_v1_dwo_sections
{
struct dwarf2_section_info abbrev;
struct dwarf2_section_info line;
struct dwarf2_section_info info_or_types;
};
+/* Similar to virtual_v1_dwo_sections, but for DWP version 2.
+ In version 2, the sections of the DWO files are concatenated together
+ and stored in one section of that name. Thus each ELF section contains
+ several "virtual" sections. */
+
+struct virtual_v2_dwo_sections
+{
+ bfd_size_type abbrev_offset;
+ bfd_size_type abbrev_size;
+
+ bfd_size_type line_offset;
+ bfd_size_type line_size;
+
+ bfd_size_type loc_offset;
+ bfd_size_type loc_size;
+
+ bfd_size_type macinfo_offset;
+ bfd_size_type macinfo_size;
+
+ bfd_size_type macro_offset;
+ bfd_size_type macro_size;
+
+ bfd_size_type str_offsets_offset;
+ bfd_size_type str_offsets_size;
+
+ /* Each DWP hash table entry records one CU or one TU.
+ That is recorded here, and copied to dwo_unit.section. */
+ bfd_size_type info_or_types_offset;
+ bfd_size_type info_or_types_size;
+};
+
/* Contents of DWP hash tables. */
struct dwp_hash_table
{
+ uint32_t version, nr_columns;
uint32_t nr_units, nr_slots;
- const gdb_byte *hash_table, *unit_table, *section_pool;
+ const gdb_byte *hash_table, *unit_table;
+ union
+ {
+ struct
+ {
+ const gdb_byte *indices;
+ } v1;
+ struct
+ {
+ /* This is indexed by column number and gives the id of the section
+ in that column. */
+#define MAX_NR_V2_DWO_SECTIONS \
+ (1 /* .debug_info or .debug_types */ \
+ + 1 /* .debug_abbrev */ \
+ + 1 /* .debug_line */ \
+ + 1 /* .debug_loc */ \
+ + 1 /* .debug_str_offsets */ \
+ + 1 /* .debug_macro or .debug_macinfo */)
+ int section_ids[MAX_NR_V2_DWO_SECTIONS];
+ const gdb_byte *offsets;
+ const gdb_byte *sizes;
+ } v2;
+ } section_pool;
};
/* Data for one DWP file. */
/* Name of the file. */
const char *name;
- /* The bfd, when the file is open. Otherwise this is NULL. */
+ /* File format version. */
+ int version;
+
+ /* The bfd. */
bfd *dbfd;
/* Section info for this file. */
struct dwp_sections sections;
- /* Table of CUs in the file. */
+ /* Table of CUs in the file. */
const struct dwp_hash_table *cus;
/* Table of TUs in the file. */
const struct dwp_hash_table *tus;
- /* Table of loaded CUs/TUs. Each entry is a struct dwo_unit *. */
- htab_t loaded_cutus;
+ /* Tables of loaded CUs/TUs. Each entry is a struct dwo_unit *. */
+ htab_t loaded_cus;
+ htab_t loaded_tus;
- /* Table to map ELF section numbers to their sections. */
+ /* Table to map ELF section numbers to their sections.
+ This is only needed for the DWP V1 file format. */
unsigned int num_sections;
asection **elf_sections;
};
struct die_reader_specs
{
- /* die_section->asection->owner. */
+ /* The bfd of die_section. */
bfd* abfd;
/* The CU of the DIE we are parsing. */
/* The end of the buffer. */
const gdb_byte *buffer_end;
+
+ /* The value of the DW_AT_comp_dir attribute. */
+ const char *comp_dir;
};
/* Type of function passed to init_cutu_and_read_dies, et.al. */
"dwarf2 compilation units is %s.\n"),
value);
}
+\f
+/* local function prototypes */
+static const char *get_section_name (const struct dwarf2_section_info *);
-/* Various complaints about symbol reading that don't abort the process. */
-
-static void
-dwarf2_statement_list_fits_in_line_number_section_complaint (void)
-{
- complaint (&symfile_complaints,
- _("statement list doesn't fit in .debug_line section"));
-}
-
-static void
-dwarf2_debug_line_missing_file_complaint (void)
-{
- complaint (&symfile_complaints,
- _(".debug_line section has line data without a file"));
-}
-
-static void
-dwarf2_debug_line_missing_end_sequence_complaint (void)
-{
- complaint (&symfile_complaints,
- _(".debug_line section has line "
- "program sequence without an end"));
-}
-
-static void
-dwarf2_complex_location_expr_complaint (void)
-{
- complaint (&symfile_complaints, _("location expression too complex"));
-}
-
-static void
-dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2,
- int arg3)
-{
- complaint (&symfile_complaints,
- _("const value length mismatch for '%s', got %d, expected %d"),
- arg1, arg2, arg3);
-}
-
-static void
-dwarf2_section_buffer_overflow_complaint (struct dwarf2_section_info *section)
-{
- complaint (&symfile_complaints,
- _("debug info runs off end of %s section"
- " [in module %s]"),
- section->asection->name,
- bfd_get_filename (section->asection->owner));
-}
-
-static void
-dwarf2_macro_malformed_definition_complaint (const char *arg1)
-{
- complaint (&symfile_complaints,
- _("macro debug info contains a "
- "malformed macro definition:\n`%s'"),
- arg1);
-}
-
-static void
-dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
-{
- complaint (&symfile_complaints,
- _("invalid attribute class or form for '%s' in '%s'"),
- arg1, arg2);
-}
-
-/* local function prototypes */
+static const char *get_section_file_name (const struct dwarf2_section_info *);
static void dwarf2_locate_sections (bfd *, asection *, void *);
static struct symbol *new_symbol_full (struct die_info *, struct type *,
struct dwarf2_cu *, struct symbol *);
-static void dwarf2_const_value (struct attribute *, struct symbol *,
+static void dwarf2_const_value (const struct attribute *, struct symbol *,
struct dwarf2_cu *);
-static void dwarf2_const_value_attr (struct attribute *attr,
+static void dwarf2_const_value_attr (const struct attribute *attr,
struct type *type,
const char *name,
struct obstack *obstack,
static struct type *die_containing_type (struct die_info *,
struct dwarf2_cu *);
-static struct type *lookup_die_type (struct die_info *, struct attribute *,
+static struct type *lookup_die_type (struct die_info *, const struct attribute *,
struct dwarf2_cu *);
static struct type *read_type_die (struct die_info *, struct dwarf2_cu *);
static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
+static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
+
static struct type *read_module_type (struct die_info *die,
struct dwarf2_cu *cu);
static void store_in_ref_table (struct die_info *,
struct dwarf2_cu *);
-static int is_ref_attr (struct attribute *);
-
-static sect_offset dwarf2_get_ref_die_offset (struct attribute *);
+static sect_offset dwarf2_get_ref_die_offset (const struct attribute *);
-static LONGEST dwarf2_get_attr_constant_value (struct attribute *, int);
+static LONGEST dwarf2_get_attr_constant_value (const struct attribute *, int);
static struct die_info *follow_die_ref_or_sig (struct die_info *,
- struct attribute *,
+ const struct attribute *,
struct dwarf2_cu **);
static struct die_info *follow_die_ref (struct die_info *,
- struct attribute *,
+ const struct attribute *,
struct dwarf2_cu **);
static struct die_info *follow_die_sig (struct die_info *,
- struct attribute *,
+ const struct attribute *,
struct dwarf2_cu **);
static struct type *get_signatured_type (struct die_info *, ULONGEST,
struct dwarf2_cu *);
static struct type *get_DW_AT_signature_type (struct die_info *,
- struct attribute *,
+ const struct attribute *,
struct dwarf2_cu *);
static void load_full_type_unit (struct dwarf2_per_cu_data *per_cu);
static void read_signatured_type (struct signatured_type *);
static struct type_unit_group *get_type_unit_group
- (struct dwarf2_cu *, struct attribute *);
+ (struct dwarf2_cu *, const struct attribute *);
static void build_type_unit_groups (die_reader_func_ftype *, void *);
static void dwarf_decode_macros (struct dwarf2_cu *, unsigned int,
const char *, int);
-static int attr_form_is_block (struct attribute *);
+static int attr_form_is_block (const struct attribute *);
-static int attr_form_is_section_offset (struct attribute *);
+static int attr_form_is_section_offset (const struct attribute *);
-static int attr_form_is_constant (struct attribute *);
+static int attr_form_is_constant (const struct attribute *);
+
+static int attr_form_is_ref (const struct attribute *);
static void fill_in_loclist_baton (struct dwarf2_cu *cu,
struct dwarf2_loclist_baton *baton,
- struct attribute *attr);
+ const struct attribute *attr);
-static void dwarf2_symbol_mark_computed (struct attribute *attr,
+static void dwarf2_symbol_mark_computed (const struct attribute *attr,
struct symbol *sym,
struct dwarf2_cu *cu,
int is_block);
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);
static void find_file_and_directory (struct die_info *die,
static htab_t allocate_dwo_unit_table (struct objfile *objfile);
+static struct dwo_unit *lookup_dwo_unit_in_dwp
+ (struct dwp_file *dwp_file, const char *comp_dir,
+ ULONGEST signature, int is_debug_types);
+
+static struct dwp_file *get_dwp_file (void);
+
static struct dwo_unit *lookup_dwo_comp_unit
(struct dwarf2_per_cu_data *, const char *, const char *, ULONGEST);
static struct dwo_unit *lookup_dwo_type_unit
(struct signatured_type *, const char *, const char *);
+static void queue_and_load_all_dwo_tus (struct dwarf2_per_cu_data *);
+
static void free_dwo_file_cleanup (void *);
static void process_cu_includes (void);
static void check_producer (struct dwarf2_cu *cu);
+\f
+/* Various complaints about symbol reading that don't abort the process. */
+
+static void
+dwarf2_statement_list_fits_in_line_number_section_complaint (void)
+{
+ complaint (&symfile_complaints,
+ _("statement list doesn't fit in .debug_line section"));
+}
+
+static void
+dwarf2_debug_line_missing_file_complaint (void)
+{
+ complaint (&symfile_complaints,
+ _(".debug_line section has line data without a file"));
+}
+
+static void
+dwarf2_debug_line_missing_end_sequence_complaint (void)
+{
+ complaint (&symfile_complaints,
+ _(".debug_line section has line "
+ "program sequence without an end"));
+}
+
+static void
+dwarf2_complex_location_expr_complaint (void)
+{
+ complaint (&symfile_complaints, _("location expression too complex"));
+}
+
+static void
+dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2,
+ int arg3)
+{
+ complaint (&symfile_complaints,
+ _("const value length mismatch for '%s', got %d, expected %d"),
+ arg1, arg2, arg3);
+}
+static void
+dwarf2_section_buffer_overflow_complaint (struct dwarf2_section_info *section)
+{
+ complaint (&symfile_complaints,
+ _("debug info runs off end of %s section"
+ " [in module %s]"),
+ get_section_name (section),
+ get_section_file_name (section));
+}
+
+static void
+dwarf2_macro_malformed_definition_complaint (const char *arg1)
+{
+ complaint (&symfile_complaints,
+ _("macro debug info contains a "
+ "malformed macro definition:\n`%s'"),
+ arg1);
+}
+
+static void
+dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2)
+{
+ complaint (&symfile_complaints,
+ _("invalid attribute class or form for '%s' in '%s'"),
+ arg1, arg2);
+}
+\f
#if WORDS_BIGENDIAN
/* Convert VALUE between big- and little-endian. */
(void *) names);
dwarf2_per_objfile->objfile = objfile;
}
- return (dwarf2_per_objfile->info.asection != NULL
- && dwarf2_per_objfile->abbrev.asection != NULL);
+ return (!dwarf2_per_objfile->info.is_virtual
+ && dwarf2_per_objfile->info.s.asection != NULL
+ && !dwarf2_per_objfile->abbrev.is_virtual
+ && dwarf2_per_objfile->abbrev.s.asection != NULL);
+}
+
+/* Return the containing section of virtual section SECTION. */
+
+static struct dwarf2_section_info *
+get_containing_section (const struct dwarf2_section_info *section)
+{
+ gdb_assert (section->is_virtual);
+ return section->s.containing_section;
+}
+
+/* Return the bfd owner of SECTION. */
+
+static struct bfd *
+get_section_bfd_owner (const struct dwarf2_section_info *section)
+{
+ if (section->is_virtual)
+ {
+ section = get_containing_section (section);
+ gdb_assert (!section->is_virtual);
+ }
+ return section->s.asection->owner;
+}
+
+/* Return the bfd section of SECTION.
+ Returns NULL if the section is not present. */
+
+static asection *
+get_section_bfd_section (const struct dwarf2_section_info *section)
+{
+ if (section->is_virtual)
+ {
+ section = get_containing_section (section);
+ gdb_assert (!section->is_virtual);
+ }
+ return section->s.asection;
+}
+
+/* Return the name of SECTION. */
+
+static const char *
+get_section_name (const struct dwarf2_section_info *section)
+{
+ asection *sectp = get_section_bfd_section (section);
+
+ gdb_assert (sectp != NULL);
+ return bfd_section_name (get_section_bfd_owner (section), sectp);
+}
+
+/* Return the name of the file SECTION is in. */
+
+static const char *
+get_section_file_name (const struct dwarf2_section_info *section)
+{
+ bfd *abfd = get_section_bfd_owner (section);
+
+ return bfd_get_filename (abfd);
+}
+
+/* Return the id of SECTION.
+ Returns 0 if SECTION doesn't exist. */
+
+static int
+get_section_id (const struct dwarf2_section_info *section)
+{
+ asection *sectp = get_section_bfd_section (section);
+
+ if (sectp == NULL)
+ return 0;
+ return sectp->id;
+}
+
+/* Return the flags of SECTION.
+ SECTION (or containing section if this is a virtual section) must exist. */
+
+static int
+get_section_flags (const struct dwarf2_section_info *section)
+{
+ asection *sectp = get_section_bfd_section (section);
+
+ gdb_assert (sectp != NULL);
+ return bfd_get_section_flags (sectp->owner, sectp);
}
/* When loading sections, we look either for uncompressed section or for
}
else if (section_is_p (sectp->name, &names->info))
{
- dwarf2_per_objfile->info.asection = sectp;
+ dwarf2_per_objfile->info.s.asection = sectp;
dwarf2_per_objfile->info.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->abbrev))
{
- dwarf2_per_objfile->abbrev.asection = sectp;
+ dwarf2_per_objfile->abbrev.s.asection = sectp;
dwarf2_per_objfile->abbrev.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->line))
{
- dwarf2_per_objfile->line.asection = sectp;
+ dwarf2_per_objfile->line.s.asection = sectp;
dwarf2_per_objfile->line.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->loc))
{
- dwarf2_per_objfile->loc.asection = sectp;
+ dwarf2_per_objfile->loc.s.asection = sectp;
dwarf2_per_objfile->loc.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->macinfo))
{
- dwarf2_per_objfile->macinfo.asection = sectp;
+ dwarf2_per_objfile->macinfo.s.asection = sectp;
dwarf2_per_objfile->macinfo.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->macro))
{
- dwarf2_per_objfile->macro.asection = sectp;
+ dwarf2_per_objfile->macro.s.asection = sectp;
dwarf2_per_objfile->macro.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->str))
{
- dwarf2_per_objfile->str.asection = sectp;
+ dwarf2_per_objfile->str.s.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.s.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;
+ dwarf2_per_objfile->frame.s.asection = sectp;
dwarf2_per_objfile->frame.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->eh_frame))
{
- dwarf2_per_objfile->eh_frame.asection = sectp;
+ dwarf2_per_objfile->eh_frame.s.asection = sectp;
dwarf2_per_objfile->eh_frame.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->ranges))
{
- dwarf2_per_objfile->ranges.asection = sectp;
+ dwarf2_per_objfile->ranges.s.asection = sectp;
dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->types))
struct dwarf2_section_info type_section;
memset (&type_section, 0, sizeof (type_section));
- type_section.asection = sectp;
+ type_section.s.asection = sectp;
type_section.size = bfd_get_section_size (sectp);
VEC_safe_push (dwarf2_section_info_def, dwarf2_per_objfile->types,
}
else if (section_is_p (sectp->name, &names->gdb_index))
{
- dwarf2_per_objfile->gdb_index.asection = sectp;
+ dwarf2_per_objfile->gdb_index.s.asection = sectp;
dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp);
}
or not present. */
static int
-dwarf2_section_empty_p (struct dwarf2_section_info *info)
+dwarf2_section_empty_p (const struct dwarf2_section_info *section)
{
- return info->asection == NULL || info->size == 0;
+ if (section->is_virtual)
+ return section->size == 0;
+ return section->s.asection == NULL || section->size == 0;
}
/* 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.
+ the section comes from. E.g., for DWO files the bfd of INFO 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)
{
- asection *sectp = info->asection;
+ asection *sectp;
bfd *abfd;
gdb_byte *buf, *retbuf;
- unsigned char header[4];
if (info->readin)
return;
if (dwarf2_section_empty_p (info))
return;
- abfd = sectp->owner;
+ sectp = get_section_bfd_section (info);
+
+ /* If this is a virtual section we need to read in the real one first. */
+ if (info->is_virtual)
+ {
+ struct dwarf2_section_info *containing_section =
+ get_containing_section (info);
+
+ gdb_assert (sectp != NULL);
+ if ((sectp->flags & SEC_RELOC) != 0)
+ {
+ error (_("Dwarf Error: DWP format V2 with relocations is not"
+ " supported in section %s [in module %s]"),
+ get_section_name (info), get_section_file_name (info));
+ }
+ dwarf2_read_section (objfile, containing_section);
+ /* Other code should have already caught virtual sections that don't
+ fit. */
+ gdb_assert (info->virtual_offset + info->size
+ <= containing_section->size);
+ /* If the real section is empty or there was a problem reading the
+ section we shouldn't get here. */
+ gdb_assert (containing_section->buffer != NULL);
+ info->buffer = containing_section->buffer + info->virtual_offset;
+ return;
+ }
/* If the section has relocations, we must read it ourselves.
Otherwise we attach it to the BFD. */
return;
}
+ abfd = get_section_bfd_owner (info);
+ gdb_assert (abfd != NULL);
+
if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
|| bfd_bread (buf, info->size, abfd) != info->size)
- error (_("Dwarf Error: Can't read DWARF data from '%s'"),
- bfd_get_filename (abfd));
+ {
+ error (_("Dwarf Error: Can't read DWARF data"
+ " in section %s [in module %s]"),
+ bfd_section_name (abfd, sectp), bfd_get_filename (abfd));
+ }
}
/* A helper function that returns the size of a section in a safe way.
dwarf2_read_section (objfile, info);
- *sectp = info->asection;
+ *sectp = get_section_bfd_section (info);
*bufp = info->buffer;
*sizep = info->size;
}
is ELF-only (at the time of writing). */
if (section_is_p (sectp->name, &dwarf2_elf_names.abbrev))
{
- dwz_file->abbrev.asection = sectp;
+ dwz_file->abbrev.s.asection = sectp;
dwz_file->abbrev.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.info))
{
- dwz_file->info.asection = sectp;
+ dwz_file->info.s.asection = sectp;
dwz_file->info.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.str))
{
- dwz_file->str.asection = sectp;
+ dwz_file->str.s.asection = sectp;
dwz_file->str.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.line))
{
- dwz_file->line.asection = sectp;
+ dwz_file->line.s.asection = sectp;
dwz_file->line.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.macro))
{
- dwz_file->macro.asection = sectp;
+ dwz_file->macro.s.asection = sectp;
dwz_file->macro.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.gdb_index))
{
- dwz_file->gdb_index.asection = sectp;
+ dwz_file->gdb_index.s.asection = sectp;
dwz_file->gdb_index.size = bfd_get_section_size (sectp);
}
}
-/* Open the separate '.dwz' debug file, if needed. Error if the file
- cannot be found. */
+/* Open the separate '.dwz' debug file, if needed. Return NULL if
+ there is no .gnu_debugaltlink section in the file. Error if there
+ is such a section but the file cannot be found. */
static struct dwz_file *
dwarf2_get_dwz_file (void)
{
- bfd *abfd, *dwz_bfd;
- asection *section;
- gdb_byte *data;
+ bfd *dwz_bfd;
+ char *data;
struct cleanup *cleanup;
const char *filename;
struct dwz_file *result;
+ bfd_size_type buildid_len_arg;
+ size_t buildid_len;
+ bfd_byte *buildid;
if (dwarf2_per_objfile->dwz_file != NULL)
return dwarf2_per_objfile->dwz_file;
- abfd = dwarf2_per_objfile->objfile->obfd;
- section = bfd_get_section_by_name (abfd, ".gnu_debugaltlink");
- if (section == NULL)
- error (_("could not find '.gnu_debugaltlink' section"));
- if (!bfd_malloc_and_get_section (abfd, section, &data))
- error (_("could not read '.gnu_debugaltlink' section: %s"),
- bfd_errmsg (bfd_get_error ()));
+ bfd_set_error (bfd_error_no_error);
+ data = bfd_get_alt_debug_link_info (dwarf2_per_objfile->objfile->obfd,
+ &buildid_len_arg, &buildid);
+ if (data == NULL)
+ {
+ if (bfd_get_error () == bfd_error_no_error)
+ return NULL;
+ error (_("could not read '.gnu_debugaltlink' section: %s"),
+ bfd_errmsg (bfd_get_error ()));
+ }
cleanup = make_cleanup (xfree, data);
+ make_cleanup (xfree, buildid);
- filename = data;
+ buildid_len = (size_t) buildid_len_arg;
+
+ filename = (const char *) data;
if (!IS_ABSOLUTE_PATH (filename))
{
- char *abs = gdb_realpath (dwarf2_per_objfile->objfile->name);
+ char *abs = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile));
char *rel;
make_cleanup (xfree, abs);
filename = rel;
}
- /* The format is just a NUL-terminated file name, followed by the
- build-id. For now, though, we ignore the build-id. */
+ /* First try the file name given in the section. If that doesn't
+ work, try to use the build-id instead. */
dwz_bfd = gdb_bfd_open (filename, gnutarget, -1);
- if (dwz_bfd == NULL)
- error (_("could not read '%s': %s"), filename,
- bfd_errmsg (bfd_get_error ()));
-
- if (!bfd_check_format (dwz_bfd, bfd_object))
+ if (dwz_bfd != NULL)
{
- gdb_bfd_unref (dwz_bfd);
- error (_("file '%s' was not usable: %s"), filename,
- bfd_errmsg (bfd_get_error ()));
+ if (!build_id_verify (dwz_bfd, buildid_len, buildid))
+ {
+ gdb_bfd_unref (dwz_bfd);
+ dwz_bfd = NULL;
+ }
}
+ if (dwz_bfd == NULL)
+ dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid);
+
+ if (dwz_bfd == NULL)
+ error (_("could not find '.gnu_debugaltlink' file for %s"),
+ objfile_name (dwarf2_per_objfile->objfile));
+
result = OBSTACK_ZALLOC (&dwarf2_per_objfile->objfile->objfile_obstack,
struct dwz_file);
result->dwz_bfd = dwz_bfd;
do_cleanups (cleanup);
+ gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, dwz_bfd);
dwarf2_per_objfile->dwz_file = result;
return result;
}
{
queue_comp_unit (per_cu, language_minimal);
load_cu (per_cu);
+
+ /* If we just loaded a CU from a DWO, and we're working with an index
+ that may badly handle TUs, load all the TUs in that DWO as well.
+ http://sourceware.org/bugzilla/show_bug.cgi?id=15021 */
+ if (!per_cu->is_debug_types
+ && per_cu->cu->dwo_unit != NULL
+ && dwarf2_per_objfile->index_table != NULL
+ && dwarf2_per_objfile->index_table->version <= 7
+ /* DWP files aren't supported yet. */
+ && get_dwp_file () == NULL)
+ queue_and_load_all_dwo_tus (per_cu);
}
process_queue ();
dwarf2_per_objfile->n_type_units = elements / 3;
dwarf2_per_objfile->all_type_units
- = obstack_alloc (&objfile->objfile_obstack,
- dwarf2_per_objfile->n_type_units
- * sizeof (struct signatured_type *));
+ = xmalloc (dwarf2_per_objfile->n_type_units
+ * sizeof (struct signatured_type *));
sig_types_hash = allocate_signatured_type_table (objfile);
cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE);
iter += 4;
- if (cu_index < dwarf2_per_objfile->n_comp_units)
+ if (lo > hi)
{
- addrmap_set_empty (mutable_map, lo + baseaddr, hi + baseaddr - 1,
- dw2_get_cu (cu_index));
+ complaint (&symfile_complaints,
+ _(".gdb_index address table has invalid range (%s - %s)"),
+ hex_string (lo), hex_string (hi));
+ continue;
}
- else
+
+ if (cu_index >= dwarf2_per_objfile->n_comp_units)
{
complaint (&symfile_complaints,
_(".gdb_index address table has invalid CU number %u"),
(unsigned) cu_index);
+ continue;
}
+
+ addrmap_set_empty (mutable_map, lo + baseaddr, hi + baseaddr - 1,
+ dw2_get_cu (cu_index));
}
objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map,
/* Older elfutils strip versions could keep the section in the main
executable while splitting it for the separate debug info file. */
- if ((bfd_get_file_flags (section->asection) & SEC_HAS_CONTENTS) == 0)
+ if ((get_section_flags (section) & SEC_HAS_CONTENTS) == 0)
return 0;
dwarf2_read_section (objfile, section);
return 0;
}
/* Version 7 indices generated by gold refer to the CU for a symbol instead
- of the TU (for symbols coming from TUs). It's just a performance bug, and
- we can't distinguish gdb-generated indices from gold-generated ones, so
- nothing to do here. */
+ of the TU (for symbols coming from TUs),
+ http://sourceware.org/bugzilla/show_bug.cgi?id=15021.
+ Plus gold-generated indices can have duplicate entries for global symbols,
+ http://sourceware.org/bugzilla/show_bug.cgi?id=15646.
+ These are just performance bugs, and we can't distinguish gdb-generated
+ indices from gold-generated ones, so issue no warning here. */
/* Indexes with higher version than the one supported by GDB may be no
longer backward compatible. */
/ (2 * sizeof (offset_type)));
++i;
- map->constant_pool = addr + MAYBE_SWAP (metadata[i]);
+ map->constant_pool = (char *) (addr + MAYBE_SWAP (metadata[i]));
return 1;
}
struct mapped_index local_map, *map;
const gdb_byte *cu_list, *types_list, *dwz_list = NULL;
offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0;
+ struct dwz_file *dwz;
- if (!read_index_from_section (objfile, objfile->name,
+ if (!read_index_from_section (objfile, objfile_name (objfile),
use_deprecated_index_sections,
&dwarf2_per_objfile->gdb_index, &local_map,
&cu_list, &cu_list_elements,
/* If there is a .dwz file, read it so we can get its CU list as
well. */
- if (bfd_get_section_by_name (objfile->obfd, ".gnu_debugaltlink") != NULL)
+ dwz = dwarf2_get_dwz_file ();
+ if (dwz != NULL)
{
- struct dwz_file *dwz = dwarf2_get_dwz_file ();
struct mapped_index dwz_map;
const gdb_byte *dwz_types_ignore;
offset_type dwz_types_elements_ignore;
{
if (qfn->real_names == NULL)
qfn->real_names = OBSTACK_CALLOC (&objfile->objfile_obstack,
- qfn->num_file_names, sizeof (char *));
+ qfn->num_file_names, char *);
if (qfn->real_names[index] == NULL)
qfn->real_names[index] = gdb_realpath (qfn->file_names[index]);
int next;
/* The number of elements in VEC, or zero if there is no match. */
int length;
+ /* Have we seen a global version of the symbol?
+ If so we can ignore all further global instances.
+ This is to work around gold/15646, inefficient gold-generated
+ indices. */
+ int global_seen;
};
/* Initialize the index symtab iterator ITER.
iter->block_index = block_index;
iter->domain = domain;
iter->next = 0;
+ iter->global_seen = 0;
if (find_slot_in_mapped_hash (index, name, &iter->vec))
iter->length = MAYBE_SWAP (*iter->vec);
offset_type cu_index_and_attrs =
MAYBE_SWAP (iter->vec[iter->next + 1]);
offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
- struct dwarf2_per_cu_data *per_cu = dw2_get_cu (cu_index);
+ struct dwarf2_per_cu_data *per_cu;
int want_static = iter->block_index != GLOBAL_BLOCK;
/* This value is only valid for index versions >= 7. */
int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
(iter->index->version >= 7
&& symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
+ /* Don't crash on bad data. */
+ if (cu_index >= (dwarf2_per_objfile->n_comp_units
+ + dwarf2_per_objfile->n_type_units))
+ {
+ complaint (&symfile_complaints,
+ _(".gdb_index entry has bad CU index"
+ " [in module %s]"),
+ objfile_name (dwarf2_per_objfile->objfile));
+ continue;
+ }
+
+ per_cu = dw2_get_cu (cu_index);
+
/* Skip if already read in. */
if (per_cu->v.quick->symtab)
continue;
- if (attrs_valid
- && iter->want_specific_block
- && want_static != is_static)
- continue;
+ /* Check static vs global. */
+ if (attrs_valid)
+ {
+ if (iter->want_specific_block
+ && want_static != is_static)
+ continue;
+ /* Work around gold/15646. */
+ if (!is_static && iter->global_seen)
+ continue;
+ if (!is_static)
+ iter->global_seen = 1;
+ }
/* Only check the symbol's kind if it has one. */
if (attrs_valid)
printf_filtered (_(" Number of unread CUs: %d\n"), count);
}
+/* This dumps minimal information about the index.
+ It is called via "mt print objfiles".
+ One use is to verify .gdb_index has been loaded by the
+ gdb.dwarf2/gdb-index.exp testcase. */
+
static void
dw2_dump (struct objfile *objfile)
{
- /* Nothing worth printing. */
+ dw2_setup (objfile);
+ gdb_assert (dwarf2_per_objfile->using_index);
+ printf_filtered (".gdb_index:");
+ if (dwarf2_per_objfile->index_table != NULL)
+ {
+ printf_filtered (" version %d\n",
+ dwarf2_per_objfile->index_table->version);
+ }
+ else
+ printf_filtered (" faked for \"readnow\"\n");
+ printf_filtered ("\n");
}
static void
-dw2_relocate (struct objfile *objfile, struct section_offsets *new_offsets,
- struct section_offsets *delta)
+dw2_relocate (struct objfile *objfile,
+ const struct section_offsets *new_offsets,
+ const struct section_offsets *delta)
{
/* There's nothing to relocate here. */
}
}
}
-/* A helper function for dw2_find_symbol_file that finds the primary
- file name for a given CU. This is a die_reader_func. */
-
-static void
-dw2_get_primary_filename_reader (const struct die_reader_specs *reader,
- const gdb_byte *info_ptr,
- struct die_info *comp_unit_die,
- int has_children,
- void *data)
-{
- const char **result_ptr = data;
- struct dwarf2_cu *cu = reader->cu;
- struct attribute *attr;
-
- attr = dwarf2_attr (comp_unit_die, DW_AT_name, cu);
- if (attr == NULL)
- *result_ptr = NULL;
- else
- *result_ptr = DW_STRING (attr);
-}
-
-static const char *
-dw2_find_symbol_file (struct objfile *objfile, const char *name)
-{
- struct dwarf2_per_cu_data *per_cu;
- offset_type *vec;
- const char *filename;
-
- dw2_setup (objfile);
-
- /* index_table is NULL if OBJF_READNOW. */
- if (!dwarf2_per_objfile->index_table)
- {
- struct symtab *s;
-
- ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
- {
- struct blockvector *bv = BLOCKVECTOR (s);
- const struct block *block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
- struct symbol *sym = lookup_block_symbol (block, name, VAR_DOMAIN);
-
- if (sym)
- {
- /* Only file extension of returned filename is recognized. */
- return SYMBOL_SYMTAB (sym)->filename;
- }
- }
- return NULL;
- }
-
- if (!find_slot_in_mapped_hash (dwarf2_per_objfile->index_table,
- name, &vec))
- return NULL;
-
- /* Note that this just looks at the very first one named NAME -- but
- actually we are looking for a function. find_main_filename
- should be rewritten so that it doesn't require a custom hook. It
- could just use the ordinary symbol tables. */
- /* vec[0] is the length, which must always be >0. */
- per_cu = dw2_get_cu (GDB_INDEX_CU_VALUE (MAYBE_SWAP (vec[1])));
-
- if (per_cu->v.quick->symtab != NULL)
- {
- /* Only file extension of returned filename is recognized. */
- return per_cu->v.quick->symtab->filename;
- }
-
- init_cutu_and_read_dies (per_cu, NULL, 0, 0,
- dw2_get_primary_filename_reader, &filename);
-
- /* Only file extension of returned filename is recognized. */
- return filename;
-}
-
static void
-dw2_map_matching_symbols (const char * name, domain_enum namespace,
- struct objfile *objfile, int global,
+dw2_map_matching_symbols (struct objfile *objfile,
+ const char * name, domain_enum namespace,
+ int global,
int (*callback) (struct block *,
struct symbol *, void *),
void *data, symbol_compare_ftype *match,
static void
dw2_expand_symtabs_matching
(struct objfile *objfile,
- int (*file_matcher) (const char *, void *, int basenames),
- int (*name_matcher) (const char *, void *),
+ expand_symtabs_file_matcher_ftype *file_matcher,
+ expand_symtabs_symbol_matcher_ftype *symbol_matcher,
enum search_domain kind,
void *data)
{
offset_type idx = 2 * iter;
const char *name;
offset_type *vec, vec_len, vec_idx;
+ int global_seen = 0;
if (index->symbol_table[idx] == 0 && index->symbol_table[idx + 1] == 0)
continue;
name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]);
- if (! (*name_matcher) (name, data))
+ if (! (*symbol_matcher) (name, data))
continue;
/* The name was matched, now expand corresponding CUs that were
{
struct dwarf2_per_cu_data *per_cu;
offset_type cu_index_and_attrs = MAYBE_SWAP (vec[vec_idx + 1]);
+ /* This value is only valid for index versions >= 7. */
+ int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
gdb_index_symbol_kind symbol_kind =
GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
int cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
+ /* Only check the symbol attributes if they're present.
+ Indices prior to version 7 don't record them,
+ and indices >= 7 may elide them for certain symbols
+ (gold does this). */
+ int attrs_valid =
+ (index->version >= 7
+ && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
+
+ /* Work around gold/15646. */
+ if (attrs_valid)
+ {
+ if (!is_static && global_seen)
+ continue;
+ if (!is_static)
+ global_seen = 1;
+ }
- /* Don't crash on bad data. */
- if (cu_index >= (dwarf2_per_objfile->n_comp_units
- + dwarf2_per_objfile->n_type_units))
- continue;
-
- /* Only check the symbol's kind if it has one.
- Indices prior to version 7 don't record it. */
- if (index->version >= 7)
+ /* Only check the symbol's kind if it has one. */
+ if (attrs_valid)
{
switch (kind)
{
}
}
+ /* Don't crash on bad data. */
+ if (cu_index >= (dwarf2_per_objfile->n_comp_units
+ + dwarf2_per_objfile->n_type_units))
+ {
+ complaint (&symfile_complaints,
+ _(".gdb_index entry has bad CU index"
+ " [in module %s]"), objfile_name (objfile));
+ continue;
+ }
+
per_cu = dw2_get_cu (cu_index);
if (file_matcher == NULL || per_cu->v.quick->mark)
dw2_instantiate_symtab (per_cu);
dw2_expand_symtabs_for_function,
dw2_expand_all_symtabs,
dw2_expand_symtabs_with_fullname,
- dw2_find_symbol_file,
dw2_map_matching_symbols,
dw2_expand_symtabs_matching,
dw2_find_pc_sect_symtab,
struct dwarf2_section_info *section,
struct dwarf2_section_info *abbrev_section)
{
- bfd *abfd = section->asection->owner;
- const char *filename = bfd_get_filename (abfd);
+ bfd *abfd = get_section_bfd_owner (section);
+ const char *filename = get_section_file_name (section);
if (header->version != 2 && header->version != 3 && header->version != 4)
error (_("Dwarf Error: wrong version in compilation unit header "
int is_debug_types_section)
{
const gdb_byte *beg_of_comp_unit = info_ptr;
- bfd *abfd = section->asection->owner;
+ bfd *abfd = get_section_bfd_owner (section);
header->offset.sect_off = beg_of_comp_unit - section->buffer;
cu_offset *type_offset_in_tu)
{
const gdb_byte *beg_of_comp_unit = info_ptr;
- bfd *abfd = section->asection->owner;
+ bfd *abfd = get_section_bfd_owner (section);
header->offset.sect_off = beg_of_comp_unit - section->buffer;
read_abbrev_offset (struct dwarf2_section_info *section,
sect_offset offset)
{
- bfd *abfd = section->asection->owner;
+ bfd *abfd = get_section_bfd_owner (section);
const gdb_byte *info_ptr;
unsigned int length, initial_length_size, offset_size;
sect_offset abbrev_offset;
if (dwarf2_read_debug)
fprintf_unfiltered (gdb_stdlog, "Reading .debug_types%s for %s:\n",
dwo_file ? ".dwo" : "",
- bfd_get_filename (abbrev_section->asection->owner));
+ get_section_file_name (abbrev_section));
for (ix = 0;
VEC_iterate (dwarf2_section_info_def, types, ix, section);
{
bfd *abfd;
const gdb_byte *info_ptr, *end_ptr;
- struct dwarf2_section_info *abbrev_section;
dwarf2_read_section (objfile, section);
info_ptr = section->buffer;
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 (dwo_file)
- abbrev_section = &dwo_file->sections.abbrev;
- else
- abbrev_section = &dwarf2_per_objfile->abbrev;
+ not present, in which case the bfd is unknown. */
+ abfd = get_section_bfd_owner (section);
/* We don't use init_cutu_and_read_dies_simple, or some such, here
because we don't need to read any dies: the signature is in the
}
*slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
- if (dwarf2_read_debug)
+ if (dwarf2_read_debug > 1)
fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature %s\n",
offset.sect_off,
hex_string (signature));
dwarf2_per_objfile->n_type_units = htab_elements (types_htab);
dwarf2_per_objfile->all_type_units
- = obstack_alloc (&objfile->objfile_obstack,
- dwarf2_per_objfile->n_type_units
- * sizeof (struct signatured_type *));
+ = xmalloc (dwarf2_per_objfile->n_type_units
+ * sizeof (struct signatured_type *));
iter = &dwarf2_per_objfile->all_type_units[0];
htab_traverse_noresize (types_htab, add_signatured_type_cu_to_table, &iter);
gdb_assert (iter - &dwarf2_per_objfile->all_type_units[0]
return 1;
}
+/* Subroutine of lookup_dwo_signatured_type and lookup_dwp_signatured_type.
+ Fill in SIG_ENTRY with DWO_ENTRY. */
+
+static void
+fill_in_sig_entry_from_dwo_entry (struct objfile *objfile,
+ struct signatured_type *sig_entry,
+ struct dwo_unit *dwo_entry)
+{
+ /* Make sure we're not clobbering something we don't expect to. */
+ gdb_assert (! sig_entry->per_cu.queued);
+ gdb_assert (sig_entry->per_cu.cu == NULL);
+ gdb_assert (sig_entry->per_cu.v.quick != NULL);
+ gdb_assert (sig_entry->per_cu.v.quick->symtab == NULL);
+ gdb_assert (sig_entry->signature == dwo_entry->signature);
+ gdb_assert (sig_entry->type_offset_in_section.sect_off == 0);
+ gdb_assert (sig_entry->type_unit_group == NULL);
+ gdb_assert (sig_entry->dwo_unit == NULL);
+
+ sig_entry->per_cu.section = dwo_entry->section;
+ sig_entry->per_cu.offset = dwo_entry->offset;
+ sig_entry->per_cu.length = dwo_entry->length;
+ sig_entry->per_cu.reading_dwo_directly = 1;
+ sig_entry->per_cu.objfile = objfile;
+ sig_entry->type_offset_in_tu = dwo_entry->type_offset_in_tu;
+ sig_entry->dwo_unit = dwo_entry;
+}
+
+/* Subroutine of lookup_signatured_type.
+ If we haven't read the TU yet, create the signatured_type data structure
+ for a TU to be read in directly from a DWO file, bypassing the stub.
+ This is the "Stay in DWO Optimization": When there is no DWP file and we're
+ using .gdb_index, then when reading a CU we want to stay in the DWO file
+ containing that CU. Otherwise we could end up reading several other DWO
+ files (due to comdat folding) to process the transitive closure of all the
+ mentioned TUs, and that can be slow. The current DWO file will have every
+ type signature that it needs.
+ We only do this for .gdb_index because in the psymtab case we already have
+ to read all the DWOs to build the type unit groups. */
+
+static struct signatured_type *
+lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct dwo_file *dwo_file;
+ struct dwo_unit find_dwo_entry, *dwo_entry;
+ struct signatured_type find_sig_entry, *sig_entry;
+
+ gdb_assert (cu->dwo_unit && dwarf2_per_objfile->using_index);
+
+ /* Note: cu->dwo_unit is the dwo_unit that references this TU, not the
+ dwo_unit of the TU itself. */
+ dwo_file = cu->dwo_unit->dwo_file;
+
+ /* We only ever need to read in one copy of a signatured type.
+ Just use the global signatured_types array. If this is the first time
+ we're reading this type, replace the recorded data from .gdb_index with
+ this TU. */
+
+ if (dwarf2_per_objfile->signatured_types == NULL)
+ return NULL;
+ find_sig_entry.signature = sig;
+ sig_entry = htab_find (dwarf2_per_objfile->signatured_types, &find_sig_entry);
+ if (sig_entry == NULL)
+ return NULL;
+
+ /* We can get here with the TU already read, *or* in the process of being
+ read. Don't reassign it if that's the case. Also note that if the TU is
+ already being read, it may not have come from a DWO, the program may be
+ a mix of Fission-compiled code and non-Fission-compiled code. */
+ /* Have we already tried to read this TU? */
+ if (sig_entry->per_cu.tu_read)
+ return sig_entry;
+
+ /* Ok, this is the first time we're reading this TU. */
+ if (dwo_file->tus == NULL)
+ return NULL;
+ find_dwo_entry.signature = sig;
+ dwo_entry = htab_find (dwo_file->tus, &find_dwo_entry);
+ if (dwo_entry == NULL)
+ return NULL;
+
+ fill_in_sig_entry_from_dwo_entry (objfile, sig_entry, dwo_entry);
+ sig_entry->per_cu.tu_read = 1;
+ return sig_entry;
+}
+
+/* Subroutine of lookup_dwp_signatured_type.
+ Add an entry for signature SIG to dwarf2_per_objfile->signatured_types. */
+
+static struct signatured_type *
+add_type_unit (ULONGEST sig)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ int n_type_units = dwarf2_per_objfile->n_type_units;
+ struct signatured_type *sig_type;
+ void **slot;
+
+ ++n_type_units;
+ dwarf2_per_objfile->all_type_units =
+ xrealloc (dwarf2_per_objfile->all_type_units,
+ n_type_units * sizeof (struct signatured_type *));
+ dwarf2_per_objfile->n_type_units = n_type_units;
+ sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct signatured_type);
+ dwarf2_per_objfile->all_type_units[n_type_units - 1] = sig_type;
+ sig_type->signature = sig;
+ sig_type->per_cu.is_debug_types = 1;
+ sig_type->per_cu.v.quick =
+ OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_per_cu_quick_data);
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
+ sig_type, INSERT);
+ gdb_assert (*slot == NULL);
+ *slot = sig_type;
+ /* The rest of sig_type must be filled in by the caller. */
+ return sig_type;
+}
+
+/* Subroutine of lookup_signatured_type.
+ Look up the type for signature SIG, and if we can't find SIG in .gdb_index
+ then try the DWP file.
+ Normally this "can't happen", but if there's a bug in signature
+ generation and/or the DWP file is built incorrectly, it can happen.
+ Using the type directly from the DWP file means we don't have the stub
+ which has some useful attributes (e.g., DW_AT_comp_dir), but they're
+ not critical. [Eventually the stub may go away for type units anyway.] */
+
+static struct signatured_type *
+lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct dwp_file *dwp_file = get_dwp_file ();
+ struct dwo_unit *dwo_entry;
+ struct signatured_type find_sig_entry, *sig_entry;
+
+ gdb_assert (cu->dwo_unit && dwarf2_per_objfile->using_index);
+ gdb_assert (dwp_file != NULL);
+
+ if (dwarf2_per_objfile->signatured_types != NULL)
+ {
+ find_sig_entry.signature = sig;
+ sig_entry = htab_find (dwarf2_per_objfile->signatured_types,
+ &find_sig_entry);
+ if (sig_entry != NULL)
+ return sig_entry;
+ }
+
+ /* This is the "shouldn't happen" case.
+ Try the DWP file and hope for the best. */
+ if (dwp_file->tus == NULL)
+ return NULL;
+ dwo_entry = lookup_dwo_unit_in_dwp (dwp_file, NULL,
+ sig, 1 /* is_debug_types */);
+ if (dwo_entry == NULL)
+ return NULL;
+
+ sig_entry = add_type_unit (sig);
+ fill_in_sig_entry_from_dwo_entry (objfile, sig_entry, dwo_entry);
+
+ /* The caller will signal a complaint if we return NULL.
+ Here we don't return NULL but we still want to complain. */
+ complaint (&symfile_complaints,
+ _("Bad type signature %s referenced by %s at 0x%x,"
+ " coping by using copy in DWP [in module %s]"),
+ hex_string (sig),
+ cu->per_cu->is_debug_types ? "TU" : "CU",
+ cu->per_cu->offset.sect_off,
+ objfile_name (objfile));
+
+ return sig_entry;
+}
+
/* Lookup a signature based type for DW_FORM_ref_sig8.
Returns NULL if signature SIG is not present in the table.
It is up to the caller to complain about this. */
static struct signatured_type *
-lookup_signatured_type (ULONGEST sig)
+lookup_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
{
- struct signatured_type find_entry, *entry;
+ if (cu->dwo_unit
+ && dwarf2_per_objfile->using_index)
+ {
+ /* We're in a DWO/DWP file, and we're using .gdb_index.
+ These cases require special processing. */
+ if (get_dwp_file () == NULL)
+ return lookup_dwo_signatured_type (cu, sig);
+ else
+ return lookup_dwp_signatured_type (cu, sig);
+ }
+ else
+ {
+ struct signatured_type find_entry, *entry;
- if (dwarf2_per_objfile->signatured_types == NULL)
- return NULL;
- find_entry.signature = sig;
- entry = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
- return entry;
+ if (dwarf2_per_objfile->signatured_types == NULL)
+ return NULL;
+ find_entry.signature = sig;
+ entry = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
+ return entry;
+ }
}
\f
/* Low level DIE reading support. */
struct dwo_file *dwo_file)
{
gdb_assert (section->readin && section->buffer != NULL);
- reader->abfd = section->asection->owner;
+ reader->abfd = get_section_bfd_owner (section);
reader->cu = cu;
reader->dwo_file = dwo_file;
reader->die_section = section;
reader->buffer = section->buffer;
reader->buffer_end = section->buffer + section->size;
+ reader->comp_dir = NULL;
}
/* Subroutine of init_cutu_and_read_dies to simplify it.
STUB_COMP_UNIT_DIE is for the stub DIE, we copy over certain attributes
from it to the DIE in the DWO. If NULL we are skipping the stub.
+ STUB_COMP_DIR is similar to STUB_COMP_UNIT_DIE: When reading a TU directly
+ from the DWO file, bypassing the stub, it contains the DW_AT_comp_dir
+ attribute of the referencing CU. Exactly one of STUB_COMP_UNIT_DIE and
+ COMP_DIR must be non-NULL.
*RESULT_READER,*RESULT_INFO_PTR,*RESULT_COMP_UNIT_DIE,*RESULT_HAS_CHILDREN
are filled in with the info of the DIE from the DWO file.
ABBREV_TABLE_PROVIDED is non-zero if the caller of init_cutu_and_read_dies
struct dwo_unit *dwo_unit,
int abbrev_table_provided,
struct die_info *stub_comp_unit_die,
+ const char *stub_comp_dir,
struct die_reader_specs *result_reader,
const gdb_byte **result_info_ptr,
struct die_info **result_comp_unit_die,
int i,num_extra_attrs;
struct dwarf2_section_info *dwo_abbrev_section;
struct attribute *attr;
+ struct attribute comp_dir_attr;
struct die_info *comp_unit_die;
+ /* Both can't be provided. */
+ gdb_assert (! (stub_comp_unit_die && stub_comp_dir));
+
/* 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.
if (attr)
cu->ranges_base = DW_UNSND (attr);
}
+ else if (stub_comp_dir != NULL)
+ {
+ /* Reconstruct the comp_dir attribute to simplify the code below. */
+ comp_dir = (struct attribute *)
+ obstack_alloc (&cu->comp_unit_obstack, sizeof (*comp_dir));
+ comp_dir->name = DW_AT_comp_dir;
+ comp_dir->form = DW_FORM_string;
+ DW_STRING_IS_CANONICAL (comp_dir) = 0;
+ DW_STRING (comp_dir) = stub_comp_dir;
+ }
/* Set up for reading the DWO CU/TU. */
cu->dwo_unit = dwo_unit;
section = dwo_unit->section;
dwarf2_read_section (objfile, section);
- abfd = section->asection->owner;
+ abfd = get_section_bfd_owner (section);
begin_info_ptr = info_ptr = section->buffer + dwo_unit->offset.sect_off;
dwo_abbrev_section = &dwo_unit->dwo_file->sections.abbrev;
init_cu_die_reader (result_reader, cu, section, dwo_unit->dwo_file);
info_ptr,
&header_signature,
&type_offset_in_tu);
- gdb_assert (sig_type->signature == header_signature);
+ /* This is not an assert because it can be caused by bad debug info. */
+ if (sig_type->signature != header_signature)
+ {
+ error (_("Dwarf Error: signature mismatch %s vs %s while reading"
+ " TU at offset 0x%x [in module %s]"),
+ hex_string (sig_type->signature),
+ hex_string (header_signature),
+ dwo_unit->offset.sect_off,
+ bfd_get_filename (abfd));
+ }
gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
/* For DWOs coming from DWP files, we don't know the CU length
nor the type's offset in the TU until now. */
{
fprintf_unfiltered (gdb_stdlog,
"Read die from %s@0x%x of %s:\n",
- bfd_section_name (abfd, section->asection),
+ get_section_name (section),
(unsigned) (begin_info_ptr - section->buffer),
bfd_get_filename (abfd));
dump_die (comp_unit_die, dwarf2_die_debug);
}
+ /* Save the comp_dir attribute. If there is no DWP file then we'll read
+ TUs by skipping the stub and going directly to the entry in the DWO file.
+ However, skipping the stub means we won't get DW_AT_comp_dir, so we have
+ to get it via circuitous means. Blech. */
+ if (comp_dir != NULL)
+ result_reader->comp_dir = DW_STRING (comp_dir);
+
/* Skip dummy compilation units. */
if (info_ptr >= begin_info_ptr + dwo_unit->length
|| peek_abbrev_code (abfd, info_ptr) == 0)
/* Subroutine of init_cutu_and_read_dies to simplify it.
Look up the DWO unit specified by COMP_UNIT_DIE of THIS_CU.
- If the specified DWO unit cannot be found an error is thrown. */
+ Returns NULL if the specified DWO unit cannot be found. */
static struct dwo_unit *
lookup_dwo_unit (struct dwarf2_per_cu_data *this_cu,
struct dwo_unit *dwo_unit;
const char *comp_dir, *dwo_name;
+ gdb_assert (cu != NULL);
+
/* Yeah, we look dwo_name up again, but it simplifies the code. */
attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_name, cu);
gdb_assert (attr != NULL);
if (! attr)
error (_("Dwarf Error: missing dwo_id for dwo_name %s"
" [in module %s]"),
- dwo_name, this_cu->objfile->name);
+ dwo_name, objfile_name (this_cu->objfile));
signature = DW_UNSND (attr);
dwo_unit = lookup_dwo_comp_unit (this_cu, dwo_name, comp_dir,
signature);
}
- if (dwo_unit == NULL)
+ return dwo_unit;
+}
+
+/* Subroutine of init_cutu_and_read_dies to simplify it.
+ Read a TU directly from a DWO file, bypassing the stub. */
+
+static void
+init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu, int keep,
+ die_reader_func_ftype *die_reader_func,
+ void *data)
+{
+ struct dwarf2_cu *cu;
+ struct signatured_type *sig_type;
+ struct cleanup *cleanups, *free_cu_cleanup;
+ struct die_reader_specs reader;
+ const gdb_byte *info_ptr;
+ struct die_info *comp_unit_die;
+ int has_children;
+
+ /* Verify we can do the following downcast, and that we have the
+ data we need. */
+ gdb_assert (this_cu->is_debug_types && this_cu->reading_dwo_directly);
+ sig_type = (struct signatured_type *) this_cu;
+ gdb_assert (sig_type->dwo_unit != NULL);
+
+ cleanups = make_cleanup (null_cleanup, NULL);
+
+ gdb_assert (this_cu->cu == NULL);
+ cu = xmalloc (sizeof (*cu));
+ init_one_comp_unit (cu, this_cu);
+ /* If an error occurs while loading, release our storage. */
+ free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
+
+ if (read_cutu_die_from_dwo (this_cu, sig_type->dwo_unit,
+ 0 /* abbrev_table_provided */,
+ NULL /* stub_comp_unit_die */,
+ sig_type->dwo_unit->dwo_file->comp_dir,
+ &reader, &info_ptr,
+ &comp_unit_die, &has_children) == 0)
+ {
+ /* Dummy die. */
+ do_cleanups (cleanups);
+ return;
+ }
+
+ /* All the "real" work is done here. */
+ die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
+
+ /* This duplicates some code in init_cutu_and_read_dies,
+ but the alternative is making the latter more complex.
+ This function is only for the special case of using DWO files directly:
+ no point in overly complicating the general case just to handle this. */
+ if (keep)
{
- error (_("Dwarf Error: CU at offset 0x%x references unknown DWO"
- " with ID %s [in module %s]"),
- this_cu->offset.sect_off, hex_string (signature),
- this_cu->objfile->name);
+ /* We've successfully allocated this compilation unit. Let our
+ caller clean it up when finished with it. */
+ discard_cleanups (free_cu_cleanup);
+
+ /* We can only discard free_cu_cleanup and all subsequent cleanups.
+ So we have to manually free the abbrev table. */
+ dwarf2_free_abbrev_table (cu);
+
+ /* Link this CU into read_in_chain. */
+ this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+ dwarf2_per_objfile->read_in_chain = this_cu;
}
+ else
+ do_cleanups (free_cu_cleanup);
- return dwo_unit;
+ do_cleanups (cleanups);
}
/* Initialize a CU (or TU) and read its DIEs.
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwarf2_section_info *section = this_cu->section;
- bfd *abfd = section->asection->owner;
+ bfd *abfd = get_section_bfd_owner (section);
struct dwarf2_cu *cu;
const gdb_byte *begin_info_ptr, *info_ptr;
struct die_reader_specs reader;
struct dwarf2_section_info *abbrev_section;
/* Non-zero if CU currently points to a DWO file and we need to
reread it. When this happens we need to reread the skeleton die
- before we can reread the DWO file. */
+ before we can reread the DWO file (this only applies to CUs, not TUs). */
int rereading_dwo_cu = 0;
if (dwarf2_die_debug)
if (use_existing_cu)
gdb_assert (keep);
+ /* If we're reading a TU directly from a DWO file, including a virtual DWO
+ file (instead of going through the stub), short-circuit all of this. */
+ if (this_cu->reading_dwo_directly)
+ {
+ /* Narrow down the scope of possibilities to have to understand. */
+ gdb_assert (this_cu->is_debug_types);
+ gdb_assert (abbrev_table == NULL);
+ gdb_assert (!use_existing_cu);
+ init_tu_and_read_dwo_dies (this_cu, keep, die_reader_func, data);
+ return;
+ }
+
cleanups = make_cleanup (null_cleanup, NULL);
/* This is cheap if the section is already read in. */
struct die_info *dwo_comp_unit_die;
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));
+ {
+ complaint (&symfile_complaints,
+ _("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));
+ }
dwo_unit = lookup_dwo_unit (this_cu, comp_unit_die);
- if (read_cutu_die_from_dwo (this_cu, dwo_unit,
- abbrev_table != NULL,
- comp_unit_die,
- &reader, &info_ptr,
- &dwo_comp_unit_die, &has_children) == 0)
+ if (dwo_unit != NULL)
{
- /* Dummy die. */
- do_cleanups (cleanups);
- return;
+ if (read_cutu_die_from_dwo (this_cu, dwo_unit,
+ abbrev_table != NULL,
+ comp_unit_die, NULL,
+ &reader, &info_ptr,
+ &dwo_comp_unit_die, &has_children) == 0)
+ {
+ /* Dummy die. */
+ do_cleanups (cleanups);
+ return;
+ }
+ comp_unit_die = dwo_comp_unit_die;
+ }
+ else
+ {
+ /* Yikes, we couldn't find the rest of the DIE, we only have
+ the stub. A complaint has already been logged. There's
+ not much more we can do except pass on the stub DIE to
+ die_reader_func. We don't want to throw an error on bad
+ debug info. */
}
- comp_unit_die = dwo_comp_unit_die;
}
/* All of the above is setup for this call. Yikes. */
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwarf2_section_info *section = this_cu->section;
- bfd *abfd = section->asection->owner;
+ bfd *abfd = get_section_bfd_owner (section);
struct dwarf2_cu cu;
const gdb_byte *begin_info_ptr, *info_ptr;
struct die_reader_specs reader;
STMT_LIST is a DW_AT_stmt_list attribute. */
static struct type_unit_group *
-get_type_unit_group (struct dwarf2_cu *cu, struct attribute *stmt_list)
+get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
{
struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
struct type_unit_group *tu_group;
func, data);
}
+ /* type_unit_groups can be NULL if there is an error in the debug info.
+ Just create an empty table so the rest of gdb doesn't have to watch
+ for this error case. */
+ if (dwarf2_per_objfile->type_unit_groups == NULL)
+ {
+ dwarf2_per_objfile->type_unit_groups =
+ allocate_type_unit_groups_table ();
+ dwarf2_per_objfile->n_type_unit_groups = 0;
+ }
+
/* Create a vector of pointers to primary type units to make it easy to
iterate over them and CUs. See dw2_get_primary_cu. */
dwarf2_per_objfile->n_type_unit_groups =
return pst;
}
+/* The DATA object passed to process_psymtab_comp_unit_reader has this
+ type. */
+
+struct process_psymtab_comp_unit_data
+{
+ /* True if we are reading a DW_TAG_partial_unit. */
+
+ int want_partial_unit;
+
+ /* The "pretend" language that is used if the CU doesn't declare a
+ language. */
+
+ enum language pretend_language;
+};
+
/* die_reader_func for process_psymtab_comp_unit. */
static void
struct partial_symtab *pst;
int has_pc_info;
const char *filename;
- int *want_partial_unit_ptr = data;
+ struct process_psymtab_comp_unit_data *info = data;
- if (comp_unit_die->tag == DW_TAG_partial_unit
- && (want_partial_unit_ptr == NULL
- || !*want_partial_unit_ptr))
+ if (comp_unit_die->tag == DW_TAG_partial_unit && !info->want_partial_unit)
return;
gdb_assert (! per_cu->is_debug_types);
- prepare_one_comp_unit (cu, comp_unit_die, language_minimal);
+ prepare_one_comp_unit (cu, comp_unit_die, info->pretend_language);
cu->list_in_scope = &file_symbols;
static void
process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
- int want_partial_unit)
+ int want_partial_unit,
+ enum language pretend_language)
{
+ struct process_psymtab_comp_unit_data info;
+
/* If this compilation unit was already read in, free the
cached copy in order to read it in again. This is
necessary because we skipped some symbols when we first
free_one_cached_comp_unit (this_cu);
gdb_assert (! this_cu->is_debug_types);
+ info.want_partial_unit = want_partial_unit;
+ info.pretend_language = pretend_language;
init_cutu_and_read_dies (this_cu, NULL, 0, 0,
process_psymtab_comp_unit_reader,
- &want_partial_unit);
+ &info);
/* Age out any secondary CUs. */
age_cached_comp_units ();
if (dwarf2_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "Building psymtabs of objfile %s ...\n",
- objfile->name);
+ objfile_name (objfile));
}
dwarf2_per_objfile->reading_partial_symbols = 1;
{
struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
- process_psymtab_comp_unit (per_cu, 0);
+ process_psymtab_comp_unit (per_cu, 0, language_minimal);
}
set_partial_user (objfile);
if (dwarf2_read_debug)
fprintf_unfiltered (gdb_stdlog, "Done building psymtabs of %s\n",
- objfile->name);
+ objfile_name (objfile));
}
/* die_reader_func for load_partial_comp_unit. */
struct dwarf2_per_cu_data ***all_comp_units)
{
const gdb_byte *info_ptr;
- bfd *abfd = section->asection->owner;
+ bfd *abfd = get_section_bfd_owner (section);
if (dwarf2_read_debug)
fprintf_unfiltered (gdb_stdlog, "Reading %s for %s\n",
- section->asection->name, bfd_get_filename (abfd));
+ get_section_name (section),
+ get_section_file_name (section));
dwarf2_read_section (objfile, section);
int n_allocated;
int n_comp_units;
struct dwarf2_per_cu_data **all_comp_units;
+ struct dwz_file *dwz;
n_comp_units = 0;
n_allocated = 10;
read_comp_units_from_section (objfile, &dwarf2_per_objfile->info, 0,
&n_allocated, &n_comp_units, &all_comp_units);
- if (bfd_get_section_by_name (objfile->obfd, ".gnu_debugaltlink") != NULL)
- {
- struct dwz_file *dwz = dwarf2_get_dwz_file ();
-
- read_comp_units_from_section (objfile, &dwz->info, 1,
- &n_allocated, &n_comp_units,
- &all_comp_units);
- }
+ dwz = dwarf2_get_dwz_file ();
+ if (dwz != NULL)
+ read_comp_units_from_section (objfile, &dwz->info, 1,
+ &n_allocated, &n_comp_units,
+ &all_comp_units);
dwarf2_per_objfile->all_comp_units
= obstack_alloc (&objfile->objfile_obstack,
{
error (_("Dwarf Error: DW_TAG_imported_unit is not"
" supported in type units [in module %s]"),
- cu->objfile->name);
+ objfile_name (cu->objfile));
}
per_cu = dwarf2_find_containing_comp_unit (pdi->d.offset,
/* Go read the partial unit, if needed. */
if (per_cu->v.psymtab == NULL)
- process_psymtab_comp_unit (per_cu, 1);
+ process_psymtab_comp_unit (per_cu, 1, cu->language);
VEC_safe_push (dwarf2_per_cu_ptr,
cu->per_cu->imported_symtabs, per_cu);
}
break;
+ case DW_TAG_imported_declaration:
+ add_partial_symbol (pdi, cu);
+ break;
default:
break;
}
&objfile->static_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
break;
+ case DW_TAG_imported_declaration:
case DW_TAG_namespace:
add_psymbol_to_list (actual_name, strlen (actual_name),
built_actual_name != NULL,
&objfile->global_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
break;
+ case DW_TAG_module:
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ built_actual_name != NULL,
+ MODULE_DOMAIN, LOC_TYPEDEF,
+ &objfile->global_psymbols,
+ 0, (CORE_ADDR) 0, cu->language, objfile);
+ break;
case DW_TAG_class_type:
case DW_TAG_interface_type:
case DW_TAG_structure_type:
add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu)
{
+ /* Add a symbol for the namespace. */
+
+ add_partial_symbol (pdi, cu);
+
/* Now scan partial symbols in that module. */
if (pdi->has_children)
complaint (&symfile_complaints,
_("ignoring absolute DW_AT_sibling"));
else
- return buffer + dwarf2_get_ref_die_offset (&attr).sect_off;
+ {
+ unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off;
+ const gdb_byte *sibling_ptr = buffer + off;
+
+ if (sibling_ptr < info_ptr)
+ complaint (&symfile_complaints,
+ _("DW_AT_sibling points backwards"));
+ else
+ return sibling_ptr;
+ }
}
/* If it isn't DW_AT_sibling, skip this attribute. */
dwarf2_queue_tail = item;
}
-/* THIS_CU has a reference to PER_CU. If necessary, load the new compilation
- unit and add it to our queue.
+/* If PER_CU is not yet queued, add it to the queue.
+ If DEPENDENT_CU is non-NULL, it has a reference to PER_CU so add a
+ dependency.
The result is non-zero if PER_CU was queued, otherwise the result is zero
- meaning either PER_CU is already queued or it is already loaded. */
+ meaning either PER_CU is already queued or it is already loaded.
+
+ N.B. There is an invariant here that if a CU is queued then it is loaded.
+ The caller is required to load PER_CU if we return non-zero. */
static int
-maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
+maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu,
struct dwarf2_per_cu_data *per_cu,
enum language pretend_language)
{
/* Mark the dependence relation so that we don't flush PER_CU
too early. */
- dwarf2_add_dependence (this_cu, per_cu);
+ if (dependent_cu != NULL)
+ dwarf2_add_dependence (dependent_cu, per_cu);
/* If it's already on the queue, we have nothing to do. */
if (per_cu->queued)
{
fprintf_unfiltered (gdb_stdlog,
"Expanding one or more symtabs of objfile %s ...\n",
- dwarf2_per_objfile->objfile->name);
+ objfile_name (dwarf2_per_objfile->objfile));
}
/* The queue starts out with one item, but following a DIE reference
: (item->per_cu->v.psymtab && !item->per_cu->v.psymtab->readin))
{
struct dwarf2_per_cu_data *per_cu = item->per_cu;
+ unsigned int debug_print_threshold;
+ char buf[100];
- if (dwarf2_read_debug)
+ if (per_cu->is_debug_types)
+ {
+ struct signatured_type *sig_type =
+ (struct signatured_type *) per_cu;
+
+ sprintf (buf, "TU %s at offset 0x%x",
+ hex_string (sig_type->signature),
+ per_cu->offset.sect_off);
+ /* There can be 100s of TUs.
+ Only print them in verbose mode. */
+ debug_print_threshold = 2;
+ }
+ else
{
- fprintf_unfiltered (gdb_stdlog,
- "Expanding symtab of %s at offset 0x%x\n",
- per_cu->is_debug_types ? "TU" : "CU",
- per_cu->offset.sect_off);
+ sprintf (buf, "CU at offset 0x%x", per_cu->offset.sect_off);
+ debug_print_threshold = 1;
}
+ if (dwarf2_read_debug >= debug_print_threshold)
+ fprintf_unfiltered (gdb_stdlog, "Expanding symtab of %s\n", buf);
+
if (per_cu->is_debug_types)
process_full_type_unit (per_cu, item->pretend_language);
else
process_full_comp_unit (per_cu, item->pretend_language);
- if (dwarf2_read_debug)
- {
- fprintf_unfiltered (gdb_stdlog,
- "Done expanding %s at offset 0x%x\n",
- per_cu->is_debug_types ? "TU" : "CU",
- per_cu->offset.sect_off);
- }
+ if (dwarf2_read_debug >= debug_print_threshold)
+ fprintf_unfiltered (gdb_stdlog, "Done expanding %s\n", buf);
}
item->per_cu->queued = 0;
if (dwarf2_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "Done expanding symtabs of %s.\n",
- dwarf2_per_objfile->objfile->name);
+ objfile_name (dwarf2_per_objfile->objfile));
}
}
_("Symtab %s has objects from two different Go packages: %s and %s"),
(SYMBOL_SYMTAB (sym)
? symtab_to_filename_for_display (SYMBOL_SYMTAB (sym))
- : cu->objfile->name),
+ : objfile_name (cu->objfile)),
this_package_name, package_name);
xfree (this_package_name);
}
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)
+recursively_compute_inclusions (VEC (symtab_ptr) **result,
+ htab_t all_children, htab_t all_type_symtabs,
+ struct dwarf2_per_cu_data *per_cu,
+ struct symtab *immediate_parent)
{
void **slot;
int ix;
+ struct symtab *symtab;
struct dwarf2_per_cu_data *iter;
slot = htab_find_slot (all_children, per_cu, INSERT);
*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);
+ symtab = get_symtab (per_cu);
+ if (symtab != NULL)
+ {
+ /* If this is a type unit only add its symbol table if we haven't
+ seen it yet (type unit per_cu's can share symtabs). */
+ if (per_cu->is_debug_types)
+ {
+ slot = htab_find_slot (all_type_symtabs, symtab, INSERT);
+ if (*slot == NULL)
+ {
+ *slot = symtab;
+ VEC_safe_push (symtab_ptr, *result, symtab);
+ if (symtab->user == NULL)
+ symtab->user = immediate_parent;
+ }
+ }
+ else
+ {
+ VEC_safe_push (symtab_ptr, *result, symtab);
+ if (symtab->user == NULL)
+ symtab->user = immediate_parent;
+ }
+ }
for (ix = 0;
VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs, ix, iter);
++ix)
- recursively_compute_inclusions (result, all_children, iter);
+ {
+ recursively_compute_inclusions (result, all_children,
+ all_type_symtabs, iter, symtab);
+ }
}
/* Compute the symtab 'includes' fields for the symtab related to
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 dwarf2_per_cu_data *per_cu_iter;
+ struct symtab *symtab_iter;
+ VEC (symtab_ptr) *result_symtabs = NULL;
+ htab_t all_children, all_type_symtabs;
struct symtab *symtab = get_symtab (per_cu);
/* If we don't have a symtab, we can just skip this case. */
all_children = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer,
NULL, xcalloc, xfree);
+ all_type_symtabs = 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, per_cu_iter);
++ix)
- recursively_compute_inclusions (&result_children, all_children, iter);
+ {
+ recursively_compute_inclusions (&result_symtabs, all_children,
+ all_type_symtabs, per_cu_iter,
+ symtab);
+ }
- /* Now we have a transitive closure of all the included CUs, and
- for .gdb_index version 7 the included TUs, so we can convert it
- to a list of symtabs. */
- len = VEC_length (dwarf2_per_cu_ptr, result_children);
+ /* Now we have a transitive closure of all the included symtabs. */
+ len = VEC_length (symtab_ptr, result_symtabs);
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);
+ VEC_iterate (symtab_ptr, result_symtabs, ix, symtab_iter);
++ix)
- symtab->includes[ix] = get_symtab (iter);
+ symtab->includes[ix] = symtab_iter;
symtab->includes[len] = NULL;
- VEC_free (dwarf2_per_cu_ptr, result_children);
+ VEC_free (symtab_ptr, result_symtabs);
htab_delete (all_children);
+ htab_delete (all_type_symtabs);
}
}
get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);
static_block
- = end_symtab_get_static_block (highpc + baseaddr, objfile, 0,
- per_cu->imported_symtabs != NULL);
+ = end_symtab_get_static_block (highpc + baseaddr, objfile, 0, 1);
/* If the comp unit has DW_AT_ranges, it may have discontiguous ranges.
Also, DW_AT_ranges may record ranges not belonging to any child DIEs
{
error (_("Dwarf Error: DW_TAG_imported_unit is not"
" supported in type units [in module %s]"),
- cu->objfile->name);
+ objfile_name (cu->objfile));
}
attr = dwarf2_attr (die, DW_AT_import, cu);
is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
per_cu = dwarf2_find_containing_comp_unit (offset, is_dwz, cu->objfile);
- /* Queue the unit, if needed. */
+ /* If necessary, add it to the queue and load its DIEs. */
if (maybe_queue_comp_unit (cu, per_cu, cu->language))
load_full_comp_unit (per_cu, cu->language);
read_module (die, cu);
break;
case DW_TAG_imported_declaration:
+ cu->processing_has_namespace_info = 1;
+ if (read_namespace_alias (die, cu))
+ break;
+ /* The declaration is not a global namespace alias: fall through. */
case DW_TAG_imported_module:
cu->processing_has_namespace_info = 1;
if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
case DW_TAG_enumerator:
case DW_TAG_subprogram:
case DW_TAG_member:
+ case DW_TAG_imported_declaration:
return 1;
case DW_TAG_variable:
complaint (&symfile_complaints,
_("Computed physname <%s> does not match demangled <%s> "
"(from linkage <%s>) - DIE at 0x%x [in module %s]"),
- physname, canon, mangled, die->offset.sect_off, objfile->name);
+ physname, canon, mangled, die->offset.sect_off,
+ objfile_name (objfile));
/* Prefer DW_AT_linkage_name (in the CANON form) - when it
is available here - over computed PHYSNAME. It is safer
return retval;
}
+/* Inspect DIE in CU for a namespace alias. If one exists, record
+ a new symbol for it.
+
+ Returns 1 if a namespace alias was recorded, 0 otherwise. */
+
+static int
+read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct attribute *attr;
+
+ /* If the die does not have a name, this is not a namespace
+ alias. */
+ attr = dwarf2_attr (die, DW_AT_name, cu);
+ if (attr != NULL)
+ {
+ int num;
+ struct die_info *d = die;
+ struct dwarf2_cu *imported_cu = cu;
+
+ /* If the compiler has nested DW_AT_imported_declaration DIEs,
+ keep inspecting DIEs until we hit the underlying import. */
+#define MAX_NESTED_IMPORTED_DECLARATIONS 100
+ for (num = 0; num < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
+ {
+ attr = dwarf2_attr (d, DW_AT_import, cu);
+ if (attr == NULL)
+ break;
+
+ d = follow_die_ref (d, attr, &imported_cu);
+ if (d->tag != DW_TAG_imported_declaration)
+ break;
+ }
+
+ if (num == MAX_NESTED_IMPORTED_DECLARATIONS)
+ {
+ complaint (&symfile_complaints,
+ _("DIE at 0x%x has too many recursively imported "
+ "declarations"), d->offset.sect_off);
+ return 0;
+ }
+
+ if (attr != NULL)
+ {
+ struct type *type;
+ sect_offset offset = dwarf2_get_ref_die_offset (attr);
+
+ type = get_die_type_at_offset (offset, cu->per_cu);
+ if (type != NULL && TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
+ {
+ /* This declaration is a global namespace alias. Add
+ a symbol for it whose type is the aliased namespace. */
+ new_symbol (die, type, cu);
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
/* Read the import statement specified by the given die and record it. */
static void
complaint (&symfile_complaints,
_("child DW_TAG_imported_declaration expected "
"- DIE at 0x%x [in module %s]"),
- child_die->offset.sect_off, objfile->name);
+ child_die->offset.sect_off, objfile_name (objfile));
continue;
}
complaint (&symfile_complaints,
_("child DW_TAG_imported_declaration has unknown "
"imported name - DIE at 0x%x [in module %s]"),
- child_die->offset.sect_off, objfile->name);
+ child_die->offset.sect_off, objfile_name (objfile));
continue;
}
static void
handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
- const char *comp_dir)
+ const char *comp_dir) /* ARI: editCase function */
{
struct attribute *attr;
attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
/* If we're using .gdb_index (includes -readnow) then
- per_cu->s.type_unit_group may not have been set up yet. */
+ per_cu->type_unit_group may not have been set up yet. */
if (sig_type->type_unit_group == NULL)
sig_type->type_unit_group = get_type_unit_group (cu, attr);
tu_group = sig_type->type_unit_group;
hash_dwo_file (const void *item)
{
const struct dwo_file *dwo_file = item;
+ hashval_t hash;
- return (htab_hash_string (dwo_file->dwo_name)
- + htab_hash_string (dwo_file->comp_dir));
+ hash = htab_hash_string (dwo_file->dwo_name);
+ if (dwo_file->comp_dir != NULL)
+ hash += htab_hash_string (dwo_file->comp_dir);
+ return hash;
}
static int
const struct dwo_file *lhs = item_lhs;
const struct dwo_file *rhs = item_rhs;
- return (strcmp (lhs->dwo_name, rhs->dwo_name) == 0
- && strcmp (lhs->comp_dir, rhs->comp_dir) == 0);
+ if (strcmp (lhs->dwo_name, rhs->dwo_name) != 0)
+ return 0;
+ if (lhs->comp_dir == NULL || rhs->comp_dir == NULL)
+ return lhs->comp_dir == rhs->comp_dir;
+ return strcmp (lhs->comp_dir, rhs->comp_dir) == 0;
}
/* Allocate a hash table for DWO files. */
/* 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;
+ abfd = get_section_bfd_owner (section);
if (dwarf2_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n",
- bfd_section_name (abfd, section->asection),
- bfd_get_filename (abfd));
+ get_section_name (section),
+ get_section_file_name (section));
}
create_dwo_cu_data.dwo_file = dwo_file;
{
complaint (&symfile_complaints,
_("Multiple CUs in DWO file %s [in module %s]"),
- dwo_file->dwo_name, objfile->name);
+ dwo_file->dwo_name, objfile_name (objfile));
break;
}
/* DWP file .debug_{cu,tu}_index section format:
[ref: http://gcc.gnu.org/wiki/DebugFissionDWP]
+ DWP Version 1:
+
Both index sections have the same format, and serve to map a 64-bit
signature to a set of section numbers. Each section begins with a header,
followed by a hash table of 64-bit signatures, a parallel table of 32-bit
indexes, and a pool of 32-bit section numbers. The index sections will be
aligned at 8-byte boundaries in the file.
- The index section header contains two unsigned 32-bit values (using the
- byte order of the application binary):
-
- N, the number of compilation units or type units in the index
- M, the number of slots in the hash table
-
- (We assume that N and M will not exceed 2^32 - 1.)
-
- The size of the hash table, M, must be 2^k such that 2^k > 3*N/2.
-
- The hash table begins at offset 8 in the section, and consists of an array
- of M 64-bit slots. Each slot contains a 64-bit signature (using the byte
- order of the application binary). Unused slots in the hash table are 0.
- (We rely on the extreme unlikeliness of a signature being exactly 0.)
-
- The parallel table begins immediately after the hash table
- (at offset 8 + 8 * M from the beginning of the section), and consists of an
- array of 32-bit indexes (using the byte order of the application binary),
- corresponding 1-1 with slots in the hash table. Each entry in the parallel
- table contains a 32-bit index into the pool of section numbers. For unused
- hash table slots, the corresponding entry in the parallel table will be 0.
-
- Given a 64-bit compilation unit signature or a type signature S, an entry
- in the hash table is located as follows:
-
- 1) Calculate a primary hash H = S & MASK(k), where MASK(k) is a mask with
- the low-order k bits all set to 1.
-
- 2) Calculate a secondary hash H' = (((S >> 32) & MASK(k)) | 1).
-
- 3) If the hash table entry at index H matches the signature, use that
- entry. If the hash table entry at index H is unused (all zeroes),
- terminate the search: the signature is not present in the table.
-
- 4) Let H = (H + H') modulo M. Repeat at Step 3.
-
- Because M > N and H' and M are relatively prime, the search is guaranteed
- to stop at an unused slot or find the match.
-
- The pool of section numbers begins immediately following the hash table
- (at offset 8 + 12 * M from the beginning of the section). The pool of
- section numbers consists of an array of 32-bit words (using the byte order
- of the application binary). Each item in the array is indexed starting
- from 0. The hash table entry provides the index of the first section
- number in the set. Additional section numbers in the set follow, and the
- set is terminated by a 0 entry (section number 0 is not used in ELF).
-
- In each set of section numbers, the .debug_info.dwo or .debug_types.dwo
- section must be the first entry in the set, and the .debug_abbrev.dwo must
- be the second entry. Other members of the set may follow in any order. */
+ The index section header consists of:
+
+ V, 32 bit version number
+ -, 32 bits unused
+ N, 32 bit number of compilation units or type units in the index
+ M, 32 bit number of slots in the hash table
+
+ Numbers are recorded using the byte order of the application binary.
+
+ The hash table begins at offset 16 in the section, and consists of an array
+ of M 64-bit slots. Each slot contains a 64-bit signature (using the byte
+ order of the application binary). Unused slots in the hash table are 0.
+ (We rely on the extreme unlikeliness of a signature being exactly 0.)
+
+ The parallel table begins immediately after the hash table
+ (at offset 16 + 8 * M from the beginning of the section), and consists of an
+ array of 32-bit indexes (using the byte order of the application binary),
+ corresponding 1-1 with slots in the hash table. Each entry in the parallel
+ table contains a 32-bit index into the pool of section numbers. For unused
+ hash table slots, the corresponding entry in the parallel table will be 0.
+
+ The pool of section numbers begins immediately following the hash table
+ (at offset 16 + 12 * M from the beginning of the section). The pool of
+ section numbers consists of an array of 32-bit words (using the byte order
+ of the application binary). Each item in the array is indexed starting
+ from 0. The hash table entry provides the index of the first section
+ number in the set. Additional section numbers in the set follow, and the
+ set is terminated by a 0 entry (section number 0 is not used in ELF).
+
+ In each set of section numbers, the .debug_info.dwo or .debug_types.dwo
+ section must be the first entry in the set, and the .debug_abbrev.dwo must
+ be the second entry. Other members of the set may follow in any order.
+
+ ---
+
+ DWP Version 2:
+
+ DWP Version 2 combines all the .debug_info, etc. sections into one,
+ and the entries in the index tables are now offsets into these sections.
+ CU offsets begin at 0. TU offsets begin at the size of the .debug_info
+ section.
+
+ Index Section Contents:
+ Header
+ Hash Table of Signatures dwp_hash_table.hash_table
+ Parallel Table of Indices dwp_hash_table.unit_table
+ Table of Section Offsets dwp_hash_table.v2.{section_ids,offsets}
+ Table of Section Sizes dwp_hash_table.v2.sizes
+
+ The index section header consists of:
+
+ V, 32 bit version number
+ L, 32 bit number of columns in the table of section offsets
+ N, 32 bit number of compilation units or type units in the index
+ M, 32 bit number of slots in the hash table
+
+ Numbers are recorded using the byte order of the application binary.
+
+ The hash table has the same format as version 1.
+ The parallel table of indices has the same format as version 1,
+ except that the entries are origin-1 indices into the table of sections
+ offsets and the table of section sizes.
+
+ The table of offsets begins immediately following the parallel table
+ (at offset 16 + 12 * M from the beginning of the section). The table is
+ a two-dimensional array of 32-bit words (using the byte order of the
+ application binary), with L columns and N+1 rows, in row-major order.
+ Each row in the array is indexed starting from 0. The first row provides
+ a key to the remaining rows: each column in this row provides an identifier
+ for a debug section, and the offsets in the same column of subsequent rows
+ refer to that section. The section identifiers are:
+
+ DW_SECT_INFO 1 .debug_info.dwo
+ DW_SECT_TYPES 2 .debug_types.dwo
+ DW_SECT_ABBREV 3 .debug_abbrev.dwo
+ DW_SECT_LINE 4 .debug_line.dwo
+ DW_SECT_LOC 5 .debug_loc.dwo
+ DW_SECT_STR_OFFSETS 6 .debug_str_offsets.dwo
+ DW_SECT_MACINFO 7 .debug_macinfo.dwo
+ DW_SECT_MACRO 8 .debug_macro.dwo
+
+ The offsets provided by the CU and TU index sections are the base offsets
+ for the contributions made by each CU or TU to the corresponding section
+ in the package file. Each CU and TU header contains an abbrev_offset
+ field, used to find the abbreviations table for that CU or TU within the
+ contribution to the .debug_abbrev.dwo section for that CU or TU, and should
+ be interpreted as relative to the base offset given in the index section.
+ Likewise, offsets into .debug_line.dwo from DW_AT_stmt_list attributes
+ should be interpreted as relative to the base offset for .debug_line.dwo,
+ and offsets into other debug sections obtained from DWARF attributes should
+ also be interpreted as relative to the corresponding base offset.
+
+ The table of sizes begins immediately following the table of offsets.
+ Like the table of offsets, it is a two-dimensional array of 32-bit words,
+ with L columns and N rows, in row-major order. Each row in the array is
+ indexed starting from 1 (row 0 is shared by the two tables).
+
+ ---
+
+ Hash table lookup is handled the same in version 1 and 2:
+
+ We assume that N and M will not exceed 2^32 - 1.
+ The size of the hash table, M, must be 2^k such that 2^k > 3*N/2.
+
+ Given a 64-bit compilation unit signature or a type signature S, an entry
+ in the hash table is located as follows:
+
+ 1) Calculate a primary hash H = S & MASK(k), where MASK(k) is a mask with
+ the low-order k bits all set to 1.
+
+ 2) Calculate a secondary hash H' = (((S >> 32) & MASK(k)) | 1).
+
+ 3) If the hash table entry at index H matches the signature, use that
+ entry. If the hash table entry at index H is unused (all zeroes),
+ terminate the search: the signature is not present in the table.
+
+ 4) Let H = (H + H') modulo M. Repeat at Step 3.
+
+ Because M > N and H' and M are relatively prime, the search is guaranteed
+ to stop at an unused slot or find the match. */
/* Create a hash table to map DWO IDs to their CU/TU entry in
.debug_{info,types}.dwo in DWP_FILE.
bfd *dbfd = dwp_file->dbfd;
const gdb_byte *index_ptr, *index_end;
struct dwarf2_section_info *index;
- uint32_t version, nr_units, nr_slots;
+ uint32_t version, nr_columns, nr_units, nr_slots;
struct dwp_hash_table *htab;
if (is_debug_types)
index_end = index_ptr + index->size;
version = read_4_bytes (dbfd, index_ptr);
- index_ptr += 8; /* Skip the unused word. */
+ index_ptr += 4;
+ if (version == 2)
+ nr_columns = read_4_bytes (dbfd, index_ptr);
+ else
+ nr_columns = 0;
+ index_ptr += 4;
nr_units = read_4_bytes (dbfd, index_ptr);
index_ptr += 4;
nr_slots = read_4_bytes (dbfd, index_ptr);
index_ptr += 4;
- if (version != 1)
+ if (version != 1 && version != 2)
{
- error (_("Dwarf Error: unsupported DWP file version (%u)"
+ error (_("Dwarf Error: unsupported DWP file version (%s)"
" [in module %s]"),
- version, dwp_file->name);
+ pulongest (version), dwp_file->name);
}
if (nr_slots != (nr_slots & -nr_slots))
{
- error (_("Dwarf Error: number of slots in DWP hash table (%u)"
+ error (_("Dwarf Error: number of slots in DWP hash table (%s)"
" is not power of 2 [in module %s]"),
- nr_slots, dwp_file->name);
+ pulongest (nr_slots), dwp_file->name);
}
htab = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_hash_table);
+ htab->version = version;
+ htab->nr_columns = nr_columns;
htab->nr_units = nr_units;
htab->nr_slots = nr_slots;
htab->hash_table = index_ptr;
htab->unit_table = htab->hash_table + sizeof (uint64_t) * nr_slots;
- htab->section_pool = htab->unit_table + sizeof (uint32_t) * nr_slots;
+
+ /* Exit early if the table is empty. */
+ if (nr_slots == 0 || nr_units == 0
+ || (version == 2 && nr_columns == 0))
+ {
+ /* All must be zero. */
+ if (nr_slots != 0 || nr_units != 0
+ || (version == 2 && nr_columns != 0))
+ {
+ complaint (&symfile_complaints,
+ _("Empty DWP but nr_slots,nr_units,nr_columns not"
+ " all zero [in modules %s]"),
+ dwp_file->name);
+ }
+ return htab;
+ }
+
+ if (version == 1)
+ {
+ htab->section_pool.v1.indices =
+ htab->unit_table + sizeof (uint32_t) * nr_slots;
+ /* It's harder to decide whether the section is too small in v1.
+ V1 is deprecated anyway so we punt. */
+ }
+ else
+ {
+ const gdb_byte *ids_ptr = htab->unit_table + sizeof (uint32_t) * nr_slots;
+ int *ids = htab->section_pool.v2.section_ids;
+ /* Reverse map for error checking. */
+ int ids_seen[DW_SECT_MAX + 1];
+ int i;
+
+ if (nr_columns < 2)
+ {
+ error (_("Dwarf Error: bad DWP hash table, too few columns"
+ " in section table [in module %s]"),
+ dwp_file->name);
+ }
+ if (nr_columns > MAX_NR_V2_DWO_SECTIONS)
+ {
+ error (_("Dwarf Error: bad DWP hash table, too many columns"
+ " in section table [in module %s]"),
+ dwp_file->name);
+ }
+ memset (ids, 255, (DW_SECT_MAX + 1) * sizeof (int32_t));
+ memset (ids_seen, 255, (DW_SECT_MAX + 1) * sizeof (int32_t));
+ for (i = 0; i < nr_columns; ++i)
+ {
+ int id = read_4_bytes (dbfd, ids_ptr + i * sizeof (uint32_t));
+
+ if (id < DW_SECT_MIN || id > DW_SECT_MAX)
+ {
+ error (_("Dwarf Error: bad DWP hash table, bad section id %d"
+ " in section table [in module %s]"),
+ id, dwp_file->name);
+ }
+ if (ids_seen[id] != -1)
+ {
+ error (_("Dwarf Error: bad DWP hash table, duplicate section"
+ " id %d in section table [in module %s]"),
+ id, dwp_file->name);
+ }
+ ids_seen[id] = i;
+ ids[i] = id;
+ }
+ /* Must have exactly one info or types section. */
+ if (((ids_seen[DW_SECT_INFO] != -1)
+ + (ids_seen[DW_SECT_TYPES] != -1))
+ != 1)
+ {
+ error (_("Dwarf Error: bad DWP hash table, missing/duplicate"
+ " DWO info/types section [in module %s]"),
+ dwp_file->name);
+ }
+ /* Must have an abbrev section. */
+ if (ids_seen[DW_SECT_ABBREV] == -1)
+ {
+ error (_("Dwarf Error: bad DWP hash table, missing DWO abbrev"
+ " section [in module %s]"),
+ dwp_file->name);
+ }
+ htab->section_pool.v2.offsets = ids_ptr + sizeof (uint32_t) * nr_columns;
+ htab->section_pool.v2.sizes =
+ htab->section_pool.v2.offsets + (sizeof (uint32_t)
+ * nr_units * nr_columns);
+ if ((htab->section_pool.v2.sizes + (sizeof (uint32_t)
+ * nr_units * nr_columns))
+ > index_end)
+ {
+ error (_("Dwarf Error: DWP index section is corrupt (too small)"
+ " [in module %s]"),
+ dwp_file->name);
+ }
+ }
return htab;
}
This function is like the other "locate" section routines that are
passed to bfd_map_over_sections, but in this context the sections to
- read comes from the DWP hash table, not the full ELF section table.
+ read comes from the DWP V1 hash table, not the full ELF section table.
The result is non-zero for success, or zero if an error was found. */
static int
-locate_virtual_dwo_sections (asection *sectp,
- struct virtual_dwo_sections *sections)
+locate_v1_virtual_dwo_sections (asection *sectp,
+ struct virtual_v1_dwo_sections *sections)
{
const struct dwop_section_names *names = &dwop_section_names;
if (section_is_p (sectp->name, &names->abbrev_dwo))
{
/* There can be only one. */
- if (sections->abbrev.asection != NULL)
+ if (sections->abbrev.s.asection != NULL)
return 0;
- sections->abbrev.asection = sectp;
+ sections->abbrev.s.asection = sectp;
sections->abbrev.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->info_dwo)
|| section_is_p (sectp->name, &names->types_dwo))
{
/* There can be only one. */
- if (sections->info_or_types.asection != NULL)
+ if (sections->info_or_types.s.asection != NULL)
return 0;
- sections->info_or_types.asection = sectp;
+ sections->info_or_types.s.asection = sectp;
sections->info_or_types.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->line_dwo))
{
/* There can be only one. */
- if (sections->line.asection != NULL)
+ if (sections->line.s.asection != NULL)
return 0;
- sections->line.asection = sectp;
+ sections->line.s.asection = sectp;
sections->line.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->loc_dwo))
{
/* There can be only one. */
- if (sections->loc.asection != NULL)
+ if (sections->loc.s.asection != NULL)
return 0;
- sections->loc.asection = sectp;
+ sections->loc.s.asection = sectp;
sections->loc.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->macinfo_dwo))
{
/* There can be only one. */
- if (sections->macinfo.asection != NULL)
+ if (sections->macinfo.s.asection != NULL)
return 0;
- sections->macinfo.asection = sectp;
+ sections->macinfo.s.asection = sectp;
sections->macinfo.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->macro_dwo))
{
/* There can be only one. */
- if (sections->macro.asection != NULL)
+ if (sections->macro.s.asection != NULL)
return 0;
- sections->macro.asection = sectp;
+ sections->macro.s.asection = sectp;
sections->macro.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->str_offsets_dwo))
{
/* There can be only one. */
- if (sections->str_offsets.asection != NULL)
+ if (sections->str_offsets.s.asection != NULL)
return 0;
- sections->str_offsets.asection = sectp;
+ sections->str_offsets.s.asection = sectp;
sections->str_offsets.size = bfd_get_section_size (sectp);
}
else
return 1;
}
-/* Create a dwo_unit object for the DWO with signature SIGNATURE.
- HTAB is the hash table from the DWP file.
- SECTION_INDEX is the index of the DWO in HTAB.
- COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU. */
+/* Create a dwo_unit object for the DWO unit with signature SIGNATURE.
+ UNIT_INDEX is the index of the DWO unit in the DWP hash table.
+ COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
+ This is for DWP version 1 files. */
static struct dwo_unit *
-create_dwo_in_dwp (struct dwp_file *dwp_file,
- const struct dwp_hash_table *htab,
- uint32_t section_index,
- const char *comp_dir,
- ULONGEST signature, int is_debug_types)
+create_dwo_unit_in_dwp_v1 (struct dwp_file *dwp_file,
+ uint32_t unit_index,
+ const char *comp_dir,
+ ULONGEST signature, int is_debug_types)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
+ const struct dwp_hash_table *dwp_htab =
+ is_debug_types ? dwp_file->tus : dwp_file->cus;
bfd *dbfd = dwp_file->dbfd;
const char *kind = is_debug_types ? "TU" : "CU";
struct dwo_file *dwo_file;
struct dwo_unit *dwo_unit;
- struct virtual_dwo_sections sections;
+ struct virtual_v1_dwo_sections sections;
void **dwo_file_slot;
char *virtual_dwo_name;
struct dwarf2_section_info *cutu;
struct cleanup *cleanups;
int i;
+ gdb_assert (dwp_file->version == 1);
+
if (dwarf2_read_debug)
{
- fprintf_unfiltered (gdb_stdlog, "Reading %s %u/%s in DWP file: %s\n",
+ fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V1 file: %s\n",
kind,
- section_index, hex_string (signature),
+ pulongest (unit_index), hex_string (signature),
dwp_file->name);
}
- /* Fetch the sections of this DWO.
+ /* Fetch the sections of this DWO unit.
Put a limit on the number of sections we look for so that bad data
doesn't cause us to loop forever. */
-#define MAX_NR_DWO_SECTIONS \
+#define MAX_NR_V1_DWO_SECTIONS \
(1 /* .debug_info or .debug_types */ \
+ 1 /* .debug_abbrev */ \
+ 1 /* .debug_line */ \
+ 1 /* .debug_loc */ \
+ 1 /* .debug_str_offsets */ \
- + 1 /* .debug_macro */ \
- + 1 /* .debug_macinfo */ \
+ + 1 /* .debug_macro or .debug_macinfo */ \
+ 1 /* trailing zero */)
memset (§ions, 0, sizeof (sections));
cleanups = make_cleanup (null_cleanup, 0);
- for (i = 0; i < MAX_NR_DWO_SECTIONS; ++i)
+ for (i = 0; i < MAX_NR_V1_DWO_SECTIONS; ++i)
{
asection *sectp;
uint32_t section_nr =
read_4_bytes (dbfd,
- htab->section_pool
- + (section_index + i) * sizeof (uint32_t));
+ dwp_htab->section_pool.v1.indices
+ + (unit_index + i) * sizeof (uint32_t));
if (section_nr == 0)
break;
}
sectp = dwp_file->elf_sections[section_nr];
- if (! locate_virtual_dwo_sections (sectp, §ions))
+ if (! locate_v1_virtual_dwo_sections (sectp, §ions))
{
error (_("Dwarf Error: bad DWP hash table, invalid section found"
" [in module %s]"),
}
if (i < 2
- || sections.info_or_types.asection == NULL
- || sections.abbrev.asection == NULL)
+ || dwarf2_section_empty_p (§ions.info_or_types)
+ || dwarf2_section_empty_p (§ions.abbrev))
{
error (_("Dwarf Error: bad DWP hash table, missing DWO sections"
" [in module %s]"),
dwp_file->name);
}
- if (i == MAX_NR_DWO_SECTIONS)
+ if (i == MAX_NR_V1_DWO_SECTIONS)
{
error (_("Dwarf Error: bad DWP hash table, too many DWO sections"
" [in module %s]"),
The DWP file can be made up of a random collection of CUs and TUs.
However, for each CU + set of TUs that came from the same original DWO
- file, we want to combine them back into a virtual DWO file to save space
- (fewer struct dwo_file objects to allocated). Remember that for really
+ file, we can combine them back into a virtual DWO file to save space
+ (fewer struct dwo_file objects to allocate). Remember that for really
large apps there can be on the order of 8K CUs and 200K TUs, or more. */
virtual_dwo_name =
xstrprintf ("virtual-dwo/%d-%d-%d-%d",
- sections.abbrev.asection ? sections.abbrev.asection->id : 0,
- sections.line.asection ? sections.line.asection->id : 0,
- sections.loc.asection ? sections.loc.asection->id : 0,
- (sections.str_offsets.asection
- ? sections.str_offsets.asection->id
- : 0));
+ get_section_id (§ions.abbrev),
+ get_section_id (§ions.line),
+ get_section_id (§ions.loc),
+ get_section_id (§ions.str_offsets));
make_cleanup (xfree, virtual_dwo_name);
/* Can we use an existing virtual DWO file? */
dwo_file_slot = lookup_dwo_file_slot (virtual_dwo_name, comp_dir);
dwo_file->sections.str_offsets = sections.str_offsets;
/* The "str" section is global to the entire DWP file. */
dwo_file->sections.str = dwp_file->sections.str;
- /* The info or types section is assigned later to dwo_unit,
+ /* The info or types section is assigned below to dwo_unit,
there's no need to record it in dwo_file.
Also, we can't simply record type sections in dwo_file because
we record a pointer into the vector in dwo_unit. As we collect more
types we'll grow the vector and eventually have to reallocate space
- for it, invalidating all the pointers into the current copy. */
+ for it, invalidating all copies of pointers into the previous
+ contents. */
*dwo_file_slot = dwo_file;
}
else
dwo_unit->section = obstack_alloc (&objfile->objfile_obstack,
sizeof (struct dwarf2_section_info));
*dwo_unit->section = sections.info_or_types;
- /* offset, length, type_offset_in_tu are set later. */
+ /* dwo_unit->{offset,length,type_offset_in_tu} are set later. */
return dwo_unit;
}
-/* Lookup the DWO with SIGNATURE in DWP_FILE. */
+/* Subroutine of create_dwo_unit_in_dwp_v2 to simplify it.
+ Given a pointer to the containing section SECTION, and OFFSET,SIZE of the
+ piece within that section used by a TU/CU, return a virtual section
+ of just that piece. */
+
+static struct dwarf2_section_info
+create_dwp_v2_section (struct dwarf2_section_info *section,
+ bfd_size_type offset, bfd_size_type size)
+{
+ struct dwarf2_section_info result;
+ asection *sectp;
+
+ gdb_assert (section != NULL);
+ gdb_assert (!section->is_virtual);
+
+ memset (&result, 0, sizeof (result));
+ result.s.containing_section = section;
+ result.is_virtual = 1;
+
+ if (size == 0)
+ return result;
+
+ sectp = get_section_bfd_section (section);
+
+ /* Flag an error if the piece denoted by OFFSET,SIZE is outside the
+ bounds of the real section. This is a pretty-rare event, so just
+ flag an error (easier) instead of a warning and trying to cope. */
+ if (sectp == NULL
+ || offset + size > bfd_get_section_size (sectp))
+ {
+ bfd *abfd = sectp->owner;
+
+ error (_("Dwarf Error: Bad DWP V2 section info, doesn't fit"
+ " in section %s [in module %s]"),
+ sectp ? bfd_section_name (abfd, sectp) : "<unknown>",
+ objfile_name (dwarf2_per_objfile->objfile));
+ }
+
+ result.virtual_offset = offset;
+ result.size = size;
+ return result;
+}
+
+/* Create a dwo_unit object for the DWO unit with signature SIGNATURE.
+ UNIT_INDEX is the index of the DWO unit in the DWP hash table.
+ COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
+ This is for DWP version 2 files. */
static struct dwo_unit *
-lookup_dwo_in_dwp (struct dwp_file *dwp_file,
- const struct dwp_hash_table *htab,
- const char *comp_dir,
- ULONGEST signature, int is_debug_types)
+create_dwo_unit_in_dwp_v2 (struct dwp_file *dwp_file,
+ uint32_t unit_index,
+ const char *comp_dir,
+ ULONGEST signature, int is_debug_types)
{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ const struct dwp_hash_table *dwp_htab =
+ is_debug_types ? dwp_file->tus : dwp_file->cus;
bfd *dbfd = dwp_file->dbfd;
- uint32_t mask = htab->nr_slots - 1;
+ const char *kind = is_debug_types ? "TU" : "CU";
+ struct dwo_file *dwo_file;
+ struct dwo_unit *dwo_unit;
+ struct virtual_v2_dwo_sections sections;
+ void **dwo_file_slot;
+ char *virtual_dwo_name;
+ struct dwarf2_section_info *cutu;
+ struct cleanup *cleanups;
+ int i;
+
+ gdb_assert (dwp_file->version == 2);
+
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V2 file: %s\n",
+ kind,
+ pulongest (unit_index), hex_string (signature),
+ dwp_file->name);
+ }
+
+ /* Fetch the section offsets of this DWO unit. */
+
+ memset (§ions, 0, sizeof (sections));
+ cleanups = make_cleanup (null_cleanup, 0);
+
+ for (i = 0; i < dwp_htab->nr_columns; ++i)
+ {
+ uint32_t offset = read_4_bytes (dbfd,
+ dwp_htab->section_pool.v2.offsets
+ + (((unit_index - 1) * dwp_htab->nr_columns
+ + i)
+ * sizeof (uint32_t)));
+ uint32_t size = read_4_bytes (dbfd,
+ dwp_htab->section_pool.v2.sizes
+ + (((unit_index - 1) * dwp_htab->nr_columns
+ + i)
+ * sizeof (uint32_t)));
+
+ switch (dwp_htab->section_pool.v2.section_ids[i])
+ {
+ case DW_SECT_INFO:
+ case DW_SECT_TYPES:
+ sections.info_or_types_offset = offset;
+ sections.info_or_types_size = size;
+ break;
+ case DW_SECT_ABBREV:
+ sections.abbrev_offset = offset;
+ sections.abbrev_size = size;
+ break;
+ case DW_SECT_LINE:
+ sections.line_offset = offset;
+ sections.line_size = size;
+ break;
+ case DW_SECT_LOC:
+ sections.loc_offset = offset;
+ sections.loc_size = size;
+ break;
+ case DW_SECT_STR_OFFSETS:
+ sections.str_offsets_offset = offset;
+ sections.str_offsets_size = size;
+ break;
+ case DW_SECT_MACINFO:
+ sections.macinfo_offset = offset;
+ sections.macinfo_size = size;
+ break;
+ case DW_SECT_MACRO:
+ sections.macro_offset = offset;
+ sections.macro_size = size;
+ break;
+ }
+ }
+
+ /* It's easier for the rest of the code if we fake a struct dwo_file and
+ have dwo_unit "live" in that. At least for now.
+
+ The DWP file can be made up of a random collection of CUs and TUs.
+ However, for each CU + set of TUs that came from the same original DWO
+ file, we can combine them back into a virtual DWO file to save space
+ (fewer struct dwo_file objects to allocate). Remember that for really
+ large apps there can be on the order of 8K CUs and 200K TUs, or more. */
+
+ virtual_dwo_name =
+ xstrprintf ("virtual-dwo/%ld-%ld-%ld-%ld",
+ (long) (sections.abbrev_size ? sections.abbrev_offset : 0),
+ (long) (sections.line_size ? sections.line_offset : 0),
+ (long) (sections.loc_size ? sections.loc_offset : 0),
+ (long) (sections.str_offsets_size
+ ? sections.str_offsets_offset : 0));
+ make_cleanup (xfree, virtual_dwo_name);
+ /* Can we use an existing virtual DWO file? */
+ dwo_file_slot = lookup_dwo_file_slot (virtual_dwo_name, comp_dir);
+ /* Create one if necessary. */
+ if (*dwo_file_slot == NULL)
+ {
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
+ virtual_dwo_name);
+ }
+ dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
+ dwo_file->dwo_name = obstack_copy0 (&objfile->objfile_obstack,
+ virtual_dwo_name,
+ strlen (virtual_dwo_name));
+ dwo_file->comp_dir = comp_dir;
+ dwo_file->sections.abbrev =
+ create_dwp_v2_section (&dwp_file->sections.abbrev,
+ sections.abbrev_offset, sections.abbrev_size);
+ dwo_file->sections.line =
+ create_dwp_v2_section (&dwp_file->sections.line,
+ sections.line_offset, sections.line_size);
+ dwo_file->sections.loc =
+ create_dwp_v2_section (&dwp_file->sections.loc,
+ sections.loc_offset, sections.loc_size);
+ dwo_file->sections.macinfo =
+ create_dwp_v2_section (&dwp_file->sections.macinfo,
+ sections.macinfo_offset, sections.macinfo_size);
+ dwo_file->sections.macro =
+ create_dwp_v2_section (&dwp_file->sections.macro,
+ sections.macro_offset, sections.macro_size);
+ dwo_file->sections.str_offsets =
+ create_dwp_v2_section (&dwp_file->sections.str_offsets,
+ sections.str_offsets_offset,
+ sections.str_offsets_size);
+ /* The "str" section is global to the entire DWP file. */
+ dwo_file->sections.str = dwp_file->sections.str;
+ /* The info or types section is assigned below to dwo_unit,
+ there's no need to record it in dwo_file.
+ Also, we can't simply record type sections in dwo_file because
+ we record a pointer into the vector in dwo_unit. As we collect more
+ types we'll grow the vector and eventually have to reallocate space
+ for it, invalidating all copies of pointers into the previous
+ contents. */
+ *dwo_file_slot = dwo_file;
+ }
+ else
+ {
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
+ virtual_dwo_name);
+ }
+ dwo_file = *dwo_file_slot;
+ }
+ do_cleanups (cleanups);
+
+ dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
+ dwo_unit->dwo_file = dwo_file;
+ dwo_unit->signature = signature;
+ dwo_unit->section = obstack_alloc (&objfile->objfile_obstack,
+ sizeof (struct dwarf2_section_info));
+ *dwo_unit->section = create_dwp_v2_section (is_debug_types
+ ? &dwp_file->sections.types
+ : &dwp_file->sections.info,
+ sections.info_or_types_offset,
+ sections.info_or_types_size);
+ /* dwo_unit->{offset,length,type_offset_in_tu} are set later. */
+
+ return dwo_unit;
+}
+
+/* Lookup the DWO unit with SIGNATURE in DWP_FILE.
+ Returns NULL if the signature isn't found. */
+
+static struct dwo_unit *
+lookup_dwo_unit_in_dwp (struct dwp_file *dwp_file, const char *comp_dir,
+ ULONGEST signature, int is_debug_types)
+{
+ const struct dwp_hash_table *dwp_htab =
+ is_debug_types ? dwp_file->tus : dwp_file->cus;
+ bfd *dbfd = dwp_file->dbfd;
+ uint32_t mask = dwp_htab->nr_slots - 1;
uint32_t hash = signature & mask;
uint32_t hash2 = ((signature >> 32) & mask) | 1;
unsigned int i;
memset (&find_dwo_cu, 0, sizeof (find_dwo_cu));
find_dwo_cu.signature = signature;
- slot = htab_find_slot (dwp_file->loaded_cutus, &find_dwo_cu, INSERT);
+ slot = htab_find_slot (is_debug_types
+ ? dwp_file->loaded_tus
+ : dwp_file->loaded_cus,
+ &find_dwo_cu, INSERT);
if (*slot != NULL)
return *slot;
/* Use a for loop so that we don't loop forever on bad debug info. */
- for (i = 0; i < htab->nr_slots; ++i)
+ for (i = 0; i < dwp_htab->nr_slots; ++i)
{
ULONGEST signature_in_table;
signature_in_table =
- read_8_bytes (dbfd, htab->hash_table + hash * sizeof (uint64_t));
+ read_8_bytes (dbfd, dwp_htab->hash_table + hash * sizeof (uint64_t));
if (signature_in_table == signature)
{
- uint32_t section_index =
- read_4_bytes (dbfd, htab->unit_table + hash * sizeof (uint32_t));
+ uint32_t unit_index =
+ read_4_bytes (dbfd,
+ dwp_htab->unit_table + hash * sizeof (uint32_t));
- *slot = create_dwo_in_dwp (dwp_file, htab, section_index,
- comp_dir, signature, is_debug_types);
+ if (dwp_file->version == 1)
+ {
+ *slot = create_dwo_unit_in_dwp_v1 (dwp_file, unit_index,
+ comp_dir, signature,
+ is_debug_types);
+ }
+ else
+ {
+ *slot = create_dwo_unit_in_dwp_v2 (dwp_file, unit_index,
+ comp_dir, signature,
+ is_debug_types);
+ }
return *slot;
}
if (signature_in_table == 0)
preliminary analysis. Return a newly initialized bfd *, which
includes a canonicalized copy of FILE_NAME.
If IS_DWP is TRUE, we're opening a DWP file, otherwise a DWO file.
- In case of trouble, return NULL.
+ SEARCH_CWD is true if the current directory is to be searched.
+ It will be searched before debug-file-directory.
+ If successful, the file is added to the bfd include table of the
+ objfile's bfd (see gdb_bfd_record_inclusion).
+ If unable to find/open the file, return NULL.
NOTE: This function is derived from symfile_bfd_open. */
static bfd *
-try_open_dwop_file (const char *file_name, int is_dwp)
+try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
{
bfd *sym_bfd;
int desc, flags;
char *absolute_name;
+ /* Blech. OPF_TRY_CWD_FIRST also disables searching the path list if
+ FILE_NAME contains a '/'. So we can't use it. Instead prepend "."
+ to debug_file_directory. */
+ char *search_path;
+ static const char dirname_separator_string[] = { DIRNAME_SEPARATOR, '\0' };
- flags = OPF_TRY_CWD_FIRST;
+ if (search_cwd)
+ {
+ if (*debug_file_directory != '\0')
+ search_path = concat (".", dirname_separator_string,
+ debug_file_directory, NULL);
+ else
+ search_path = xstrdup (".");
+ }
+ else
+ search_path = xstrdup (debug_file_directory);
+
+ flags = OPF_RETURN_REALPATH;
if (is_dwp)
flags |= OPF_SEARCH_IN_PATH;
- desc = openp (debug_file_directory, flags, file_name,
+ desc = openp (search_path, flags, file_name,
O_RDONLY | O_BINARY, &absolute_name);
+ xfree (search_path);
if (desc < 0)
return NULL;
sym_bfd = gdb_bfd_open (absolute_name, gnutarget, desc);
- if (!sym_bfd)
- {
- xfree (absolute_name);
- return NULL;
- }
xfree (absolute_name);
+ if (sym_bfd == NULL)
+ return NULL;
bfd_set_cacheable (sym_bfd, 1);
if (!bfd_check_format (sym_bfd, bfd_object))
return NULL;
}
+ /* Success. Record the bfd as having been included by the objfile's bfd.
+ This is important because things like demangled_names_hash lives in the
+ objfile's per_bfd space and may have references to things like symbol
+ names that live in the DWO/DWP file's per_bfd space. PR 16426. */
+ gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd);
+
return sym_bfd;
}
bfd *abfd;
if (IS_ABSOLUTE_PATH (file_name))
- return try_open_dwop_file (file_name, 0 /*is_dwp*/);
+ return try_open_dwop_file (file_name, 0 /*is_dwp*/, 0 /*search_cwd*/);
/* Before trying the search path, try DWO_NAME in COMP_DIR. */
/* NOTE: If comp_dir is a relative path, this will also try the
search path, which seems useful. */
- abfd = try_open_dwop_file (path_to_try, 0 /*is_dwp*/);
+ abfd = try_open_dwop_file (path_to_try, 0 /*is_dwp*/, 1 /*search_cwd*/);
xfree (path_to_try);
if (abfd != NULL)
return abfd;
if (*debug_file_directory == '\0')
return NULL;
- return try_open_dwop_file (file_name, 0 /*is_dwp*/);
+ return try_open_dwop_file (file_name, 0 /*is_dwp*/, 1 /*search_cwd*/);
}
/* This function is mapped across the sections and remembers the offset and
if (section_is_p (sectp->name, &names->abbrev_dwo))
{
- dwo_sections->abbrev.asection = sectp;
+ dwo_sections->abbrev.s.asection = sectp;
dwo_sections->abbrev.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->info_dwo))
{
- dwo_sections->info.asection = sectp;
+ dwo_sections->info.s.asection = sectp;
dwo_sections->info.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->line_dwo))
{
- dwo_sections->line.asection = sectp;
+ dwo_sections->line.s.asection = sectp;
dwo_sections->line.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->loc_dwo))
{
- dwo_sections->loc.asection = sectp;
+ dwo_sections->loc.s.asection = sectp;
dwo_sections->loc.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->macinfo_dwo))
{
- dwo_sections->macinfo.asection = sectp;
+ dwo_sections->macinfo.s.asection = sectp;
dwo_sections->macinfo.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->macro_dwo))
{
- dwo_sections->macro.asection = sectp;
+ dwo_sections->macro.s.asection = sectp;
dwo_sections->macro.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->str_dwo))
{
- dwo_sections->str.asection = sectp;
+ dwo_sections->str.s.asection = sectp;
dwo_sections->str.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &names->str_offsets_dwo))
{
- dwo_sections->str_offsets.asection = sectp;
+ dwo_sections->str_offsets.s.asection = sectp;
dwo_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.s.asection = sectp;
type_section.size = bfd_get_section_size (sectp);
VEC_safe_push (dwarf2_section_info_def, dwo_sections->types,
&type_section);
}
/* This function is mapped across the sections and remembers the offset and
- size of each of the DWP debugging sections we are interested in. */
+ size of each of the DWP debugging sections common to version 1 and 2 that
+ we are interested in. */
static void
-dwarf2_locate_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
+dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp,
+ void *dwp_file_ptr)
{
struct dwp_file *dwp_file = dwp_file_ptr;
const struct dwop_section_names *names = &dwop_section_names;
unsigned int elf_section_nr = elf_section_data (sectp)->this_idx;
/* Record the ELF section number for later lookup: this is what the
- .debug_cu_index,.debug_tu_index tables use. */
+ .debug_cu_index,.debug_tu_index tables use in DWP V1. */
gdb_assert (elf_section_nr < dwp_file->num_sections);
dwp_file->elf_sections[elf_section_nr] = sectp;
/* Look for specific sections that we need. */
if (section_is_p (sectp->name, &names->str_dwo))
{
- dwp_file->sections.str.asection = sectp;
- dwp_file->sections.str.size = bfd_get_section_size (sectp);
+ dwp_file->sections.str.s.asection = sectp;
+ dwp_file->sections.str.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->cu_index))
+ {
+ dwp_file->sections.cu_index.s.asection = sectp;
+ dwp_file->sections.cu_index.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->tu_index))
+ {
+ dwp_file->sections.tu_index.s.asection = sectp;
+ dwp_file->sections.tu_index.size = bfd_get_section_size (sectp);
+ }
+}
+
+/* This function is mapped across the sections and remembers the offset and
+ size of each of the DWP version 2 debugging sections that we are interested
+ in. This is split into a separate function because we don't know if we
+ have version 1 or 2 until we parse the cu_index/tu_index sections. */
+
+static void
+dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
+{
+ struct dwp_file *dwp_file = dwp_file_ptr;
+ const struct dwop_section_names *names = &dwop_section_names;
+ unsigned int elf_section_nr = elf_section_data (sectp)->this_idx;
+
+ /* Record the ELF section number for later lookup: this is what the
+ .debug_cu_index,.debug_tu_index tables use in DWP V1. */
+ gdb_assert (elf_section_nr < dwp_file->num_sections);
+ dwp_file->elf_sections[elf_section_nr] = sectp;
+
+ /* Look for specific sections that we need. */
+ if (section_is_p (sectp->name, &names->abbrev_dwo))
+ {
+ dwp_file->sections.abbrev.s.asection = sectp;
+ dwp_file->sections.abbrev.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->info_dwo))
+ {
+ dwp_file->sections.info.s.asection = sectp;
+ dwp_file->sections.info.size = bfd_get_section_size (sectp);
}
- else if (section_is_p (sectp->name, &names->cu_index))
+ else if (section_is_p (sectp->name, &names->line_dwo))
{
- dwp_file->sections.cu_index.asection = sectp;
- dwp_file->sections.cu_index.size = bfd_get_section_size (sectp);
+ dwp_file->sections.line.s.asection = sectp;
+ dwp_file->sections.line.size = bfd_get_section_size (sectp);
}
- else if (section_is_p (sectp->name, &names->tu_index))
+ else if (section_is_p (sectp->name, &names->loc_dwo))
{
- dwp_file->sections.tu_index.asection = sectp;
- dwp_file->sections.tu_index.size = bfd_get_section_size (sectp);
+ dwp_file->sections.loc.s.asection = sectp;
+ dwp_file->sections.loc.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->macinfo_dwo))
+ {
+ dwp_file->sections.macinfo.s.asection = sectp;
+ dwp_file->sections.macinfo.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->macro_dwo))
+ {
+ dwp_file->sections.macro.s.asection = sectp;
+ dwp_file->sections.macro.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->str_offsets_dwo))
+ {
+ dwp_file->sections.str_offsets.s.asection = sectp;
+ dwp_file->sections.str_offsets.size = bfd_get_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->types_dwo))
+ {
+ dwp_file->sections.types.s.asection = sectp;
+ dwp_file->sections.types.size = bfd_get_section_size (sectp);
}
}
static bfd *
open_dwp_file (const char *file_name)
{
- return try_open_dwop_file (file_name, 1 /*is_dwp*/);
+ bfd *abfd;
+
+ abfd = try_open_dwop_file (file_name, 1 /*is_dwp*/, 1 /*search_cwd*/);
+ if (abfd != NULL)
+ return abfd;
+
+ /* Work around upstream bug 15652.
+ http://sourceware.org/bugzilla/show_bug.cgi?id=15652
+ [Whether that's a "bug" is debatable, but it is getting in our way.]
+ We have no real idea where the dwp file is, because gdb's realpath-ing
+ of the executable's path may have discarded the needed info.
+ [IWBN if the dwp file name was recorded in the executable, akin to
+ .gnu_debuglink, but that doesn't exist yet.]
+ Strip the directory from FILE_NAME and search again. */
+ if (*debug_file_directory != '\0')
+ {
+ /* Don't implicitly search the current directory here.
+ If the user wants to search "." to handle this case,
+ it must be added to debug-file-directory. */
+ return try_open_dwop_file (lbasename (file_name), 1 /*is_dwp*/,
+ 0 /*search_cwd*/);
+ }
+
+ return NULL;
}
/* Initialize the use of the DWP file for the current objfile.
bfd *dbfd;
struct cleanup *cleanups;
- dwp_name = xstrprintf ("%s.dwp", dwarf2_per_objfile->objfile->name);
+ /* Try to find first .dwp for the binary file before any symbolic links
+ resolving. */
+ dwp_name = xstrprintf ("%s.dwp", objfile->original_name);
cleanups = make_cleanup (xfree, dwp_name);
dbfd = open_dwp_file (dwp_name);
+ if (dbfd == NULL
+ && strcmp (objfile->original_name, objfile_name (objfile)) != 0)
+ {
+ /* Try to find .dwp for the binary file after gdb_realpath resolving. */
+ dwp_name = xstrprintf ("%s.dwp", objfile_name (objfile));
+ make_cleanup (xfree, dwp_name);
+ dbfd = open_dwp_file (dwp_name);
+ }
+
if (dbfd == NULL)
{
if (dwarf2_read_debug)
return NULL;
}
dwp_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_file);
- dwp_file->name = obstack_copy0 (&objfile->objfile_obstack,
- dwp_name, strlen (dwp_name));
+ dwp_file->name = bfd_get_filename (dbfd);
dwp_file->dbfd = dbfd;
do_cleanups (cleanups);
OBSTACK_CALLOC (&objfile->objfile_obstack,
dwp_file->num_sections, asection *);
- bfd_map_over_sections (dbfd, dwarf2_locate_dwp_sections, dwp_file);
+ bfd_map_over_sections (dbfd, dwarf2_locate_common_dwp_sections, dwp_file);
dwp_file->cus = create_dwp_hash_table (dwp_file, 0);
dwp_file->tus = create_dwp_hash_table (dwp_file, 1);
- dwp_file->loaded_cutus = allocate_dwp_loaded_cutus_table (objfile);
+ /* The DWP file version is stored in the hash table. Oh well. */
+ if (dwp_file->cus->version != dwp_file->tus->version)
+ {
+ /* Technically speaking, we should try to limp along, but this is
+ pretty bizarre. We use pulongest here because that's the established
+ portability solution (e.g, we cannot use %u for uint32_t). */
+ error (_("Dwarf Error: DWP file CU version %s doesn't match"
+ " TU version %s [in DWP file %s]"),
+ pulongest (dwp_file->cus->version),
+ pulongest (dwp_file->tus->version), dwp_name);
+ }
+ dwp_file->version = dwp_file->cus->version;
+
+ if (dwp_file->version == 2)
+ bfd_map_over_sections (dbfd, dwarf2_locate_v2_dwp_sections, dwp_file);
+
+ dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table (objfile);
+ dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table (objfile);
if (dwarf2_read_debug)
{
fprintf_unfiltered (gdb_stdlog, "DWP file found: %s\n", dwp_file->name);
fprintf_unfiltered (gdb_stdlog,
- " %u CUs, %u TUs\n",
- dwp_file->cus ? dwp_file->cus->nr_units : 0,
- dwp_file->tus ? dwp_file->tus->nr_units : 0);
+ " %s CUs, %s TUs\n",
+ pulongest (dwp_file->cus ? dwp_file->cus->nr_units : 0),
+ pulongest (dwp_file->tus ? dwp_file->tus->nr_units : 0));
}
return dwp_file;
struct dwo_file *dwo_file;
struct dwp_file *dwp_file;
- /* Have we already read SIGNATURE from a DWP file? */
+ /* First see if there's a DWP file.
+ If we have a DWP file but didn't find the DWO inside it, don't
+ look for the original DWO file. It makes gdb behave differently
+ depending on whether one is debugging in the build tree. */
dwp_file = get_dwp_file ();
if (dwp_file != NULL)
if (dwp_htab != NULL)
{
struct dwo_unit *dwo_cutu =
- lookup_dwo_in_dwp (dwp_file, dwp_htab, comp_dir,
- signature, is_debug_types);
+ lookup_dwo_unit_in_dwp (dwp_file, comp_dir,
+ signature, is_debug_types);
if (dwo_cutu != NULL)
{
}
}
}
-
- /* Have we already seen DWO_NAME? */
-
- dwo_file_slot = lookup_dwo_file_slot (dwo_name, comp_dir);
- if (*dwo_file_slot == NULL)
- {
- /* Read in the file and build a table of the DWOs it contains. */
- *dwo_file_slot = open_and_init_dwo_file (this_unit, dwo_name, comp_dir);
- }
- /* NOTE: This will be NULL if unable to open the file. */
- dwo_file = *dwo_file_slot;
-
- if (dwo_file != NULL)
+ else
{
- struct dwo_unit *dwo_cutu = NULL;
+ /* No DWP file, look for the DWO file. */
- if (is_debug_types && dwo_file->tus)
+ dwo_file_slot = lookup_dwo_file_slot (dwo_name, comp_dir);
+ if (*dwo_file_slot == NULL)
{
- struct dwo_unit find_dwo_cutu;
-
- memset (&find_dwo_cutu, 0, sizeof (find_dwo_cutu));
- find_dwo_cutu.signature = signature;
- dwo_cutu = htab_find (dwo_file->tus, &find_dwo_cutu);
- }
- else if (!is_debug_types && dwo_file->cu)
- {
- if (signature == dwo_file->cu->signature)
- dwo_cutu = dwo_file->cu;
+ /* Read in the file and build a table of the CUs/TUs it contains. */
+ *dwo_file_slot = open_and_init_dwo_file (this_unit, dwo_name, comp_dir);
}
+ /* NOTE: This will be NULL if unable to open the file. */
+ dwo_file = *dwo_file_slot;
- if (dwo_cutu != NULL)
+ if (dwo_file != NULL)
{
- if (dwarf2_read_debug)
+ struct dwo_unit *dwo_cutu = NULL;
+
+ if (is_debug_types && dwo_file->tus)
+ {
+ struct dwo_unit find_dwo_cutu;
+
+ memset (&find_dwo_cutu, 0, sizeof (find_dwo_cutu));
+ find_dwo_cutu.signature = signature;
+ dwo_cutu = htab_find (dwo_file->tus, &find_dwo_cutu);
+ }
+ else if (!is_debug_types && dwo_file->cu)
{
- fprintf_unfiltered (gdb_stdlog, "DWO %s %s(%s) found: @%s\n",
- kind, dwo_name, hex_string (signature),
- host_address_to_string (dwo_cutu));
+ if (signature == dwo_file->cu->signature)
+ dwo_cutu = dwo_file->cu;
+ }
+
+ if (dwo_cutu != NULL)
+ {
+ if (dwarf2_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "DWO %s %s(%s) found: @%s\n",
+ kind, dwo_name, hex_string (signature),
+ host_address_to_string (dwo_cutu));
+ }
+ return dwo_cutu;
}
- return dwo_cutu;
}
}
kind, dwo_name, hex_string (signature));
}
- complaint (&symfile_complaints,
- _("Could not find DWO %s referenced by CU at offset 0x%x"
+ /* This is a warning and not a complaint because it can be caused by
+ pilot error (e.g., user accidentally deleting the DWO). */
+ {
+ /* Print the name of the DWP file if we looked there, helps the user
+ better diagnose the problem. */
+ char *dwp_text = NULL;
+ struct cleanup *cleanups;
+
+ if (dwp_file != NULL)
+ dwp_text = xstrprintf (" [in DWP file %s]", lbasename (dwp_file->name));
+ cleanups = make_cleanup (xfree, dwp_text);
+
+ warning (_("Could not find DWO %s %s(%s)%s referenced by %s at offset 0x%x"
" [in module %s]"),
- kind, this_unit->offset.sect_off, objfile->name);
+ kind, dwo_name, hex_string (signature),
+ dwp_text != NULL ? dwp_text : "",
+ this_unit->is_debug_types ? "TU" : "CU",
+ this_unit->offset.sect_off, objfile_name (objfile));
+
+ do_cleanups (cleanups);
+ }
return NULL;
}
return lookup_dwo_cutu (&this_tu->per_cu, dwo_name, comp_dir, this_tu->signature, 1);
}
+/* Traversal function for queue_and_load_all_dwo_tus. */
+
+static int
+queue_and_load_dwo_tu (void **slot, void *info)
+{
+ struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot;
+ struct dwarf2_per_cu_data *per_cu = (struct dwarf2_per_cu_data *) info;
+ ULONGEST signature = dwo_unit->signature;
+ struct signatured_type *sig_type =
+ lookup_dwo_signatured_type (per_cu->cu, signature);
+
+ if (sig_type != NULL)
+ {
+ struct dwarf2_per_cu_data *sig_cu = &sig_type->per_cu;
+
+ /* We pass NULL for DEPENDENT_CU because we don't yet know if there's
+ a real dependency of PER_CU on SIG_TYPE. That is detected later
+ while processing PER_CU. */
+ if (maybe_queue_comp_unit (NULL, sig_cu, per_cu->cu->language))
+ load_full_type_unit (sig_cu);
+ VEC_safe_push (dwarf2_per_cu_ptr, per_cu->imported_symtabs, sig_cu);
+ }
+
+ return 1;
+}
+
+/* Queue all TUs contained in the DWO of PER_CU to be read in.
+ The DWO may have the only definition of the type, though it may not be
+ referenced anywhere in PER_CU. Thus we have to load *all* its TUs.
+ http://sourceware.org/bugzilla/show_bug.cgi?id=15021 */
+
+static void
+queue_and_load_all_dwo_tus (struct dwarf2_per_cu_data *per_cu)
+{
+ struct dwo_unit *dwo_unit;
+ struct dwo_file *dwo_file;
+
+ gdb_assert (!per_cu->is_debug_types);
+ gdb_assert (get_dwp_file () == NULL);
+ gdb_assert (per_cu->cu != NULL);
+
+ dwo_unit = per_cu->cu->dwo_unit;
+ gdb_assert (dwo_unit != NULL);
+
+ dwo_file = dwo_unit->dwo_file;
+ if (dwo_file->tus != NULL)
+ htab_traverse_noresize (dwo_file->tus, queue_and_load_dwo_tu, per_cu);
+}
+
/* Free all resources associated with DWO_FILE.
Close the DWO file and munmap the sections.
All memory should be on the objfile obstack. */
complaint (&symfile_complaints,
_("missing DW_AT_low_pc for DW_TAG_GNU_call_site "
"DIE 0x%x [in module %s]"),
- die->offset.sect_off, objfile->name);
+ die->offset.sect_off, objfile_name (objfile));
return;
}
pc = DW_ADDR (attr) + baseaddr;
complaint (&symfile_complaints,
_("Duplicate PC %s for DW_TAG_GNU_call_site "
"DIE 0x%x [in module %s]"),
- paddress (gdbarch, pc), die->offset.sect_off, objfile->name);
+ paddress (gdbarch, pc), die->offset.sect_off,
+ objfile_name (objfile));
return;
}
complaint (&symfile_complaints,
_("Tag %d is not DW_TAG_GNU_call_site_parameter in "
"DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
- child_die->tag, child_die->offset.sect_off, objfile->name);
+ child_die->tag, child_die->offset.sect_off,
+ objfile_name (objfile));
continue;
}
complaint (&symfile_complaints,
_("Cannot find function owning DW_TAG_GNU_call_site "
"DIE 0x%x [in module %s]"),
- die->offset.sect_off, objfile->name);
+ die->offset.sect_off, objfile_name (objfile));
}
}
SET_FIELD_DWARF_BLOCK (call_site->target, dlbaton);
}
- else if (is_ref_attr (attr))
+ else if (attr_form_is_ref (attr))
{
struct dwarf2_cu *target_cu = cu;
struct die_info *target_die;
complaint (&symfile_complaints,
_("DW_AT_GNU_call_site_target target DIE has invalid "
"physname, for referencing DIE 0x%x [in module %s]"),
- die->offset.sect_off, objfile->name);
+ die->offset.sect_off, objfile_name (objfile));
else
SET_FIELD_PHYSNAME (call_site->target, target_physname);
}
complaint (&symfile_complaints,
_("DW_AT_GNU_call_site_target target DIE has invalid "
"low pc, for referencing DIE 0x%x [in module %s]"),
- die->offset.sect_off, objfile->name);
+ die->offset.sect_off, objfile_name (objfile));
else
SET_FIELD_PHYSADDR (call_site->target, lowpc + baseaddr);
}
complaint (&symfile_complaints,
_("DW_TAG_GNU_call_site DW_AT_GNU_call_site_target is neither "
"block nor reference, for DIE 0x%x [in module %s]"),
- die->offset.sect_off, objfile->name);
+ die->offset.sect_off, objfile_name (objfile));
call_site->per_cu = cu->per_cu;
loc = dwarf2_attr (child_die, DW_AT_location, cu);
origin = dwarf2_attr (child_die, DW_AT_abstract_origin, cu);
- if (loc == NULL && origin != NULL && is_ref_attr (origin))
+ if (loc == NULL && origin != NULL && attr_form_is_ref (origin))
{
sect_offset offset;
_("DW_AT_abstract_origin offset is not in CU for "
"DW_TAG_GNU_call_site child DIE 0x%x "
"[in module %s]"),
- child_die->offset.sect_off, objfile->name);
+ child_die->offset.sect_off, objfile_name (objfile));
continue;
}
parameter->u.param_offset.cu_off = (offset.sect_off
complaint (&symfile_complaints,
_("No DW_FORM_block* DW_AT_location for "
"DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
- child_die->offset.sect_off, objfile->name);
+ child_die->offset.sect_off, objfile_name (objfile));
continue;
}
else
"for DW_FORM_block* DW_AT_location is supported for "
"DW_TAG_GNU_call_site child DIE 0x%x "
"[in module %s]"),
- child_die->offset.sect_off, objfile->name);
+ child_die->offset.sect_off, objfile_name (objfile));
continue;
}
}
complaint (&symfile_complaints,
_("No DW_FORM_block* DW_AT_GNU_call_site_value for "
"DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
- child_die->offset.sect_off, objfile->name);
+ child_die->offset.sect_off, objfile_name (objfile));
continue;
}
parameter->value = DW_BLOCK (attr)->data;
complaint (&symfile_complaints,
_("No DW_FORM_block* DW_AT_GNU_call_site_data_value for "
"DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
- child_die->offset.sect_off, objfile->name);
+ child_die->offset.sect_off, objfile_name (objfile));
else
{
parameter->data_value = DW_BLOCK (attr)->data;
{
complaint (&symfile_complaints,
_(".debug_ranges entry has start address of zero"
- " [in module %s]"), objfile->name);
+ " [in module %s]"), objfile_name (objfile));
continue;
}
address range list in the .debug_ranges section. */
unsigned long offset = (DW_UNSND (attr)
+ (need_ranges_base ? cu->ranges_base : 0));
- const gdb_byte *buffer = dwarf2_per_objfile->ranges.buffer + offset;
+ const gdb_byte *buffer;
/* For some target architectures, but not others, the
read_address function sign-extends the addresses it returns.
CORE_ADDR base = cu->base_address;
int base_known = cu->base_known;
- gdb_assert (dwarf2_per_objfile->ranges.readin);
+ dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges);
if (offset >= dwarf2_per_objfile->ranges.size)
{
complaint (&symfile_complaints,
offset);
return;
}
+ buffer = dwarf2_per_objfile->ranges.buffer + offset;
for (;;)
{
{
complaint (&symfile_complaints,
_(".debug_ranges entry has start address of zero"
- " [in module %s]"), objfile->name);
+ " [in module %s]"), objfile_name (objfile));
continue;
}
_("Variable in common block has "
"DW_AT_data_member_location "
"- DIE at 0x%x [in module %s]"),
- child_die->offset.sect_off, cu->objfile->name);
+ child_die->offset.sect_off,
+ objfile_name (cu->objfile));
if (attr_form_is_section_offset (member_loc))
dwarf2_complex_location_expr_complaint ();
read_module (struct die_info *die, struct dwarf2_cu *cu)
{
struct die_info *child_die = die->child;
+ struct type *type;
+
+ type = read_type_die (die, cu);
+ new_symbol (die, type, cu);
while (child_die && child_die->tag)
{
return set_die_type (die, type, cu);
}
+/* Assuming that DIE corresponds to a function, returns nonzero
+ if the function is prototyped. */
+
+static int
+prototyped_function_p (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct attribute *attr;
+
+ attr = dwarf2_attr (die, DW_AT_prototyped, cu);
+ if (attr && (DW_UNSND (attr) != 0))
+ return 1;
+
+ /* The DWARF standard implies that the DW_AT_prototyped attribute
+ is only meaninful for C, but the concept also extends to other
+ languages that allow unprototyped functions (Eg: Objective C).
+ For all other languages, assume that functions are always
+ prototyped. */
+ if (cu->language != language_c
+ && cu->language != language_objc
+ && cu->language != language_opencl)
+ return 1;
+
+ /* RealView does not emit DW_AT_prototyped. We can not distinguish
+ prototyped and unprototyped functions; default to prototyped,
+ since that is more common in modern code (and RealView warns
+ about unprototyped functions). */
+ if (producer_is_realview (cu->producer))
+ return 1;
+
+ return 0;
+}
+
/* Handle DIES due to C code like:
struct foo
ftype = lookup_function_type (type);
- /* All functions in C++, Pascal and Java have prototypes. */
- attr = dwarf2_attr (die, DW_AT_prototyped, cu);
- if ((attr && (DW_UNSND (attr) != 0))
- || cu->language == language_cplus
- || cu->language == language_java
- || cu->language == language_pascal)
- TYPE_PROTOTYPED (ftype) = 1;
- else if (producer_is_realview (cu->producer))
- /* RealView does not emit DW_AT_prototyped. We can not
- distinguish prototyped and unprototyped functions; default to
- prototyped, since that is more common in modern code (and
- RealView warns about unprototyped functions). */
+ if (prototyped_function_p (die, cu))
TYPE_PROTOTYPED (ftype) = 1;
/* Store the calling convention in the type if it's available in
complaint (&symfile_complaints,
_("Self-referential DW_TAG_typedef "
"- DIE at 0x%x [in module %s]"),
- die->offset.sect_off, objfile->name);
+ die->offset.sect_off, objfile_name (objfile));
TYPE_TARGET_TYPE (this_type) = NULL;
}
return this_type;
else if (!low_default_is_valid)
complaint (&symfile_complaints, _("Missing DW_AT_lower_bound "
"- DIE at 0x%x [in module %s]"),
- die->offset.sect_off, cu->objfile->name);
+ die->offset.sect_off, objfile_name (cu->objfile));
attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
if (attr)
{
- if (attr_form_is_block (attr) || is_ref_attr (attr))
+ if (attr_form_is_block (attr) || attr_form_is_ref (attr))
{
/* GCC encodes arrays with unspecified or dynamic length
with a DW_FORM_block1 attribute or a reference attribute.
{
fprintf_unfiltered (gdb_stdlog,
"Read die from %s@0x%x of %s:\n",
- bfd_section_name (reader->abfd,
- reader->die_section->asection),
+ get_section_name (reader->die_section),
(unsigned) (info_ptr - reader->die_section->buffer),
bfd_get_filename (reader->abfd));
dump_die (die, dwarf2_die_debug);
{
fprintf_unfiltered (gdb_stdlog,
"Read die from %s@0x%x of %s:\n",
- bfd_section_name (reader->abfd,
- reader->die_section->asection),
+ get_section_name (reader->die_section),
(unsigned) (info_ptr - reader->die_section->buffer),
bfd_get_filename (reader->abfd));
dump_die (*diep, dwarf2_die_debug);
sect_offset offset)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
- bfd *abfd = section->asection->owner;
+ bfd *abfd = get_section_bfd_owner (section);
struct abbrev_table *abbrev_table;
const gdb_byte *abbrev_ptr;
struct abbrev_info *cur_abbrev;
struct attr_abbrev *cur_attrs;
unsigned int allocated_attrs;
- abbrev_table = XMALLOC (struct abbrev_table);
+ abbrev_table = XNEW (struct abbrev_table);
abbrev_table->offset = offset;
obstack_init (&abbrev_table->abbrev_obstack);
abbrev_table->abbrevs = obstack_alloc (&abbrev_table->abbrev_obstack,
{
struct dwarf2_cu *cu = ptr_to_cu;
- abbrev_table_free (cu->abbrev_table);
+ if (cu->abbrev_table != NULL)
+ abbrev_table_free (cu->abbrev_table);
/* Set this to NULL so that we SEGV if we try to read it later,
and also because free_comp_unit verifies this is NULL. */
cu->abbrev_table = NULL;
&& abbrev->tag != DW_TAG_namespace
&& abbrev->tag != DW_TAG_module
&& abbrev->tag != DW_TAG_member
- && abbrev->tag != DW_TAG_imported_unit)
+ && abbrev->tag != DW_TAG_imported_unit
+ && abbrev->tag != DW_TAG_imported_declaration)
{
/* Otherwise we skip to the next sibling, if any. */
info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
complaint (&symfile_complaints,
_("DW_TAG_typedef has childen - GCC PR debug/47510 bug "
"- DIE at 0x%x [in module %s]"),
- part_die->offset.sect_off, objfile->name);
+ part_die->offset.sect_off, objfile_name (objfile));
/* If we're at the second level, and we're an enumerator, and
our parent has no specification (meaning possibly lives in a
complaint (&symfile_complaints,
_("ignoring absolute DW_AT_sibling"));
else
- part_die->sibling = buffer + dwarf2_get_ref_die_offset (&attr).sect_off;
+ {
+ unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off;
+ const gdb_byte *sibling_ptr = buffer + off;
+
+ if (sibling_ptr < info_ptr)
+ complaint (&symfile_complaints,
+ _("DW_AT_sibling points backwards"));
+ else
+ part_die->sibling = sibling_ptr;
+ }
break;
case DW_AT_byte_size:
part_die->has_byte_size = 1;
practice. */
if (DW_UNSND (&attr) == DW_CC_program
&& cu->language == language_fortran)
- {
- set_main_name (part_die->name);
-
- /* As this DIE has a static linkage the name would be difficult
- to look up later. */
- language_of_main = language_fortran;
- }
+ set_objfile_main_name (objfile, part_die->name, language_fortran);
break;
case DW_AT_inline:
if (DW_UNSND (&attr) == DW_INL_inlined
_("DW_AT_low_pc %s is zero "
"for DIE at 0x%x [in module %s]"),
paddress (gdbarch, part_die->lowpc),
- part_die->offset.sect_off, objfile->name);
+ part_die->offset.sect_off, objfile_name (objfile));
}
/* dwarf2_get_pc_bounds has also the strict low < high requirement. */
else if (part_die->lowpc >= part_die->highpc)
"for DIE at 0x%x [in module %s]"),
paddress (gdbarch, part_die->lowpc),
paddress (gdbarch, part_die->highpc),
- part_die->offset.sect_off, objfile->name);
+ part_die->offset.sect_off, objfile_name (objfile));
}
else
part_die->has_pc_info = 1;
}
/* Super hack. */
- if (cu->per_cu->is_dwz && is_ref_attr (attr))
+ if (cu->per_cu->is_dwz && attr_form_is_ref (attr))
attr->form = DW_FORM_GNU_ref_alt;
/* We have seen instances where the compiler tried to emit a byte
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);
+ objfile_name (objfile));
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);
+ objfile_name (objfile));
info_ptr = (dwarf2_per_objfile->addr.buffer
+ addr_base + addr_index * addr_size);
if (addr_size == 4)
return read_addr_index_1 (addr_index, addr_base, addr_size);
}
-/* Given a DW_AT_str_index, fetch the string. */
+/* Given a DW_FORM_GNU_str_index, fetch the string.
+ This is only used by the Fission support. */
static const 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;
+ const char *dwo_name = objfile_name (objfile);
bfd *abfd = objfile->obfd;
- struct dwo_sections *sections = &reader->dwo_file->sections;
+ struct dwarf2_section_info *str_section = &reader->dwo_file->sections.str;
+ struct dwarf2_section_info *str_offsets_section =
+ &reader->dwo_file->sections.str_offsets;
const gdb_byte *info_ptr;
ULONGEST str_offset;
+ static const char form_name[] = "DW_FORM_GNU_str_index";
- 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"
+ dwarf2_read_section (objfile, str_section);
+ dwarf2_read_section (objfile, str_offsets_section);
+ if (str_section->buffer == NULL)
+ error (_("%s 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"
+ form_name, (long) cu->header.offset.sect_off, dwo_name);
+ if (str_offsets_section->buffer == NULL)
+ error (_("%s 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"
+ form_name, (long) cu->header.offset.sect_off, dwo_name);
+ if (str_index * cu->header.offset_size >= str_offsets_section->size)
+ error (_("%s 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
+ form_name, (long) cu->header.offset.sect_off, dwo_name);
+ info_ptr = (str_offsets_section->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"
+ if (str_offset >= str_section->size)
+ error (_("Offset from %s 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 (const char *) (sections->str.buffer + str_offset);
+ form_name, (long) cu->header.offset.sect_off, dwo_name);
+ return (const char *) (str_section->buffer + str_offset);
}
/* Return the length of an LEB128 number in BUF. */
case DW_LANG_C89:
case DW_LANG_C99:
case DW_LANG_C:
+ case DW_LANG_UPC:
cu->language = language_c;
break;
case DW_LANG_C_plus_plus:
/* 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;
+ abfd = get_section_bfd_owner (section);
/* 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 (line_ptr + lh->total_length > (section->buffer + section->size))
{
dwarf2_statement_list_fits_in_line_number_section_complaint ();
+ do_cleanups (back_to);
return 0;
}
lh->statement_program_end = line_ptr + lh->total_length;
complaint (&symfile_complaints,
_(".debug_line address at offset 0x%lx is 0 "
"[in module %s]"),
- line_offset, objfile->name);
+ line_offset, objfile_name (objfile));
p_record_line = noop_record_line;
}
? &global_symbols : cu->list_in_scope);
}
break;
+ case DW_TAG_imported_declaration:
case DW_TAG_namespace:
SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
list_to_add = &global_symbols;
break;
+ case DW_TAG_module:
+ SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
+ SYMBOL_DOMAIN (sym) = MODULE_DOMAIN;
+ list_to_add = &global_symbols;
+ break;
case DW_TAG_common_block:
SYMBOL_ACLASS_INDEX (sym) = LOC_COMMON_BLOCK;
SYMBOL_DOMAIN (sym) = COMMON_BLOCK_DOMAIN;
because that is the interpretation long in use by GCC. */
static gdb_byte *
-dwarf2_const_value_data (struct attribute *attr, struct type *type,
- const char *name, struct obstack *obstack,
+dwarf2_const_value_data (const struct attribute *attr, struct obstack *obstack,
struct dwarf2_cu *cu, LONGEST *value, int bits)
{
struct objfile *objfile = cu->objfile;
expression. */
static void
-dwarf2_const_value_attr (struct attribute *attr, struct type *type,
+dwarf2_const_value_attr (const struct attribute *attr, struct type *type,
const char *name, struct obstack *obstack,
struct dwarf2_cu *cu,
LONGEST *value, const gdb_byte **bytes,
/* Symbols of this form are reasonably rare, so we just
piggyback on the existing location code rather than writing
a new implementation of symbol_computed_ops. */
- *baton = obstack_alloc (&objfile->objfile_obstack,
- sizeof (struct dwarf2_locexpr_baton));
+ *baton = obstack_alloc (obstack, sizeof (struct dwarf2_locexpr_baton));
(*baton)->per_cu = cu->per_cu;
gdb_assert ((*baton)->per_cu);
(*baton)->size = 2 + cu_header->addr_size;
- data = obstack_alloc (&objfile->objfile_obstack, (*baton)->size);
+ data = obstack_alloc (obstack, (*baton)->size);
(*baton)->data = data;
data[0] = DW_OP_addr;
converted to host endianness, so we just need to sign- or
zero-extend it as appropriate. */
case DW_FORM_data1:
- *bytes = dwarf2_const_value_data (attr, type, name,
- obstack, cu, value, 8);
+ *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 8);
break;
case DW_FORM_data2:
- *bytes = dwarf2_const_value_data (attr, type, name,
- obstack, cu, value, 16);
+ *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 16);
break;
case DW_FORM_data4:
- *bytes = dwarf2_const_value_data (attr, type, name,
- obstack, cu, value, 32);
+ *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 32);
break;
case DW_FORM_data8:
- *bytes = dwarf2_const_value_data (attr, type, name,
- obstack, cu, value, 64);
+ *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 64);
break;
case DW_FORM_sdata:
/* Copy constant value from an attribute to a symbol. */
static void
-dwarf2_const_value (struct attribute *attr, struct symbol *sym,
+dwarf2_const_value (const struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
type_attr = dwarf2_attr (die, DW_AT_containing_type, cu);
if (!type_attr)
error (_("Dwarf Error: Problem turning containing type into gdb type "
- "[in module %s]"), cu->objfile->name);
+ "[in module %s]"), objfile_name (cu->objfile));
return lookup_die_type (die, type_attr, cu);
}
char *message, *saved;
message = xstrprintf (_("<unknown type in %s, CU 0x%x, DIE 0x%x>"),
- objfile->name,
+ objfile_name (objfile),
cu->header.offset.sect_off,
die->offset.sect_off);
saved = obstack_copy0 (&objfile->objfile_obstack,
If there is no type substitute an error marker. */
static struct type *
-lookup_die_type (struct die_info *die, struct attribute *attr,
+lookup_die_type (struct die_info *die, const struct attribute *attr,
struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
per_cu = dwarf2_find_containing_comp_unit (offset, 1, cu->objfile);
this_type = get_die_type_at_offset (offset, per_cu);
}
- else if (is_ref_attr (attr))
+ else if (attr_form_is_ref (attr))
{
sect_offset offset = dwarf2_get_ref_die_offset (attr);
_("Dwarf Error: Bad type attribute %s in DIE"
" at 0x%x [in module %s]"),
dwarf_attr_name (attr->name), die->offset.sect_off,
- objfile->name);
+ objfile_name (objfile));
return build_error_marker_type (cu, die);
}
struct die_info *type_die = NULL;
struct dwarf2_cu *type_cu = cu;
- if (is_ref_attr (attr))
+ if (attr_form_is_ref (attr))
type_die = follow_die_ref (die, attr, &type_cu);
if (type_die == NULL)
return build_error_marker_type (cu, die);
*slot = die;
}
-/* DW_ADDR is always stored already as sect_offset; despite for the forms
- besides DW_FORM_ref_addr it is stored as cu_offset in the DWARF file. */
-
-static int
-is_ref_attr (struct attribute *attr)
-{
- switch (attr->form)
- {
- case DW_FORM_ref_addr:
- case DW_FORM_ref1:
- case DW_FORM_ref2:
- case DW_FORM_ref4:
- case DW_FORM_ref8:
- case DW_FORM_ref_udata:
- case DW_FORM_GNU_ref_alt:
- return 1;
- default:
- return 0;
- }
-}
-
/* Return DIE offset of ATTR. Return 0 with complaint if ATTR is not of the
required kind. */
static sect_offset
-dwarf2_get_ref_die_offset (struct attribute *attr)
+dwarf2_get_ref_die_offset (const struct attribute *attr)
{
sect_offset retval = { DW_UNSND (attr) };
- if (is_ref_attr (attr))
+ if (attr_form_is_ref (attr))
return retval;
retval.sect_off = 0;
* the value held by the attribute is not constant. */
static LONGEST
-dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
+dwarf2_get_attr_constant_value (const struct attribute *attr, int default_value)
{
if (attr->form == DW_FORM_sdata)
return DW_SND (attr);
On exit *REF_CU is the CU of the result. */
static struct die_info *
-follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr,
+follow_die_ref_or_sig (struct die_info *src_die, const struct attribute *attr,
struct dwarf2_cu **ref_cu)
{
struct die_info *die;
- if (is_ref_attr (attr))
+ if (attr_form_is_ref (attr))
die = follow_die_ref (src_die, attr, ref_cu);
else if (attr->form == DW_FORM_ref_sig8)
die = follow_die_sig (src_die, attr, ref_cu);
{
dump_die_for_error (src_die);
error (_("Dwarf Error: Expected reference attribute [in module %s]"),
- (*ref_cu)->objfile->name);
+ objfile_name ((*ref_cu)->objfile));
}
return die;
On exit *REF_CU is the CU of the result. */
static struct die_info *
-follow_die_ref (struct die_info *src_die, struct attribute *attr,
+follow_die_ref (struct die_info *src_die, const struct attribute *attr,
struct dwarf2_cu **ref_cu)
{
sect_offset offset = dwarf2_get_ref_die_offset (attr);
if (!die)
error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
"at 0x%x [in module %s]"),
- offset.sect_off, src_die->offset.sect_off, cu->objfile->name);
+ offset.sect_off, src_die->offset.sect_off,
+ objfile_name (cu->objfile));
return die;
}
die = follow_die_offset (offset, per_cu->is_dwz, &cu);
if (!die)
error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
- offset.sect_off, per_cu->objfile->name);
+ offset.sect_off, objfile_name (per_cu->objfile));
attr = dwarf2_attr (die, DW_AT_location, cu);
if (!attr)
if (!attr_form_is_block (attr))
error (_("Dwarf Error: DIE at 0x%x referenced in module %s "
"is neither DW_FORM_block* nor DW_FORM_exprloc"),
- offset.sect_off, per_cu->objfile->name);
+ offset.sect_off, objfile_name (per_cu->objfile));
retval.data = DW_BLOCK (attr)->data;
retval.size = DW_BLOCK (attr)->size;
return dwarf2_fetch_die_loc_sect_off (offset, per_cu, get_frame_pc, baton);
}
+/* Write a constant of a given type as target-ordered bytes into
+ OBSTACK. */
+
+static const gdb_byte *
+write_constant_as_bytes (struct obstack *obstack,
+ enum bfd_endian byte_order,
+ struct type *type,
+ ULONGEST value,
+ LONGEST *len)
+{
+ gdb_byte *result;
+
+ *len = TYPE_LENGTH (type);
+ result = obstack_alloc (obstack, *len);
+ store_unsigned_integer (result, *len, byte_order, value);
+
+ return result;
+}
+
+/* If the DIE at OFFSET in PER_CU has a DW_AT_const_value, return a
+ pointer to the constant bytes and set LEN to the length of the
+ data. If memory is needed, allocate it on OBSTACK. If the DIE
+ does not have a DW_AT_const_value, return NULL. */
+
+const gdb_byte *
+dwarf2_fetch_constant_bytes (sect_offset offset,
+ struct dwarf2_per_cu_data *per_cu,
+ struct obstack *obstack,
+ LONGEST *len)
+{
+ struct dwarf2_cu *cu;
+ struct die_info *die;
+ struct attribute *attr;
+ const gdb_byte *result = NULL;
+ struct type *type;
+ LONGEST value;
+ enum bfd_endian byte_order;
+
+ dw2_setup (per_cu->objfile);
+
+ if (per_cu->cu == NULL)
+ load_cu (per_cu);
+ cu = per_cu->cu;
+
+ die = follow_die_offset (offset, per_cu->is_dwz, &cu);
+ if (!die)
+ error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
+ offset.sect_off, objfile_name (per_cu->objfile));
+
+
+ attr = dwarf2_attr (die, DW_AT_const_value, cu);
+ if (attr == NULL)
+ return NULL;
+
+ byte_order = (bfd_big_endian (per_cu->objfile->obfd)
+ ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE);
+
+ switch (attr->form)
+ {
+ case DW_FORM_addr:
+ case DW_FORM_GNU_addr_index:
+ {
+ gdb_byte *tem;
+
+ *len = cu->header.addr_size;
+ tem = obstack_alloc (obstack, *len);
+ store_unsigned_integer (tem, *len, byte_order, DW_ADDR (attr));
+ result = tem;
+ }
+ break;
+ case DW_FORM_string:
+ case DW_FORM_strp:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_GNU_strp_alt:
+ /* DW_STRING is already allocated on the objfile obstack, point
+ directly to it. */
+ result = (const gdb_byte *) DW_STRING (attr);
+ *len = strlen (DW_STRING (attr));
+ break;
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ case DW_FORM_block:
+ case DW_FORM_exprloc:
+ result = DW_BLOCK (attr)->data;
+ *len = DW_BLOCK (attr)->size;
+ break;
+
+ /* The DW_AT_const_value attributes are supposed to carry the
+ symbol's value "represented as it would be on the target
+ architecture." By the time we get here, it's already been
+ converted to host endianness, so we just need to sign- or
+ zero-extend it as appropriate. */
+ case DW_FORM_data1:
+ type = die_type (die, cu);
+ result = dwarf2_const_value_data (attr, obstack, cu, &value, 8);
+ if (result == NULL)
+ result = write_constant_as_bytes (obstack, byte_order,
+ type, value, len);
+ break;
+ case DW_FORM_data2:
+ type = die_type (die, cu);
+ result = dwarf2_const_value_data (attr, obstack, cu, &value, 16);
+ if (result == NULL)
+ result = write_constant_as_bytes (obstack, byte_order,
+ type, value, len);
+ break;
+ case DW_FORM_data4:
+ type = die_type (die, cu);
+ result = dwarf2_const_value_data (attr, obstack, cu, &value, 32);
+ if (result == NULL)
+ result = write_constant_as_bytes (obstack, byte_order,
+ type, value, len);
+ break;
+ case DW_FORM_data8:
+ type = die_type (die, cu);
+ result = dwarf2_const_value_data (attr, obstack, cu, &value, 64);
+ if (result == NULL)
+ result = write_constant_as_bytes (obstack, byte_order,
+ type, value, len);
+ break;
+
+ case DW_FORM_sdata:
+ type = die_type (die, cu);
+ result = write_constant_as_bytes (obstack, byte_order,
+ type, DW_SND (attr), len);
+ break;
+
+ case DW_FORM_udata:
+ type = die_type (die, cu);
+ result = write_constant_as_bytes (obstack, byte_order,
+ type, DW_UNSND (attr), len);
+ break;
+
+ default:
+ complaint (&symfile_complaints,
+ _("unsupported const value attribute form: '%s'"),
+ dwarf_form_name (attr->form));
+ break;
+ }
+
+ return result;
+}
+
/* Return the type of the DIE at DIE_OFFSET in the CU named by
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;
+ gdb_assert (sig_cu != NULL);
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,
If the referenced type cannot be found an error is thrown. */
static struct die_info *
-follow_die_sig (struct die_info *src_die, struct attribute *attr,
+follow_die_sig (struct die_info *src_die, const struct attribute *attr,
struct dwarf2_cu **ref_cu)
{
ULONGEST signature = DW_SIGNATURE (attr);
gdb_assert (attr->form == DW_FORM_ref_sig8);
- sig_type = lookup_signatured_type (signature);
+ sig_type = lookup_signatured_type (*ref_cu, signature);
/* sig_type will be NULL if the signatured type is missing from
the debug info. */
if (sig_type == NULL)
error (_("Dwarf Error: Cannot find signatured DIE %s referenced"
" from DIE at 0x%x [in module %s]"),
hex_string (signature), src_die->offset.sect_off,
- (*ref_cu)->objfile->name);
+ objfile_name ((*ref_cu)->objfile));
}
die = follow_die_sig_1 (src_die, sig_type, ref_cu);
error (_("Dwarf Error: Problem reading signatured DIE %s referenced"
" from DIE at 0x%x [in module %s]"),
hex_string (signature), src_die->offset.sect_off,
- (*ref_cu)->objfile->name);
+ objfile_name ((*ref_cu)->objfile));
}
return die;
struct die_info *type_die;
struct type *type;
- sig_type = lookup_signatured_type (signature);
+ sig_type = lookup_signatured_type (cu, signature);
/* sig_type will be NULL if the signatured type is missing from
the debug info. */
if (sig_type == NULL)
_("Dwarf Error: Cannot find signatured DIE %s referenced"
" from DIE at 0x%x [in module %s]"),
hex_string (signature), die->offset.sect_off,
- dwarf2_per_objfile->objfile->name);
+ objfile_name (dwarf2_per_objfile->objfile));
return build_error_marker_type (cu, die);
}
_("Dwarf Error: Cannot build signatured type %s"
" referenced from DIE at 0x%x [in module %s]"),
hex_string (signature), die->offset.sect_off,
- dwarf2_per_objfile->objfile->name);
+ objfile_name (dwarf2_per_objfile->objfile));
type = build_error_marker_type (cu, die);
}
}
_("Dwarf Error: Problem reading signatured DIE %s referenced"
" from DIE at 0x%x [in module %s]"),
hex_string (signature), die->offset.sect_off,
- dwarf2_per_objfile->objfile->name);
+ objfile_name (dwarf2_per_objfile->objfile));
type = build_error_marker_type (cu, die);
}
sig_type->type = type;
reading in and processing the type unit if necessary. */
static struct type *
-get_DW_AT_signature_type (struct die_info *die, struct attribute *attr,
- struct dwarf2_cu *cu)
+get_DW_AT_signature_type (struct die_info *die, const struct attribute *attr,
+ struct dwarf2_cu *cu) /* ARI: editCase function */
{
/* Yes, DW_AT_signature can use a non-ref_sig8 reference. */
- if (is_ref_attr (attr))
+ if (attr_form_is_ref (attr))
{
struct dwarf2_cu *type_cu = cu;
struct die_info *type_die = follow_die_ref (die, attr, &type_cu);
_("Dwarf Error: DW_AT_signature has bad form %s in DIE"
" at 0x%x [in module %s]"),
dwarf_form_name (attr->form), die->offset.sect_off,
- dwarf2_per_objfile->objfile->name);
+ objfile_name (dwarf2_per_objfile->objfile));
return build_error_marker_type (cu, die);
}
}
init_cutu_and_read_dies (per_cu, NULL, 0, 1,
read_signatured_type_reader, NULL);
+ sig_type->per_cu.tu_read = 1;
}
/* Decode simple location descriptions.
/* File name relative to the compilation directory of this source file. */
char *file_name = file_file_name (file, lh);
- /* We don't create a macro table for this compilation unit
- at all until we actually get a filename. */
- if (! pending_macros)
- pending_macros = new_macro_table (&objfile->per_bfd->storage_obstack,
- objfile->per_bfd->macro_cache,
- comp_dir);
-
if (! current_file)
{
+ /* Note: We don't create a macro table for this compilation unit
+ at all until we actually get a filename. */
+ struct macro_table *macro_table = get_macro_table (objfile, comp_dir);
+
/* 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, file_name);
- macro_define_special (pending_macros);
+ current_file = macro_set_main (macro_table, file_name);
+ macro_define_special (macro_table);
}
else
current_file = macro_include (current_file, line, file_name);
complain:
complaint (&symfile_complaints,
_("invalid form 0x%x in `%s'"),
- form,
- section->asection->name);
+ form, get_section_name (section));
return NULL;
}
}
dwarf2_read_section (dwarf2_per_objfile->objfile,
&dwz->macro);
- include_bfd = dwz->macro.asection->owner;
include_section = &dwz->macro;
+ include_bfd = get_section_bfd_owner (include_section);
include_mac_end = dwz->macro.buffer + dwz->macro.size;
is_dwz = 1;
}
complaint (&symfile_complaints, _("missing %s section"), section_name);
return;
}
- abfd = section->asection->owner;
+ abfd = get_section_bfd_owner (section);
/* First pass: Find the name of the base filename.
This filename is needed in order to process all macros whose definition
if so return true else false. */
static int
-attr_form_is_block (struct attribute *attr)
+attr_form_is_block (const struct attribute *attr)
{
return (attr == NULL ? 0 :
attr->form == DW_FORM_block1
of them. */
static int
-attr_form_is_section_offset (struct attribute *attr)
+attr_form_is_section_offset (const struct attribute *attr)
{
return (attr->form == DW_FORM_data4
|| attr->form == DW_FORM_data8
taken as section offsets, not constants. */
static int
-attr_form_is_constant (struct attribute *attr)
+attr_form_is_constant (const struct attribute *attr)
{
switch (attr->form)
{
}
}
+
+/* DW_ADDR is always stored already as sect_offset; despite for the forms
+ besides DW_FORM_ref_addr it is stored as cu_offset in the DWARF file. */
+
+static int
+attr_form_is_ref (const struct attribute *attr)
+{
+ switch (attr->form)
+ {
+ case DW_FORM_ref_addr:
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_udata:
+ case DW_FORM_GNU_ref_alt:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
/* Return the .debug_loc section to use for CU.
For DWO files use .debug_loc.dwo. */
static void
fill_in_loclist_baton (struct dwarf2_cu *cu,
struct dwarf2_loclist_baton *baton,
- struct attribute *attr)
+ const struct attribute *attr)
{
struct dwarf2_section_info *section = cu_debug_loc_section (cu);
}
static void
-dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
+dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
struct dwarf2_cu *cu, int is_block)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwarf2_per_objfile *data = d;
int ix;
- 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);
+ /* Make sure we don't accidentally use dwarf2_per_objfile while
+ cleaning up. */
+ dwarf2_per_objfile = NULL;
+
+ for (ix = 0; ix < data->n_comp_units; ++ix)
+ VEC_free (dwarf2_per_cu_ptr, data->all_comp_units[ix]->imported_symtabs);
- for (ix = 0; ix < dwarf2_per_objfile->n_type_units; ++ix)
+ for (ix = 0; ix < data->n_type_units; ++ix)
VEC_free (dwarf2_per_cu_ptr,
- dwarf2_per_objfile->all_type_units[ix]->per_cu.imported_symtabs);
+ data->all_type_units[ix]->per_cu.imported_symtabs);
+ xfree (data->all_type_units);
VEC_free (dwarf2_section_info_def, data->types);
htab_t cu_index_htab;
struct psymtab_cu_index_map *psymtab_cu_index_map;
- if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
- return;
-
if (dwarf2_per_objfile->using_index)
error (_("Cannot use an index to create the index"));
if (VEC_length (dwarf2_section_info_def, dwarf2_per_objfile->types) > 1)
error (_("Cannot make an index when the file has multiple .debug_types sections"));
- if (stat (objfile->name, &st) < 0)
- perror_with_name (objfile->name);
+ if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
+ return;
+
+ if (stat (objfile_name (objfile), &st) < 0)
+ perror_with_name (objfile_name (objfile));
- filename = concat (dir, SLASH_STRING, lbasename (objfile->name),
+ filename = concat (dir, SLASH_STRING, lbasename (objfile_name (objfile)),
INDEX_SUFFIX, (char *) NULL);
cleanup = make_cleanup (xfree, filename);
- out_file = fopen (filename, "wb");
+ out_file = gdb_fopen_cloexec (filename, "wb");
if (!out_file)
error (_("Can't open `%s' for writing"), filename);
struct psymtab_cu_index_map *map;
void **slot;
+ /* CU of a shared file from 'dwz -m' may be unused by this main file.
+ It may be referenced from a local scope but in such case it does not
+ need to be present in .gdb_index. */
+ if (psymtab == NULL)
+ continue;
+
if (psymtab->user == NULL)
recursively_write_psymbols (objfile, psymtab, symtab, psyms_seen, i);
struct stat st;
/* If the objfile does not correspond to an actual file, skip it. */
- if (stat (objfile->name, &st) < 0)
+ if (stat (objfile_name (objfile), &st) < 0)
continue;
dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
if (except.reason < 0)
exception_fprintf (gdb_stderr, except,
_("Error while writing index for `%s': "),
- objfile->name);
+ objfile_name (objfile));
}
}
}
&set_dwarf2_cmdlist,
&show_dwarf2_cmdlist);
- add_setshow_boolean_cmd ("dwarf2-read", no_class, &dwarf2_read_debug, _("\
+ add_setshow_zuinteger_cmd ("dwarf2-read", no_class, &dwarf2_read_debug, _("\
Set debugging of the dwarf2 reader."), _("\
Show debugging of the dwarf2 reader."), _("\
-When enabled, debugging messages are printed during dwarf2 reading\n\
-and symtab expansion."),
+When enabled (non-zero), debugging messages are printed during dwarf2\n\
+reading and symtab expansion. A value of 1 (one) provides basic\n\
+information. A value greater than 1 provides more verbose information."),
NULL,
NULL,
&setdebuglist, &showdebuglist);