[binutils-gdb] gdb/dwarf: use (section, offset) as stmt_list key
Simon Marchi via Gdb-cvs <[email protected]>
| Newsgroups | gmane.comp.gdb.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=ee43d7c01354d9176b4271ea3f5411e548ddc5f1 commit ee43d7c01354d9176b4271ea3f5411e548ddc5f1 Author: Simon Marchi <[email protected]> Date: Sat Feb 21 15:07:32 2026 -0500 gdb/dwarf: use (section, offset) as stmt_list key It occurred to me that we could use (section, offset-in-section) tuples as the key for a line table, replacing stmt_list_hash, just like we use (section, offset-in-section) as the sort key in the dwarf2_per_bfd::all_units vector. This is functionally the same, the goal is to uniquely identify a line table, but I think it's clearer this way. The tuple (section, offset-in-section) precisely and unambiguously specifies a spot in an object file. This allows deleting some specialized code, and eventually share code with other places that would want to use section_and_offset as a key. Change-Id: I1b45c7f653d71656b964c3f3789d8bb459774340 Approved-By: Tom Tromey <[email protected]> Diff: --- gdb/dwarf2/read.c | 46 ++++++++-------------------------------------- gdb/dwarf2/read.h | 37 +++++++------------------------------ gdb/dwarf2/section.h | 31 +++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 68 deletions(-) diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 0f1bd7cad82..8714d7bb501 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -1526,36 +1526,6 @@ struct readnow_functions : public dwarf2_base_index_functions } }; -/* See read.h. */ - -std::uint64_t -stmt_list_hash_hash::operator() (const stmt_list_hash &key) const noexcept -{ - std::uint64_t v = 0; - - if (key.dwo_unit != nullptr) - v += ankerl::unordered_dense::hash<dwo_file *> () (key.dwo_unit->dwo_file); - - v += (ankerl::unordered_dense::hash<std::uint64_t> () - (to_underlying (key.line_sect_off))); - return v; -} - -/* See read.h. */ - -bool -stmt_list_hash::operator== (const stmt_list_hash &rhs) const noexcept -{ - if ((this->dwo_unit != nullptr) != (rhs.dwo_unit != nullptr)) - return false; - - if (this->dwo_unit != nullptr - && this->dwo_unit->dwo_file != rhs.dwo_unit->dwo_file) - return false; - - return this->line_sect_off == rhs.line_sect_off; -} - /* Read in CU (dwarf2_cu object) for PER_CU in the context of PER_OBJFILE. This function is unrelated to symtabs, symtab would have to be created afterwards. You should call age_cached_comp_units after processing the CU. @@ -1763,7 +1733,7 @@ dw2_get_file_names_reader (dwarf2_cu *cu, die_info *comp_unit_die) line_header_up lh; file_and_directory &fnd = find_file_and_directory (comp_unit_die, cu); - std::optional<stmt_list_hash> stmt_list_hash_key; + std::optional<section_and_offset> stmt_list_key; attribute *attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, cu); if (attr != nullptr && attr->form_is_unsigned ()) @@ -1772,9 +1742,9 @@ dw2_get_file_names_reader (dwarf2_cu *cu, die_info *comp_unit_die) /* We may have already read in this line header (TU line header sharing). If we have we're done. */ - stmt_list_hash_key = {cu->dwo_unit, line_offset}; + stmt_list_key = {get_debug_line_section (cu), line_offset}; - if (auto it = per_bfd->quick_file_names_table.find (*stmt_list_hash_key); + if (auto it = per_bfd->quick_file_names_table.find (*stmt_list_key); it != per_bfd->quick_file_names_table.end ()) { this_cu->file_names = it->second; @@ -1793,8 +1763,8 @@ dw2_get_file_names_reader (dwarf2_cu *cu, die_info *comp_unit_die) auto *qfn = XOBNEW (&per_bfd->obstack, quick_file_names); /* There may not be a DW_AT_stmt_list. */ - if (stmt_list_hash_key.has_value ()) - per_bfd->quick_file_names_table.emplace (*stmt_list_hash_key, qfn); + if (stmt_list_key.has_value ()) + per_bfd->quick_file_names_table.emplace (*stmt_list_key, qfn); std::vector<const char *> include_names; if (lh != nullptr) @@ -3178,7 +3148,7 @@ cutu_reader::cutu_reader (dwarf2_per_cu &this_cu, /* Get the type unit group key for type unit CU. STMT_LIST is a DW_AT_stmt_list attribute. */ -static stmt_list_hash +static section_and_offset get_type_unit_group_key (struct dwarf2_cu *cu, const struct attribute *stmt_list) { dwarf2_per_objfile *per_objfile = cu->per_objfile; @@ -3205,7 +3175,7 @@ get_type_unit_group_key (struct dwarf2_cu *cu, const struct attribute *stmt_list ++tu_stats->nr_stmt_less_type_units; } - return {cu->dwo_unit, static_cast<sect_offset> (line_offset)}; + return {get_debug_line_section (cu), static_cast<sect_offset> (line_offset)}; } /* A subclass of cooked_index_worker that handles scanning @@ -4534,7 +4504,7 @@ rust_union_quirks (struct dwarf2_cu *cu) type_unit_group_unshareable * dwarf2_per_objfile::get_type_unit_group_unshareable - (stmt_list_hash tu_group_key) + (section_and_offset tu_group_key) { auto [it, inserted] = m_type_units.emplace (tu_group_key, nullptr); diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h index dfe0efc0d99..89b1437a849 100644 --- a/gdb/dwarf2/read.h +++ b/gdb/dwarf2/read.h @@ -72,27 +72,6 @@ struct dwarf2_queue_item }; -/* A struct that can be used as a hash key for tables based on DW_AT_stmt_list. - This includes type_unit_group and quick_file_names. */ - -struct stmt_list_hash -{ - bool operator== (const stmt_list_hash &other) const noexcept; - - /* The DWO unit this table is from or NULL if there is none. */ - struct dwo_unit *dwo_unit; - - /* Offset in .debug_line or .debug_line.dwo. */ - sect_offset line_sect_off; -}; - -struct stmt_list_hash_hash -{ - using is_avalanching = void; - - std::uint64_t operator() (const stmt_list_hash &key) const noexcept; -}; - /* A deleter for dwarf2_per_cu that knows to downcast to signatured_type as appropriate. This approach lets us avoid a virtual destructor, which saves a bit of space. */ @@ -453,10 +432,10 @@ struct signatured_type : public dwarf2_per_cu Zero is otherwise not a valid section offset. */ sect_offset type_offset_in_section {}; - /* Type units are grouped by their DW_AT_stmt_list entry so that they - can share them. This is the key of the group this type unit is part - of. */ - std::optional<stmt_list_hash> type_unit_group_key; + /* Type units are grouped by their DW_AT_stmt_list entry (i.e. which line + table they use) so that they can share them. This is the key of the group + this type unit is part of. */ + std::optional<section_and_offset> type_unit_group_key; /* Containing DWO unit. This field is valid iff per_cu.reading_dwo_directly. */ @@ -715,8 +694,7 @@ public: sorted all the TUs into "type unit groups", grouped by their DW_AT_stmt_list value. Therefore the only sharing done here is with a CU and its associated TU group if there is one. */ - gdb::unordered_map<stmt_list_hash, quick_file_names *, stmt_list_hash_hash> - quick_file_names_table; + unordered_section_and_offset_map<quick_file_names *> quick_file_names_table; /* If we loaded the index from an external file, this contains the resources associated to the open file, memory mapping, etc. */ @@ -919,7 +897,7 @@ struct dwarf2_per_objfile /* Get the type_unit_group_unshareable corresponding to TU_GROUP_KEY. If one does not exist, create it. */ type_unit_group_unshareable *get_type_unit_group_unshareable - (stmt_list_hash tu_group_key); + (section_and_offset tu_group_key); struct type *get_type_for_signatured_type (signatured_type *sig_type) const; @@ -990,8 +968,7 @@ private: /* Map from a type unit group key to the corresponding unshared structure. */ - gdb::unordered_map<stmt_list_hash, type_unit_group_unshareable_up, - stmt_list_hash_hash> + unordered_section_and_offset_map<type_unit_group_unshareable_up> m_type_units; /* Map from signatured types to the corresponding struct type. */ diff --git a/gdb/dwarf2/section.h b/gdb/dwarf2/section.h index e63c21d8685..34a1810a387 100644 --- a/gdb/dwarf2/section.h +++ b/gdb/dwarf2/section.h @@ -27,6 +27,8 @@ #ifndef GDB_DWARF2_SECTION_H #define GDB_DWARF2_SECTION_H +#include "gdbsupport/unordered_map.h" + /* A descriptor for dwarf sections. S.ASECTION, SIZE are typically initialized when the objfile is first @@ -124,4 +126,33 @@ struct section_and_offset sect_offset offset; }; +/* Hash function for section_and_offset. */ + +struct section_and_offset_hash +{ + template <typename T> + using hash = ankerl::unordered_dense::hash<T>; + using is_avalanching = void; + + std::uint64_t operator() (const section_and_offset &sao) const noexcept + { + return (hash<const dwarf2_section_info *> () (sao.section) + + hash<sect_offset> () (sao.offset)); + } +}; + +/* Equality function for section_and_offset. */ + +struct section_and_offset_eq +{ + bool operator() (const section_and_offset &a, + const section_and_offset &b) const noexcept + { return a.section == b.section && a.offset == b.offset; } +}; + +template<typename Value> +using unordered_section_and_offset_map + = gdb::unordered_map<section_and_offset, Value, + section_and_offset_hash, section_and_offset_eq>; + #endif /* GDB_DWARF2_SECTION_H */