From 7c4fcff44aecc0eaff937e73854c5aa3469fe36b Mon Sep 17 00:00:00 2001 From: Heather McIntyre Date: Fri, 12 Jul 2024 18:35:00 -0400 Subject: [PATCH] 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 --- libdw/dwarf_begin_elf.c | 1 + libdw/dwarf_end.c | 1 + libdw/dwarf_getalt.c | 31 +++++++++++++++++++++++++++---- libdw/dwarf_setalt.c | 3 +++ libdw/libdwP.h | 4 ++++ 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c index b4f3a83ae..e4826ddac 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 60a3e4fda..eaa97050b 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 0a12dfae9..26433b815 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 dc9b61cb0..f98a457c6 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 ae9386f1b..85b4e01ad 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. */ -- 2.47.2