]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
revise abbrev_lock
authorAaron Merey <amerey@redhat.com>
Fri, 29 Aug 2025 23:00:33 +0000 (19:00 -0400)
committerAaron Merey <amerey@redhat.com>
Sat, 30 Aug 2025 18:21:27 +0000 (14:21 -0400)
libdw/Makefile.am
libdw/dwarf_begin_elf.c
libdw/dwarf_decl_file.c
libdw/dwarf_end.c
libdw/dwarf_getscopevar.c
libdw/dwarf_tag.c
libdw/libdwP.h
libdw/libdw_findcu.c

index c98fe31fc0f879d3e39c9576fe8170981812f0a4..030ec933a614d1514c262620360746fbf50e5bf9 100644 (file)
@@ -109,7 +109,8 @@ libdw_so_LIBS = ../libebl/libebl_pic.a ../backends/libebl_backends_pic.a \
                ../libcpu/libcpu_pic.a libdw_pic.a ../libdwelf/libdwelf_pic.a \
                ../libdwfl/libdwfl_pic.a ../libdwfl_stacktrace/libdwfl_stacktrace_pic.a
 libdw_so_DEPS = ../lib/libeu.a ../libelf/libelf.so
-libdw_so_LDLIBS = $(libdw_so_DEPS) -ldl -lz $(argp_LDADD) $(fts_LIBS) $(obstack_LIBS) $(zip_LIBS) -pthread
+libdw_so_LDLIBS = $(libdw_so_DEPS) -ldl -lz $(argp_LDADD) $(fts_LIBS) \
+                 $(obstack_LIBS) $(zip_LIBS) -pthread -latomic
 libdw.so: $(srcdir)/libdw.map $(libdw_so_LIBS) $(libdw_so_DEPS)
        $(AM_V_CCLD)$(LINK) $(dso_LDFLAGS) -o $@ \
                -Wl,--soname,$@.$(VERSION),--enable-new-dtags \
index 63e2805d3439627c2f60d7229384eb761c5b806d..f5cabde0711135a9e1cca529a8a12716ca8250ee 100644 (file)
@@ -359,8 +359,8 @@ valid_p (Dwarf *result)
          result->fake_loc_cu->version = 4;
          result->fake_loc_cu->split = NULL;
          eu_search_tree_init (&result->fake_loc_cu->locs_tree);
-         rwlock_init (result->fake_loc_cu->abbrev_lock);
          rwlock_init (result->fake_loc_cu->split_lock);
+         mutex_init (result->fake_loc_cu->abbrev_lock);
          mutex_init (result->fake_loc_cu->src_lock);
          mutex_init (result->fake_loc_cu->str_off_base_lock);
          mutex_init (result->fake_loc_cu->intern_lock);
@@ -392,8 +392,8 @@ valid_p (Dwarf *result)
          result->fake_loclists_cu->version = 5;
          result->fake_loclists_cu->split = NULL;
          eu_search_tree_init (&result->fake_loclists_cu->locs_tree);
-         rwlock_init (result->fake_loclists_cu->abbrev_lock);
          rwlock_init (result->fake_loclists_cu->split_lock);
+         mutex_init (result->fake_loclists_cu->abbrev_lock);
          mutex_init (result->fake_loclists_cu->src_lock);
          mutex_init (result->fake_loclists_cu->str_off_base_lock);
          mutex_init (result->fake_loclists_cu->intern_lock);
@@ -430,8 +430,8 @@ valid_p (Dwarf *result)
          result->fake_addr_cu->version = 5;
          result->fake_addr_cu->split = NULL;
          eu_search_tree_init (&result->fake_addr_cu->locs_tree);
-         rwlock_init (result->fake_addr_cu->abbrev_lock);
          rwlock_init (result->fake_addr_cu->split_lock);
+         mutex_init (result->fake_addr_cu->abbrev_lock);
          mutex_init (result->fake_addr_cu->src_lock);
          mutex_init (result->fake_addr_cu->str_off_base_lock);
          mutex_init (result->fake_addr_cu->intern_lock);
index 1b91a4e9f03e99898962f46ee16937cb5d42728f..03040e12080814d3fdd12b05ab9dd07ba012450f 100644 (file)
@@ -50,7 +50,8 @@ dwarf_decl_file (Dwarf_Die *die)
 
   Dwarf_Files *files;
   size_t nfiles;
-  if (INTUSE(dwarf_getsrcfiles) (&CUDIE (attr_mem.cu), &files, &nfiles) != 0)
+  Dwarf_Die cudie = CUDIE (attr_mem.cu);
+  if (INTUSE(dwarf_getsrcfiles) (&cudie, &files, &nfiles) != 0)
     return NULL;
 
   if (idx >= nfiles)
index 979b11689edac09c466f1604333d7abab797a70e..fa27b19e1ba4fb2aec18973044510da7240259ca 100644 (file)
@@ -63,8 +63,8 @@ cu_free (void *arg)
   struct Dwarf_CU *p = (struct Dwarf_CU *) arg;
 
   eu_search_tree_fini (&p->locs_tree, noop_free);
-  rwlock_fini (p->abbrev_lock);
   rwlock_fini (p->split_lock);
+  mutex_fini (p->abbrev_lock);
   mutex_fini (p->src_lock);
   mutex_fini (p->str_off_base_lock);
   mutex_fini (p->intern_lock);
index 7b1416f3a24d75e286eab0b9955897e6749cfa9e..306ccae0136c7d8ea2f386b49d83daac8c603a9a 100644 (file)
@@ -40,7 +40,8 @@
 static int
 getfiles (Dwarf_Die *die, Dwarf_Files **files)
 {
-  return INTUSE(dwarf_getsrcfiles) (&CUDIE (die->cu), files, NULL);
+  Dwarf_Die cudie = CUDIE (die->cu);
+  return INTUSE(dwarf_getsrcfiles) (&cudie, files, NULL);
 }
 
 /* Fetch an attribute that should have a constant integer form.  */
index 218382a173386dbb5739c13228ac7f2a922b3a48..7daa48134601131f6bf55e73d6f45b0e48159a00 100644 (file)
@@ -53,15 +53,19 @@ __libdw_findabbrev (struct Dwarf_CU *cu, unsigned int code)
 
        /* 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)
index b77db1423fe0bb68e4634b9f3b1be6ebe50f0e81..900cc5c6170c90e81c544fcf3eade57df2a0ac47 100644 (file)
@@ -455,14 +455,14 @@ struct Dwarf_CU
      Don't access directly, call __libdw_cu_locs_base.  */
   Dwarf_Off locs_base;
 
-  /* Synchronize access to the abbrev member of a Dwarf_Die that
-     refers to this Dwarf_CU.  Covers __libdw_die_abbrev. */
-  rwlock_define(, abbrev_lock);
-
   /* Synchronize access to the split member of this Dwarf_CU.
      Covers __libdw_find_split_unit.  */
   rwlock_define(, split_lock);
 
+  /* Synchronize access to the last_abbrev_offset member of a Dwarf_Die
+     that refers to this Dwarf_CU.  */
+  mutex_define(, abbrev_lock);
+
   /* Synchronize access to the lines and files members.
      Covers dwarf_getsrclines and dwarf_getsrcfiles.  */
   mutex_define(, src_lock);
@@ -823,41 +823,44 @@ static inline Dwarf_Abbrev *
 __nonnull_attribute__ (1)
 __libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp)
 {
+  Dwarf_Abbrev *end_abbrev = DWARF_END_ABBREV;
+  Dwarf_Abbrev *expected = (Dwarf_Abbrev *) NULL;
+
   if (unlikely (die->cu == NULL))
     {
-      die->abbrev = DWARF_END_ABBREV;
-      return DWARF_END_ABBREV;
+      __atomic_compare_exchange_n (&die->abbrev, &expected, end_abbrev, false,
+                                  __ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
+      return end_abbrev;
     }
 
-  rwlock_wrlock (die->cu->abbrev_lock);
+  Dwarf_Abbrev *abbrev = __atomic_load_n (&die->abbrev, __ATOMIC_ACQUIRE);
+  if (abbrev != NULL && readp == NULL)
+    return abbrev;
 
-  /* Do we need to get the abbreviation, or need to read after the code?  */
-  if (die->abbrev == NULL || readp != NULL)
+  /* We need to get the abbreviation or need to read after the code.  */
+  unsigned int code;
+  const unsigned char *addr = die->addr;
+  if (addr >= (const unsigned char *) die->cu->endp)
     {
-      /* Get the abbreviation code.  */
-      unsigned int code;
-      const unsigned char *addr = die->addr;
-
-      if (addr >= (const unsigned char *) die->cu->endp)
-       {
-         die->abbrev = DWARF_END_ABBREV;
-         rwlock_unlock (die->cu->abbrev_lock);
-         return DWARF_END_ABBREV;
-       }
+      __atomic_compare_exchange_n (&die->abbrev, &expected, end_abbrev, false,
+                                  __ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
+      return end_abbrev;
+    }
 
-      get_uleb128 (code, addr, die->cu->endp);
-      if (readp != NULL)
-       *readp = addr;
+  /* Get the abbreviation code.  */
+  get_uleb128 (code, addr, die->cu->endp);
+  if (readp != NULL)
+    *readp = addr;
 
-      /* Find the abbreviation.  */
-      if (die->abbrev == NULL)
-       die->abbrev = __libdw_findabbrev (die->cu, code);
-    }
+  if (abbrev != NULL)
+    return abbrev;
 
-  Dwarf_Abbrev *result = die->abbrev;
-  rwlock_unlock (die->cu->abbrev_lock);
+  /* Find the abbreviation.  */
+  abbrev = __libdw_findabbrev (die->cu, code);
+  __atomic_compare_exchange_n (&die->abbrev, &expected, abbrev, false,
+                              __ATOMIC_RELEASE, __ATOMIC_ACQUIRE);
 
-  return result;
+  return abbrev;
 }
 
 /* Helper functions for form handling.  */
index 592673439c488dbb20ad13b7203827017180ef8a..a1f700d38970f5c96e976029a22df00c1e9a9e8d 100644 (file)
@@ -177,8 +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);
+  mutex_init (newp->abbrev_lock);
   mutex_init (newp->src_lock);
   mutex_init (newp->str_off_base_lock);
   mutex_init (newp->intern_lock);