]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/dwarf: use (section, offset) as stmt_list key
authorSimon Marchi <simon.marchi@efficios.com>
Sat, 21 Feb 2026 20:07:32 +0000 (15:07 -0500)
committerSimon Marchi <simon.marchi@polymtl.ca>
Tue, 10 Mar 2026 17:35:25 +0000 (13:35 -0400)
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 <tom@tromey.com>
gdb/dwarf2/read.c
gdb/dwarf2/read.h
gdb/dwarf2/section.h

index 0f1bd7cad8252a5d538ac2b9c6f48e9bdec7765c..8714d7bb501c02e893836961668970e65d03bcac 100644 (file)
@@ -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);
 
index dfe0efc0d99ebfaed2cfe336fb984e889a32c3e0..89b1437a849d6d684911d75f7e30fdb3575e3a5c 100644 (file)
@@ -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.  */
index e63c21d86851439b67809034e2be3a8aa59ec78a..34a1810a387f5ea688cded7482385cb69c1d4ecd 100644 (file)
@@ -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 */