From: Simon Marchi Date: Mon, 10 Mar 2025 20:14:35 +0000 (-0400) Subject: Revert past commits X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c19c928f7b303697345ea368923cc798cad2102d;p=thirdparty%2Fbinutils-gdb.git 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 --- diff --git a/gdb/dwarf2/cooked-index.h b/gdb/dwarf2/cooked-index.h index d9c8ae2d3d0..4c35d5b65dd 100644 --- a/gdb/dwarf2/cooked-index.h +++ b/gdb/dwarf2/cooked-index.h @@ -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 { diff --git a/gdb/dwarf2/cooked-indexer.c b/gdb/dwarf2/cooked-indexer.c index e343bbe85c6..18c9c3b2459 100644 --- a/gdb/dwarf2/cooked-indexer.c +++ b/gdb/dwarf2/cooked-indexer.c @@ -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 §ion, - 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 == §ion + 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 origin; + sect_offset origin_offset {}; + std::optional low_pc; std::optional 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 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); diff --git a/gdb/dwarf2/cooked-indexer.h b/gdb/dwarf2/cooked-indexer.h index 3db6e8b3666..a33f5d18c47 100644 --- a/gdb/dwarf2/cooked-indexer.h +++ b/gdb/dwarf2/cooked-indexer.h @@ -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 §ion, - 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 diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c index ddb8517a018..9d876b1b93c 100644 --- a/gdb/dwarf2/index-write.c +++ b/gdb/dwarf2/index-write.c @@ -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 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); diff --git a/gdb/dwarf2/read-debug-names.c b/gdb/dwarf2/read-debug-names.c index b7d771d0986..6e9ea667c3a 100644 --- a/gdb/dwarf2/read-debug-names.c +++ b/gdb/dwarf2/read-debug-names.c @@ -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 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 type_units_table; - struct index_val { ULONGEST dwarf_tag; @@ -122,14 +114,6 @@ struct mapped_debug_names_reader gdb::unordered_map 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 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 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 §ion, - bool is_dwz) +check_cus_from_debug_names_list (dwarf2_per_bfd *per_bfd, + const mapped_debug_names_reader &map, + dwarf2_section_info §ion, + 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; } diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c index 907aecb270a..f6c73d0c98a 100644 --- a/gdb/dwarf2/read-gdb-index.c +++ b/gdb/dwarf2/read-gdb-index.c @@ -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 units; - /* The address table data. */ gdb::array_view 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 &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 &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 &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); diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index f74f05f4025..a25daa36d38 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -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 (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 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 (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 (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 -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 (*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 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 §ion - = 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 (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 §ion = 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 (§ion != 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 §ion - = 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 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 §ion, - sect_offset sect_off, - const std::vector &all_units) +static int +dwarf2_find_containing_comp_unit + (sect_offset sect_off, + unsigned int offset_in_dwz, + const std::vector &all_units) { - auto it = std::lower_bound (all_units.begin (), all_units.end (), - section_and_offset { §ion, sect_off }, - [] (const dwarf2_per_cu_up &per_cu, - const section_and_offset &key) - { - return all_units_less_than - (*per_cu, key); - }); - - if (it == all_units.begin ()) - return sect_off >= (*it)->sect_off ? it->get () : nullptr; + int low, high; - if (it == all_units.end ()) - return 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 (); - 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 §ion, - 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 (0x4000); - auto &dwz_section = *reinterpret_cast(0x5000); + char dummy_section; - const auto create_dummy_per_cu = [&] (dwarf2_section_info §ion, - 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 (&dummy_per_bfd); + auto section = reinterpret_cast (&dummy_section); - return dwarf2_per_cu_up (new dwarf2_per_cu (per_bfd, §ion, 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 units; @@ -19847,21 +19763,21 @@ run_test () units.push_back (std::move (three)); units.push_back (std::move (four)); - dwarf2_per_cu *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_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); + int result; + + 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_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); } } diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index 4961c4dd1c8..e178c60509e 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -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 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 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 all_comp_units; + gdb::array_view all_type_units; + + std::vector all_comp_units_index_cus; + std::vector 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 §ion, 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 */ diff --git a/gdb/dwarf2/section.h b/gdb/dwarf2/section.h index 9b0a408e9f7..09bddd4fd47 100644 --- a/gdb/dwarf2/section.h +++ b/gdb/dwarf2/section.h @@ -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 */ diff --git a/gdb/dwarf2/stringify.c b/gdb/dwarf2/stringify.c index 98d7c7029d3..1a4e280fc76 100644 --- a/gdb/dwarf2/stringify.c +++ b/gdb/dwarf2/stringify.c @@ -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; -} diff --git a/gdb/dwarf2/stringify.h b/gdb/dwarf2/stringify.h index 6dbde678f18..1fb7ab3f5de 100644 --- a/gdb/dwarf2/stringify.h +++ b/gdb/dwarf2/stringify.h @@ -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 */ diff --git a/gdb/testsuite/gdb.base/maint.exp b/gdb/testsuite/gdb.base/maint.exp index 708ae3a12ce..c77612d845b 100644 --- a/gdb/testsuite/gdb.base/maint.exp +++ b/gdb/testsuite/gdb.base/maint.exp @@ -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" \ diff --git a/gdb/testsuite/gdb.dwarf2/dw-form-ref-addr-with-type-units.exp b/gdb/testsuite/gdb.dwarf2/dw-form-ref-addr-with-type-units.exp deleted file mode 100644 index ba5c3fb0f57..00000000000 --- a/gdb/testsuite/gdb.dwarf2/dw-form-ref-addr-with-type-units.exp +++ /dev/null @@ -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 . - -# 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
" diff --git a/gdb/testsuite/gdb.dwarf2/varval.exp b/gdb/testsuite/gdb.dwarf2/varval.exp index a8b29f43ff5..5c4af784d5f 100644 --- a/gdb/testsuite/gdb.dwarf2/varval.exp +++ b/gdb/testsuite/gdb.dwarf2/varval.exp @@ -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\\." diff --git a/include/dwarf2.def b/include/dwarf2.def index b992633cb65..6d6c0e0cc39 100644 --- a/include/dwarf2.def +++ b/include/dwarf2.def @@ -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 diff --git a/include/dwarf2.h b/include/dwarf2.h index 69aa86536d4..0b193a250de 100644 --- a/include/dwarf2.h +++ b/include/dwarf2.h @@ -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 */ diff --git a/libiberty/dwarfnames.c b/libiberty/dwarfnames.c index 4de143d5b38..cf0780cfa31 100644 --- a/libiberty/dwarfnames.c +++ b/libiberty/dwarfnames.c @@ -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