[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 */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.