[binutils-gdb] gdb/dwarf: use gdb::unordered_map for line headers

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=34909f3a1dea81b0b83654c0de9375be20ac3d3b

commit 34909f3a1dea81b0b83654c0de9375be20ac3d3b
Author: Simon Marchi <[email protected]>
Date:   Sat Feb 21 15:07:34 2026 -0500

    gdb/dwarf: use gdb::unordered_map for line headers
    
    Change htab_t for gdb::unordered_map, more specifically the
    unordered_section_and_offset_map specialization.
    
    It is no longer necessary to keep the section and offset inside the
    line_header structure itself, because it's just used for the map key, so
    remove that.
    
    I tried my best to preserve the logic in decode_line_header_for_cu, but
    I don't fully understand it.
    
    Change-Id: I512652e6da8b25db77ac9974135f9a06ce3d831e
    Approved-By: Tom Tromey <[email protected]>

Diff:
---
 gdb/dwarf2/cu.h          |   2 +-
 gdb/dwarf2/line-header.h |   9 ----
 gdb/dwarf2/read.c        | 105 +++++++++++++++--------------------------------
 gdb/dwarf2/read.h        |   2 +-
 4 files changed, 36 insertions(+), 82 deletions(-)

diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h
index 182871295c8..41c1d5717cd 100644
--- a/gdb/dwarf2/cu.h
+++ b/gdb/dwarf2/cu.h
@@ -342,7 +342,7 @@ public:
   /* Header data from the line table, during full symbol processing.  */
   struct line_header *line_header = nullptr;
   /* Non-NULL if LINE_HEADER is owned by this DWARF_CU.  Otherwise,
-     it's owned by dwarf2_per_bfd::line_header_hash.  If non-NULL,
+     it's owned by dwarf2_per_objfile::line_headers.  If non-NULL,
      this is the DW_TAG_compile_unit die for this CU.  We'll hold on
      to the line header as long as this DIE is being processed.  See
      process_die_scope.  */
diff --git a/gdb/dwarf2/line-header.h b/gdb/dwarf2/line-header.h
index 6c8d62d6ae2..06ce5f0e124 100644
--- a/gdb/dwarf2/line-header.h
+++ b/gdb/dwarf2/line-header.h
@@ -92,12 +92,6 @@ struct line_header
     : m_comp_dir (comp_dir)
   {}
 
-  /* This constructor should only be used to create line_header instances to do
-     hash table lookups.  */
-  line_header (section_and_offset sect_and_offset)
-    : sect_and_offset (sect_and_offset)
-  {}
-
   /* Add an entry to the include directory table.  */
   void add_include_dir (const char *include_dir);
 
@@ -156,9 +150,6 @@ struct line_header
   const std::vector<file_entry> &file_names () const
   { return m_file_names; }
 
-  /* Section containing this line header, and its offset into that section.  */
-  section_and_offset sect_and_offset;
-
   unsigned short version {};
   unsigned char minimum_instruction_length {};
   unsigned char maximum_ops_per_instruction {};
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index fbe0b0bdbec..2f27a9ac75f 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -1029,36 +1029,6 @@ dwarf2_per_objfile::relocate (unrelocated_addr addr)
   return gdbarch_adjust_dwarf2_addr (objfile->arch (), tem);
 }
 
-/* Hash function for line_header_hash.  */
-
-static hashval_t
-line_header_hash (const struct line_header *ofs)
-{
-  return section_and_offset_hash () (ofs->sect_and_offset);
-}
-
-/* Hash function for htab_create_alloc_ex for line_header_hash.  */
-
-static hashval_t
-line_header_hash_voidp (const void *item)
-{
-  const struct line_header *ofs = (const struct line_header *) item;
-
-  return line_header_hash (ofs);
-}
-
-/* Equality function for line_header_hash.  */
-
-static int
-line_header_eq_voidp (const void *item_lhs, const void *item_rhs)
-{
-  const struct line_header *ofs_lhs = (const struct line_header *) item_lhs;
-  const struct line_header *ofs_rhs = (const struct line_header *) item_rhs;
-
-  return section_and_offset_eq () (ofs_lhs->sect_and_offset,
-				   ofs_rhs->sect_and_offset);
-}
-
 /* See declaration.  */
 
 dwarf2_per_bfd::dwarf2_per_bfd (bfd *obfd, const dwarf2_debug_sections *names,
@@ -5792,32 +5762,22 @@ decode_line_header_for_cu (struct die_info *die, struct dwarf2_cu *cu,
      compile_unit, then use the line header hash table if it's already
      created, but don't create one just yet.  */
 
-  if (per_objfile->line_header_hash == NULL
+  if (!per_objfile->line_headers.has_value ()
       && die->tag == DW_TAG_partial_unit)
-    {
-      per_objfile->line_header_hash
-	.reset (htab_create_alloc (127, line_header_hash_voidp,
-				   line_header_eq_voidp,
-				   htab_delete_entry<line_header>,
-				   xcalloc, xfree));
-    }
+    per_objfile->line_headers.emplace ();
 
-  void **slot;
-  line_header line_header_local ({ get_debug_line_section (cu), line_offset });
-  hashval_t line_header_local_hash = line_header_hash (&line_header_local);
-  if (per_objfile->line_header_hash != NULL)
-    {
-      slot = htab_find_slot_with_hash (per_objfile->line_header_hash.get (),
-				       &line_header_local,
-				       line_header_local_hash, NO_INSERT);
+  section_and_offset sao {get_debug_line_section (cu), line_offset};
 
-      /* For DW_TAG_compile_unit we need info like symtab::linetable which
-	 is not present in *SLOT (since if there is something in *SLOT then
-	 it will be for a partial_unit).  */
-      if (die->tag == DW_TAG_partial_unit && slot != NULL)
+  /* For DW_TAG_compile_unit we need info like symtab::linetable which is not
+     present in the LINE_HEADERS hash table (since if there is something in the
+     hash table, it will be for a partial_unit).  */
+  if (die->tag == DW_TAG_partial_unit
+      && per_objfile->line_headers.has_value ())
+    {
+      if (auto line_header_it = per_objfile->line_headers->find (sao);
+	  line_header_it != per_objfile->line_headers->end ())
 	{
-	  gdb_assert (*slot != NULL);
-	  cu->line_header = (struct line_header *) *slot;
+	  cu->line_header = line_header_it->second.get ();
 	  return;
 	}
     }
@@ -5832,29 +5792,32 @@ decode_line_header_for_cu (struct die_info *die, struct dwarf2_cu *cu,
   cu->line_header = lh.release ();
   cu->line_header_die_owner = die;
 
-  if (per_objfile->line_header_hash == NULL)
-    slot = NULL;
-  else
-    {
-      slot = htab_find_slot_with_hash (per_objfile->line_header_hash.get (),
-				       &line_header_local,
-				       line_header_local_hash, INSERT);
-      gdb_assert (slot != NULL);
-    }
-  if (slot != NULL && *slot == NULL)
+  bool inserted = false;
+
+  if (per_objfile->line_headers.has_value ())
     {
-      /* This newly decoded line number information unit will be owned
-	 by line_header_hash hash table.  */
-      *slot = cu->line_header;
-      cu->line_header_die_owner = NULL;
+      auto [_, inserted_]
+	= per_objfile->line_headers->try_emplace (sao, cu->line_header);
+      inserted = inserted_;
+
+      if (inserted)
+	{
+	  /* There was no existing entry for this key.  The new line_header
+	     will be owned by the line_headers hash table.  */
+	  cu->line_header_die_owner = nullptr;
+	}
     }
-  else
+
+  if (!inserted)
     {
-      /* We cannot free any current entry in (*slot) as that struct line_header
-	 may be already used by multiple CUs.  Create only temporary decoded
+      /* There is already an existing line table with this key, or we're not
+	 using the line_headers hash table.
+
+	 We cannot free an existing entry, as that struct line_header may
+	 be already used by multiple CUs.  Create only temporary decoded
 	 line_header for this CU - it may happen at most once for each line
-	 number information unit.  And if we're not using line_header_hash
-	 then this is what we want as well.  */
+	 number information unit.  And if we're not using the line_headers
+	 hash table then this is what we want as well.  */
       gdb_assert (die->tag != DW_TAG_partial_unit);
     }
 
diff --git a/gdb/dwarf2/read.h b/gdb/dwarf2/read.h
index 5dd7a0993a3..e2d75e16146 100644
--- a/gdb/dwarf2/read.h
+++ b/gdb/dwarf2/read.h
@@ -952,7 +952,7 @@ struct dwarf2_per_objfile
     die_type_hash;
 
   /* Table containing line_header indexed by (section, offset-in-section).  */
-  htab_up line_header_hash;
+  std::optional<unordered_section_and_offset_map<line_header_up>> line_headers;
 
   /* The CU containing the m_builder in scope.  */
   dwarf2_cu *sym_cu = nullptr;
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.