[PATCH v2] dwarf_tag.c: Protect cu->last_abbrev_offset with lock

Aaron Merey amerey@redhat.com
Thu Feb 26 18:41:27 GMT 2026


Acquire abbrev_lock before reading cu->last_abbrev_offset in dwarf_tag.

Also double check for abbrev hash table entry once lock is held to
avoid multiple threads attempting to populate the abbrev hash table.

Signed-off-by: Aaron Merey <amerey@redhat.com>
---

v2: Refactor based on Mark's suggestion:
https://patchwork.sourceware.org/project/elfutils/patch/20260209131642.2681308-1-amerey@redhat.com/#224420

 libdw/dwarf_tag.c | 58 +++++++++++++++++++++++++++--------------------
 1 file changed, 34 insertions(+), 24 deletions(-)

diff --git a/libdw/dwarf_tag.c b/libdw/dwarf_tag.c
index 7daa4813..9dfb653e 100644
--- a/libdw/dwarf_tag.c
+++ b/libdw/dwarf_tag.c
@@ -47,30 +47,40 @@ __libdw_findabbrev (struct Dwarf_CU *cu, unsigned int code)
   /* See whether the entry is already in the hash table.  */
   abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code);
   if (abb == NULL)
-    while (cu->last_abbrev_offset != (size_t) -1l)
-      {
-	size_t length;
-
-	/* Find the next entry.  It gets automatically added to the
-	   hash table.  */
-	mutex_lock (cu->abbrev_lock);
-	abb = __libdw_getabbrev (cu->dbg, cu, cu->last_abbrev_offset, &length);
-
-	if (abb == NULL || abb == DWARF_END_ABBREV)
-	  {
-	    /* Make sure we do not try to search for it again.  */
-	    cu->last_abbrev_offset = (size_t) -1l;
-	    mutex_unlock (cu->abbrev_lock);
-	    return DWARF_END_ABBREV;
-	  }
-
-	cu->last_abbrev_offset += length;
-	mutex_unlock (cu->abbrev_lock);
-
-	/* Is this the code we are looking for?  */
-	if (abb->code == code)
-	  break;
-      }
+    {
+      mutex_lock (cu->abbrev_lock);
+
+      /* Check once more in case entry was added before abbrev_lock
+	 was aquired.  */
+      if (cu->last_abbrev_offset == (size_t) -1l)
+	abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code);
+
+      while (cu->last_abbrev_offset != (size_t) -1l)
+	{
+	  size_t length;
+
+	  /* Find the next entry.  It gets automatically added to the
+	     hash table.  */
+	  abb = __libdw_getabbrev (cu->dbg, cu, cu->last_abbrev_offset,
+				   &length);
+
+	  if (abb == NULL || abb == DWARF_END_ABBREV)
+	    {
+	      /* Make sure we do not try to search for it again.  */
+	      cu->last_abbrev_offset = (size_t) -1l;
+	      mutex_unlock (cu->abbrev_lock);
+	      return DWARF_END_ABBREV;
+	    }
+
+	  cu->last_abbrev_offset += length;
+
+	  /* Is this the code we are looking for?  */
+	  if (abb->code == code)
+	    break;
+	}
+
+      mutex_unlock (cu->abbrev_lock);
+    }
 
   /* This is our second (or third, etc.) call to __libdw_findabbrev
      and the code is invalid.  */
-- 
2.53.0



More information about the Elfutils-devel mailing list