Revert past commits

I accidentally pushed my work-in-progress branch... revert that.  Sorry
for the noise :(.

The list of commits reverted are:

    ae2a50a9ae15 attempt to revamp to the CU/TU list
    e9386435c94f gdb/dwarf: print DWARF CUs/TUs in "maint print objfiles"
    6cbd64aa3eb0 gdb/dwarf: add dwarf_source_language_name
    32a187da7622 libiberty: move DW_LANG_* definitions to dwarf2.def
    b3fa38aef59d gdb/dwarf: move index unit vectors to debug names reader and use them
    30ba74418982 gdb/dwarf: track comp and type units count
    bedb4e09f292 gdb/dwarf: remove unnecessary braces
    b4f18de12c77 gdb/dwarf: use ranged for loop in some pots

Change-Id: I80aed2847025f5b15c16c997680783b39858a703
This commit is contained in:
Simon Marchi 2025-03-10 16:14:35 -04:00
parent ae2a50a9ae
commit c19c928f7b
17 changed files with 419 additions and 651 deletions

View File

@ -696,7 +696,13 @@ struct cooked_index_functions : public dwarf2_base_index_functions
dwarf2_base_index_functions::print_stats (objfile, print_bcache);
}
void dump (struct objfile *objfile) override;
void dump (struct objfile *objfile) override
{
cooked_index *index = wait (objfile, true);
gdb_printf ("Cooked index in use:\n");
gdb_printf ("\n");
index->dump (objfile->arch ());
}
void expand_all_symtabs (struct objfile *objfile) override
{

View File

@ -84,17 +84,18 @@ tag_can_have_linkage_name (enum dwarf_tag tag)
cutu_reader *
cooked_indexer::ensure_cu_exists (cutu_reader *reader,
dwarf2_per_objfile *per_objfile,
const dwarf2_section_info &section,
sect_offset sect_off, bool for_scanning)
sect_offset sect_off, bool is_dwz,
bool for_scanning)
{
/* Lookups for type unit references are always in the CU, and
cross-CU references will crash. */
if (reader->cu ()->per_cu->section == &section
if (reader->cu ()->per_cu->is_dwz == is_dwz
&& reader->cu ()->header.offset_in_cu_p (sect_off))
return reader;
dwarf2_per_cu *per_cu
= dwarf2_find_containing_unit (section, sect_off, per_objfile->per_bfd);
= dwarf2_find_containing_comp_unit (sect_off, is_dwz,
per_objfile->per_bfd);
/* When scanning, we only want to visit a given CU a single time.
Doing this check here avoids self-imports as well. */
@ -147,8 +148,10 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
bool *is_enum_class,
bool for_specification)
{
bool origin_is_dwz = false;
bool is_declaration = false;
std::optional<section_and_offset> origin;
sect_offset origin_offset {};
std::optional<unrelocated_addr> low_pc;
std::optional<unrelocated_addr> high_pc;
bool high_pc_relative = false;
@ -215,8 +218,8 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
case DW_AT_specification:
case DW_AT_abstract_origin:
case DW_AT_extension:
origin = { &get_section_for_ref (attr, reader->cu ()->per_cu),
attr.get_ref_die_offset () };
origin_offset = attr.get_ref_die_offset ();
origin_is_dwz = attr.form == DW_FORM_GNU_ref_alt;
break;
case DW_AT_external:
@ -305,20 +308,20 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
|| (*linkage_name == nullptr
&& tag_can_have_linkage_name (abbrev->tag))
|| (*parent_entry == nullptr && m_language != language_c))
&& origin.has_value ())
&& origin_offset != sect_offset (0))
{
cutu_reader *new_reader
= ensure_cu_exists (reader, reader->cu ()->per_objfile,
*origin->section, origin->offset, false);
= ensure_cu_exists (reader, reader->cu ()->per_objfile, origin_offset,
origin_is_dwz, false);
if (new_reader == nullptr)
error (_(DWARF_ERROR_PREFIX
"cannot follow reference to DIE at %s"
" [in module %s]"),
sect_offset_str (origin->offset),
sect_offset_str (origin_offset),
bfd_get_filename (reader->abfd ()));
const gdb_byte *new_info_ptr
= (new_reader->buffer () + to_underlying (origin->offset));
= (new_reader->buffer () + to_underlying (origin_offset));
if (*parent_entry == nullptr)
{
@ -342,7 +345,7 @@ cooked_indexer::scan_attributes (dwarf2_per_cu *scanning_per_cu,
if (new_abbrev == nullptr)
error (_(DWARF_ERROR_PREFIX
"Unexpected null DIE at offset %s [in module %s]"),
sect_offset_str (origin->offset),
sect_offset_str (origin_offset),
bfd_get_filename (new_reader->abfd ()));
new_info_ptr += bytes_read;
@ -406,7 +409,8 @@ cooked_indexer::index_imported_unit (cutu_reader *reader,
const gdb_byte *info_ptr,
const abbrev_info *abbrev)
{
std::optional<section_and_offset> target;
sect_offset sect_off {};
bool is_dwz = false;
for (int i = 0; i < abbrev->num_attrs; ++i)
{
@ -415,18 +419,20 @@ cooked_indexer::index_imported_unit (cutu_reader *reader,
info_ptr = reader->read_attribute (&attr, &abbrev->attrs[i], info_ptr);
if (attr.name == DW_AT_import)
target = { &get_section_for_ref (attr, reader->cu ()->per_cu),
attr.get_ref_die_offset () };
{
sect_off = attr.get_ref_die_offset ();
is_dwz = (attr.form == DW_FORM_GNU_ref_alt
|| reader->cu ()->per_cu->is_dwz);
}
}
/* Did not find DW_AT_import. */
if (!target.has_value ())
if (sect_off == sect_offset (0))
return info_ptr;
dwarf2_per_objfile *per_objfile = reader->cu ()->per_objfile;
cutu_reader *new_reader
= ensure_cu_exists (reader, per_objfile, *target->section, target->offset,
true);
= ensure_cu_exists (reader, per_objfile, sect_off, is_dwz, true);
if (new_reader != nullptr)
{
index_dies (new_reader, new_reader->info_ptr (), nullptr, false);

View File

@ -56,8 +56,9 @@ private:
up just a single DIE. */
cutu_reader *ensure_cu_exists (cutu_reader *reader,
dwarf2_per_objfile *per_objfile,
const dwarf2_section_info &section,
sect_offset sect_off, bool for_scanning);
sect_offset sect_off,
bool is_dwz,
bool for_scanning);
/* Index DIEs in the READER starting at INFO_PTR. PARENT is
the entry for the enclosing scope (nullptr at top level). FULLY

View File

@ -1313,27 +1313,14 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
/* Store out the .debug_type CUs, if any. */
data_buf types_cu_list;
/* dwarf_per_bfd::all_units is not necessarily sorted as needed in .gdb_index,
so sort it here. */
std::vector<dwarf2_per_cu *> units;
for (const auto &per_cu : per_bfd->all_units)
units.emplace_back (per_cu.get ());
std::sort (units.begin (), units.end (),
[] (const dwarf2_per_cu *a, const dwarf2_per_cu *b)
{
/* Comp units go before type units. */
if (a->is_debug_types != b->is_debug_types)
return a->is_debug_types < b->is_debug_types;
/* Then, sort by section offset. */
return a->sect_off < b->sect_off;
});
/* The CU list is already sorted, so we don't need to do additional
work here. */
int counter = 0;
for (const dwarf2_per_cu *per_cu : units)
for (int i = 0; i < per_bfd->all_units.size (); ++i)
{
dwarf2_per_cu *per_cu = per_bfd->all_units[i].get ();
const auto insertpair = cu_index_htab.emplace (per_cu, counter);
gdb_assert (insertpair.second);
@ -1350,7 +1337,7 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table,
to_underlying (per_cu->sect_off));
if (per_cu->is_debug_types)
{
const signatured_type *sig_type = (const signatured_type *) per_cu;
signatured_type *sig_type = (signatured_type *) per_cu;
cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
to_underlying (sig_type->type_offset_in_tu));
cu_list.append_uint (8, BFD_ENDIAN_LITTLE,
@ -1413,12 +1400,14 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
debug_names nametable (per_bfd, dwarf5_is_dwarf64, dwarf5_byte_order);
int counter = 0;
int types_counter = 0;
for (const dwarf2_per_cu_up &per_cu : per_bfd->all_units)
for (int i = 0; i < per_bfd->all_units.size (); ++i)
{
dwarf2_per_cu *per_cu = per_bfd->all_units[i].get ();
int &this_counter = per_cu->is_debug_types ? types_counter : counter;
data_buf &this_list = per_cu->is_debug_types ? types_cu_list : cu_list;
nametable.add_cu (per_cu.get (), this_counter);
nametable.add_cu (per_cu, this_counter);
this_list.append_uint (nametable.dwarf5_offset_size (),
dwarf5_byte_order,
to_underlying (per_cu->sect_off));
@ -1426,8 +1415,8 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table,
}
/* Verify that all units are represented. */
gdb_assert (counter == per_bfd->num_comp_units);
gdb_assert (types_counter == per_bfd->num_type_units);
gdb_assert (counter == per_bfd->all_comp_units.size ());
gdb_assert (types_counter == per_bfd->all_type_units.size ());
for (const cooked_index_entry *entry : table->all_entries ())
nametable.insert (entry);

View File

@ -95,14 +95,6 @@ struct mapped_debug_names_reader
const gdb_byte *name_table_entry_offs_reordered = nullptr;
const gdb_byte *entry_pool = nullptr;
/* The compilation units table, as found in this index. The CU indices in
index entries can index directly into this. */
std::vector<dwarf2_per_cu *> comp_units_table;
/* The type units table, as found in this index. The TU indices in index
entries can index directly into this. */
std::vector<dwarf2_per_cu *> type_units_table;
struct index_val
{
ULONGEST dwarf_tag;
@ -122,14 +114,6 @@ struct mapped_debug_names_reader
gdb::unordered_map<ULONGEST, index_val> abbrev_map;
/* List of CUs in the same order as found in the index header (DWARF 5 section
6.1.1.4.2). */
std::vector<dwarf2_per_cu *> comp_units;
/* List of local TUs in the same order as found in the index (DWARF 5 section
6.1.1.4.3). */
std::vector<dwarf2_per_cu *> type_units;
/* Even though the scanning of .debug_names and creation of the cooked index
entries is done serially, we create multiple shards so that the
finalization step can be parallelized. The shards are filled in a round
@ -247,7 +231,7 @@ mapped_debug_names_reader::scan_one_entry (const char *name,
case DW_IDX_compile_unit:
{
/* Don't crash on bad data. */
if (ull >= this->comp_units.size ())
if (ull >= per_objfile->per_bfd->all_comp_units.size ())
{
complaint (_(".debug_names entry has bad CU index %s"
" [in module %s]"),
@ -255,31 +239,30 @@ mapped_debug_names_reader::scan_one_entry (const char *name,
bfd_get_filename (abfd));
continue;
}
per_cu = this->comp_units[ull];
break;
}
per_cu = per_objfile->per_bfd->get_cu (ull);
break;
case DW_IDX_type_unit:
/* Don't crash on bad data. */
if (ull >= per_objfile->per_bfd->all_type_units.size ())
{
complaint (_(".debug_names entry has bad TU index %s"
" [in module %s]"),
pulongest (ull),
bfd_get_filename (abfd));
continue;
}
{
/* Don't crash on bad data. */
if (ull >= this->type_units.size ())
{
complaint (_(".debug_names entry has bad TU index %s"
" [in module %s]"),
pulongest (ull),
bfd_get_filename (abfd));
continue;
}
per_cu = this->type_units[ull];
break;
int nr_cus = per_objfile->per_bfd->all_comp_units.size ();
per_cu = per_objfile->per_bfd->get_cu (nr_cus + ull);
}
break;
case DW_IDX_die_offset:
die_offset = sect_offset (ull);
/* In a per-CU index (as opposed to a per-module index), index
entries without CU attribute implicitly refer to the single CU. */
if (per_cu == nullptr)
per_cu = this->comp_units[0];
if (per_cu == NULL)
per_cu = per_objfile->per_bfd->get_cu (0);
break;
case DW_IDX_parent:
parent = ull;
@ -459,49 +442,45 @@ cooked_index_worker_debug_names::do_reading ()
bfd_thread_cleanup ();
}
/* Build the list of TUs (mapped_debug_names_reader::type_units) from the index
header and verify that it matches the list of TUs read from the DIEs in
`.debug_info`.
Return true if they match, false otherwise. */
/* Check the signatured type hash table from .debug_names. */
static bool
build_and_check_tu_list_from_debug_names (dwarf2_per_objfile *per_objfile,
mapped_debug_names_reader &map,
dwarf2_section_info *section)
check_signatured_type_table_from_debug_names
(dwarf2_per_objfile *per_objfile,
const mapped_debug_names_reader &map,
struct dwarf2_section_info *section)
{
struct objfile *objfile = per_objfile->objfile;
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
int nr_cus = per_bfd->all_comp_units.size ();
int nr_cus_tus = per_bfd->all_units.size ();
section->read (objfile);
uint32_t j = nr_cus;
for (uint32_t i = 0; i < map.tu_count; ++i)
{
/* Read one entry from the TU list. */
sect_offset sect_off
= (sect_offset) (extract_unsigned_integer
(map.tu_table_reordered + i * map.offset_size,
map.offset_size,
map.dwarf5_byte_order));
/* Find the matching dwarf2_per_cu. */
auto found
= std::find_if (per_bfd->all_units.begin (), per_bfd->all_units.end (),
[sect_off] (const dwarf2_per_cu_up &unit) {
return unit->sect_off == sect_off
&& unit->is_debug_types;
});
if (found == per_bfd->all_units.end ())
bool found = false;
for (; j < nr_cus_tus; j++)
if (per_bfd->get_cu (j)->sect_off == sect_off)
{
found = true;
break;
}
if (!found)
{
warning (_("Section .debug_names has incorrect entry in TU table,"
" ignoring .debug_names."));
return false;
}
map.type_units.emplace_back (found);
per_bfd->all_comp_units_index_tus.push_back (per_bfd->get_cu (j));
}
return true;
}
@ -723,12 +702,42 @@ read_debug_names_from_section (dwarf2_per_objfile *per_objfile,
list. */
static bool
build_and_check_cu_list_from_debug_names (dwarf2_per_bfd *per_bfd,
mapped_debug_names_reader &map,
dwarf2_section_info &section,
bool is_dwz)
check_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd,
const mapped_debug_names_reader &map,
dwarf2_section_info &section,
bool is_dwz)
{
if (map.cu_count != per_bfd->num_comp_units)
int nr_cus = per_bfd->all_comp_units.size ();
if (!map.augmentation_is_gdb)
{
uint32_t j = 0;
for (uint32_t i = 0; i < map.cu_count; ++i)
{
sect_offset sect_off
= (sect_offset) (extract_unsigned_integer
(map.cu_table_reordered + i * map.offset_size,
map.offset_size,
map.dwarf5_byte_order));
bool found = false;
for (; j < nr_cus; j++)
if (per_bfd->get_cu (j)->sect_off == sect_off)
{
found = true;
break;
}
if (!found)
{
warning (_("Section .debug_names has incorrect entry in CU table,"
" ignoring .debug_names."));
return false;
}
per_bfd->all_comp_units_index_cus.push_back (per_bfd->get_cu (j));
}
return true;
}
if (map.cu_count != nr_cus)
{
warning (_("Section .debug_names has incorrect number of CUs in CU table,"
" ignoring .debug_names."));
@ -737,57 +746,40 @@ build_and_check_cu_list_from_debug_names (dwarf2_per_bfd *per_bfd,
for (uint32_t i = 0; i < map.cu_count; ++i)
{
/* Read one entry from the CU list. */
sect_offset sect_off
= (sect_offset) (extract_unsigned_integer
(map.cu_table_reordered + i * map.offset_size,
map.offset_size,
map.dwarf5_byte_order));
/* Find the matching dwarf2_per_cu. */
auto found
= std::find_if (per_bfd->all_units.begin (), per_bfd->all_units.end (),
[is_dwz, sect_off] (const dwarf2_per_cu_up &unit) {
return unit->sect_off == sect_off
&& !unit->is_debug_types
&& unit->is_dwz == is_dwz;
});
if (found == per_bfd->all_units.end ())
if (sect_off != per_bfd->get_cu (i)->sect_off)
{
warning (_("Section .debug_names has incorrect entry in CU table,"
" ignoring .debug_names."));
return false;
}
map.comp_units.emplace_back (found);
}
return true;
}
/* Build the list of CUs (mapped_debug_names_reader::compile_units) from the
index header and verify that it matches the list of CUs read from the DIEs in
`.debug_info`.
Return true if they match, false otherwise. */
/* Read the CU list from the mapped index, and use it to create all
the CU objects for this dwarf2_per_objfile. */
static bool
build_and_check_cu_lists_from_debug_names (dwarf2_per_bfd *per_bfd,
mapped_debug_names_reader &map,
mapped_debug_names_reader &dwz_map)
check_cus_from_debug_names (dwarf2_per_bfd *per_bfd,
const mapped_debug_names_reader &map,
const mapped_debug_names_reader &dwz_map)
{
if (!build_and_check_cu_list_from_debug_names (per_bfd, map,
per_bfd->infos[0],
false /* is_dwz */))
if (!check_cus_from_debug_names_list (per_bfd, map, per_bfd->infos[0],
false /* is_dwz */))
return false;
if (dwz_map.cu_count == 0)
return true;
dwz_file *dwz = per_bfd->get_dwz_file ();
return build_and_check_cu_list_from_debug_names (per_bfd, dwz_map, dwz->info,
true /* is_dwz */);
return check_cus_from_debug_names_list (per_bfd, dwz_map, dwz->info,
true /* is_dwz */);
}
/* This does all the work for dwarf2_read_debug_names, but putting it
@ -825,7 +817,7 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
}
create_all_units (per_objfile);
if (!build_and_check_cu_lists_from_debug_names (per_bfd, map, dwz_map))
if (!check_cus_from_debug_names (per_bfd, map, dwz_map))
return false;
if (map.tu_count != 0)
@ -841,8 +833,8 @@ do_dwarf2_read_debug_names (dwarf2_per_objfile *per_objfile)
? &per_bfd->types[0]
: &per_bfd->infos[0]);
if (!build_and_check_tu_list_from_debug_names (per_objfile, map,
section))
if (!check_signatured_type_table_from_debug_names (per_objfile,
map, section))
return false;
}

View File

@ -117,10 +117,6 @@ struct mapped_gdb_index : public dwarf_scanner_base
/* Index data format version. */
int version = 0;
/* Compile units followed by type units, in the order as found in the
index. Indices found in index entries can index directly in into this. */
std::vector<dwarf2_per_cu *> units;
/* The address table data. */
gdb::array_view<const gdb_byte> address_table;
@ -1110,16 +1106,17 @@ dw2_expand_marked_cus (dwarf2_per_objfile *per_objfile, offset_type idx,
}
/* Don't crash on bad data. */
if (cu_index >= index.units.size ())
if (cu_index >= per_objfile->per_bfd->all_units.size ())
{
complaint (_(".gdb_index entry has bad CU index"
" [in module %s]"), objfile_name (per_objfile->objfile));
continue;
}
if (!dw2_expand_symtabs_matching_one (index.units[cu_index], per_objfile,
file_matcher, expansion_notify,
lang_matcher))
dwarf2_per_cu *per_cu = per_objfile->per_bfd->get_cu (cu_index);
if (!dw2_expand_symtabs_matching_one (per_cu, per_objfile, file_matcher,
expansion_notify, lang_matcher))
return false;
}
@ -1316,7 +1313,7 @@ static void
create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd,
const gdb_byte *cu_list, offset_type n_elements,
struct dwarf2_section_info *section,
int is_dwz, std::vector<dwarf2_per_cu *> &units)
int is_dwz)
{
for (offset_type i = 0; i < n_elements; i += 2)
{
@ -1331,7 +1328,6 @@ create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd,
sect_off,
length,
is_dwz));
units.emplace_back (per_bfd->all_units.back ().get ());
}
}
@ -1341,21 +1337,20 @@ create_cus_from_gdb_index_list (dwarf2_per_bfd *per_bfd,
static void
create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd,
const gdb_byte *cu_list, offset_type cu_list_elements,
std::vector<dwarf2_per_cu *> &units,
const gdb_byte *dwz_list, offset_type dwz_elements)
{
gdb_assert (per_bfd->all_units.empty ());
per_bfd->all_units.reserve ((cu_list_elements + dwz_elements) / 2);
create_cus_from_gdb_index_list (per_bfd, cu_list, cu_list_elements,
&per_bfd->infos[0], 0, units);
&per_bfd->infos[0], 0);
if (dwz_elements == 0)
return;
dwz_file *dwz = per_bfd->get_dwz_file ();
create_cus_from_gdb_index_list (per_bfd, dwz_list, dwz_elements,
&dwz->info, 1, units);
&dwz->info, 1);
}
/* Create the signatured type hash table from the index. */
@ -1363,8 +1358,7 @@ create_cus_from_gdb_index (dwarf2_per_bfd *per_bfd,
static void
create_signatured_type_table_from_gdb_index
(dwarf2_per_bfd *per_bfd, struct dwarf2_section_info *section,
const gdb_byte *bytes, offset_type elements,
std::vector<dwarf2_per_cu *> &units)
const gdb_byte *bytes, offset_type elements)
{
signatured_type_set sig_types_hash;
@ -1388,7 +1382,6 @@ create_signatured_type_table_from_gdb_index
sig_type->type_offset_in_tu = type_offset_in_tu;
sig_types_hash.emplace (sig_type.get ());
units.emplace_back (sig_type.get ());
per_bfd->all_units.emplace_back (sig_type.release ());
}
@ -1426,14 +1419,14 @@ create_addrmap_from_gdb_index (dwarf2_per_objfile *per_objfile,
continue;
}
if (cu_index >= index->units.size ())
if (cu_index >= per_bfd->all_units.size ())
{
complaint (_(".gdb_index address table has invalid CU number %u"),
(unsigned) cu_index);
continue;
}
mutable_map.set_empty (lo, hi - 1, index->units[cu_index]);
mutable_map.set_empty (lo, hi - 1, per_bfd->get_cu (cu_index));
}
index->index_addrmap
@ -1535,8 +1528,8 @@ dwarf2_read_gdb_index
}
}
create_cus_from_gdb_index (per_bfd, cu_list, cu_list_elements, map->units,
dwz_list, dwz_list_elements);
create_cus_from_gdb_index (per_bfd, cu_list, cu_list_elements, dwz_list,
dwz_list_elements);
if (types_list_elements)
{
@ -1555,8 +1548,7 @@ dwarf2_read_gdb_index
: &per_bfd->infos[0]);
create_signatured_type_table_from_gdb_index (per_bfd, section, types_list,
types_list_elements,
map->units);
types_list_elements);
}
finalize_all_units (per_bfd);

View File

@ -1733,7 +1733,6 @@ dwarf2_per_bfd::allocate_per_cu (dwarf2_section_info *section,
dwarf2_per_cu_up result (new dwarf2_per_cu (this, section, sect_off,
length, is_dwz));
result->index = all_units.size ();
this->num_comp_units++;
return result;
}
@ -1750,7 +1749,7 @@ dwarf2_per_bfd::allocate_signatured_type (dwarf2_section_info *section,
= std::make_unique<signatured_type> (this, section, sect_off, length,
is_dwz, signature);
result->index = all_units.size ();
this->num_type_units++;
tu_stats.nr_tus++;
return result;
}
@ -1949,32 +1948,36 @@ dwarf2_base_index_functions::print_stats (struct objfile *objfile,
return;
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
unsigned int read_count = 0;
unsigned int unread_count = 0;
int total = per_objfile->per_bfd->all_units.size ();
int count = 0;
for (auto &per_cu : per_objfile->per_bfd->all_units)
if (per_objfile->symtab_set_p (&*per_cu))
++read_count;
else
++unread_count;
for (int i = 0; i < total; ++i)
{
dwarf2_per_cu *per_cu = per_objfile->per_bfd->get_cu (i);
gdb_printf (_(" Number of read units: %u\n"), read_count);
gdb_printf (_(" Number of unread units: %u\n"), unread_count);
if (!per_objfile->symtab_set_p (per_cu))
++count;
}
gdb_printf (_(" Number of read CUs: %d\n"), total - count);
gdb_printf (_(" Number of unread CUs: %d\n"), count);
}
void
dwarf2_base_index_functions::expand_all_symtabs (struct objfile *objfile)
{
dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile);
int total_units = per_objfile->per_bfd->all_units.size ();
for (const dwarf2_per_cu_up &per_cu : per_objfile->per_bfd->all_units)
for (int i = 0; i < total_units; ++i)
{
dwarf2_per_cu *per_cu = per_objfile->per_bfd->get_cu (i);
/* We don't want to directly expand a partial CU, because if we
read it with the wrong language, then assertion failures can
be triggered later on. See PR symtab/23010. So, tell
dw2_instantiate_symtab to skip partial CUs -- any important
partial CU will be read via DW_TAG_imported_unit anyway. */
dw2_instantiate_symtab (per_cu.get (), per_objfile, true);
dw2_instantiate_symtab (per_cu, per_objfile, true);
}
}
@ -3559,6 +3562,9 @@ build_type_psymtabs (dwarf2_per_objfile *per_objfile,
/* It's up to the caller to not call us multiple times. */
gdb_assert (per_objfile->per_bfd->type_unit_groups == NULL);
if (per_objfile->per_bfd->all_type_units.size () == 0)
return;
/* TUs typically share abbrev tables, and there can be way more TUs than
abbrev tables. Sort by abbrev table to reduce the number of times we
read each abbrev table in.
@ -3583,17 +3589,18 @@ build_type_psymtabs (dwarf2_per_objfile *per_objfile,
/* Sort in a separate table to maintain the order of all_units
for .gdb_index: TU indices directly index all_type_units. */
std::vector<tu_abbrev_offset> sorted_by_abbrev;
sorted_by_abbrev.reserve (per_objfile->per_bfd->num_type_units);
sorted_by_abbrev.reserve (per_objfile->per_bfd->all_type_units.size ());
for (const auto &cu : per_objfile->per_bfd->all_units)
if (cu->is_debug_types)
{
auto sig_type = static_cast<signatured_type *> (cu.get ());
sorted_by_abbrev.emplace_back (sig_type,
read_abbrev_offset (per_objfile,
sig_type->section,
sig_type->sect_off));
}
{
if (cu->is_debug_types)
{
auto sig_type = static_cast<signatured_type *> (cu.get ());
sorted_by_abbrev.emplace_back
(sig_type, read_abbrev_offset (per_objfile, sig_type->section,
sig_type->sect_off));
}
}
std::sort (sorted_by_abbrev.begin (), sorted_by_abbrev.end ());
@ -3625,11 +3632,10 @@ build_type_psymtabs (dwarf2_per_objfile *per_objfile,
static void
print_tu_stats (dwarf2_per_objfile *per_objfile)
{
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
struct tu_stats *tu_stats = &per_bfd->tu_stats;
struct tu_stats *tu_stats = &per_objfile->per_bfd->tu_stats;
dwarf_read_debug_printf ("Type unit statistics:");
dwarf_read_debug_printf (" %d TUs", per_bfd->num_type_units);
dwarf_read_debug_printf (" %d TUs", tu_stats->nr_tus);
dwarf_read_debug_printf (" %d uniq abbrev tables",
tu_stats->nr_uniq_abbrev_tables);
dwarf_read_debug_printf (" %d symtabs from stmt_list entries",
@ -3932,51 +3938,17 @@ read_comp_units_from_section (dwarf2_per_objfile *per_objfile,
per_objfile->per_bfd->all_units.push_back (std::move (this_cu));
}
}
/* "less than" function used to both sort and bisect units in the
`dwarf2_per_bfd::all_units` vector. Return true if the LHS CU comes before
(is "less" than) the section and offset in RHS.
For simplicity, sort sections by their pointer. This is not ideal, because
it can cause the behavior to change across runs, making some bugs harder to
investigate. Instead, sections could be sorted by their properties, but it
is important that two different sections never compare equal.
LENGTH_REQUIRED indicates whether the length of the units is required
to be set already. When this functions gets called to sort units,
the length of the units may not be known yet (for example, when readin
.gdb_index). But this doesn't affect the outcome when sorting. On the
other hand, when called in the context of looking up a unit by section
offset, the length is required in order to know if the offset falls within
the section or not. */
template<bool length_required>
static bool
all_units_less_than (const dwarf2_per_cu &lhs,
const section_and_offset &rhs)
{
if (lhs.section != rhs.section)
return lhs.section < rhs.section;
/* Compare the end of the unit'srange, so that std::lower_bound finds the
unit we are looking for, not the one after. */
return lhs.sect_off + lhs.length (length_required) - 1 < rhs.offset;
}
/* Initialize the views on all_units. */
void
finalize_all_units (dwarf2_per_bfd *per_bfd)
{
/* Ensure that the all_units vector is in the expected order for
dwarf2_find_containing_unit to be able to perform a binary search.
Sort first by section (using the pointer of the section as the key) and
then by the offset within the section. */
std::
sort (per_bfd->all_units.begin (), per_bfd->all_units.end (),
[] (const dwarf2_per_cu_up &a, const dwarf2_per_cu_up &b)
{
return all_units_less_than<false> (*a, { b->section, b->sect_off });
});
size_t nr_tus = per_bfd->tu_stats.nr_tus;
size_t nr_cus = per_bfd->all_units.size () - nr_tus;
gdb::array_view<dwarf2_per_cu_up> tmp = per_bfd->all_units;
per_bfd->all_comp_units = tmp.slice (0, nr_cus);
per_bfd->all_type_units = tmp.slice (nr_cus, nr_tus);
}
/* See read.h. */
@ -5245,19 +5217,6 @@ process_full_type_unit (dwarf2_cu *cu,
cu->reset_builder ();
}
/* See read.h. */
dwarf2_section_info &
get_section_for_ref (const attribute &attr, dwarf2_per_cu *per_cu)
{
gdb_assert (attr.form_is_ref ());
if (attr.form == DW_FORM_GNU_ref_alt)
return per_cu->per_bfd->get_dwz_file (true)->info;
return *per_cu->section;
}
/* Process an imported unit DIE. */
static void
@ -5277,12 +5236,12 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
attr = dwarf2_attr (die, DW_AT_import, cu);
if (attr != NULL)
{
const dwarf2_section_info &section
= get_section_for_ref (*attr, cu->per_cu);
sect_offset sect_off = attr->get_ref_die_offset ();
bool is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
dwarf2_per_objfile *per_objfile = cu->per_objfile;
dwarf2_per_cu *per_cu
= dwarf2_find_containing_unit (section, sect_off, per_objfile->per_bfd);
= dwarf2_find_containing_comp_unit (sect_off, is_dwz,
per_objfile->per_bfd);
/* We're importing a C++ compilation unit with tag DW_TAG_compile_unit
into another compilation unit, at root level. Regard this as a hint,
@ -14776,60 +14735,6 @@ cutu_reader::read_toplevel_die (die_info **diep, const gdb_byte *info_ptr,
return result;
}
void
cooked_index_functions::dump (struct objfile *objfile)
{
/* Building the index fills some information in dwarf2_per_cu (e.g. the
unit type), which we print in the CU/TU list. We also need to wait for the
index to be built before calling `cooked_index::dump` below. */
cooked_index *index = this->wait (objfile, true);
const auto per_bfd = get_dwarf2_per_objfile (objfile)->per_bfd;
gdb_printf (" Number of compilation units: %u\n", per_bfd->num_comp_units);
gdb_printf (" Number of type units: %u\n", per_bfd->num_type_units);
gdb_printf ("\n");
gdb_printf (" Compilation/type units:\n");
gdb_printf ("\n");
for (std::size_t i = 0; i < per_bfd->all_units.size (); ++i)
{
const auto &unit = *per_bfd->all_units[i];
const char *gdb_type_name
= unit.is_debug_types ? "signatured_type" : "dwarf2_per_cu";
const auto bool_str
= [] (const bool val) { return val ? "true" : "false"; };
gdb_printf (" [%zu] ((%s *) %p)\n", i, gdb_type_name, &unit);
gdb_printf (" type: %s\n",
dwarf_unit_type_name (unit.unit_type (false)));
gdb_printf (" offset: 0x%" PRIx64 "\n",
to_underlying (unit.sect_off));
gdb_printf (" size: 0x%x\n", unit.length ());
if (unit.is_debug_types)
{
const auto &tu = static_cast<const signatured_type &> (unit);
gdb_printf (" signature: 0x%s\n", phex (tu.signature, 8));
}
else
{
gdb_printf (" artificial: %s\n", bool_str (unit.lto_artificial));
gdb_printf (" GDB lang: %s\n", language_str (unit.lang (false)));
gdb_printf (" DWARF lang: %s\n",
dwarf_source_language_name (unit.dw_lang ()));
}
gdb_printf ("\n");
}
gdb_printf ("Cooked index in use:\n");
gdb_printf ("\n");
index->dump (objfile->arch ());
}
struct compunit_symtab *
cooked_index_functions::find_compunit_symtab_by_address
(struct objfile *objfile, CORE_ADDR address)
@ -15558,7 +15463,6 @@ cutu_reader::read_attribute_value (attribute *attr, unsigned form,
}
/* Super hack. */
// RLY NEEDED?,get_section_for_ref should return the dwz section if the ref source if in the dwz
if (m_cu->per_cu->is_dwz && attr->form_is_ref ())
attr->form = DW_FORM_GNU_ref_alt;
@ -17900,11 +17804,9 @@ lookup_die_type (struct die_info *die, const struct attribute *attr,
if (attr->form == DW_FORM_GNU_ref_alt)
{
dwarf2_per_bfd *per_bfd = per_objfile->per_bfd;
const dwarf2_section_info &section = per_bfd->get_dwz_file ()->info;
sect_offset sect_off = attr->get_ref_die_offset ();
dwarf2_per_cu *per_cu
= dwarf2_find_containing_unit (section, sect_off, per_bfd);
= dwarf2_find_containing_comp_unit (sect_off, 1, per_objfile->per_bfd);
this_type = get_die_type_at_offset (sect_off, per_cu, per_objfile);
}
@ -18607,41 +18509,42 @@ follow_die_ref_or_sig (struct die_info *src_die, const struct attribute *attr,
return die;
}
/* Follow reference TARGET.
On entry *REF_CU is the CU of the source die referencing TARGET.
/* Follow reference OFFSET.
On entry *REF_CU is the CU of the source die referencing OFFSET.
On exit *REF_CU is the CU of the result.
Returns NULL if TARGET is invalid. */
Returns NULL if OFFSET is invalid. */
static die_info *
follow_die_offset (const section_and_offset &target, dwarf2_cu **ref_cu)
static struct die_info *
follow_die_offset (sect_offset sect_off, int offset_in_dwz,
struct dwarf2_cu **ref_cu)
{
struct dwarf2_cu *source_cu = *ref_cu;
dwarf2_per_objfile *per_objfile = source_cu->per_objfile;
struct dwarf2_cu *target_cu, *cu = *ref_cu;
dwarf2_per_objfile *per_objfile = cu->per_objfile;
gdb_assert (source_cu->per_cu != NULL);
gdb_assert (cu->per_cu != NULL);
dwarf2_cu *target_cu = source_cu;
target_cu = cu;
dwarf_read_debug_printf_v ("source CU offset: %s, target offset: %s, "
"source CU contains target offset: %d",
sect_offset_str (source_cu->per_cu->sect_off),
sect_offset_str (cu->per_cu->sect_off),
sect_offset_str (sect_off),
source_cu->header.offset_in_cu_p (sect_off));
cu->header.offset_in_cu_p (sect_off));
if (source_cu->per_cu->is_debug_types)
if (cu->per_cu->is_debug_types)
{
/* .debug_types CUs cannot reference anything outside their CU.
If they need to, they have to reference a signatured type via
DW_FORM_ref_sig8. */
if (!source_cu->header.offset_in_cu_p (sect_off))
if (!cu->header.offset_in_cu_p (sect_off))
return NULL;
}
else if (&section != source_cu->per_cu->section
|| !source_cu->header.offset_in_cu_p (sect_off))
else if (offset_in_dwz != cu->per_cu->is_dwz
|| !cu->header.offset_in_cu_p (sect_off))
{
dwarf2_per_cu *per_cu
= dwarf2_find_containing_unit (section, sect_off,
per_objfile->per_bfd);
= dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
per_objfile->per_bfd);
dwarf_read_debug_printf_v ("target CU offset: %s, "
"target CU DIEs loaded: %d",
@ -18653,11 +18556,10 @@ follow_die_offset (const section_and_offset &target, dwarf2_cu **ref_cu)
Even if maybe_queue_comp_unit doesn't require us to load the CU's DIEs,
it doesn't mean they are currently loaded. Since we require them
to be loaded, we must check for ourselves. */
if (maybe_queue_comp_unit (source_cu, per_cu, per_objfile,
source_cu->lang ())
if (maybe_queue_comp_unit (cu, per_cu, per_objfile, cu->lang ())
|| per_objfile->get_cu (per_cu) == nullptr)
load_full_comp_unit (per_cu, per_objfile, per_objfile->get_cu (per_cu),
false, source_cu->lang ());
false, cu->lang ());
target_cu = per_objfile->get_cu (per_cu);
if (target_cu == nullptr)
@ -18667,10 +18569,10 @@ follow_die_offset (const section_and_offset &target, dwarf2_cu **ref_cu)
sect_offset_str (sect_off),
objfile_name (per_objfile->objfile));
}
else if (source_cu->dies == NULL)
else if (cu->dies == NULL)
{
/* We're loading full DIEs during partial symbol reading. */
load_full_comp_unit (source_cu->per_cu, per_objfile, source_cu, false,
load_full_comp_unit (cu->per_cu, per_objfile, cu, false,
language_minimal);
}
@ -18689,24 +18591,24 @@ follow_die_ref (struct die_info *src_die, const struct attribute *attr,
struct dwarf2_cu **ref_cu)
{
sect_offset sect_off = attr->get_ref_die_offset ();
struct dwarf2_cu *source_cu = *ref_cu;
struct dwarf2_cu *cu = *ref_cu;
struct die_info *die;
if (attr->form == DW_FORM_GNU_ref_alt && src_die->sect_off == sect_off)
if (attr->form != DW_FORM_GNU_ref_alt && src_die->sect_off == sect_off)
{
/* Self-reference, we're done. */
return src_die;
}
const dwarf2_section_info &section
= get_section_for_ref (*attr, source_cu->per_cu);
die_info *die = follow_die_offset (section, sect_off,
ref_cu);
if (die == nullptr)
die = follow_die_offset (sect_off,
(attr->form == DW_FORM_GNU_ref_alt
|| cu->per_cu->is_dwz),
ref_cu);
if (!die)
error (_(DWARF_ERROR_PREFIX
"Cannot find DIE at %s referenced from DIE at %s [in module %s]"),
sect_offset_str (sect_off), sect_offset_str (src_die->sect_off),
objfile_name (source_cu->per_objfile->objfile));
objfile_name (cu->per_objfile->objfile));
return die;
}
@ -18719,6 +18621,7 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
gdb::function_view<CORE_ADDR ()> get_frame_pc,
bool resolve_abstract_p)
{
struct die_info *die;
struct attribute *attr;
struct dwarf2_locexpr_baton retval;
struct objfile *objfile = per_objfile->objfile;
@ -18736,8 +18639,8 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
sect_offset_str (sect_off), objfile_name (objfile));
}
die_info *die = follow_die_offset (*per_cu->section, sect_off, &cu);
if (die == nullptr)
die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
if (!die)
error (_(DWARF_ERROR_PREFIX
"Cannot find DIE at %s referenced [in module %s]"),
sect_offset_str (sect_off), objfile_name (objfile));
@ -18754,7 +18657,7 @@ dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
{
struct dwarf2_cu *cand_cu = cu;
struct die_info *cand
= follow_die_offset (*per_cu->section, cand_off, &cand_cu);
= follow_die_offset (cand_off, per_cu->is_dwz, &cand_cu);
if (!cand
|| !cand->parent
|| cand->parent->tag != DW_TAG_subprogram)
@ -18877,7 +18780,7 @@ dwarf2_fetch_constant_bytes (sect_offset sect_off,
sect_offset_str (sect_off), objfile_name (objfile));
}
die = follow_die_offset (*per_cu->section, sect_off, &cu);
die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
if (!die)
error (_(DWARF_ERROR_PREFIX
"Cannot find DIE at %s referenced [in module %s]"),
@ -19003,7 +18906,7 @@ dwarf2_fetch_die_type_sect_off (sect_offset sect_off, dwarf2_per_cu *per_cu,
if (cu == nullptr)
return nullptr;
die = follow_die_offset (*per_cu->section, sect_off, &cu);
die = follow_die_offset (sect_off, per_cu->is_dwz, &cu);
if (!die)
return NULL;
@ -19759,45 +19662,63 @@ dwarf2_per_cu::ensure_lang (dwarf2_per_objfile *per_objfile)
occur in any CU. This is separate so that it can be unit
tested. */
static dwarf2_per_cu *
dwarf2_find_containing_unit (section_and_offset const dwarf2_section_info &section,
sect_offset sect_off,
const std::vector<dwarf2_per_cu_up> &all_units)
static int
dwarf2_find_containing_comp_unit
(sect_offset sect_off,
unsigned int offset_in_dwz,
const std::vector<dwarf2_per_cu_up> &all_units)
{
auto it = std::lower_bound (all_units.begin (), all_units.end (),
section_and_offset { &section, sect_off },
[] (const dwarf2_per_cu_up &per_cu,
const section_and_offset &key)
{
return all_units_less_than<true>
(*per_cu, key);
});
int low, high;
if (it == all_units.begin ())
return sect_off >= (*it)->sect_off ? it->get () : nullptr;
low = 0;
high = all_units.size () - 1;
while (high > low)
{
int mid = low + (high - low) / 2;
dwarf2_per_cu *mid_cu = all_units[mid].get ();
if (it == all_units.end ())
return nullptr;
return it->get ();
if (mid_cu->is_dwz > offset_in_dwz
|| (mid_cu->is_dwz == offset_in_dwz
&& mid_cu->sect_off + mid_cu->length () > sect_off))
high = mid;
else
low = mid + 1;
}
gdb_assert (low == high);
return low;
}
/* See read.h. */
dwarf2_per_cu *
dwarf2_find_containing_unit (section_and_offset const dwarf2_section_info &section,
sect_offset sect_off, dwarf2_per_bfd *per_bfd)
dwarf2_find_containing_comp_unit (sect_offset sect_off,
unsigned int offset_in_dwz,
dwarf2_per_bfd *per_bfd)
{
dwarf2_per_cu *per_cu
= dwarf2_find_containing_unit (section, sect_off, per_bfd->all_units);
int low = dwarf2_find_containing_comp_unit
(sect_off, offset_in_dwz, per_bfd->all_units);
dwarf2_per_cu *this_cu = per_bfd->all_units[low].get ();
if (per_cu == nullptr)
error (_(DWARF_ERROR_PREFIX
"could not find compile or type unit containing offset %s "
"[in module %s]"),
sect_offset_str (sect_off), per_bfd->filename ());
if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off)
{
if (low == 0 || this_cu->is_dwz != offset_in_dwz)
error (_(DWARF_ERROR_PREFIX
"could not find CU containing offset %s [in module %s]"),
sect_offset_str (sect_off),
per_bfd->filename ());
return per_cu;
gdb_assert (per_bfd->all_units[low-1]->sect_off
<= sect_off);
return per_bfd->all_units[low - 1].get ();
}
else
{
if (low == per_bfd->all_units.size () - 1
&& sect_off >= this_cu->sect_off + this_cu->length ())
error (_("invalid dwarf2 offset %s"), sect_offset_str (sect_off));
gdb_assert (sect_off < this_cu->sect_off + this_cu->length ());
return this_cu;
}
}
#if GDB_SELF_TEST
@ -19809,36 +19730,31 @@ static void
run_test ()
{
char dummy_per_bfd;
auto &main_section = *reinterpret_cast<dwarf2_section_info *> (0x4000);
auto &dwz_section = *reinterpret_cast<dwarf2_section_info *>(0x5000);
char dummy_section;
const auto create_dummy_per_cu = [&] (dwarf2_section_info &section,
sect_offset sect_off,
const auto create_dummy_per_cu = [&] (sect_offset sect_off,
unsigned int length,
bool is_dwz)
{
auto per_bfd = reinterpret_cast<dwarf2_per_bfd *> (&dummy_per_bfd);
auto section = reinterpret_cast<dwarf2_section_info *> (&dummy_section);
return dwarf2_per_cu_up (new dwarf2_per_cu (per_bfd, &section, sect_off,
return dwarf2_per_cu_up (new dwarf2_per_cu (per_bfd, section, sect_off,
length, is_dwz));
};
/* Units in the main file. */
dwarf2_per_cu_up one
= create_dummy_per_cu (main_section, sect_offset (0), 5, false);
dwarf2_per_cu_up one = create_dummy_per_cu (sect_offset (0), 5, false);
dwarf2_per_cu *one_ptr = one.get ();
dwarf2_per_cu_up two
= create_dummy_per_cu (main_section, sect_offset (one->length ()), 7,
false);
= create_dummy_per_cu (sect_offset (one->length ()), 7, false);
dwarf2_per_cu *two_ptr = two.get ();
/* Units in the supplementary (dwz) file. */
dwarf2_per_cu_up three
= create_dummy_per_cu (dwz_section, sect_offset (0), 5, true);
dwarf2_per_cu_up three = create_dummy_per_cu (sect_offset (0), 5, true);
dwarf2_per_cu *three_ptr = three.get ();
dwarf2_per_cu_up four
= create_dummy_per_cu (dwz_section, sect_offset (three->length ()), 7,
true);
= create_dummy_per_cu (sect_offset (three->length ()), 7, true);
dwarf2_per_cu *four_ptr = four.get ();
std::vector<dwarf2_per_cu_up> units;
@ -19847,21 +19763,21 @@ run_test ()
units.push_back (std::move (three));
units.push_back (std::move (four));
dwarf2_per_cu *result;
int result;
result = dwarf2_find_containing_unit (main_section, sect_offset (0), units);
SELF_CHECK (result == one_ptr);
result = dwarf2_find_containing_unit (main_section, sect_offset (3), units);
SELF_CHECK (result == one_ptr);
result = dwarf2_find_containing_unit (main_section, sect_offset (5), units);
SELF_CHECK (result == two_ptr);
result = dwarf2_find_containing_comp_unit (sect_offset (0), 0, units);
SELF_CHECK (units[result].get () == one_ptr);
result = dwarf2_find_containing_comp_unit (sect_offset (3), 0, units);
SELF_CHECK (units[result].get () == one_ptr);
result = dwarf2_find_containing_comp_unit (sect_offset (5), 0, units);
SELF_CHECK (units[result].get () == two_ptr);
result = dwarf2_find_containing_unit (dwz_section, sect_offset (0), units);
SELF_CHECK (result == three_ptr);
result = dwarf2_find_containing_unit (dwz_section, sect_offset (3), units);
SELF_CHECK (result == three_ptr);
result = dwarf2_find_containing_unit (dwz_section, sect_offset (5), units);
SELF_CHECK (result == four_ptr);
result = dwarf2_find_containing_comp_unit (sect_offset (0), 1, units);
SELF_CHECK (units[result].get () == three_ptr);
result = dwarf2_find_containing_comp_unit (sect_offset (3), 1, units);
SELF_CHECK (units[result].get () == three_ptr);
result = dwarf2_find_containing_comp_unit (sect_offset (5), 1, units);
SELF_CHECK (units[result].get () == four_ptr);
}
}

View File

@ -44,6 +44,7 @@ struct tu_stats
int nr_symtab_sharers = 0;
int nr_stmt_less_type_units = 0;
int nr_all_type_units_reallocs = 0;
int nr_tus = 0;
};
struct abbrev_table_cache;
@ -269,10 +270,10 @@ public:
int ref_addr_size () const;
/* Return length of this CU. */
unsigned int length (bool require = true) const
unsigned int length () const
{
/* Make sure it's set already. */
gdb_assert (!require || m_length != 0);
gdb_assert (m_length != 0);
return m_length;
}
@ -494,12 +495,26 @@ struct dwarf2_per_bfd
const char *filename () const
{ return bfd_get_filename (this->obfd); }
/* Return the unit given its index. */
dwarf2_per_cu *get_unit (int index) const
/* Return the CU given its index. */
dwarf2_per_cu *get_cu (int index) const
{
return this->all_units[index].get ();
}
/* Return the CU given its index in the CU table in the index. */
dwarf2_per_cu *get_index_cu (int index) const
{
if (this->all_comp_units_index_cus.empty ())
return get_cu (index);
return this->all_comp_units_index_cus[index];
}
dwarf2_per_cu *get_index_tu (int index) const
{
return this->all_comp_units_index_tus[index];
}
/* Return the separate '.dwz' debug file. If there is no
.gnu_debugaltlink section in the file, then the result depends on
REQUIRE: if REQUIRE is true, error out; if REQUIRE is false,
@ -580,12 +595,17 @@ public:
std::vector<dwarf2_section_info> types;
/* Table of all the compilation and type units. This is used to locate
/* Table of all the compilation units. This is used to locate
the target compilation unit of a particular reference. */
std::vector<dwarf2_per_cu_up> all_units;
unsigned int num_comp_units = 0;
unsigned int num_type_units = 0;
/* The all_units vector contains both CUs and TUs. Provide views on the
vector that are limited to either the CU part or the TU part. */
gdb::array_view<dwarf2_per_cu_up> all_comp_units;
gdb::array_view<dwarf2_per_cu_up> all_type_units;
std::vector<dwarf2_per_cu *> all_comp_units_index_cus;
std::vector<dwarf2_per_cu *> all_comp_units_index_tus;
/* Table of struct type_unit_group objects.
The hash key is the DW_AT_stmt_list value. */
@ -671,7 +691,7 @@ public:
dwarf2_per_cu *operator* () const
{
return m_per_bfd->get_unit (m_index);
return m_per_bfd->get_cu (m_index);
}
bool operator== (const all_units_iterator &other) const
@ -1174,7 +1194,7 @@ extern void dw_expand_symtabs_matching_file_matcher
extern const char *read_indirect_string_at_offset
(dwarf2_per_objfile *per_objfile, LONGEST str_offset);
/* Finalize the all_units vector. */
/* Initialize the views on all_units. */
extern void finalize_all_units (dwarf2_per_bfd *per_bfd);
@ -1223,12 +1243,14 @@ extern pc_bounds_kind dwarf2_get_pc_bounds (die_info *die,
dwarf2_cu *cu, addrmap_mutable *map,
void *datum);
/* Locate the unit in PER_BFD which contains the DIE at OFFSET. Raises an
error on failure. */
/* Locate the .debug_info compilation unit from CU's objfile which contains
the DIE at OFFSET. Raises an error on failure. */
extern dwarf2_per_cu *dwarf2_find_containing_unit
(const dwarf2_section_info &section, sect_offset sect_off,
dwarf2_per_bfd *per_bfd);
extern dwarf2_per_cu *dwarf2_find_containing_comp_unit (sect_offset sect_off,
unsigned int
offset_in_dwz,
dwarf2_per_bfd
*per_bfd);
/* Decode simple location descriptions.
@ -1271,9 +1293,4 @@ extern int dwarf2_ranges_read (unsigned offset, unrelocated_addr *low_return,
extern file_and_directory &find_file_and_directory (die_info *die,
dwarf2_cu *cu);
/* Return the section that ATTR, an attribute with ref form, references. */
extern dwarf2_section_info &get_section_for_ref (const attribute &attr,
dwarf2_per_cu *per_cu);
#endif /* GDB_DWARF2_READ_H */

View File

@ -43,8 +43,6 @@
the real section this "virtual" section is contained in, and BUFFER,SIZE
describe the virtual section. */
#include "dwarf2/types.h"
struct dwarf2_section_info
{
/* Return the name of this section. */
@ -127,12 +125,4 @@ struct dwarf2_section_info
bool is_virtual;
};
/* A pair-like structure to represent an offset into a section. */
struct section_and_offset
{
const dwarf2_section_info *section;
sect_offset offset;
};
#endif /* GDB_DWARF2_SECTION_H */

View File

@ -124,16 +124,3 @@ dwarf_unit_type_name (int unit_type)
return name;
}
/* See stringify.h. */
const char *
dwarf_source_language_name (unsigned int lang)
{
const char *name = get_DW_LANG_name (lang);
if (name == nullptr)
return dwarf_unknown ("LANG", lang);
return name;
}

View File

@ -38,7 +38,4 @@ extern const char *dwarf_type_encoding_name (unsigned enc);
/* Convert a DWARF unit type into its string name. */
extern const char *dwarf_unit_type_name (int unit_type);
/* Convert a DWARF language into its string name. */
extern const char *dwarf_source_language_name (unsigned int lang);
#endif /* GDB_DWARF2_STRINGIFY_H */

View File

@ -205,8 +205,8 @@ set re \
"( Number of \"partial\" symbols read: $decimal" \
")?( Number of psym tables \\(not yet expanded\\): $decimal" \
")?( Total memory used for psymbol cache: $decimal" \
")?( Number of read units: $decimal" \
" Number of unread units: $decimal" \
")?( Number of read CUs: $decimal" \
" Number of unread CUs: $decimal" \
")? Total memory used for objfile obstack: $decimal" \
" Total memory used for BFD obstack: $decimal" \
" Total memory used for string cache: $decimal" \

View File

@ -1,108 +0,0 @@
# Copyright 2025 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# This is a reproducer for PR 29518:
#
# https://sourceware.org/bugzilla/show_bug.cgi?id=29518
#
# The root cause for the problem was that function
# dwarf2_find_containing_comp_unit was searching the whole "all_units" vector,
# containing both compile units and type units, causing it to sometimes
# erroneously return a type unit. It should have been restricted to searching
# compile units.
#
# To get dwarf2_find_containing_comp_unit to be called and reproduce the
# original bug, we need a value with form DW_FORM_ref_addr pointing to a
# different compile unit. This is produced by `%$int_type` below.
#
# We need enough type units in the "all_units" vector trick the binary search
# in dwarf2_find_containing_comp_unit in returning a type unit instead of a
# compile unit.
#
# Finally, since the type units are sorted after the compile units in the
# "all_units" vector, it helps to have the target compile unit have a section
# offset larger than the type unit. This makes the binary search go towards
# the end of the vector, where type units are located.
load_lib dwarf.exp
require dwarf2_support
standard_testfile main.c .S
set asm_file [standard_output_file $srcfile2]
Dwarf::assemble $asm_file {
global srcfile
declare_labels int_type
# The source CU.
cu {version 5} {
compile_unit {
} {
subprogram {
{MACRO_AT_func {main}}
{type %$int_type}
}
}
}
# Create many TUs.
for {set i 1} {$i < 20} {incr i} {
tu {version 5} $i the_type_i {
type_unit {} {
declare_labels dummy_int_type
the_type_i: structure_type {
{name s}
{byte_size 4 sdata}
} {
member {
{name i}
{type :$dummy_int_type}
}
}
dummy_int_type: base_type {
{name int}
{encoding @DW_ATE_signed}
{byte_size 4 sdata}
}
}
}
}
# The target CU.
cu {version 5} {
compile_unit {
} {
int_type: DW_TAG_base_type {
{DW_AT_byte_size 4 DW_FORM_sdata}
{DW_AT_encoding @DW_ATE_signed}
{DW_AT_name int}
}
}
}
}
if { [prepare_for_testing "failed to prepare" ${testfile} \
[list $srcfile $asm_file] {nodebug}] } {
return -1
}
# Without the corresponding fix, we get:
#
# (gdb) p main
# invalid dwarf2 offset 0x398
#
gdb_test "p main" " = {int \\(void\\)} $hex <main>"

View File

@ -348,6 +348,6 @@ if ![runto_main] {
}
gdb_test "print badval" "value has been optimized out"
gdb_test "print bad_die_val1" \
{DWARF Error: could not find compile or type unit containing offset 0xabcdef11 \[in module .*/varval\]}
"invalid dwarf2 offset 0xabcdef11"
gdb_test "print bad_die_val2" \
"Bad DW_OP_GNU_variable_value DIE\\."

View File

@ -827,92 +827,3 @@ DW_UT (DW_UT_split_type, 0x06)
DW_UT (DW_UT_lo_user, 0x80)
DW_UT (DW_UT_hi_user, 0xff)
DW_END_UT
DW_FIRST_LANG (DW_LANG_C89, 0x0001)
DW_LANG (DW_LANG_C, 0x0002)
DW_LANG (DW_LANG_Ada83, 0x0003)
DW_LANG (DW_LANG_C_plus_plus, 0x0004)
DW_LANG (DW_LANG_Cobol74, 0x0005)
DW_LANG (DW_LANG_Cobol85, 0x0006)
DW_LANG (DW_LANG_Fortran77, 0x0007)
DW_LANG (DW_LANG_Fortran90, 0x0008)
DW_LANG (DW_LANG_Pascal83, 0x0009)
DW_LANG (DW_LANG_Modula2, 0x000a)
/* DWARF 3. */
DW_LANG (DW_LANG_Java, 0x000b)
DW_LANG (DW_LANG_C99, 0x000c)
DW_LANG (DW_LANG_Ada95, 0x000d)
DW_LANG (DW_LANG_Fortran95, 0x000e)
DW_LANG (DW_LANG_PLI, 0x000f)
DW_LANG (DW_LANG_ObjC, 0x0010)
DW_LANG (DW_LANG_ObjC_plus_plus, 0x0011)
DW_LANG (DW_LANG_UPC, 0x0012)
DW_LANG (DW_LANG_D, 0x0013)
/* DWARF 4. */
DW_LANG (DW_LANG_Python, 0x0014)
/* DWARF 5. */
DW_LANG (DW_LANG_OpenCL, 0x0015)
DW_LANG (DW_LANG_Go, 0x0016)
DW_LANG (DW_LANG_Modula3, 0x0017)
DW_LANG (DW_LANG_Haskell, 0x0018)
DW_LANG (DW_LANG_C_plus_plus_03, 0x0019)
DW_LANG (DW_LANG_C_plus_plus_11, 0x001a)
DW_LANG (DW_LANG_OCaml, 0x001b)
DW_LANG (DW_LANG_Rust, 0x001c)
DW_LANG (DW_LANG_C11, 0x001d)
DW_LANG (DW_LANG_Swift, 0x001e)
DW_LANG (DW_LANG_Julia, 0x001f)
DW_LANG (DW_LANG_Dylan, 0x0020)
DW_LANG (DW_LANG_C_plus_plus_14, 0x0021)
DW_LANG (DW_LANG_Fortran03, 0x0022)
DW_LANG (DW_LANG_Fortran08, 0x0023)
DW_LANG (DW_LANG_RenderScript, 0x0024)
DW_LANG (DW_LANG_BLISS, 0x0025)
/* Post DWARF 5 additions to the DWARF set.
See https://dwarfstd.org/languages.html . */
DW_LANG (DW_LANG_Kotlin, 0x0026)
DW_LANG (DW_LANG_Zig, 0x0027)
DW_LANG (DW_LANG_Crystal, 0x0028)
DW_LANG (DW_LANG_C_plus_plus_17, 0x002a)
DW_LANG (DW_LANG_C_plus_plus_20, 0x002b)
DW_LANG (DW_LANG_C17, 0x002c)
DW_LANG (DW_LANG_Fortran18, 0x002d)
DW_LANG (DW_LANG_Ada2005, 0x002e)
DW_LANG (DW_LANG_Ada2012, 0x002f)
DW_LANG (DW_LANG_HIP, 0x0030)
DW_LANG (DW_LANG_Assembly, 0x0031)
DW_LANG (DW_LANG_C_sharp, 0x0032)
DW_LANG (DW_LANG_Mojo, 0x0033)
DW_LANG (DW_LANG_GLSL, 0x0034)
DW_LANG (DW_LANG_GLSL_ES, 0x0035)
DW_LANG (DW_LANG_HLSL, 0x0036)
DW_LANG (DW_LANG_OpenCL_CPP, 0x0037)
DW_LANG (DW_LANG_CPP_for_OpenCL, 0x0038)
DW_LANG (DW_LANG_SYCL, 0x0039)
DW_LANG (DW_LANG_C_plus_plus_23, 0x003a)
DW_LANG (DW_LANG_Odin, 0x003b)
DW_LANG (DW_LANG_P4, 0x003c)
DW_LANG (DW_LANG_Metal, 0x003d)
DW_LANG (DW_LANG_C23, 0x003e)
DW_LANG (DW_LANG_Fortran23, 0x003f)
DW_LANG (DW_LANG_Ruby, 0x0040)
DW_LANG (DW_LANG_Move, 0x0041)
DW_LANG (DW_LANG_Hylo, 0x0042)
DW_LANG (DW_LANG_lo_user, 0x8000) /* Implementation-defined range start. */
DW_LANG (DW_LANG_hi_user, 0xffff) /* Implementation-defined range start. */
/* MIPS. */
DW_LANG (DW_LANG_Mips_Assembler, 0x8001)
/* UPC. */
DW_LANG (DW_LANG_Upc, 0x8765)
/* HP extensions. */
DW_LANG (DW_LANG_HP_Bliss, 0x8003)
DW_LANG (DW_LANG_HP_Basic91, 0x8004)
DW_LANG (DW_LANG_HP_Pascal91, 0x8005)
DW_LANG (DW_LANG_HP_IMacro, 0x8006)
DW_LANG (DW_LANG_HP_Assembler, 0x8007)
/* Rust extension, but replaced in DWARF 5. */
DW_LANG (DW_LANG_Rust_old, 0x9000)
DW_END_LANG

View File

@ -56,7 +56,6 @@
#define DW_IDX(name, value) , name = value
#define DW_IDX_DUP(name, value) , name = value
#define DW_UT(name, value) , name = value
#define DW_LANG(name, value) , name = value
#define DW_FIRST_TAG(name, value) enum dwarf_tag { \
name = value
@ -87,9 +86,6 @@
#define DW_FIRST_UT(name, value) enum dwarf_unit_type { \
name = value
#define DW_END_UT };
#define DW_FIRST_LANG(name, value) enum dwarf_source_language { \
name = value
#define DW_END_LANG };
#include "dwarf2.def"
@ -109,8 +105,6 @@
#undef DW_END_IDX
#undef DW_FIRST_UT
#undef DW_END_UT
#undef DW_FIRST_LANG
#undef DW_END_LANG
#undef DW_TAG
#undef DW_TAG_DUP
@ -126,7 +120,6 @@
#undef DW_IDX
#undef DW_IDX_DUP
#undef DW_UT
#undef DW_LANG
/* Flag that tells whether entry has a child or not. */
#define DW_children_no 0
@ -343,6 +336,98 @@ enum dwarf_location_list_entry_type
#define DW_ADDR_none 0
/* Source language names and codes. */
enum dwarf_source_language
{
DW_LANG_C89 = 0x0001,
DW_LANG_C = 0x0002,
DW_LANG_Ada83 = 0x0003,
DW_LANG_C_plus_plus = 0x0004,
DW_LANG_Cobol74 = 0x0005,
DW_LANG_Cobol85 = 0x0006,
DW_LANG_Fortran77 = 0x0007,
DW_LANG_Fortran90 = 0x0008,
DW_LANG_Pascal83 = 0x0009,
DW_LANG_Modula2 = 0x000a,
/* DWARF 3. */
DW_LANG_Java = 0x000b,
DW_LANG_C99 = 0x000c,
DW_LANG_Ada95 = 0x000d,
DW_LANG_Fortran95 = 0x000e,
DW_LANG_PLI = 0x000f,
DW_LANG_ObjC = 0x0010,
DW_LANG_ObjC_plus_plus = 0x0011,
DW_LANG_UPC = 0x0012,
DW_LANG_D = 0x0013,
/* DWARF 4. */
DW_LANG_Python = 0x0014,
/* DWARF 5. */
DW_LANG_OpenCL = 0x0015,
DW_LANG_Go = 0x0016,
DW_LANG_Modula3 = 0x0017,
DW_LANG_Haskell = 0x0018,
DW_LANG_C_plus_plus_03 = 0x0019,
DW_LANG_C_plus_plus_11 = 0x001a,
DW_LANG_OCaml = 0x001b,
DW_LANG_Rust = 0x001c,
DW_LANG_C11 = 0x001d,
DW_LANG_Swift = 0x001e,
DW_LANG_Julia = 0x001f,
DW_LANG_Dylan = 0x0020,
DW_LANG_C_plus_plus_14 = 0x0021,
DW_LANG_Fortran03 = 0x0022,
DW_LANG_Fortran08 = 0x0023,
DW_LANG_RenderScript = 0x0024,
DW_LANG_BLISS = 0x0025,
/* Post DWARF 5 additions to the DWARF set.
See https://dwarfstd.org/languages.html . */
DW_LANG_Kotlin = 0x0026,
DW_LANG_Zig = 0x0027,
DW_LANG_Crystal = 0x0028,
DW_LANG_C_plus_plus_17 = 0x002a,
DW_LANG_C_plus_plus_20 = 0x002b,
DW_LANG_C17 = 0x002c,
DW_LANG_Fortran18 = 0x002d,
DW_LANG_Ada2005 = 0x002e,
DW_LANG_Ada2012 = 0x002f,
DW_LANG_HIP = 0x0030,
DW_LANG_Assembly = 0x0031,
DW_LANG_C_sharp = 0x0032,
DW_LANG_Mojo = 0x0033,
DW_LANG_GLSL = 0x0034,
DW_LANG_GLSL_ES = 0x0035,
DW_LANG_HLSL = 0x0036,
DW_LANG_OpenCL_CPP = 0x0037,
DW_LANG_CPP_for_OpenCL = 0x0038,
DW_LANG_SYCL = 0x0039,
DW_LANG_C_plus_plus_23 = 0x003a,
DW_LANG_Odin = 0x003b,
DW_LANG_P4 = 0x003c,
DW_LANG_Metal = 0x003d,
DW_LANG_C23 = 0x003e,
DW_LANG_Fortran23 = 0x003f,
DW_LANG_Ruby = 0x0040,
DW_LANG_Move = 0x0041,
DW_LANG_Hylo = 0x0042,
DW_LANG_lo_user = 0x8000, /* Implementation-defined range start. */
DW_LANG_hi_user = 0xffff, /* Implementation-defined range start. */
/* MIPS. */
DW_LANG_Mips_Assembler = 0x8001,
/* UPC. */
DW_LANG_Upc = 0x8765,
/* HP extensions. */
DW_LANG_HP_Bliss = 0x8003,
DW_LANG_HP_Basic91 = 0x8004,
DW_LANG_HP_Pascal91 = 0x8005,
DW_LANG_HP_IMacro = 0x8006,
DW_LANG_HP_Assembler = 0x8007,
/* Rust extension, but replaced in DWARF 5. */
DW_LANG_Rust_old = 0x9000
};
/* Names and codes for macro information. */
enum dwarf_macinfo_record_type
{
@ -500,10 +585,6 @@ extern const char *get_DW_IDX_name (unsigned int idx);
recognized. */
extern const char *get_DW_UT_name (unsigned int ut);
/* Return the name of a DW_LANG_ constant, or NULL if the value is not
recognized. */
extern const char *get_DW_LANG_name (unsigned int lang);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -69,11 +69,6 @@ Boston, MA 02110-1301, USA. */
switch (ut) { \
DW_UT (name, value)
#define DW_END_UT } return 0; }
#define DW_FIRST_LANG(name, value) \
const char *get_DW_LANG_name (unsigned int lang) { \
switch (lang) { \
DW_LANG (name, value)
#define DW_END_LANG } return 0; }
#define DW_TAG(name, value) case name: return # name ;
#define DW_TAG_DUP(name, value)
@ -89,7 +84,6 @@ Boston, MA 02110-1301, USA. */
#define DW_IDX(name, value) case name: return # name ;
#define DW_IDX_DUP(name, value)
#define DW_UT(name, value) case name: return # name ;
#define DW_LANG(name, value) case name: return # name ;
#include "dwarf2.def"
@ -108,8 +102,6 @@ Boston, MA 02110-1301, USA. */
#undef DW_FIRST_IDX
#undef DW_END_IDX
#undef DW_END_UT
#undef DW_FIRST_LANG
#undef DW_END_LANG
#undef DW_TAG
#undef DW_TAG_DUP
@ -124,4 +116,3 @@ Boston, MA 02110-1301, USA. */
#undef DW_CFA_DUP
#undef DW_IDX
#undef DW_IDX_DUP
#undef DW_LANG