]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
libdw: make dwarf_getalt and dwarf_setalt thread-safe
authorHeather McIntyre <hsm2@rice.edu>
Fri, 12 Jul 2024 22:35:00 +0000 (18:35 -0400)
committerAaron Merey <amerey@redhat.com>
Wed, 21 Aug 2024 00:19:13 +0000 (20:19 -0400)
* libdw/dwarf_begin_elf.c (dwarf_begin_elf): Init dwarf_lock.
* libdw/dwarf_end.c (dwarf_end): Free dwarf_lock.
* libdw/dwarf_getalt.c (dwarf_getalt): Add locking.
* libdw/dwarf_setalt.c (dwarf_setalt): Ditto.
* libdw/libdwP.h (struct Dwarf): Define dwarf_lock.

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>
libdw/dwarf_begin_elf.c
libdw/dwarf_end.c
libdw/dwarf_getalt.c
libdw/dwarf_setalt.c
libdw/libdwP.h

index b4f3a83ae94303bc9d5caca258788ef4b2809d10..e4826ddac91a50363e57d753e61e8384cefbce86 100644 (file)
@@ -579,6 +579,7 @@ dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
       __libdw_seterrno (DWARF_E_NOMEM); /* no memory.  */
       return NULL;
     }
+  rwlock_init (result->dwarf_lock);
   result->mem_stacks = 0;
   result->mem_tails = NULL;
 
index 60a3e4fda6670a468eac20cfa3ceacdd3f22f95f..eaa97050b56b2707ee7e4d4213e8c6fb5b23cc8b 100644 (file)
@@ -127,6 +127,7 @@ dwarf_end (Dwarf *dwarf)
       if (dwarf->mem_tails != NULL)
         free (dwarf->mem_tails);
       pthread_rwlock_destroy (&dwarf->mem_rwl);
+      rwlock_fini (dwarf->dwarf_lock);
 
       /* Free the pubnames helper structure.  */
       free (dwarf->pubnames_sets);
index 0a12dfae96772bf49033da744d5db9255aaf3440..26433b8155ce1696333f768786d99bd256dc2416 100644 (file)
@@ -160,15 +160,34 @@ find_debug_altlink (Dwarf *dbg)
     }
 }
 
+/* find_debug_altlink() modifies "dbg->alt_dwarf".
+   dwarf_getalt() reads "main->alt_dwarf".
+   Mutual exclusion is enforced to prevent a race. */
+
 Dwarf *
 dwarf_getalt (Dwarf *main)
 {
-  /* Only try once.  */
-  if (main == NULL || main->alt_dwarf == (void *) -1)
+  if (main == NULL)
     return NULL;
 
+  rwlock_wrlock(main->dwarf_lock);
+
+  /* Only try once.  */
+  if (main->alt_dwarf == (void *) -1)
+    {
+      rwlock_unlock (main->dwarf_lock);
+      return NULL;
+    }
+
+  /* Assign result before releasing the lock.  */
+  Dwarf *result;
+
   if (main->alt_dwarf != NULL)
-    return main->alt_dwarf;
+    {
+      result = main->alt_dwarf;
+      rwlock_unlock (main->dwarf_lock);
+      return result;
+    }
 
   find_debug_altlink (main);
 
@@ -176,9 +195,13 @@ dwarf_getalt (Dwarf *main)
   if (main->alt_dwarf == NULL)
     {
       main->alt_dwarf = (void *) -1;
+      rwlock_unlock (main->dwarf_lock);
       return NULL;
     }
 
-  return main->alt_dwarf;
+  result = main->alt_dwarf;
+  rwlock_unlock (main->dwarf_lock);
+
+  return result;
 }
 INTDEF (dwarf_getalt)
index dc9b61cb0f355d60550c8ae486fce696d45e483b..f98a457c690738b0b43cd65c7ed5037d9ed56fac 100644 (file)
@@ -35,6 +35,8 @@
 void
 dwarf_setalt (Dwarf *main, Dwarf *alt)
 {
+  rwlock_wrlock (main->dwarf_lock);
+
   if (main->alt_fd != -1)
     {
       INTUSE(dwarf_end) (main->alt_dwarf);
@@ -43,5 +45,6 @@ dwarf_setalt (Dwarf *main, Dwarf *alt)
     }
 
   main->alt_dwarf = alt;
+  rwlock_unlock (main->dwarf_lock);
 }
 INTDEF (dwarf_setalt)
index ae9386f1bb12a4411adac427238badc2ecd70938..85b4e01ad54e5605229d124d87c15456a8c6e0f8 100644 (file)
@@ -264,6 +264,10 @@ struct Dwarf
      allocations for this Dwarf.  */
   pthread_rwlock_t mem_rwl;
 
+  /* The dwarf_lock is a read-write lock designed to ensure thread-safe access
+     and modification of an entire Dwarf object.  */
+  rwlock_define(, dwarf_lock);
+
   /* Internal memory handling.  This is basically a simplified thread-local
      reimplementation of obstacks.  Unfortunately the standard obstack
      implementation is not usable in libraries.  */