/* Size of .debug_loclists section header for 64-bit DWARF format. */
#define LOCLIST_HEADER_SIZE64 20
+/* Size of .debug_rnglists section header for 32-bit DWARF format. */
+#define RNGLIST_HEADER_SIZE32 12
+
+/* Size of .debug_rnglists section header for 64-bit DWARF format. */
+#define RNGLIST_HEADER_SIZE64 20
+
/* An index into a (C++) symbol name component in a symbol name as
recorded in the mapped_index's symbol table. For each C++ symbol
in the symbol table, we record one entry for the start of each
struct dwarf2_section_names loclists_dwo;
struct dwarf2_section_names macinfo_dwo;
struct dwarf2_section_names macro_dwo;
+ struct dwarf2_section_names rnglists_dwo;
struct dwarf2_section_names str_dwo;
struct dwarf2_section_names str_offsets_dwo;
struct dwarf2_section_names types_dwo;
{ ".debug_loclists.dwo", ".zdebug_loclists.dwo" },
{ ".debug_macinfo.dwo", ".zdebug_macinfo.dwo" },
{ ".debug_macro.dwo", ".zdebug_macro.dwo" },
+ { ".debug_rnglists.dwo", ".zdebug_rnglists.dwo" },
{ ".debug_str.dwo", ".zdebug_str.dwo" },
{ ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo" },
{ ".debug_types.dwo", ".zdebug_types.dwo" },
/* local data types */
-/* The location list section (.debug_loclists) begins with a header,
- which contains the following information. */
-struct loclist_header
+/* The location list and range list sections (.debug_loclists & .debug_rnglists)
+ begin with a header, which contains the following information. */
+struct loclists_rnglists_header
{
/* A 4-byte or 12-byte length containing the length of the
set of entries for this compilation unit, not including the
struct dwarf2_section_info loclists;
struct dwarf2_section_info macinfo;
struct dwarf2_section_info macro;
+ struct dwarf2_section_info rnglists;
struct dwarf2_section_info str;
struct dwarf2_section_info str_offsets;
/* In the case of a virtual DWO file, these two are unused. */
gdb_bfd_ref_ptr dbfd;
/* The sections that make up this DWO file.
- Remember that for virtual DWO files in DWP V2, these are virtual
+ Remember that for virtual DWO files in DWP V2 or DWP V5, these are virtual
sections (for lack of a better name). */
struct dwo_sections sections {};
struct dwp_sections
{
- /* These are used by both DWP version 1 and 2. */
+ /* These are used by all DWP versions (1, 2 and 5). */
struct dwarf2_section_info str;
struct dwarf2_section_info cu_index;
struct dwarf2_section_info tu_index;
- /* These are only used by DWP version 2 files.
+ /* These are only used by DWP version 2 and version 5 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.
+ In DWP version 2 or 5 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 loclists;
struct dwarf2_section_info macinfo;
struct dwarf2_section_info macro;
+ struct dwarf2_section_info rnglists;
struct dwarf2_section_info str_offsets;
struct dwarf2_section_info types;
};
struct dwarf2_section_info info_or_types;
};
-/* Similar to virtual_v1_dwo_sections, but for DWP version 2.
+/* Similar to virtual_v1_dwo_sections, but for DWP version 2 or 5.
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
+struct virtual_v2_or_v5_dwo_sections
{
bfd_size_type abbrev_offset;
bfd_size_type abbrev_size;
bfd_size_type loc_offset;
bfd_size_type loc_size;
+ bfd_size_type loclists_offset;
+ bfd_size_type loclists_size;
+
bfd_size_type macinfo_offset;
bfd_size_type macinfo_size;
bfd_size_type macro_offset;
bfd_size_type macro_size;
+ bfd_size_type rnglists_offset;
+ bfd_size_type rnglists_size;
+
bfd_size_type str_offsets_offset;
bfd_size_type str_offsets_size;
const gdb_byte *offsets;
const gdb_byte *sizes;
} v2;
+ struct
+ {
+ /* This is indexed by column number and gives the id of the section
+ in that column. */
+#define MAX_NR_V5_DWO_SECTIONS \
+ (1 /* .debug_info */ \
+ + 1 /* .debug_abbrev */ \
+ + 1 /* .debug_line */ \
+ + 1 /* .debug_loclists */ \
+ + 1 /* .debug_str_offsets */ \
+ + 1 /* .debug_macro */ \
+ + 1 /* .debug_rnglists */)
+ int section_ids[MAX_NR_V5_DWO_SECTIONS];
+ const gdb_byte *offsets;
+ const gdb_byte *sizes;
+ } v5;
} section_pool;
};
pass lists of data member fields and lists of member function fields
in an instance of a field_info structure, as defined below. */
struct field_info
- {
- /* List of data member and baseclasses fields. */
- std::vector<struct nextfield> fields;
- std::vector<struct nextfield> baseclasses;
+{
+ /* List of data member and baseclasses fields. */
+ std::vector<struct nextfield> fields;
+ std::vector<struct nextfield> baseclasses;
- /* Set if the accessibility of one of the fields is not public. */
- int non_public_fields = 0;
+ /* Set if the accessibility of one of the fields is not public. */
+ int non_public_fields = 0;
- /* Member function fieldlist array, contains name of possibly overloaded
- member function, number of overloaded member functions and a pointer
- to the head of the member function field chain. */
- std::vector<struct fnfieldlist> fnfieldlists;
+ /* Member function fieldlist array, contains name of possibly overloaded
+ member function, number of overloaded member functions and a pointer
+ to the head of the member function field chain. */
+ std::vector<struct fnfieldlist> fnfieldlists;
- /* typedefs defined inside this class. TYPEDEF_FIELD_LIST contains head of
- a NULL terminated list of TYPEDEF_FIELD_LIST_COUNT elements. */
- std::vector<struct decl_field> typedef_field_list;
+ /* typedefs defined inside this class. TYPEDEF_FIELD_LIST contains head of
+ a NULL terminated list of TYPEDEF_FIELD_LIST_COUNT elements. */
+ std::vector<struct decl_field> typedef_field_list;
- /* Nested types defined by this class and the number of elements in this
- list. */
- std::vector<struct decl_field> nested_types_list;
+ /* Nested types defined by this class and the number of elements in this
+ list. */
+ std::vector<struct decl_field> nested_types_list;
- /* If non-null, this is the variant part we are currently
- reading. */
- variant_part_builder *current_variant_part = nullptr;
- /* This holds all the top-level variant parts attached to the type
- we're reading. */
- std::vector<variant_part_builder> variant_parts;
+ /* If non-null, this is the variant part we are currently
+ reading. */
+ variant_part_builder *current_variant_part = nullptr;
+ /* This holds all the top-level variant parts attached to the type
+ we're reading. */
+ std::vector<variant_part_builder> variant_parts;
- /* Return the total number of fields (including baseclasses). */
- int nfields () const
- {
- return fields.size () + baseclasses.size ();
- }
- };
+ /* Return the total number of fields (including baseclasses). */
+ int nfields () const
+ {
+ return fields.size () + baseclasses.size ();
+ }
+};
/* Loaded secondary compilation units are kept in memory until they
have not been referenced for the processing of this many
const gdb_byte *, bool *need_reprocess);
static void read_attribute_reprocess (const struct die_reader_specs *reader,
- struct attribute *attr);
+ struct attribute *attr, dwarf_tag tag);
static CORE_ADDR read_addr_index (struct dwarf2_cu *cu, unsigned int addr_index);
static void read_variable (struct die_info *die, struct dwarf2_cu *cu);
-static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *,
- struct dwarf2_cu *, dwarf2_psymtab *);
-
/* Return the .debug_loclists section to use for cu. */
static struct dwarf2_section_info *cu_debug_loc_section (struct dwarf2_cu *cu);
+/* Return the .debug_rnglists section to use for cu. */
+static struct dwarf2_section_info *cu_debug_rnglists_section
+ (struct dwarf2_cu *cu, dwarf_tag tag);
+
/* How dwarf2_get_pc_bounds constructed its *LOWPC and *HIGHPC return
values. Keep the items ordered with increasing constraints compliance. */
enum pc_bounds_kind
offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0;
struct dwz_file *dwz;
struct objfile *objfile = per_objfile->objfile;
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
gdb::array_view<const gdb_byte> main_index_contents
- = get_gdb_index_contents (objfile, per_objfile->per_bfd);
+ = get_gdb_index_contents (objfile, per_bfd);
if (main_index_contents.empty ())
return 0;
/* If there is a .dwz file, read it so we can get its CU list as
well. */
- dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
+ dwz = dwarf2_get_dwz_file (per_bfd);
if (dwz != NULL)
{
struct mapped_index dwz_map;
}
}
- create_cus_from_index (per_objfile->per_bfd, cu_list, cu_list_elements,
- dwz_list, dwz_list_elements);
+ create_cus_from_index (per_bfd, cu_list, cu_list_elements, dwz_list,
+ dwz_list_elements);
if (types_list_elements)
{
/* We can only handle a single .debug_types when we have an
index. */
- if (per_objfile->per_bfd->types.size () != 1)
+ if (per_bfd->types.size () != 1)
return 0;
- dwarf2_section_info *section = &per_objfile->per_bfd->types[0];
+ dwarf2_section_info *section = &per_bfd->types[0];
- create_signatured_type_table_from_index (per_objfile->per_bfd,
- section, types_list,
+ create_signatured_type_table_from_index (per_bfd, section, types_list,
types_list_elements);
}
create_addrmap_from_index (per_objfile, map.get ());
- per_objfile->per_bfd->index_table = std::move (map);
- per_objfile->per_bfd->using_index = 1;
- per_objfile->per_bfd->quick_file_names_table =
- create_quick_file_names_table (per_objfile->per_bfd->all_comp_units.size ());
+ per_bfd->index_table = std::move (map);
+ per_bfd->using_index = 1;
+ per_bfd->quick_file_names_table =
+ create_quick_file_names_table (per_bfd->all_comp_units.size ());
+
+ /* Save partial symtabs in the per_bfd object, for the benefit of subsequent
+ objfiles using the same BFD. */
+ gdb_assert (per_bfd->partial_symtabs == nullptr);
+ per_bfd->partial_symtabs = objfile->partial_symtabs;
return 1;
}
int global_seen;
};
-/* Initialize the index symtab iterator ITER. */
+/* Initialize the index symtab iterator ITER, common part. */
static void
-dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
- dwarf2_per_objfile *per_objfile,
- gdb::optional<block_enum> block_index,
- domain_enum domain,
- const char *name)
+dw2_symtab_iter_init_common (struct dw2_symtab_iterator *iter,
+ dwarf2_per_objfile *per_objfile,
+ gdb::optional<block_enum> block_index,
+ domain_enum domain)
{
iter->per_objfile = per_objfile;
iter->block_index = block_index;
iter->domain = domain;
iter->next = 0;
iter->global_seen = 0;
+ iter->vec = NULL;
+ iter->length = 0;
+}
- mapped_index *index = per_objfile->per_bfd->index_table.get ();
+/* Initialize the index symtab iterator ITER, const char *NAME variant. */
+static void
+dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
+ dwarf2_per_objfile *per_objfile,
+ gdb::optional<block_enum> block_index,
+ domain_enum domain,
+ const char *name)
+{
+ dw2_symtab_iter_init_common (iter, per_objfile, block_index, domain);
+
+ mapped_index *index = per_objfile->per_bfd->index_table.get ();
/* index is NULL if OBJF_READNOW. */
- if (index != NULL && find_slot_in_mapped_hash (index, name, &iter->vec))
+ if (index == NULL)
+ return;
+
+ if (find_slot_in_mapped_hash (index, name, &iter->vec))
iter->length = MAYBE_SWAP (*iter->vec);
- else
- {
- iter->vec = NULL;
- iter->length = 0;
- }
+}
+
+/* Initialize the index symtab iterator ITER, offset_type NAMEI variant. */
+
+static void
+dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
+ dwarf2_per_objfile *per_objfile,
+ gdb::optional<block_enum> block_index,
+ domain_enum domain, offset_type namei)
+{
+ dw2_symtab_iter_init_common (iter, per_objfile, block_index, domain);
+
+ mapped_index *index = per_objfile->per_bfd->index_table.get ();
+ /* index is NULL if OBJF_READNOW. */
+ if (index == NULL)
+ return;
+
+ gdb_assert (!index->symbol_name_slot_invalid (namei));
+ const auto &bucket = index->symbol_table[namei];
+
+ iter->vec = (offset_type *) (index->constant_pool
+ + MAYBE_SWAP (bucket.vec));
+ iter->length = MAYBE_SWAP (*iter->vec);
}
/* Return the next matching CU or NULL if there are no more. */
if (per_objfile->per_bfd->index_table != nullptr)
{
- /* Ada currently doesn't support .gdb_index (see PR24713). We can get
- here though if the current language is Ada for a non-Ada objfile
- using GNU index. */
mapped_index &index = *per_objfile->per_bfd->index_table;
const char *match_name = name.ada ().lookup_name ().c_str ();
struct dwarf2_per_cu_data *per_cu;
dw2_symtab_iter_init (&iter, per_objfile, block_kind, domain,
- match_name);
+ namei);
while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
dw2_expand_symtabs_matching_one (per_cu, per_objfile, nullptr,
nullptr);
const language_defn *lang = language_def (lang_e);
symbol_name_matcher_ftype *name_matcher
- = get_symbol_name_matcher (lang, lookup_name_without_params);
+ = lang->get_symbol_name_matcher (lookup_name_without_params);
name_and_matcher key {
name_matcher,
std::unique_ptr<mapped_debug_names> map (new mapped_debug_names);
mapped_debug_names dwz_map;
struct objfile *objfile = per_objfile->objfile;
+ dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
if (!read_debug_names_from_section (objfile, objfile_name (objfile),
&per_objfile->per_bfd->debug_names, *map))
/* If there is a .dwz file, read it so we can get its CU list as
well. */
- dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd);
+ dwz_file *dwz = dwarf2_get_dwz_file (per_bfd);
if (dwz != NULL)
{
if (!read_debug_names_from_section (objfile,
}
}
- create_cus_from_debug_names (per_objfile->per_bfd, *map, dwz_map);
+ create_cus_from_debug_names (per_bfd, *map, dwz_map);
if (map->tu_count != 0)
{
/* We can only handle a single .debug_types when we have an
index. */
- if (per_objfile->per_bfd->types.size () != 1)
+ if (per_bfd->types.size () != 1)
return false;
- dwarf2_section_info *section = &per_objfile->per_bfd->types[0];
+ dwarf2_section_info *section = &per_bfd->types[0];
create_signatured_type_table_from_debug_names
- (per_objfile, *map, section, &per_objfile->per_bfd->abbrev);
+ (per_objfile, *map, section, &per_bfd->abbrev);
}
- create_addrmap_from_aranges (per_objfile,
- &per_objfile->per_bfd->debug_aranges);
+ create_addrmap_from_aranges (per_objfile, &per_bfd->debug_aranges);
- per_objfile->per_bfd->debug_names_table = std::move (map);
- per_objfile->per_bfd->using_index = 1;
- per_objfile->per_bfd->quick_file_names_table =
+ per_bfd->debug_names_table = std::move (map);
+ per_bfd->using_index = 1;
+ per_bfd->quick_file_names_table =
create_quick_file_names_table (per_objfile->per_bfd->all_comp_units.size ());
+ /* Save partial symtabs in the per_bfd object, for the benefit of subsequent
+ objfiles using the same BFD. */
+ gdb_assert (per_bfd->partial_symtabs == nullptr);
+ per_bfd->partial_symtabs = objfile->partial_symtabs;
+
return true;
}
if (per_bfd->debug_names_table != nullptr)
{
*index_kind = dw_index_kind::DEBUG_NAMES;
+ per_objfile->objfile->partial_symtabs = per_bfd->partial_symtabs;
per_objfile->resize_symtabs ();
return true;
}
if (per_bfd->index_table != nullptr)
{
*index_kind = dw_index_kind::GDB_INDEX;
+ per_objfile->objfile->partial_symtabs = per_bfd->partial_symtabs;
per_objfile->resize_symtabs ();
return true;
}
+ /* There might already be partial symtabs built for this BFD. This happens
+ when loading the same binary twice with the index-cache enabled. If so,
+ don't try to read an index. The objfile / per_objfile initialization will
+ be completed in dwarf2_build_psymtabs, in the standard partial symtabs
+ code path. */
+ if (per_bfd->partial_symtabs != nullptr)
+ return false;
+
if (dwarf2_read_debug_names (per_objfile))
{
*index_kind = dw_index_kind::DEBUG_NAMES;
/* Skip dummy type units. */
if (ptr >= info_ptr + length
|| peek_abbrev_code (abfd, ptr) == 0
- || header.unit_type != DW_UT_type)
+ || (header.unit_type != DW_UT_type
+ && header.unit_type != DW_UT_split_type))
{
info_ptr += length;
continue;
/* A helper that allocates a variant part to attach to a Rust enum
type. OBSTACK is where the results should be allocated. TYPE is
the type we're processing. DISCRIMINANT_INDEX is the index of the
- discriminant. It must be the index of one of the fields of TYPE.
+ discriminant. It must be the index of one of the fields of TYPE,
+ or -1 to mean there is no discriminant (univariant enum).
DEFAULT_INDEX is the index of the default field; or -1 if there is
no default. RANGES is indexed by "effective" field number (the
field index, but omitting the discriminant and default fields) and
int discriminant_index, int default_index,
gdb::array_view<discriminant_range> ranges)
{
- /* When DISCRIMINANT_INDEX == -1, we have a univariant enum. Those
- must be handled by the caller. */
- gdb_assert (discriminant_index >= 0
- && discriminant_index < type->num_fields ());
+ /* When DISCRIMINANT_INDEX == -1, we have a univariant enum. */
+ gdb_assert (discriminant_index == -1
+ || (discriminant_index >= 0
+ && discriminant_index < type->num_fields ()));
gdb_assert (default_index == -1
|| (default_index >= 0 && default_index < type->num_fields ()));
/* We have one variant for each non-discriminant field. */
- int n_variants = type->num_fields () - 1;
+ int n_variants = type->num_fields ();
+ if (discriminant_index != -1)
+ --n_variants;
variant *variants = new (obstack) variant[n_variants];
int var_idx = 0;
variant_part *part = new (obstack) variant_part;
part->discriminant_index = discriminant_index;
- part->is_unsigned = TYPE_UNSIGNED (TYPE_FIELD_TYPE (type,
- discriminant_index));
+ /* If there is no discriminant, then whether it is signed is of no
+ consequence. */
+ part->is_unsigned
+ = (discriminant_index == -1
+ ? false
+ : TYPE_UNSIGNED (type->field (discriminant_index).type ()));
part->variants = gdb::array_view<variant> (variants, n_variants);
void *storage = obstack_alloc (obstack, sizeof (gdb::array_view<variant_part>));
= new (storage) gdb::array_view<variant_part> (part, 1);
struct dynamic_prop prop;
- prop.kind = PROP_VARIANT_PARTS;
- prop.data.variant_parts = prop_value;
+ prop.set_variant_parts (prop_value);
type->add_dyn_prop (DYN_PROP_VARIANT_PARTS, prop);
}
/* Decode the field name to find the offset of the
discriminant. */
ULONGEST bit_offset = 0;
- struct type *field_type = TYPE_FIELD_TYPE (type, 0);
+ struct type *field_type = type->field (0).type ();
while (name[0] >= '0' && name[0] <= '9')
{
char *tail;
++name;
bit_offset += TYPE_FIELD_BITPOS (field_type, index);
- field_type = TYPE_FIELD_TYPE (field_type, index);
+ field_type = field_type->field (index).type ();
}
/* Smash this type to be a structure type. We have to do this
((struct field *) TYPE_ZALLOC (type, 3 * sizeof (struct field)));
/* Put the discriminant at index 0. */
- TYPE_FIELD_TYPE (type, 0) = field_type;
+ type->field (0).set_type (field_type);
TYPE_FIELD_ARTIFICIAL (type, 0) = 1;
TYPE_FIELD_NAME (type, 0) = "<<discriminant>>";
SET_FIELD_BITPOS (type->field (0), bit_offset);
field at index 1 and the data-less field at index 2. */
type->field (1) = saved_field;
TYPE_FIELD_NAME (type, 1)
- = rust_last_path_segment (TYPE_FIELD_TYPE (type, 1)->name ());
- TYPE_FIELD_TYPE (type, 1)->set_name
+ = rust_last_path_segment (type->field (1).type ()->name ());
+ type->field (1).type ()->set_name
(rust_fully_qualify (&objfile->objfile_obstack, type->name (),
TYPE_FIELD_NAME (type, 1)));
name);
struct type *dataless_type = init_type (objfile, TYPE_CODE_VOID, 0,
dataless_name);
- TYPE_FIELD_TYPE (type, 2) = dataless_type;
+ type->field (2).set_type (dataless_type);
/* NAME points into the original discriminant name, which
already has the correct lifetime. */
TYPE_FIELD_NAME (type, 2) = name;
because the type has already been recorded. */
type->set_code (TYPE_CODE_STRUCT);
- struct type *field_type = TYPE_FIELD_TYPE (type, 0);
+ struct type *field_type = type->field (0).type ();
const char *variant_name
= rust_last_path_segment (field_type->name ());
TYPE_FIELD_NAME (type, 0) = variant_name;
field_type->set_name
(rust_fully_qualify (&objfile->objfile_obstack,
type->name (), variant_name));
+
+ alloc_rust_variant (&objfile->objfile_obstack, type, -1, 0, {});
}
else
{
struct type *disr_type = nullptr;
for (int i = 0; i < type->num_fields (); ++i)
{
- disr_type = TYPE_FIELD_TYPE (type, i);
+ disr_type = type->field (i).type ();
if (disr_type->code () != TYPE_CODE_STRUCT)
{
/* We need a way to find the correct discriminant given a
variant name. For convenience we build a map here. */
- struct type *enum_type = FIELD_TYPE (*disr_field);
+ struct type *enum_type = disr_field->type ();
std::unordered_map<std::string, ULONGEST> discriminant_map;
for (int i = 0; i < enum_type->num_fields (); ++i)
{
That name can be used to look up the correct
discriminant. */
const char *variant_name
- = rust_last_path_segment (TYPE_FIELD_TYPE (type, i)->name ());
+ = rust_last_path_segment (type->field (i).type ()->name ());
auto iter = discriminant_map.find (variant_name);
if (iter != discriminant_map.end ())
{
- ranges[i].low = iter->second;
- ranges[i].high = iter->second;
+ ranges[i - 1].low = iter->second;
+ ranges[i - 1].high = iter->second;
}
+ /* In Rust, each element should have the size of the
+ enclosing enum. */
+ TYPE_LENGTH (type->field (i).type ()) = TYPE_LENGTH (type);
+
/* Remove the discriminant field, if it exists. */
- struct type *sub_type = TYPE_FIELD_TYPE (type, i);
+ struct type *sub_type = type->field (i).type ();
if (sub_type->num_fields () > 0)
{
sub_type->set_num_fields (sub_type->num_fields () - 1);
}
/* Indicate that this is a variant type. */
- alloc_rust_variant (&objfile->objfile_obstack, type, 0, 1,
+ alloc_rust_variant (&objfile->objfile_obstack, type, 0, -1,
gdb::array_view<discriminant_range> (ranges,
n_fields - 1));
}
the two cases. */
if (type->num_fields () > 0
&& TYPE_FIELD_ARTIFICIAL (type, 0)
- && TYPE_FIELD_TYPE (type, 0)->code () == TYPE_CODE_PTR
- && TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type,
- 0))))
+ && type->field (0).type ()->code () == TYPE_CODE_PTR
+ && TYPE_CONST (TYPE_TARGET_TYPE (type->field (0).type ())))
buf.puts (" const");
}
}
/* DWP file .debug_{cu,tu}_index section format:
[ref: http://gcc.gnu.org/wiki/DebugFissionDWP]
+ [ref: http://dwarfstd.org/doc/DWARF5.pdf, sect 7.3.5 "DWARF Package Files"]
+
+ DWP Versions 1 & 2 are older, pre-standard format versions. The first
+ officially standard DWP format was published with DWARF v5 and is called
+ Version 5. There are no versions 3 or 4.
DWP Version 1:
---
- DWP Version 2:
+ DWP Versions 2 and 5:
- DWP Version 2 combines all the .debug_info, etc. sections into one,
+ DWP Versions 2 and 5 combine 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.
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
+ Table of Section Offsets dwp_hash_table.{v2|v5}.{section_ids,offsets}
+ Table of Section Sizes dwp_hash_table.{v2|v5}.sizes
The index section header consists of:
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:
+ refer to that section. The section identifiers for Version 2 are:
DW_SECT_INFO 1 .debug_info.dwo
DW_SECT_TYPES 2 .debug_types.dwo
DW_SECT_MACINFO 7 .debug_macinfo.dwo
DW_SECT_MACRO 8 .debug_macro.dwo
+ The section identifiers for Version 5 are:
+
+ DW_SECT_INFO_V5 1 .debug_info.dwo
+ DW_SECT_RESERVED_V5 2 --
+ DW_SECT_ABBREV_V5 3 .debug_abbrev.dwo
+ DW_SECT_LINE_V5 4 .debug_line.dwo
+ DW_SECT_LOCLISTS_V5 5 .debug_loclists.dwo
+ DW_SECT_STR_OFFSETS_V5 6 .debug_str_offsets.dwo
+ DW_SECT_MACRO_V5 7 .debug_macro.dwo
+ DW_SECT_RNGLISTS_V5 8 .debug_rnglists.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
index_ptr = index->buffer;
index_end = index_ptr + index->size;
+ /* For Version 5, the version is really 2 bytes of data & 2 bytes of padding.
+ For now it's safe to just read 4 bytes (particularly as it's difficult to
+ tell if you're dealing with Version 5 before you've read the version). */
version = read_4_bytes (dbfd, index_ptr);
index_ptr += 4;
- if (version == 2)
+ if (version == 2 || version == 5)
nr_columns = read_4_bytes (dbfd, index_ptr);
else
nr_columns = 0;
nr_slots = read_4_bytes (dbfd, index_ptr);
index_ptr += 4;
- if (version != 1 && version != 2)
+ if (version != 1 && version != 2 && version != 5)
{
error (_("Dwarf Error: unsupported DWP file version (%s)"
" [in module %s]"),
/* Exit early if the table is empty. */
if (nr_slots == 0 || nr_units == 0
- || (version == 2 && nr_columns == 0))
+ || (version == 2 && nr_columns == 0)
+ || (version == 5 && nr_columns == 0))
{
/* All must be zero. */
if (nr_slots != 0 || nr_units != 0
- || (version == 2 && nr_columns != 0))
+ || (version == 2 && nr_columns != 0)
+ || (version == 5 && nr_columns != 0))
{
complaint (_("Empty DWP but nr_slots,nr_units,nr_columns not"
" all zero [in modules %s]"),
/* It's harder to decide whether the section is too small in v1.
V1 is deprecated anyway so we punt. */
}
- else
+ else if (version == 2)
{
const gdb_byte *ids_ptr = htab->unit_table + sizeof (uint32_t) * nr_slots;
int *ids = htab->section_pool.v2.section_ids;
dwp_file->name);
}
}
+ else /* version == 5 */
+ {
+ const gdb_byte *ids_ptr = htab->unit_table + sizeof (uint32_t) * nr_slots;
+ int *ids = htab->section_pool.v5.section_ids;
+ size_t sizeof_ids = sizeof (htab->section_pool.v5.section_ids);
+ /* Reverse map for error checking. */
+ int ids_seen[DW_SECT_MAX_V5 + 1];
+
+ 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_V5_DWO_SECTIONS)
+ {
+ error (_("Dwarf Error: bad DWP hash table, too many columns"
+ " in section table [in module %s]"),
+ dwp_file->name);
+ }
+ memset (ids, 255, sizeof_ids);
+ memset (ids_seen, 255, sizeof (ids_seen));
+ for (int 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_V5)
+ {
+ 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 seen an info section. */
+ if (ids_seen[DW_SECT_INFO_V5] == -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_V5] == -1)
+ {
+ error (_("Dwarf Error: bad DWP hash table, missing DWO abbrev"
+ " section [in module %s]"),
+ dwp_file->name);
+ }
+ htab->section_pool.v5.offsets = ids_ptr + sizeof (uint32_t) * nr_columns;
+ htab->section_pool.v5.sizes
+ = htab->section_pool.v5.offsets + (sizeof (uint32_t)
+ * nr_units * nr_columns);
+ if ((htab->section_pool.v5.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;
}
return dwo_unit;
}
-/* 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. */
+/* Subroutine of create_dwo_unit_in_dwp_v2 and create_dwo_unit_in_dwp_v5 to
+ simplify them. 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 (dwarf2_per_objfile *per_objfile,
- struct dwarf2_section_info *section,
- bfd_size_type offset, bfd_size_type size)
+create_dwp_v2_or_v5_section (dwarf2_per_objfile *per_objfile,
+ struct dwarf2_section_info *section,
+ bfd_size_type offset, bfd_size_type size)
{
struct dwarf2_section_info result;
asection *sectp;
if (sectp == NULL
|| offset + size > bfd_section_size (sectp))
{
- error (_("Dwarf Error: Bad DWP V2 section info, doesn't fit"
+ error (_("Dwarf Error: Bad DWP V2 or V5 section info, doesn't fit"
" in section %s [in module %s]"),
sectp ? bfd_section_name (sectp) : "<unknown>",
objfile_name (per_objfile->objfile));
const char *kind = is_debug_types ? "TU" : "CU";
struct dwo_file *dwo_file;
struct dwo_unit *dwo_unit;
- struct virtual_v2_dwo_sections sections;
+ struct virtual_v2_or_v5_dwo_sections sections;
void **dwo_file_slot;
int i;
dwo_file->dwo_name = per_objfile->objfile->intern (virtual_dwo_name);
dwo_file->comp_dir = comp_dir;
dwo_file->sections.abbrev =
- create_dwp_v2_section (per_objfile, &dwp_file->sections.abbrev,
- sections.abbrev_offset, sections.abbrev_size);
+ create_dwp_v2_or_v5_section (per_objfile, &dwp_file->sections.abbrev,
+ sections.abbrev_offset,
+ sections.abbrev_size);
dwo_file->sections.line =
- create_dwp_v2_section (per_objfile, &dwp_file->sections.line,
- sections.line_offset, sections.line_size);
+ create_dwp_v2_or_v5_section (per_objfile, &dwp_file->sections.line,
+ sections.line_offset,
+ sections.line_size);
dwo_file->sections.loc =
- create_dwp_v2_section (per_objfile, &dwp_file->sections.loc,
- sections.loc_offset, sections.loc_size);
+ create_dwp_v2_or_v5_section (per_objfile, &dwp_file->sections.loc,
+ sections.loc_offset, sections.loc_size);
dwo_file->sections.macinfo =
- create_dwp_v2_section (per_objfile, &dwp_file->sections.macinfo,
- sections.macinfo_offset, sections.macinfo_size);
+ create_dwp_v2_or_v5_section (per_objfile, &dwp_file->sections.macinfo,
+ sections.macinfo_offset,
+ sections.macinfo_size);
dwo_file->sections.macro =
- create_dwp_v2_section (per_objfile, &dwp_file->sections.macro,
- sections.macro_offset, sections.macro_size);
+ create_dwp_v2_or_v5_section (per_objfile, &dwp_file->sections.macro,
+ sections.macro_offset,
+ sections.macro_size);
dwo_file->sections.str_offsets =
- create_dwp_v2_section (per_objfile,
- &dwp_file->sections.str_offsets,
- sections.str_offsets_offset,
- sections.str_offsets_size);
+ create_dwp_v2_or_v5_section (per_objfile,
+ &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,
dwo_unit->signature = signature;
dwo_unit->section =
XOBNEW (&per_objfile->per_bfd->obstack, struct dwarf2_section_info);
- *dwo_unit->section = create_dwp_v2_section (per_objfile,
- is_debug_types
- ? &dwp_file->sections.types
- : &dwp_file->sections.info,
- sections.info_or_types_offset,
- sections.info_or_types_size);
+ *dwo_unit->section = create_dwp_v2_or_v5_section
+ (per_objfile,
+ 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;
+}
+
+/* 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 5 files. */
+
+static struct dwo_unit *
+create_dwo_unit_in_dwp_v5 (dwarf2_per_objfile *per_objfile,
+ struct dwp_file *dwp_file,
+ uint32_t unit_index,
+ 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.get ();
+ const char *kind = is_debug_types ? "TU" : "CU";
+ struct dwo_file *dwo_file;
+ struct dwo_unit *dwo_unit;
+ struct virtual_v2_or_v5_dwo_sections sections {};
+ void **dwo_file_slot;
+
+ gdb_assert (dwp_file->version == 5);
+
+ if (dwarf_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V5 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)); */
+
+ for (int i = 0; i < dwp_htab->nr_columns; ++i)
+ {
+ uint32_t offset = read_4_bytes (dbfd,
+ dwp_htab->section_pool.v5.offsets
+ + (((unit_index - 1)
+ * dwp_htab->nr_columns
+ + i)
+ * sizeof (uint32_t)));
+ uint32_t size = read_4_bytes (dbfd,
+ dwp_htab->section_pool.v5.sizes
+ + (((unit_index - 1) * dwp_htab->nr_columns
+ + i)
+ * sizeof (uint32_t)));
+
+ switch (dwp_htab->section_pool.v5.section_ids[i])
+ {
+ case DW_SECT_ABBREV_V5:
+ sections.abbrev_offset = offset;
+ sections.abbrev_size = size;
+ break;
+ case DW_SECT_INFO_V5:
+ sections.info_or_types_offset = offset;
+ sections.info_or_types_size = size;
+ break;
+ case DW_SECT_LINE_V5:
+ sections.line_offset = offset;
+ sections.line_size = size;
+ break;
+ case DW_SECT_LOCLISTS_V5:
+ sections.loclists_offset = offset;
+ sections.loclists_size = size;
+ break;
+ case DW_SECT_MACRO_V5:
+ sections.macro_offset = offset;
+ sections.macro_size = size;
+ break;
+ case DW_SECT_RNGLISTS_V5:
+ sections.rnglists_offset = offset;
+ sections.rnglists_size = size;
+ break;
+ case DW_SECT_STR_OFFSETS_V5:
+ sections.str_offsets_offset = offset;
+ sections.str_offsets_size = size;
+ break;
+ case DW_SECT_RESERVED_V5:
+ default:
+ 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. */
+
+ std::string virtual_dwo_name =
+ string_printf ("virtual-dwo/%ld-%ld-%ld-%ld-%ld-%ld",
+ (long) (sections.abbrev_size ? sections.abbrev_offset : 0),
+ (long) (sections.line_size ? sections.line_offset : 0),
+ (long) (sections.loclists_size ? sections.loclists_offset : 0),
+ (long) (sections.str_offsets_size
+ ? sections.str_offsets_offset : 0),
+ (long) (sections.macro_size ? sections.macro_offset : 0),
+ (long) (sections.rnglists_size ? sections.rnglists_offset: 0));
+ /* Can we use an existing virtual DWO file? */
+ dwo_file_slot = lookup_dwo_file_slot (per_objfile,
+ virtual_dwo_name.c_str (),
+ comp_dir);
+ /* Create one if necessary. */
+ if (*dwo_file_slot == NULL)
+ {
+ if (dwarf_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
+ virtual_dwo_name.c_str ());
+ }
+ dwo_file = new struct dwo_file;
+ dwo_file->dwo_name = per_objfile->objfile->intern (virtual_dwo_name);
+ dwo_file->comp_dir = comp_dir;
+ dwo_file->sections.abbrev =
+ create_dwp_v2_or_v5_section (per_objfile,
+ &dwp_file->sections.abbrev,
+ sections.abbrev_offset,
+ sections.abbrev_size);
+ dwo_file->sections.line =
+ create_dwp_v2_or_v5_section (per_objfile,
+ &dwp_file->sections.line,
+ sections.line_offset, sections.line_size);
+ dwo_file->sections.macro =
+ create_dwp_v2_or_v5_section (per_objfile,
+ &dwp_file->sections.macro,
+ sections.macro_offset,
+ sections.macro_size);
+ dwo_file->sections.loclists =
+ create_dwp_v2_or_v5_section (per_objfile,
+ &dwp_file->sections.loclists,
+ sections.loclists_offset,
+ sections.loclists_size);
+ dwo_file->sections.rnglists =
+ create_dwp_v2_or_v5_section (per_objfile,
+ &dwp_file->sections.rnglists,
+ sections.rnglists_offset,
+ sections.rnglists_size);
+ dwo_file->sections.str_offsets =
+ create_dwp_v2_or_v5_section (per_objfile,
+ &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 (dwarf_read_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
+ virtual_dwo_name.c_str ());
+ }
+ dwo_file = (struct dwo_file *) *dwo_file_slot;
+ }
+
+ dwo_unit = OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack, struct dwo_unit);
+ dwo_unit->dwo_file = dwo_file;
+ dwo_unit->signature = signature;
+ dwo_unit->section
+ = XOBNEW (&per_objfile->per_bfd->obstack, struct dwarf2_section_info);
+ *dwo_unit->section = create_dwp_v2_or_v5_section (per_objfile,
+ &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;
unit_index, comp_dir,
signature, is_debug_types);
}
- else
+ else if (dwp_file->version == 2)
{
*slot = create_dwo_unit_in_dwp_v2 (per_objfile, dwp_file,
unit_index, comp_dir,
signature, is_debug_types);
}
+ else /* version == 5 */
+ {
+ *slot = create_dwo_unit_in_dwp_v5 (per_objfile, dwp_file,
+ unit_index, comp_dir,
+ signature, is_debug_types);
+ }
return (struct dwo_unit *) *slot;
}
if (signature_in_table == 0)
dwo_sections->macro.s.section = sectp;
dwo_sections->macro.size = bfd_section_size (sectp);
}
+ else if (section_is_p (sectp->name, &names->rnglists_dwo))
+ {
+ dwo_sections->rnglists.s.section = sectp;
+ dwo_sections->rnglists.size = bfd_section_size (sectp);
+ }
else if (section_is_p (sectp->name, &names->str_dwo))
{
dwo_sections->str.s.section = sectp;
create_cus_hash_table (per_objfile, cu, *dwo_file, dwo_file->sections.info,
dwo_file->cus);
- create_debug_types_hash_table (per_objfile, dwo_file.get (),
- dwo_file->sections.types, dwo_file->tus);
+ if (cu->per_cu->dwarf_version < 5)
+ {
+ create_debug_types_hash_table (per_objfile, dwo_file.get (),
+ dwo_file->sections.types, dwo_file->tus);
+ }
+ else
+ {
+ create_debug_type_hash_table (per_objfile, dwo_file.get (),
+ &dwo_file->sections.info, dwo_file->tus,
+ rcuh_kind::TYPE);
+ }
if (dwarf_read_debug)
fprintf_unfiltered (gdb_stdlog, "DWO file found: %s\n", dwo_name);
/* 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. */
+ have version 1 or 2 or 5 until we parse the cu_index/tu_index sections. */
static void
dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
}
}
+/* This function is mapped across the sections and remembers the offset and
+ size of each of the DWP version 5 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 or 5 until we parse the cu_index/tu_index sections. */
+
+static void
+dwarf2_locate_v5_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
+{
+ struct dwp_file *dwp_file = (struct 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.section = sectp;
+ dwp_file->sections.abbrev.size = bfd_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->info_dwo))
+ {
+ dwp_file->sections.info.s.section = sectp;
+ dwp_file->sections.info.size = bfd_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->line_dwo))
+ {
+ dwp_file->sections.line.s.section = sectp;
+ dwp_file->sections.line.size = bfd_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->loclists_dwo))
+ {
+ dwp_file->sections.loclists.s.section = sectp;
+ dwp_file->sections.loclists.size = bfd_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->macro_dwo))
+ {
+ dwp_file->sections.macro.s.section = sectp;
+ dwp_file->sections.macro.size = bfd_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->rnglists_dwo))
+ {
+ dwp_file->sections.rnglists.s.section = sectp;
+ dwp_file->sections.rnglists.size = bfd_section_size (sectp);
+ }
+ else if (section_is_p (sectp->name, &names->str_offsets_dwo))
+ {
+ dwp_file->sections.str_offsets.s.section = sectp;
+ dwp_file->sections.str_offsets.size = bfd_section_size (sectp);
+ }
+}
+
/* Hash function for dwp_file loaded CUs/TUs. */
static hashval_t
bfd_map_over_sections (dwp_file->dbfd.get (),
dwarf2_locate_v2_dwp_sections,
dwp_file.get ());
+ else if (dwp_file->version == 5)
+ bfd_map_over_sections (dwp_file->dbfd.get (),
+ dwarf2_locate_v5_dwp_sections,
+ dwp_file.get ());
+
dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table ();
dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table ();
template <typename Callback>
static bool
dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
- Callback &&callback)
+ dwarf_tag tag, Callback &&callback)
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
struct objfile *objfile = per_objfile->objfile;
const gdb_byte *buffer;
CORE_ADDR baseaddr;
bool overflow = false;
+ ULONGEST addr_index;
+ struct dwarf2_section_info *rnglists_section;
base = cu->base_address;
+ rnglists_section = cu_debug_rnglists_section (cu, tag);
+ rnglists_section->read (objfile);
- per_objfile->per_bfd->rnglists.read (objfile);
- if (offset >= per_objfile->per_bfd->rnglists.size)
+ if (offset >= rnglists_section->size)
{
complaint (_("Offset %d out of bounds for DW_AT_ranges attribute"),
offset);
return false;
}
- buffer = per_objfile->per_bfd->rnglists.buffer + offset;
+ buffer = rnglists_section->buffer + offset;
baseaddr = objfile->text_section_offset ();
{
/* Initialize it due to a false compiler warning. */
CORE_ADDR range_beginning = 0, range_end = 0;
- const gdb_byte *buf_end = (per_objfile->per_bfd->rnglists.buffer
- + per_objfile->per_bfd->rnglists.size);
+ const gdb_byte *buf_end = (rnglists_section->buffer
+ + rnglists_section->size);
unsigned int bytes_read;
if (buffer == buf_end)
base = cu->header.read_address (obfd, buffer, &bytes_read);
buffer += bytes_read;
break;
+ case DW_RLE_base_addressx:
+ addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+ buffer += bytes_read;
+ base = read_addr_index (cu, addr_index);
+ break;
case DW_RLE_start_length:
if (buffer + cu->header.addr_size > buf_end)
{
break;
}
break;
+ case DW_RLE_startx_length:
+ addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+ buffer += bytes_read;
+ range_beginning = read_addr_index (cu, addr_index);
+ if (buffer > buf_end)
+ {
+ overflow = true;
+ break;
+ }
+ range_end = (range_beginning
+ + read_unsigned_leb128 (obfd, buffer, &bytes_read));
+ buffer += bytes_read;
+ break;
case DW_RLE_offset_pair:
range_beginning = read_unsigned_leb128 (obfd, buffer, &bytes_read);
buffer += bytes_read;
range_end = cu->header.read_address (obfd, buffer, &bytes_read);
buffer += bytes_read;
break;
+ case DW_RLE_startx_endx:
+ addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+ buffer += bytes_read;
+ range_beginning = read_addr_index (cu, addr_index);
+ if (buffer > buf_end)
+ {
+ overflow = true;
+ break;
+ }
+ addr_index = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+ buffer += bytes_read;
+ range_end = read_addr_index (cu, addr_index);
+ break;
default:
complaint (_("Invalid .debug_rnglists data (no base address)"));
return false;
if (rlet == DW_RLE_base_address)
continue;
- if (!base.has_value ())
- {
- /* We have no valid base address for the ranges
- data. */
- complaint (_("Invalid .debug_rnglists data (no base address)"));
- return false;
- }
-
if (range_beginning > range_end)
{
/* Inverted range entries are invalid. */
if (range_beginning == range_end)
continue;
- range_beginning += *base;
- range_end += *base;
+ /* Only DW_RLE_offset_pair needs the base address added. */
+ if (rlet == DW_RLE_offset_pair)
+ {
+ if (!base.has_value ())
+ {
+ /* We have no valid base address for the DW_RLE_offset_pair. */
+ complaint (_("Invalid .debug_rnglists data (no base address for "
+ "DW_RLE_offset_pair)"));
+ return false;
+ }
+
+ range_beginning += *base;
+ range_end += *base;
+ }
/* A not-uncommon case of bad debug info.
Don't pollute the addrmap with bad data. */
template <typename Callback>
static int
-dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
+dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, dwarf_tag tag,
Callback &&callback)
{
dwarf2_per_objfile *per_objfile = cu->per_objfile;
CORE_ADDR baseaddr;
if (cu_header->version >= 5)
- return dwarf2_rnglists_process (offset, cu, callback);
+ return dwarf2_rnglists_process (offset, cu, tag, callback);
base = cu->base_address;
static int
dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
CORE_ADDR *high_return, struct dwarf2_cu *cu,
- dwarf2_psymtab *ranges_pst)
+ dwarf2_psymtab *ranges_pst, dwarf_tag tag)
{
struct objfile *objfile = cu->per_objfile->objfile;
struct gdbarch *gdbarch = objfile->arch ();
CORE_ADDR high = 0;
int retval;
- retval = dwarf2_ranges_process (offset, cu,
+ retval = dwarf2_ranges_process (offset, cu, tag,
[&] (CORE_ADDR range_beginning, CORE_ADDR range_end)
{
if (ranges_pst != NULL)
{
/* DW_AT_rnglists_base does not apply to DIEs from the DWO skeleton.
We take advantage of the fact that DW_AT_ranges does not appear
- in DW_TAG_compile_unit of DWO files. */
- int need_ranges_base = die->tag != DW_TAG_compile_unit;
+ in DW_TAG_compile_unit of DWO files.
+
+ Attributes of the form DW_FORM_rnglistx have already had their
+ value changed by read_rnglist_index and already include
+ DW_AT_rnglists_base, so don't need to add the ranges base,
+ either. */
+ int need_ranges_base = (die->tag != DW_TAG_compile_unit
+ && attr->form != DW_FORM_rnglistx);
unsigned int ranges_offset = (DW_UNSND (attr)
+ (need_ranges_base
? cu->ranges_base
/* Value of the DW_AT_ranges attribute is the offset in the
.debug_ranges section. */
- if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst))
+ if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst,
+ die->tag))
return PC_BOUNDS_INVALID;
/* Found discontinuous range of addresses. */
ret = PC_BOUNDS_RANGES;
{
/* DW_AT_rnglists_base does not apply to DIEs from the DWO skeleton.
We take advantage of the fact that DW_AT_ranges does not appear
- in DW_TAG_compile_unit of DWO files. */
- int need_ranges_base = die->tag != DW_TAG_compile_unit;
+ in DW_TAG_compile_unit of DWO files.
+
+ Attributes of the form DW_FORM_rnglistx have already had their
+ value changed by read_rnglist_index and already include
+ DW_AT_rnglists_base, so don't need to add the ranges base,
+ either. */
+ int need_ranges_base = (die->tag != DW_TAG_compile_unit
+ && attr->form != DW_FORM_rnglistx);
/* The value of the DW_AT_ranges attribute is the offset of the
address range list in the .debug_ranges section. */
+ (need_ranges_base ? cu->ranges_base : 0));
std::vector<blockrange> blockvec;
- dwarf2_ranges_process (offset, cu,
+ dwarf2_ranges_process (offset, cu, die->tag,
[&] (CORE_ADDR start, CORE_ADDR end)
{
start += baseaddr;
/* Data member other than a C++ static data member. */
/* Get type of field. */
- fp->type = die_type (die, cu);
+ fp->set_type (die_type (die, cu));
SET_FIELD_BITPOS (*fp, 0);
the bit field must be inferred from the type
attribute of the data member containing the
bit field. */
- anonymous_size = TYPE_LENGTH (fp->type);
+ anonymous_size = TYPE_LENGTH (fp->type ());
}
SET_FIELD_BITPOS (*fp,
(FIELD_BITPOS (*fp)
/* The name is already allocated along with this objfile, so we don't
need to duplicate it for the type. */
SET_FIELD_PHYSNAME (*fp, physname ? physname : "");
- FIELD_TYPE (*fp) = die_type (die, cu);
+ fp->set_type (die_type (die, cu));
FIELD_NAME (*fp) = fieldname;
}
else if (die->tag == DW_TAG_inheritance)
/* C++ base class field. */
handle_data_member_location (die, cu, fp);
FIELD_BITSIZE (*fp) = 0;
- FIELD_TYPE (*fp) = die_type (die, cu);
- FIELD_NAME (*fp) = fp->type->name ();
+ fp->set_type (die_type (die, cu));
+ FIELD_NAME (*fp) = fp->type ()->name ();
}
else
gdb_assert_not_reached ("missing case in dwarf2_add_field");
{
result.discriminant_index = iter->second;
result.is_unsigned
- = TYPE_UNSIGNED (FIELD_TYPE
- (fi->fields[result.discriminant_index].field));
+ = TYPE_UNSIGNED (fi->fields[result.discriminant_index].field.type ());
}
size_t n = builder.variants.size ();
fip->variant_parts);
struct dynamic_prop prop;
- prop.kind = PROP_VARIANT_PARTS;
- prop.data.variant_parts
- = ((gdb::array_view<variant_part> *)
- obstack_copy (&objfile->objfile_obstack, &parts, sizeof (parts)));
+ prop.set_variant_parts ((gdb::array_view<variant_part> *)
+ obstack_copy (&objfile->objfile_obstack, &parts,
+ sizeof (parts)));
type->add_dyn_prop (DYN_PROP_VARIANT_PARTS, prop);
}
else
{
fnp->fcontext
- = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (this_type, 0));
+ = TYPE_TARGET_TYPE (this_type->field (0).type ());
}
}
}
return;
/* Find the type of the method. */
- pfn_type = TYPE_FIELD_TYPE (type, 0);
+ pfn_type = type->field (0).type ();
if (pfn_type == NULL
|| pfn_type->code () != TYPE_CODE_PTR
|| TYPE_TARGET_TYPE (pfn_type)->code () != TYPE_CODE_FUNC)
/* Look for the "this" argument. */
pfn_type = TYPE_TARGET_TYPE (pfn_type);
if (pfn_type->num_fields () == 0
- /* || TYPE_FIELD_TYPE (pfn_type, 0) == NULL */
- || TYPE_FIELD_TYPE (pfn_type, 0)->code () != TYPE_CODE_PTR)
+ /* || pfn_type->field (0).type () == NULL */
+ || pfn_type->field (0).type ()->code () != TYPE_CODE_PTR)
return;
- self_type = TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (pfn_type, 0));
+ self_type = TYPE_TARGET_TYPE (pfn_type->field (0).type ());
new_type = alloc_type (objfile);
smash_to_method_type (new_type, self_type, TYPE_TARGET_TYPE (pfn_type),
pfn_type->fields (), pfn_type->num_fields (),
{
struct dynamic_prop low_bound;
- low_bound.kind = PROP_CONST;
- low_bound.data.const_val = 1;
+ low_bound.set_const_val (1);
range_type = create_range_type (NULL, index_type, &low_bound, &prop, 0);
}
char_type = language_string_char_type (cu->language_defn, gdbarch);
/* TYPE_FIELD_TYPE must never be NULL. Pre-fill the array to ensure it
even if we error out during the parameters reading below. */
for (iparams = 0; iparams < nparams; iparams++)
- TYPE_FIELD_TYPE (ftype, iparams) = void_type;
+ ftype->field (iparams).set_type (void_type);
iparams = 0;
child_die = die->child;
arg_type, 0);
}
- TYPE_FIELD_TYPE (ftype, iparams) = arg_type;
+ ftype->field (iparams).set_type (arg_type);
iparams++;
}
child_die = child_die->sibling;
baton->locexpr.is_reference = false;
break;
}
- prop->data.baton = baton;
- prop->kind = PROP_LOCEXPR;
- gdb_assert (prop->data.baton != NULL);
+
+ prop->set_locexpr (baton);
+ gdb_assert (prop->baton () != NULL);
}
else if (attr->form_is_ref ())
{
baton = XOBNEW (obstack, struct dwarf2_property_baton);
baton->property_type = die_type (target_die, target_cu);
fill_in_loclist_baton (cu, &baton->loclist, target_attr);
- prop->data.baton = baton;
- prop->kind = PROP_LOCLIST;
- gdb_assert (prop->data.baton != NULL);
+ prop->set_loclist (baton);
+ gdb_assert (prop->baton () != NULL);
}
else if (target_attr->form_is_block ())
{
baton->locexpr.size = DW_BLOCK (target_attr)->size;
baton->locexpr.data = DW_BLOCK (target_attr)->data;
baton->locexpr.is_reference = true;
- prop->data.baton = baton;
- prop->kind = PROP_LOCEXPR;
- gdb_assert (prop->data.baton != NULL);
+ prop->set_locexpr (baton);
+ gdb_assert (prop->baton () != NULL);
}
else
{
target_cu);
baton->offset_info.offset = offset;
baton->offset_info.type = die_type (target_die, target_cu);
- prop->data.baton = baton;
- prop->kind = PROP_ADDR_OFFSET;
+ prop->set_addr_offset (baton);
break;
}
}
}
else if (attr->form_is_constant ())
- {
- prop->data.const_val = attr->constant_value (0);
- prop->kind = PROP_CONST;
- }
+ prop->set_const_val (attr->constant_value (0));
else
{
dwarf2_invalid_attrib_class_complaint (dwarf_form_name (attr->form),
if (range_type)
return range_type;
- low.kind = PROP_CONST;
- high.kind = PROP_CONST;
- high.data.const_val = 0;
+ high.set_const_val (0);
/* Set LOW_DEFAULT_IS_VALID if current language and DWARF version allow
omitting DW_AT_lower_bound. */
{
case language_c:
case language_cplus:
- low.data.const_val = 0;
+ low.set_const_val (0);
low_default_is_valid = 1;
break;
case language_fortran:
- low.data.const_val = 1;
+ low.set_const_val (1);
low_default_is_valid = 1;
break;
case language_d:
case language_objc:
case language_rust:
- low.data.const_val = 0;
+ low.set_const_val (0);
low_default_is_valid = (cu->header.version >= 4);
break;
case language_ada:
case language_m2:
case language_pascal:
- low.data.const_val = 1;
+ low.set_const_val (1);
low_default_is_valid = (cu->header.version >= 4);
break;
default:
- low.data.const_val = 0;
+ low.set_const_val (0);
low_default_is_valid = 0;
break;
}
if (attr_to_dynamic_prop (attr, die, cu, &high, base_type))
{
/* If bounds are constant do the final calculation here. */
- if (low.kind == PROP_CONST && high.kind == PROP_CONST)
- high.data.const_val = low.data.const_val + high.data.const_val - 1;
+ if (low.kind () == PROP_CONST && high.kind () == PROP_CONST)
+ high.set_const_val (low.const_val () + high.const_val () - 1);
else
high_bound_is_count = 1;
}
the base type is signed. */
negative_mask =
-((ULONGEST) 1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1));
- if (low.kind == PROP_CONST
- && !TYPE_UNSIGNED (base_type) && (low.data.const_val & negative_mask))
- low.data.const_val |= negative_mask;
- if (high.kind == PROP_CONST
- && !TYPE_UNSIGNED (base_type) && (high.data.const_val & negative_mask))
- high.data.const_val |= negative_mask;
+ if (low.kind () == PROP_CONST
+ && !TYPE_UNSIGNED (base_type) && (low.const_val () & negative_mask))
+ low.set_const_val (low.const_val () | negative_mask);
+ if (high.kind () == PROP_CONST
+ && !TYPE_UNSIGNED (base_type) && (high.const_val () & negative_mask))
+ high.set_const_val (high.const_val () | negative_mask);
/* Check for bit and byte strides. */
struct dynamic_prop byte_stride_prop;
range_type = create_range_type (NULL, orig_base_type, &low, &high, bias);
if (high_bound_is_count)
- TYPE_RANGE_DATA (range_type)->flag_upper_bound_is_count = 1;
+ range_type->bounds ()->flag_upper_bound_is_count = 1;
/* Ada expects an empty array on no boundary attributes. */
if (attr == NULL && cu->language != language_ada)
- TYPE_HIGH_BOUND_KIND (range_type) = PROP_UNDEFINED;
+ range_type->bounds ()->high.set_undefined ();
name = dwarf2_name (die, cu);
if (name)
auto maybe_addr_base = die->addr_base ();
if (maybe_addr_base.has_value ())
cu->addr_base = *maybe_addr_base;
+
+ attr = die->attr (DW_AT_rnglists_base);
+ if (attr != nullptr)
+ cu->ranges_base = DW_UNSND (attr);
+
for (int index : indexes_that_need_reprocess)
- read_attribute_reprocess (reader, &die->attrs[index]);
+ read_attribute_reprocess (reader, &die->attrs[index], die->tag);
*diep = die;
return info_ptr;
}
already been read at this point, so there is no need to wait until
the loop terminates to do the reprocessing. */
if (need_reprocess)
- read_attribute_reprocess (reader, &attr);
+ read_attribute_reprocess (reader, &attr, tag);
/* Store the data if it is of an attribute we want to keep in a
partial symbol table. */
switch (attr.name)
case DW_AT_ranges:
{
- /* It would be nice to reuse dwarf2_get_pc_bounds here,
- but that requires a full DIE, so instead we just
- reimplement it. */
- int need_ranges_base = tag != DW_TAG_compile_unit;
+ /* DW_AT_rnglists_base does not apply to DIEs from the DWO
+ skeleton. We take advantage of the fact the DW_AT_ranges
+ does not appear in DW_TAG_compile_unit of DWO files.
+
+ Attributes of the form DW_FORM_rnglistx have already had
+ their value changed by read_rnglist_index and already
+ include DW_AT_rnglists_base, so don't need to add the ranges
+ base, either. */
+ int need_ranges_base = (tag != DW_TAG_compile_unit
+ && attr.form != DW_FORM_rnglistx);
unsigned int ranges_offset = (DW_UNSND (&attr)
+ (need_ranges_base
? cu->ranges_base
/* Value of the DW_AT_ranges attribute is the offset in the
.debug_ranges section. */
if (dwarf2_ranges_read (ranges_offset, &lowpc, &highpc, cu,
- nullptr))
+ nullptr, tag))
has_pc_info = 1;
}
break;
}
if (pd == NULL)
- internal_error (__FILE__, __LINE__,
- _("could not find partial DIE %s "
- "in cache [from module %s]\n"),
+ error (_("Dwarf Error: Cannot not find DIE at %s [from module %s]\n"),
sect_offset_str (sect_off), bfd_get_filename (objfile->obfd));
return { cu, pd };
}
&& child_pdi->linkage_name != NULL)
{
gdb::unique_xmalloc_ptr<char> actual_class_name
- (language_class_name_from_physname (cu->language_defn,
- child_pdi->linkage_name));
+ (cu->language_defn->class_name_from_physname
+ (child_pdi->linkage_name));
if (actual_class_name != NULL)
{
struct objfile *objfile = cu->per_objfile->objfile;
fixup_called = 1;
}
-/* Read the .debug_loclists header contents from the given SECTION in the
- HEADER. */
+/* Read the .debug_loclists or .debug_rnglists header (they are the same format)
+ contents from the given SECTION in the HEADER. */
static void
-read_loclist_header (struct loclist_header *header,
- struct dwarf2_section_info *section)
+read_loclists_rnglists_header (struct loclists_rnglists_header *header,
+ struct dwarf2_section_info *section)
{
unsigned int bytes_read;
bfd *abfd = section->get_bfd_owner ();
if (section->buffer == NULL)
complaint (_("DW_FORM_loclistx used without .debug_loclists "
"section [in module %s]"), objfile_name (objfile));
- struct loclist_header header;
- read_loclist_header (&header, section);
+ struct loclists_rnglists_header header;
+ read_loclists_rnglists_header (&header, section);
if (loclist_index >= header.offset_entry_count)
complaint (_("DW_FORM_loclistx pointing outside of "
".debug_loclists offset array [in module %s]"),
return bfd_get_64 (abfd, info_ptr) + loclist_base;
}
+/* Given a DW_FORM_rnglistx value RNGLIST_INDEX, fetch the offset from the
+ array of offsets in the .debug_rnglists section. */
+static CORE_ADDR
+read_rnglist_index (struct dwarf2_cu *cu, ULONGEST rnglist_index,
+ dwarf_tag tag)
+{
+ struct dwarf2_per_objfile *dwarf2_per_objfile = cu->per_objfile;
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ bfd *abfd = objfile->obfd;
+ ULONGEST rnglist_header_size =
+ (cu->header.initial_length_size == 4 ? RNGLIST_HEADER_SIZE32
+ : RNGLIST_HEADER_SIZE64);
+ ULONGEST rnglist_base =
+ (cu->dwo_unit != nullptr) ? rnglist_header_size : cu->ranges_base;
+ ULONGEST start_offset =
+ rnglist_base + rnglist_index * cu->header.offset_size;
+
+ /* Get rnglists section. */
+ struct dwarf2_section_info *section = cu_debug_rnglists_section (cu, tag);
+
+ /* Read the rnglists section content. */
+ section->read (objfile);
+ if (section->buffer == nullptr)
+ error (_("DW_FORM_rnglistx used without .debug_rnglists section "
+ "[in module %s]"),
+ objfile_name (objfile));
+
+ /* Verify the rnglist index is valid. */
+ struct loclists_rnglists_header header;
+ read_loclists_rnglists_header (&header, section);
+ if (rnglist_index >= header.offset_entry_count)
+ error (_("DW_FORM_rnglistx index pointing outside of "
+ ".debug_rnglists offset array [in module %s]"),
+ objfile_name (objfile));
+
+ /* Validate that the offset is within the section's range. */
+ if (start_offset >= section->size)
+ error (_("DW_FORM_rnglistx pointing outside of "
+ ".debug_rnglists section [in module %s]"),
+ objfile_name (objfile));
+
+ /* Validate that reading won't go beyond the end of the section. */
+ if (start_offset + cu->header.offset_size > rnglist_base + section->size)
+ error (_("Reading DW_FORM_rnglistx index beyond end of"
+ ".debug_rnglists section [in module %s]"),
+ objfile_name (objfile));
+
+ const gdb_byte *info_ptr = section->buffer + start_offset;
+
+ if (cu->header.offset_size == 4)
+ return read_4_bytes (abfd, info_ptr) + rnglist_base;
+ else
+ return read_8_bytes (abfd, info_ptr) + rnglist_base;
+}
+
/* Process the attributes that had to be skipped in the first round. These
attributes are the ones that need str_offsets_base or addr_base attributes.
They could not have been processed in the first round, because at the time
the values of str_offsets_base or addr_base may not have been known. */
static void
read_attribute_reprocess (const struct die_reader_specs *reader,
- struct attribute *attr)
+ struct attribute *attr, dwarf_tag tag)
{
struct dwarf2_cu *cu = reader->cu;
switch (attr->form)
case DW_FORM_loclistx:
DW_UNSND (attr) = read_loclist_index (cu, DW_UNSND (attr));
break;
+ case DW_FORM_rnglistx:
+ DW_UNSND (attr) = read_rnglist_index (cu, DW_UNSND (attr), tag);
+ break;
case DW_FORM_strx:
case DW_FORM_strx1:
case DW_FORM_strx2:
DW_SND (attr) = read_signed_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
- case DW_FORM_udata:
case DW_FORM_rnglistx:
+ *need_reprocess = true;
+ /* FALLTHROUGH */
+ case DW_FORM_udata:
DW_UNSND (attr) = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
break;
we're processing the end of a sequence. */
void record_line (bool end_sequence);
- /* Check ADDRESS is zero and less than UNRELOCATED_LOWPC and if true
+ /* Check ADDRESS is -1, or zero and less than UNRELOCATED_LOWPC, and if true
nop-out rest of the lines in this sequence. */
void check_line_address (struct dwarf2_cu *cu,
const gdb_byte *line_ptr,
bool file_changed
= m_last_subfile != m_cu->get_builder ()->get_current_subfile ();
bool ignore_this_line
- = (file_changed && !end_sequence && m_last_address == m_address
- && !m_is_stmt && m_stmt_at_address);
+ = ((file_changed && !end_sequence && m_last_address == m_address
+ && !m_is_stmt && m_stmt_at_address)
+ || (!end_sequence && m_line == 0));
if ((file_changed && !ignore_this_line) || end_sequence)
{
const gdb_byte *line_ptr,
CORE_ADDR unrelocated_lowpc, CORE_ADDR address)
{
- /* If ADDRESS < UNRELOCATED_LOWPC then it's not a usable value, it's outside
- the pc range of the CU. However, we restrict the test to only ADDRESS
- values of zero to preserve GDB's previous behaviour which is to handle
- the specific case of a function being GC'd by the linker. */
+ /* Linkers resolve a symbolic relocation referencing a GC'd function to 0 or
+ -1. If ADDRESS is 0, ignoring the opcode will err if the text section is
+ located at 0x0. In this case, additionally check that if
+ ADDRESS < UNRELOCATED_LOWPC. */
- if (address == 0 && address < unrelocated_lowpc)
+ if ((address == 0 && address < unrelocated_lowpc)
+ || address == (CORE_ADDR) -1)
{
/* This line table is for a function which has been
GCd by the linker. Ignore it. PR gdb/12528 */
extended_end = line_ptr + extended_len;
extended_op = read_1_byte (abfd, line_ptr);
line_ptr += 1;
+ if (DW_LNE_lo_user <= extended_op
+ && extended_op <= DW_LNE_hi_user)
+ {
+ /* Vendor extension, ignore. */
+ line_ptr = extended_end;
+ break;
+ }
switch (extended_op)
{
case DW_LNE_end_sequence:
if (linkage_name != NULL)
{
gdb::unique_xmalloc_ptr<char> actual_name
- (language_class_name_from_physname (cu->language_defn,
- linkage_name));
+ (cu->language_defn->class_name_from_physname (linkage_name));
const char *name = NULL;
if (actual_name != NULL)
dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
dwarf2_per_cu_data *per_cu,
dwarf2_per_objfile *per_objfile,
- CORE_ADDR (*get_frame_pc) (void *baton),
- void *baton, bool resolve_abstract_p)
+ gdb::function_view<CORE_ADDR ()> get_frame_pc,
+ bool resolve_abstract_p)
{
struct die_info *die;
struct attribute *attr;
&& (per_objfile->per_bfd->abstract_to_concrete.find (die->sect_off)
!= per_objfile->per_bfd->abstract_to_concrete.end ()))
{
- CORE_ADDR pc = (*get_frame_pc) (baton);
+ CORE_ADDR pc = get_frame_pc ();
CORE_ADDR baseaddr = objfile->text_section_offset ();
struct gdbarch *gdbarch = objfile->arch ();
else if (attr->form_is_section_offset ())
{
struct dwarf2_loclist_baton loclist_baton;
- CORE_ADDR pc = (*get_frame_pc) (baton);
+ CORE_ADDR pc = get_frame_pc ();
size_t size;
fill_in_loclist_baton (cu, &loclist_baton, attr);
dwarf2_fetch_die_loc_cu_off (cu_offset offset_in_cu,
dwarf2_per_cu_data *per_cu,
dwarf2_per_objfile *per_objfile,
- CORE_ADDR (*get_frame_pc) (void *baton),
- void *baton)
+ gdb::function_view<CORE_ADDR ()> get_frame_pc)
{
sect_offset sect_off = per_cu->sect_off + to_underlying (offset_in_cu);
return dwarf2_fetch_die_loc_sect_off (sect_off, per_cu, per_objfile,
- get_frame_pc, baton);
+ get_frame_pc);
}
/* Write a constant of a given type as target-ordered bytes into
: &per_objfile->per_bfd->loc);
}
+/* Return the .debug_rnglists section to use for CU. */
+static struct dwarf2_section_info *
+cu_debug_rnglists_section (struct dwarf2_cu *cu, dwarf_tag tag)
+{
+ if (cu->header.version < 5)
+ error (_(".debug_rnglists section cannot be used in DWARF %d"),
+ cu->header.version);
+ struct dwarf2_per_objfile *dwarf2_per_objfile = cu->per_objfile;
+
+ /* Make sure we read the .debug_rnglists section from the file that
+ contains the DW_AT_ranges attribute we are reading. Normally that
+ would be the .dwo file, if there is one. However for DW_TAG_compile_unit
+ or DW_TAG_skeleton unit, we always want to read from objfile/linked
+ program. */
+ if (cu->dwo_unit != nullptr
+ && tag != DW_TAG_compile_unit
+ && tag != DW_TAG_skeleton_unit)
+ {
+ struct dwo_sections *sections = &cu->dwo_unit->dwo_file->sections;
+
+ if (sections->rnglists.size > 0)
+ return §ions->rnglists;
+ else
+ error (_(".debug_rnglists section is missing from .dwo file."));
+ }
+ return &dwarf2_per_objfile->per_bfd->rnglists;
+}
+
/* A helper function that fills in a dwarf2_loclist_baton. */
static void
/* Read DW_AT_allocated and set in type. */
attr = dwarf2_attr (die, DW_AT_allocated, cu);
- if (attr != NULL && attr->form_is_block ())
+ if (attr != NULL)
{
struct type *prop_type = cu->addr_sized_int_type (false);
if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type))
type->add_dyn_prop (DYN_PROP_ALLOCATED, prop);
}
- else if (attr != NULL)
- {
- complaint (_("DW_AT_allocated has the wrong form (%s) at DIE %s"),
- (attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
- sect_offset_str (die->sect_off));
- }
/* Read DW_AT_associated and set in type. */
attr = dwarf2_attr (die, DW_AT_associated, cu);
- if (attr != NULL && attr->form_is_block ())
+ if (attr != NULL)
{
struct type *prop_type = cu->addr_sized_int_type (false);
if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type))
type->add_dyn_prop (DYN_PROP_ASSOCIATED, prop);
}
- else if (attr != NULL)
- {
- complaint (_("DW_AT_associated has the wrong form (%s) at DIE %s"),
- (attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
- sect_offset_str (die->sect_off));
- }
/* Read DW_AT_data_location and set in type. */
attr = dwarf2_attr (die, DW_AT_data_location, cu);