* libdw/dwarf_end.c (cu_free): Free str_off_base_lock.
        * libdw/libdwP.h (struct Dwarf_CU): Add str_off_base_lock member.
        (str_offsets_base_off): Add locking.
        * libdw/libdw_findcu.c (__libdw_intern_next_unit): Initialize
        str_off_base_lock.

Signed-off-by: Aaron Merey <ame...@redhat.com>
---
v3: 
https://patchwork.sourceware.org/project/elfutils/patch/20250220043644.2058519-3-ame...@redhat.com/

v4: simplify unlocking in str_offsets_base_off.

 libdw/dwarf_end.c    |  1 +
 libdw/libdwP.h       | 17 +++++++++++++++--
 libdw/libdw_findcu.c |  1 +
 3 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index c12815e1..1628e448 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -71,6 +71,7 @@ cu_free (void *arg)
       rwlock_fini (p->abbrev_lock);
       rwlock_fini (p->split_lock);
       mutex_fini (p->src_lock);
+      mutex_fini (p->str_off_base_lock);
 
       /* Free split dwarf one way (from skeleton to split).  */
       if (p->unit_type == DW_UT_skeleton
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 974d6a50..383a26b4 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -467,6 +467,10 @@ struct Dwarf_CU
      Covers dwarf_getsrclines and dwarf_getsrcfiles.  */
   mutex_define(, src_lock);
 
+  /* Synchronize access to the str_off_base of this Dwarf_CU.
+     Covers __libdw_str_offsets_base_off.  */
+  mutex_define(, str_off_base_lock);
+
   /* Memory boundaries of this CU.  */
   void *startp;
   void *endp;
@@ -1208,6 +1212,7 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
   Dwarf_Off off = 0;
   if (cu != NULL)
     {
+      mutex_lock (cu->str_off_base_lock);
       if (cu->str_off_base == (Dwarf_Off) -1)
        {
          Dwarf_Off dwp_offset;
@@ -1222,6 +1227,7 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
              if (dwarf_formudata (&attr, &base) == 0)
                {
                  cu->str_off_base = off + base;
+                 mutex_unlock (cu->str_off_base_lock);
                  return cu->str_off_base;
                }
            }
@@ -1229,6 +1235,7 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
          if (cu->version < 5)
            {
              cu->str_off_base = off;
+             mutex_unlock (cu->str_off_base_lock);
              return cu->str_off_base;
            }
 
@@ -1236,7 +1243,10 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
            dbg = cu->dbg;
        }
       else
-       return cu->str_off_base;
+       {
+         mutex_unlock (cu->str_off_base_lock);
+         return cu->str_off_base;
+       }
     }
 
   /* No str_offsets_base attribute, we have to assume "zero".
@@ -1286,7 +1296,10 @@ str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
 
  no_header:
   if (cu != NULL)
-    cu->str_off_base = off;
+    {
+      cu->str_off_base = off;
+      mutex_unlock (cu->str_off_base_lock);
+    }
 
   return off;
 }
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
index f0243643..8805af9b 100644
--- a/libdw/libdw_findcu.c
+++ b/libdw/libdw_findcu.c
@@ -180,6 +180,7 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
   rwlock_init (newp->abbrev_lock);
   rwlock_init (newp->split_lock);
   mutex_init (newp->src_lock);
+  mutex_init (newp->str_off_base_lock);
 
   /* v4 debug type units have version == 4 and unit_type == DW_UT_type.  */
   if (debug_types)
-- 
2.48.1

Reply via email to