diff options
Diffstat (limited to 'gdb/dwarf2/index-write.c')
-rw-r--r-- | gdb/dwarf2/index-write.c | 182 |
1 files changed, 97 insertions, 85 deletions
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c index 70688d7..0a3b9d0 100644 --- a/gdb/dwarf2/index-write.c +++ b/gdb/dwarf2/index-write.c @@ -1,6 +1,6 @@ /* DWARF index writing support for GDB. - Copyright (C) 1994-2024 Free Software Foundation, Inc. + Copyright (C) 1994-2025 Free Software Foundation, Inc. This file is part of GDB. @@ -38,15 +38,11 @@ #include "objfiles.h" #include "ada-lang.h" #include "dwarf2/tag.h" -#include "gdbsupport/gdb_tilde_expand.h" #include "dwarf2/read-debug-names.h" #include "extract-store-integer.h" #include <algorithm> -#include <cmath> #include <map> -#include <unordered_map> -#include <unordered_set> /* Ensure only legit values are used. */ #define DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE(cu_index, value) \ @@ -132,6 +128,15 @@ public: ::store_unsigned_integer (grow (len), len, byte_order, val); } + /* Accept a host-format integer in VAL and write it in the buffer at offset + OFFSET as a target-format integer which is LEN bytes long. */ + void write_uint (size_t offset, size_t len, bfd_endian byte_order, + ULONGEST val) + { + gdb_assert (offset + len <= m_vec.size ()); + ::store_unsigned_integer (&m_vec[offset], len, byte_order, val); + } + /* Copy VALUE to the end of the buffer, little-endian. */ void append_offset (offset_type value) { @@ -307,7 +312,8 @@ mapped_symtab::hash_expand () /* See mapped_symtab class declaration. */ -void mapped_symtab::sort () +void +mapped_symtab::sort () { /* Move contents out of this->data vector. */ std::vector<symtab_index_entry> original_data = std::move (m_data); @@ -425,7 +431,7 @@ symtab_index_entry::minimize () this, we want to keep the entry from the first CU -- but this is implicit due to the sort. This choice is done because it's similar to what gdb historically did for partial symbols. */ - std::unordered_set<offset_type> seen; + gdb::unordered_set<offset_type> seen; from = std::remove_if (cu_indices.begin (), cu_indices.end (), [&] (offset_type val) { @@ -471,7 +477,7 @@ private: const char *const m_cstr; }; -/* A std::unordered_map::hasher for c_str_view that uses the right +/* A gdb::unordered_map::hasher for c_str_view that uses the right hash function for strings in a mapped index. */ class c_str_view_hasher { @@ -482,7 +488,7 @@ public: } }; -/* A std::unordered_map::hasher for std::vector<>. */ +/* A gdb::unordered_map::hasher for std::vector<>. */ template<typename T> class vector_hasher { @@ -503,7 +509,7 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool) { /* Elements are sorted vectors of the indices of all the CUs that hold an object of this name. */ - std::unordered_map<std::vector<offset_type>, offset_type, + gdb::unordered_map<std::vector<offset_type>, offset_type, vector_hasher<offset_type>> symbol_hash_table; @@ -530,7 +536,7 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool) } /* Now write out the hash table. */ - std::unordered_map<c_str_view, offset_type, c_str_view_hasher> str_table; + gdb::unordered_map<c_str_view, offset_type, c_str_view_hasher> str_table; for (const auto &entry : *symtab) { offset_type str_off, vec_off; @@ -556,8 +562,7 @@ write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool) } } -using cu_index_map - = std::unordered_map<const dwarf2_per_cu_data *, unsigned int>; +using cu_index_map = gdb::unordered_map<const dwarf2_per_cu *, unsigned int>; /* Helper struct for building the address table. */ struct addrmap_index_data @@ -598,8 +603,7 @@ add_address_entry (data_buf &addr_vec, int addrmap_index_data::operator() (CORE_ADDR start_addr, const void *obj) { - const dwarf2_per_cu_data *per_cu - = static_cast<const dwarf2_per_cu_data *> (obj); + const dwarf2_per_cu *per_cu = static_cast<const dwarf2_per_cu *> (obj); if (previous_valid) add_address_entry (addr_vec, @@ -672,15 +676,11 @@ public: /* Insert one symbol. */ void insert (const cooked_index_entry *entry) { - /* These entries are synthesized by the reader, and so should not - be written. */ - if (entry->lang == language_ada && entry->tag == DW_TAG_namespace) + /* Synthesized entries should not be written. */ + if ((entry->flags & IS_SYNTHESIZED) != 0) return; - const auto insertpair - = m_name_to_value_set.try_emplace (c_str_view (entry->name)); - entry_list &elist = insertpair.first->second; - elist.entries.push_back (entry); + m_name_to_value_set[entry->name].emplace_back (entry); } /* Build all the tables. All symbols must be already inserted. @@ -694,25 +694,16 @@ public: m_name_table_string_offs.reserve (name_count); m_name_table_entry_offs.reserve (name_count); - /* The name table is indexed from 1. The numbers are needed here - so that parent entries can be handled correctly. */ - int next_name = 1; - for (auto &item : m_name_to_value_set) - item.second.index = next_name++; - /* The next available abbrev number. */ int next_abbrev = 1; - for (auto &item : m_name_to_value_set) + for (auto &[name, these_entries] : m_name_to_value_set) { - const c_str_view &name = item.first; - entry_list &these_entries = item.second; - /* Sort the items within each bucket. This ensures that the generated index files will be the same no matter the order in which symbols were added into the index. */ - std::sort (these_entries.entries.begin (), - these_entries.entries.end (), + std::sort (these_entries.begin (), + these_entries.end (), [] (const cooked_index_entry *a, const cooked_index_entry *b) { @@ -732,16 +723,16 @@ public: (m_debugstrlookup.lookup (name.c_str ())); /* ??? */ m_name_table_entry_offs.push_back_reorder (m_entry_pool.size ()); - for (const cooked_index_entry *entry : these_entries.entries) + for (const cooked_index_entry *entry : these_entries) { unit_kind kind = (entry->per_cu->is_debug_types ? unit_kind::tu : unit_kind::cu); - /* Currently Ada parentage is synthesized by the - reader and so must be ignored here. */ - const cooked_index_entry *parent = (entry->lang == language_ada - ? nullptr - : entry->get_parent ()); + /* Some Ada parentage is synthesized by the reader and so + must be ignored here. */ + const cooked_index_entry *parent = entry->get_parent (); + if (parent != nullptr && (parent->flags & IS_SYNTHESIZED) != 0) + parent = nullptr; int &idx = m_indexkey_to_idx[index_key (entry->tag, kind, @@ -762,7 +753,8 @@ public: m_abbrev_table.append_unsigned_leb128 (DW_FORM_ref_addr); m_abbrev_table.append_unsigned_leb128 (DW_IDX_GNU_language); m_abbrev_table.append_unsigned_leb128 (DW_FORM_udata); - if ((entry->flags & IS_STATIC) != 0) + if (!tag_is_type (entry->tag) + && (entry->flags & IS_STATIC) != 0) { m_abbrev_table.append_unsigned_leb128 (DW_IDX_GNU_internal); m_abbrev_table.append_unsigned_leb128 (DW_FORM_flag_present); @@ -780,7 +772,7 @@ public: if (parent != nullptr) { m_abbrev_table.append_unsigned_leb128 (DW_IDX_parent); - m_abbrev_table.append_unsigned_leb128 (DW_FORM_udata); + m_abbrev_table.append_unsigned_leb128 (DW_FORM_data4); } /* Terminate attributes list. */ @@ -788,6 +780,14 @@ public: m_abbrev_table.append_unsigned_leb128 (0); } + /* Record the offset in the pool at which this entry will + reside. */ + const auto offset_inserted + = (m_entry_pool_offsets.emplace (entry, m_entry_pool.size ()) + .second); + gdb_assert (offset_inserted); + + /* Write the entry to the pool. */ m_entry_pool.append_unsigned_leb128 (idx); const auto it = m_cu_index_htab.find (entry->per_cu); @@ -802,11 +802,11 @@ public: if (parent != nullptr) { - c_str_view par_name (parent->name); - auto name_iter = m_name_to_value_set.find (par_name); - gdb_assert (name_iter != m_name_to_value_set.end ()); - gdb_assert (name_iter->second.index != 0); - m_entry_pool.append_unsigned_leb128 (name_iter->second.index); + m_offsets_to_patch.emplace_back (m_entry_pool.size (), parent); + + /* Write a dummy number, this gets patched later. */ + m_entry_pool.append_uint (4, m_dwarf5_byte_order, + 0xfafafafa); } } @@ -816,6 +816,15 @@ public: /* Terminate tags list. */ m_abbrev_table.append_unsigned_leb128 (0); + + /* Write the parent offset values. */ + for (const auto &[reloc_offset, parent] : m_offsets_to_patch) + { + const auto parent_offset_it = m_entry_pool_offsets.find (parent); + gdb_assert (parent_offset_it != m_entry_pool_offsets.cend ()); + m_entry_pool.write_uint (reloc_offset, 4, m_dwarf5_byte_order, + parent_offset_it->second); + } } /* Return .debug_names names count. This must be called only after @@ -863,7 +872,7 @@ public: m_debugstrlookup.file_write (file_str); } - void add_cu (dwarf2_per_cu_data *per_cu, offset_type index) + void add_cu (dwarf2_per_cu *per_cu, offset_type index) { m_cu_index_htab.emplace (per_cu, index); } @@ -878,8 +887,7 @@ private: /* Object constructor to be called for current DWARF2_PER_BFD. */ debug_str_lookup (dwarf2_per_bfd *per_bfd) - : m_abfd (per_bfd->obfd), - m_per_bfd (per_bfd) + : m_per_bfd (per_bfd) { } @@ -912,8 +920,7 @@ private: } private: - std::unordered_map<c_str_view, size_t, c_str_view_hasher> m_str_table; - bfd *const m_abfd; + gdb::unordered_map<c_str_view, size_t, c_str_view_hasher> m_str_table; dwarf2_per_bfd *m_per_bfd; /* Data to add at the end of .debug_str for new needed symbol names. */ @@ -951,7 +958,7 @@ private: const bool has_parent; }; - /* Provide std::unordered_map::hasher for index_key. */ + /* Provide gdb::unordered_map::hasher for index_key. */ class index_key_hasher { public: @@ -1061,15 +1068,26 @@ private: offset_vec_tmpl<OffsetSize> m_name_table_entry_offs; }; - struct entry_list - { - unsigned index = 0; - std::vector<const cooked_index_entry *> entries; - }; + /* Store the index entries for each name. + + Note that we rely on the sorting behavior of map to make the output + stable. */ + std::map<c_str_view, std::vector<const cooked_index_entry *>> + m_name_to_value_set; + + /* Offset at which each entry is written in the entry pool. */ + gdb::unordered_map<const cooked_index_entry *, offset_type> + m_entry_pool_offsets; + + /* The locations where we need to patch offset to entries. - /* Store value of each symbol. Note that we rely on the sorting - behavior of map to make the output stable. */ - std::map<c_str_view, entry_list> m_name_to_value_set; + The first element of the pair is the offset into the pool that needs to + be patched. + + The second element is the entry the offset to which needs to be + patched in. */ + std::vector<std::pair<offset_type, const cooked_index_entry *>> + m_offsets_to_patch; const bfd_endian m_dwarf5_byte_order; dwarf_tmpl<uint32_t> m_dwarf32; @@ -1080,7 +1098,7 @@ private: /* Map each used .debug_names abbreviation tag parameter to its index value. */ - std::unordered_map<index_key, int, index_key_hasher> m_indexkey_to_idx; + gdb::unordered_map<index_key, int, index_key_hasher> m_indexkey_to_idx; /* .debug_names abbreviation table. */ data_buf m_abbrev_table; @@ -1260,7 +1278,7 @@ write_shortcuts_table (cooked_index *table, data_buf &shortcuts, if (dw_lang != 0) { auto_obstack obstack; - const auto main_name = main_info->full_name (&obstack, true); + const auto main_name = main_info->full_name (&obstack, FOR_MAIN); main_name_offset = cpool.size (); cpool.append_cstr0 (main_name); @@ -1284,10 +1302,9 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table, data_buf objfile_cu_list; data_buf dwz_cu_list; - /* While we're scanning CU's create a table that maps a dwarf2_per_cu_data - (which is what addrmap records) to its index (which is what is recorded - in the index file). This will later be needed to write the address - table. */ + /* While we're scanning CU's create a table that maps a dwarf2_per_cu (which + is what addrmap records) to its index (which is what is recorded in the + index file). This will later be needed to write the address table. */ cu_index_map cu_index_htab; cu_index_htab.reserve (per_bfd->all_units.size ()); @@ -1298,11 +1315,9 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table, work here. */ int counter = 0; - for (int i = 0; i < per_bfd->all_units.size (); ++i) + for (const dwarf2_per_cu_up &per_cu : per_bfd->all_units) { - dwarf2_per_cu_data *per_cu = per_bfd->all_units[i].get (); - - const auto insertpair = cu_index_htab.emplace (per_cu, counter); + const auto insertpair = cu_index_htab.emplace (per_cu.get (), counter); gdb_assert (insertpair.second); /* See enhancement PR symtab/30838. */ @@ -1318,7 +1333,7 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table, to_underlying (per_cu->sect_off)); if (per_cu->is_debug_types) { - signatured_type *sig_type = (signatured_type *) per_cu; + signatured_type *sig_type = (signatured_type *) per_cu.get (); cu_list.append_uint (8, BFD_ENDIAN_LITTLE, to_underlying (sig_type->type_offset_in_tu)); cu_list.append_uint (8, BFD_ENDIAN_LITTLE, @@ -1335,7 +1350,8 @@ write_gdbindex (dwarf2_per_bfd *per_bfd, cooked_index *table, /* Dump the address map. */ data_buf addr_vec; for (auto map : table->get_addrmaps ()) - write_address_map (map, addr_vec, cu_index_htab); + if (map != nullptr) + write_address_map (map, addr_vec, cu_index_htab); /* Ensure symbol hash is built domestically. */ symtab.sort (); @@ -1380,14 +1396,12 @@ 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 (int i = 0; i < per_bfd->all_units.size (); ++i) + for (const dwarf2_per_cu_up &per_cu : per_bfd->all_units) { - dwarf2_per_cu_data *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, this_counter); + nametable.add_cu (per_cu.get (), this_counter); this_list.append_uint (nametable.dwarf5_offset_size (), dwarf5_byte_order, to_underlying (per_cu->sect_off)); @@ -1408,7 +1422,7 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table, const offset_type bytes_of_header = ((dwarf5_is_dwarf64 ? 12 : 4) + 2 + 2 + 7 * 4 - + sizeof (dwarf5_augmentation)); + + sizeof (dwarf5_augmentation_3)); size_t expected_bytes = 0; expected_bytes += bytes_of_header; expected_bytes += cu_list.size (); @@ -1460,9 +1474,9 @@ write_debug_names (dwarf2_per_bfd *per_bfd, cooked_index *table, /* augmentation_string_size - The size in bytes of the augmentation string. This value is rounded up to a multiple of 4. */ - static_assert (sizeof (dwarf5_augmentation) % 4 == 0); - header.append_uint (4, dwarf5_byte_order, sizeof (dwarf5_augmentation)); - header.append_array (dwarf5_augmentation); + static_assert (sizeof (dwarf5_augmentation_3) % 4 == 0); + header.append_uint (4, dwarf5_byte_order, sizeof (dwarf5_augmentation_3)); + header.append_array (dwarf5_augmentation_3); gdb_assert (header.size () == bytes_of_header); @@ -1660,7 +1674,7 @@ save_gdb_index_command (const char *args, int from_tty) try { const char *basename = lbasename (objfile_name (objfile)); - const dwz_file *dwz = dwarf2_get_dwz_file (per_objfile->per_bfd); + const dwz_file *dwz = per_objfile->per_bfd->get_dwz_file (); const char *dwz_basename = NULL; if (dwz != NULL) @@ -1754,9 +1768,7 @@ gdb_index () } /* selftests namespace. */ #endif -void _initialize_dwarf_index_write (); -void -_initialize_dwarf_index_write () +INIT_GDB_FILE (dwarf_index_write) { #if GDB_SELF_TEST selftests::register_test ("gdb_index", selftests::gdb_index); |