From: Heather McIntyre Date: Fri, 12 Jul 2024 22:35:00 +0000 (-0400) Subject: libdw: make dwarf_getalt and dwarf_setalt thread-safe X-Git-Tag: elfutils-0.192~46 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7c4fcff44aecc0eaff937e73854c5aa3469fe36b;p=thirdparty%2Felfutils.git libdw: make dwarf_getalt and dwarf_setalt thread-safe * 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 Signed-off-by: Aaron Merey Signed-off-by: Mark Wielaard --- diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c index b4f3a83a..e4826dda 100644 --- a/libdw/dwarf_begin_elf.c +++ b/libdw/dwarf_begin_elf.c @@ -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; diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c index 60a3e4fd..eaa97050 100644 --- a/libdw/dwarf_end.c +++ b/libdw/dwarf_end.c @@ -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); diff --git a/libdw/dwarf_getalt.c b/libdw/dwarf_getalt.c index 0a12dfae..26433b81 100644 --- a/libdw/dwarf_getalt.c +++ b/libdw/dwarf_getalt.c @@ -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) diff --git a/libdw/dwarf_setalt.c b/libdw/dwarf_setalt.c index dc9b61cb..f98a457c 100644 --- a/libdw/dwarf_setalt.c +++ b/libdw/dwarf_setalt.c @@ -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) diff --git a/libdw/libdwP.h b/libdw/libdwP.h index ae9386f1..85b4e01a 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -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. */