* libdw/dwarf_begin_elf.c (dwarf_begin_elf): Init macro_lock. * libdw/dwarf_end.c (cu_free): Free src_lock. (dwarf_end): Free macro_lock. * libdw/dwarf_getsrcfiles.c (dwarf_getsrcfiles): Use src_lock. * libdw/dwarf_getsrclines.c (dwarf_getsrclines): Ditto. * libdw/dwarf_macro_getsrclines.c (dwarf_macro_getsrclines): Use macro_lock. * libdw/libdwP.h (struct Dwarf): Define macro_lock. (struct Dwarf_CU): Define src_lock. * libdw/libdw_findcu.c (__libdw_intern_next_unit): Init src_lock.
Signed-off-by: Aaron Merey <ame...@redhat.com> --- v3: https://patchwork.sourceware.org/project/elfutils/patch/20250220043644.2058519-3-ame...@redhat.com/ v4: Instead of using dwarf_lock, define a new lock for dwarf_getsrclines and dwarf_getsrcfiles as well as dwarf_macro_getsrcfiles. libdw/dwarf_begin_elf.c | 1 + libdw/dwarf_end.c | 2 ++ libdw/dwarf_getsrcfiles.c | 11 +++++++---- libdw/dwarf_getsrclines.c | 25 +++++++++++++++++++------ libdw/dwarf_macro_getsrcfiles.c | 10 +++++++++- libdw/libdwP.h | 10 ++++++++-- libdw/libdw_findcu.c | 1 + 7 files changed, 47 insertions(+), 13 deletions(-) diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c index 8a3a939b..58a309e9 100644 --- a/libdw/dwarf_begin_elf.c +++ b/libdw/dwarf_begin_elf.c @@ -580,6 +580,7 @@ dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp) return NULL; } mutex_init (result->dwarf_lock); + mutex_init (result->macro_lock); eu_search_tree_init (&result->cu_tree); eu_search_tree_init (&result->tu_tree); eu_search_tree_init (&result->split_tree); diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c index 92389c07..c12815e1 100644 --- a/libdw/dwarf_end.c +++ b/libdw/dwarf_end.c @@ -70,6 +70,7 @@ cu_free (void *arg) Dwarf_Abbrev_Hash_free (&p->abbrev_hash); rwlock_fini (p->abbrev_lock); rwlock_fini (p->split_lock); + mutex_fini (p->src_lock); /* Free split dwarf one way (from skeleton to split). */ if (p->unit_type == DW_UT_skeleton @@ -130,6 +131,7 @@ dwarf_end (Dwarf *dwarf) free (dwarf->mem_tails); pthread_rwlock_destroy (&dwarf->mem_rwl); mutex_fini (dwarf->dwarf_lock); + mutex_fini (dwarf->macro_lock); /* Free the pubnames helper structure. */ free (dwarf->pubnames_sets); diff --git a/libdw/dwarf_getsrcfiles.c b/libdw/dwarf_getsrcfiles.c index 24e4b7d2..9becd1d5 100644 --- a/libdw/dwarf_getsrcfiles.c +++ b/libdw/dwarf_getsrcfiles.c @@ -47,9 +47,10 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, size_t *nfiles) } int res = -1; + struct Dwarf_CU *const cu = cudie->cu; + mutex_lock (cudie->cu->src_lock); /* Get the information if it is not already known. */ - struct Dwarf_CU *const cu = cudie->cu; if (cu->files == NULL) { /* For split units there might be a simple file table (without lines). @@ -96,7 +97,10 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, size_t *nfiles) Dwarf_Off debug_line_offset; if (__libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE, NULL, &debug_line_offset) == NULL) - return -1; + { + mutex_unlock (cudie->cu->src_lock); + return -1; + } res = __libdw_getsrcfiles (cu->dbg, debug_line_offset, __libdw_getcompdir (cudie), @@ -115,8 +119,7 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, size_t *nfiles) *nfiles = cu->files->nfiles; } - // XXX Eventually: unlocking here. - + mutex_unlock (cudie->cu->src_lock); return res; } INTDEF (dwarf_getsrcfiles) diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c index da78db67..be10cdee 100644 --- a/libdw/dwarf_getsrclines.c +++ b/libdw/dwarf_getsrclines.c @@ -1442,8 +1442,10 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines) return -1; } - /* Get the information if it is not already known. */ struct Dwarf_CU *const cu = cudie->cu; + mutex_lock (cu->src_lock); + + /* Get the information if it is not already known. */ if (cu->lines == NULL) { /* For split units always pick the lines from the skeleton. */ @@ -1464,10 +1466,13 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines) *lines = cu->lines; *nlines = cu->lines->nlines; } + + mutex_unlock (cu->src_lock); return res; } __libdw_seterrno (DWARF_E_NO_DEBUG_LINE); + mutex_unlock (cu->src_lock); return -1; } @@ -1485,21 +1490,29 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines) Dwarf_Off debug_line_offset; if (__libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE, NULL, &debug_line_offset) == NULL) - return -1; + { + mutex_unlock (cu->src_lock); + return -1; + } if (__libdw_getsrclines (cu->dbg, debug_line_offset, __libdw_getcompdir (cudie), cu->address_size, &cu->lines, &cu->files) < 0) - return -1; + { + mutex_unlock (cu->src_lock); + return -1; + } } else if (cu->lines == (void *) -1l) - return -1; + { + mutex_unlock (cu->src_lock); + return -1; + } *lines = cu->lines; *nlines = cu->lines->nlines; - // XXX Eventually: unlocking here. - + mutex_unlock (cu->src_lock); return 0; } INTDEF(dwarf_getsrclines) diff --git a/libdw/dwarf_macro_getsrcfiles.c b/libdw/dwarf_macro_getsrcfiles.c index 5e02935d..6ccbeadb 100644 --- a/libdw/dwarf_macro_getsrcfiles.c +++ b/libdw/dwarf_macro_getsrcfiles.c @@ -41,6 +41,8 @@ dwarf_macro_getsrcfiles (Dwarf *dbg, Dwarf_Macro *macro, /* macro is declared NN */ Dwarf_Macro_Op_Table *const table = macro->table; + + mutex_lock (table->dbg->macro_lock); if (table->files == NULL) { Dwarf_Off line_offset = table->line_offset; @@ -48,6 +50,7 @@ dwarf_macro_getsrcfiles (Dwarf *dbg, Dwarf_Macro *macro, { *files = NULL; *nfiles = 0; + mutex_unlock (table->dbg->macro_lock); return 0; } @@ -80,9 +83,14 @@ dwarf_macro_getsrcfiles (Dwarf *dbg, Dwarf_Macro *macro, } if (table->files == (void *) -1) - return -1; + { + mutex_unlock (table->dbg->macro_lock); + return -1; + } *files = table->files; *nfiles = table->files->nfiles; + + mutex_unlock (table->dbg->macro_lock); return 0; } diff --git a/libdw/libdwP.h b/libdw/libdwP.h index d121914d..974d6a50 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -265,11 +265,13 @@ struct Dwarf pthread_rwlock_t mem_rwl; /* Recursive mutex intended for setting/getting alt_dwarf, next_tu_offset, - and next_cu_offset. Covers dwarf_getsrclines, dwarf_getsrcfiles and - dwarf_macro_getsrcfiles. Should also be held when calling + and next_cu_offset. Should be held when calling __libdw_intern_next_unit. */ mutex_define(, dwarf_lock); + /* Synchronize access to dwarf_macro_getsrcfiles. */ + mutex_define(, macro_lock); + /* Internal memory handling. This is basically a simplified thread-local reimplementation of obstacks. Unfortunately the standard obstack implementation is not usable in libraries. */ @@ -461,6 +463,10 @@ struct Dwarf_CU Covers __libdw_find_split_unit. */ rwlock_define(, split_lock); + /* Synchronize access to the lines and files members. + Covers dwarf_getsrclines and dwarf_getsrcfiles. */ + mutex_define(, src_lock); + /* Memory boundaries of this CU. */ void *startp; void *endp; diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c index 613f61c8..f0243643 100644 --- a/libdw/libdw_findcu.c +++ b/libdw/libdw_findcu.c @@ -179,6 +179,7 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types) eu_search_tree_init (&newp->locs_tree); rwlock_init (newp->abbrev_lock); rwlock_init (newp->split_lock); + mutex_init (newp->src_lock); /* v4 debug type units have version == 4 and unit_type == DW_UT_type. */ if (debug_types) -- 2.48.1