]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdw: Make libdw_findcu thread-safe
authorAaron Merey <amerey@redhat.com>
Tue, 16 Jul 2024 16:37:32 +0000 (12:37 -0400)
committerAaron Merey <amerey@redhat.com>
Tue, 16 Jul 2024 20:22:36 +0000 (16:22 -0400)
        * libdw/libdw_findcu.c (findcu_cb): Use eu_tsearch.
        (__libdw_findcu): Use eu_tfind and dwarf_lock
        (__libdw_findcu_addr): Use eu_tfind.
        (__libdw_find_split_dbg_addr): Likewise.

Signed-off-by: Heather S. McIntyre <hsm2@rice.edu>
Signed-off-by: Aaron Merey <amerey@redhat.com>
Signed-off-by: Mark Wielaard <mark@klomp.org>
v2 changes:
Use per-Dwarf_CU lock instead of a global lock.

libdw/libdw_findcu.c

index 72cf261c0c75775f54b89aac50b8b41001ec61b7..8acff448e8c243b4bf9da3b895a70502836729da 100644 (file)
@@ -177,6 +177,8 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
   newp->startp = data->d_buf + newp->start;
   newp->endp = data->d_buf + newp->end;
   eu_search_tree_init (&newp->locs_tree);
+  rwlock_init (newp->abbrev_lock);
+  rwlock_init (newp->split_lock);
 
   /* v4 debug type units have version == 4 and unit_type == DW_UT_type.  */
   if (debug_types)
@@ -243,27 +245,38 @@ __libdw_findcu (Dwarf *dbg, Dwarf_Off start, bool v4_debug_types)
   /* Maybe we already know that CU.  */
   struct Dwarf_CU fake = { .start = start, .end = 0 };
   struct Dwarf_CU **found = eu_tfind (&fake, tree, findcu_cb);
+  struct Dwarf_CU *result = NULL;
   if (found != NULL)
     return *found;
 
-  if (start < *next_offset)
-    {
-      __libdw_seterrno (DWARF_E_INVALID_DWARF);
-      return NULL;
-    }
+  rwlock_wrlock (dbg->dwarf_lock);
 
-  /* No.  Then read more CUs.  */
-  while (1)
-    {
-      struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, v4_debug_types);
-      if (newp == NULL)
-       return NULL;
-
-      /* Is this the one we are looking for?  */
-      if (start < *next_offset || start == newp->start)
-       return newp;
-    }
-  /* NOTREACHED */
+  if (start < *next_offset)
+    __libdw_seterrno (DWARF_E_INVALID_DWARF);
+  else
+    {   
+      /* No.  Then read more CUs.  */
+      while (1) 
+        {   
+          struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg,
+                                                            v4_debug_types);
+          if (newp == NULL)
+            {   
+              result = NULL;
+              break;
+            }
+
+          /* Is this the one we are looking for?  */
+          if (start < *next_offset || start == newp->start)
+            {
+              result = newp;
+              break;
+            }
+        }
+    }   
+
+  rwlock_unlock (dbg->dwarf_lock);
+  return result;
 }
 
 struct Dwarf_CU *