[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