From 84df268c5c89bd54cfc345f7ac325602ae952bf2 Mon Sep 17 00:00:00 2001 From: Aaron Merey Date: Wed, 26 Jun 2024 17:17:05 -0400 Subject: [PATCH] thread safety v2 WIP --- lib/eu-config.h | 13 ++++++-- lib/eu-search.c | 57 +++++++++++++++++++++++++--------- lib/eu-search.h | 33 +++++++++++++++++--- libcpu/i386_parse.y | 46 +++++++++++++-------------- libdw/cfi.h | 6 ++-- libdw/cie.c | 6 ++-- libdw/dwarf_begin_elf.c | 7 +++-- libdw/dwarf_end.c | 15 +++++---- libdw/dwarf_formref_die.c | 2 ++ libdw/dwarf_getalt.c | 41 ++++++++++++------------ libdw/dwarf_getcfi.c | 5 ++- libdw/dwarf_getlocation.c | 17 +++++----- libdw/dwarf_getmacros.c | 4 +-- libdw/dwarf_getsrclines.c | 4 +-- libdw/dwarf_hasattr.c | 5 ++- libdw/dwarf_setalt.c | 4 +++ libdw/fde.c | 1 + libdw/frame-cache.c | 8 ++--- libdw/libdw.h | 3 +- libdw/libdwP.h | 31 ++++++++++++------ libdw/libdw_find_split_unit.c | 34 ++++++-------------- libdw/libdw_findcu.c | 15 ++++----- libdwfl/cu.c | 6 ++-- libdwfl/dwfl_module.c | 4 +-- libdwfl/libdwflP.h | 3 +- libelf/common.h | 18 +++++++---- libelf/elf_begin.c | 2 ++ libelf/elf_cntl.c | 6 ++-- libelf/elf_end.c | 13 ++++---- libelf/elf_getdata_rawchunk.c | 12 +++---- libelf/elf_readall.c | 7 +++-- libelf/libelfP.h | 10 ++++-- tests/.Makefile.am.rej.swp | Bin 12288 -> 0 bytes 33 files changed, 260 insertions(+), 178 deletions(-) delete mode 100644 tests/.Makefile.am.rej.swp diff --git a/lib/eu-config.h b/lib/eu-config.h index feb079dbc..0b9f03421 100644 --- a/lib/eu-config.h +++ b/lib/eu-config.h @@ -29,6 +29,8 @@ #ifndef EU_CONFIG_H #define EU_CONFIG_H 1 +#include + #ifdef USE_LOCKS # include # include @@ -40,9 +42,14 @@ ({ int _err = pthread_ ## call; assert_perror (_err); }) # define rwlock_init(lock) RWLOCK_CALL (init (&lock, NULL)) # define rwlock_fini(lock) RWLOCK_CALL (destroy (&lock)) -# define rwlock_rdlock(lock) RWLOCK_CALL (rdlock (&lock)) -# define rwlock_wrlock(lock) RWLOCK_CALL (wrlock (&lock)) -# define rwlock_unlock(lock) RWLOCK_CALL (unlock (&lock)) + +# define rwlock_rdlock(lock) RWLOCK_CALL (rdlock (&lock)) +# define rwlock_wrlock(lock) RWLOCK_CALL (wrlock (&lock)) +# define rwlock_unlock(lock) RWLOCK_CALL (unlock (&lock)) + +//# define rwlock_rdlock(lock) ({ printf ("rw locking %lx\n", (unsigned long) &lock); fflush(NULL); RWLOCK_CALL (rdlock (&lock)); }) +//# define rwlock_wrlock(lock) ({ printf ("wr locking %lx\n", (unsigned long) &lock); fflush(NULL); RWLOCK_CALL (wrlock (&lock)); }) +//# define rwlock_unlock(lock) ({ printf ("unlocking %lx\n", (unsigned long) &lock); fflush(NULL); RWLOCK_CALL (unlock (&lock)); }) # define once(once_control, init_routine) \ ONCE_CALL (once (&once_control, init_routine)) #else diff --git a/lib/eu-search.c b/lib/eu-search.c index a6b04f4fc..c952c113a 100644 --- a/lib/eu-search.c +++ b/lib/eu-search.c @@ -30,31 +30,58 @@ #include #endif -#include #include "eu-search.h" -rwlock_define(static, search_find_lock); +#include -void *eu_tsearch(const void *key, void **rootp, - int (*compar)(const void *, const void *)) +void *eu_tsearch (const void *key, search_tree *tree, + int (*compare)(const void *, const void *)) { - void *ret = NULL; - rwlock_wrlock(search_find_lock); + rwlock_wrlock (tree->lock); + void *ret = tsearch (key, &tree->root, compare); + rwlock_unlock (tree->lock); - ret = tsearch(key, rootp, compar); - - rwlock_unlock(search_find_lock); return ret; } -void *eu_tfind(const void *key, void *const *rootp, - int (*compar)(const void *, const void *)) +void *eu_tfind (const void *key, search_tree *tree, + int (*compare)(const void *, const void *)) { - void *ret = NULL; - rwlock_rdlock(search_find_lock); + rwlock_rdlock (tree->lock); + void *ret = tfind (key, &tree->root, compare); + rwlock_unlock (tree->lock); + + return ret; +} - ret = tfind(key, rootp, compar); +void *eu_tdelete (const void *key, search_tree *tree, + int (*compare)(const void *, const void *)) +{ + rwlock_wrlock (tree->lock); + void *ret = tdelete (key, &tree->root, compare); + rwlock_unlock (tree->lock); - rwlock_unlock(search_find_lock); return ret; } + +void eu_tdestroy (search_tree *tree, void (*free_node)(void *)) +{ + rwlock_wrlock (tree->lock); + + tdestroy (tree->root, free_node); + tree->root = NULL; + + rwlock_unlock (tree->lock); +} + +void eu_search_tree_init (search_tree *tree) +{ + tree->root = NULL; + rwlock_init (tree->lock); +} + +void eu_search_tree_fini (search_tree *tree, void (*free_node)(void *)) +{ + eu_tdestroy (tree, free_node); + rwlock_fini (tree->lock); +} diff --git a/lib/eu-search.h b/lib/eu-search.h index 4ce0139aa..2dab63648 100644 --- a/lib/eu-search.h +++ b/lib/eu-search.h @@ -29,11 +29,36 @@ #ifndef EU_SEARCH_H #define EU_SEARCH_H 1 +#include #include +#include -extern void *eu_tsearch(const void *key, void **rootp, - int (*compar)(const void *, const void *)); -extern void *eu_tfind(const void *key, void *const *rootp, - int (*compar)(const void *, const void *)); +typedef struct +{ + void *root; + rwlock_define (, lock); +} search_tree; + +/* Search TREE for KEY and add KEY if not found. Synchronized using + TREE's lock. */ +extern void *eu_tsearch (const void *key, search_tree *tree, + int (*compare)(const void *, const void *)); + +/* Search TREE for KEY. Synchronized with TREE's lock. */ +extern void *eu_tfind (const void *key, search_tree *tree, + int (*compare)(const void *, const void *)); + +/* Delete key from TREE. Synchronized with TREE's lock. */ +extern void *eu_tdelete (const void *key, search_tree *tree, + int (*compare)(const void *, const void *)); + +/* Free all nodes from TREE. */ +void eu_tdestroy (search_tree *tree, void (*free_node)(void *)); + +/* Initialize TREE's root and lock. */ +void eu_search_tree_init (search_tree *tree); + +/* Free all nodes from TREE as well as TREE's lock. */ +void eu_search_tree_fini (search_tree *tree, void (*free_node)(void *)); #endif diff --git a/libcpu/i386_parse.y b/libcpu/i386_parse.y index 3d7cb89e2..29c912a55 100644 --- a/libcpu/i386_parse.y +++ b/libcpu/i386_parse.y @@ -269,12 +269,12 @@ mask: kMASK kBITFIELD kNUMBER struct synonym *newp = xmalloc (sizeof (*newp)); newp->from = $2; newp->to = $3; - if (eu_tfind (newp, &synonyms, compare_syn) != NULL) + if (tfind (newp, &synonyms, compare_syn) != NULL) error (0, 0, "%d: duplicate definition for synonym '%s'", i386_lineno, $2); - else if (eu_tsearch ( newp, &synonyms, compare_syn) == NULL) - error (EXIT_FAILURE, 0, "eu_tsearch"); + else if (tsearch ( newp, &synonyms, compare_syn) == NULL) + error (EXIT_FAILURE, 0, "tsearch"); } | ; @@ -308,12 +308,12 @@ instr: bytes ':' bitfieldopt kID bitfieldopt optargs newp->bytes = $1; newp->mnemonic = $4; if (newp->mnemonic != (void *) -1l - && eu_tfind ($4, &mnemonics, + && tfind ($4, &mnemonics, (int (*)(const void *, const void *)) strcmp) == NULL) { - if (eu_tsearch ($4, &mnemonics, + if (tsearch ($4, &mnemonics, (int (*)(const void *, const void *)) strcmp) == NULL) - error (EXIT_FAILURE, errno, "eu_tsearch"); + error (EXIT_FAILURE, errno, "tsearch"); ++nmnemonics; } @@ -339,15 +339,15 @@ instr: bytes ':' bitfieldopt kID bitfieldopt optargs infname, i386_lineno - 1, $5->name); struct suffix search = { .name = $5->name }; - if (eu_tfind (&search, &suffixes, compare_suf) + if (tfind (&search, &suffixes, compare_suf) == NULL) { struct suffix *ns = xmalloc (sizeof (*ns)); ns->name = $5->name; ns->idx = ++nsuffixes; - if (eu_tsearch (ns, &suffixes, compare_suf) + if (tsearch (ns, &suffixes, compare_suf) == NULL) - error (EXIT_FAILURE, errno, "eu_tsearch"); + error (EXIT_FAILURE, errno, "tsearch"); } } @@ -374,7 +374,7 @@ bitfieldopt: kBITFIELD struct known_bitfield search; search.name = $1; struct known_bitfield **res; - res = eu_tfind (&search, &bitfields, bitfield_compare); + res = tfind (&search, &bitfields, bitfield_compare); if (res == NULL) { error (0, 0, "%d: unknown bitfield '%s'", @@ -437,7 +437,7 @@ bit: '0' struct known_bitfield search; search.name = $1; struct known_bitfield **res; - res = eu_tfind (&search, &bitfields, bitfield_compare); + res = tfind (&search, &bitfields, bitfield_compare); if (res == NULL) { error (0, 0, "%d: unknown bitfield '%s'", @@ -497,7 +497,7 @@ argcomp: kBITFIELD struct known_bitfield search; search.name = $1; struct known_bitfield **res; - res = eu_tfind (&search, &bitfields, bitfield_compare); + res = tfind (&search, &bitfields, bitfield_compare); if (res == NULL) { if (strcmp ($1, "ax") == 0) @@ -575,7 +575,7 @@ new_bitfield (char *name, unsigned long int num) newp->bits = num; newp->tmp = 0; - if (eu_tfind (newp, &bitfields, bitfield_compare) != NULL) + if (tfind (newp, &bitfields, bitfield_compare) != NULL) { error (0, 0, "%d: duplicated definition of bitfield '%s'", i386_lineno, name); @@ -584,7 +584,7 @@ new_bitfield (char *name, unsigned long int num) return; } - if (eu_tsearch (newp, &bitfields, bitfield_compare) == NULL) + if (tsearch (newp, &bitfields, bitfield_compare) == NULL) error (EXIT_FAILURE, errno, "%d: cannot insert new bitfield '%s'", i386_lineno, name); } @@ -813,7 +813,7 @@ fillin_arg (struct bitvalue *bytes, struct argname *name, struct synonym search = { .from = fieldname }; - struct synonym **res = eu_tfind (&search, &synonyms, compare_syn); + struct synonym **res = tfind (&search, &synonyms, compare_syn); if (res != NULL) fieldname = (*res)->to; @@ -914,26 +914,26 @@ find_numbers (void) if (runp->operands[i].fct != NULL) { struct argstring search = { .str = runp->operands[i].fct }; - if (eu_tfind (&search, &fct_names[i], compare_argstring) == NULL) + if (tfind (&search, &fct_names[i], compare_argstring) == NULL) { struct argstring *newp = xmalloc (sizeof (*newp)); newp->str = runp->operands[i].fct; newp->idx = 0; - if (eu_tsearch (newp, &fct_names[i], compare_argstring) == NULL) - error (EXIT_FAILURE, errno, "eu_tsearch"); + if (tsearch (newp, &fct_names[i], compare_argstring) == NULL) + error (EXIT_FAILURE, errno, "tsearch"); ++nfct_names[i]; } if (runp->operands[i].str != NULL) { search.str = runp->operands[i].str; - if (eu_tfind (&search, &strs[i], compare_argstring) == NULL) + if (tfind (&search, &strs[i], compare_argstring) == NULL) { struct argstring *newp = xmalloc (sizeof (*newp)); newp->str = runp->operands[i].str; newp->idx = 0; - if (eu_tsearch (newp, &strs[i], compare_argstring) == NULL) - error (EXIT_FAILURE, errno, "eu_tsearch"); + if (tsearch (newp, &strs[i], compare_argstring) == NULL) + error (EXIT_FAILURE, errno, "tsearch"); ++nstrs[i]; } } @@ -1206,7 +1206,7 @@ instrtable_out (void) if (instr->operands[i].fct != NULL) { struct argstring search = { .str = instr->operands[i].fct }; - struct argstring **res = eu_tfind (&search, &fct_names[i], + struct argstring **res = tfind (&search, &fct_names[i], compare_argstring); assert (res != NULL); idx = (*res)->idx; @@ -1217,7 +1217,7 @@ instrtable_out (void) if (instr->operands[i].str != NULL) { struct argstring search = { .str = instr->operands[i].str }; - struct argstring **res = eu_tfind (&search, &strs[i], + struct argstring **res = tfind (&search, &strs[i], compare_argstring); assert (res != NULL); idx = (*res)->idx; diff --git a/libdw/cfi.h b/libdw/cfi.h index 1b0d712f8..bb9dc0df3 100644 --- a/libdw/cfi.h +++ b/libdw/cfi.h @@ -90,13 +90,13 @@ struct Dwarf_CFI_s Dwarf_Off next_offset; /* Search tree for the CIEs, indexed by CIE_pointer (section offset). */ - void *cie_tree; + search_tree cie_tree; /* Search tree for the FDEs, indexed by PC address. */ - void *fde_tree; + search_tree fde_tree; /* Search tree for parsed DWARF expressions, indexed by raw pointer. */ - void *expr_tree; + search_tree expr_tree; /* Backend hook. */ struct ebl *ebl; diff --git a/libdw/cie.c b/libdw/cie.c index 758daef5c..3d56b0578 100644 --- a/libdw/cie.c +++ b/libdw/cie.c @@ -160,7 +160,8 @@ internal_function __libdw_find_cie (Dwarf_CFI *cache, Dwarf_Off offset) { const struct dwarf_cie cie_key = { .offset = offset }; - struct dwarf_cie **found = eu_tfind (&cie_key, &cache->cie_tree, &compare_cie); + struct dwarf_cie **found = eu_tfind (&cie_key, &cache->cie_tree, + &compare_cie); if (found != NULL) return *found; @@ -189,7 +190,8 @@ internal_function __libdw_intern_cie (Dwarf_CFI *cache, Dwarf_Off offset, const Dwarf_CIE *info) { const struct dwarf_cie cie_key = { .offset = offset }; - struct dwarf_cie **found = eu_tfind (&cie_key, &cache->cie_tree, &compare_cie); + struct dwarf_cie **found = eu_tfind (&cie_key, &cache->cie_tree, + &compare_cie); if (found == NULL) /* We have not read this CIE yet. Enter it. */ (void) intern_new_cie (cache, offset, info); diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c index ca2b7e2ac..8b806c909 100644 --- a/libdw/dwarf_begin_elf.c +++ b/libdw/dwarf_begin_elf.c @@ -354,11 +354,11 @@ valid_p (Dwarf *result) result->fake_loc_cu->endp = (result->sectiondata[IDX_debug_loc]->d_buf + result->sectiondata[IDX_debug_loc]->d_size); - result->fake_loc_cu->locs = NULL; result->fake_loc_cu->address_size = elf_addr_size; result->fake_loc_cu->offset_size = 4; result->fake_loc_cu->version = 4; result->fake_loc_cu->split = NULL; + result->fake_loc_cu->locs_tree.root = NULL; } } @@ -382,11 +382,11 @@ valid_p (Dwarf *result) result->fake_loclists_cu->endp = (result->sectiondata[IDX_debug_loclists]->d_buf + result->sectiondata[IDX_debug_loclists]->d_size); - result->fake_loclists_cu->locs = NULL; result->fake_loclists_cu->address_size = elf_addr_size; result->fake_loclists_cu->offset_size = 4; result->fake_loclists_cu->version = 5; result->fake_loclists_cu->split = NULL; + result->fake_loclists_cu->locs_tree.root = NULL; } } @@ -415,11 +415,11 @@ valid_p (Dwarf *result) result->fake_addr_cu->endp = (result->sectiondata[IDX_debug_addr]->d_buf + result->sectiondata[IDX_debug_addr]->d_size); - result->fake_addr_cu->locs = NULL; result->fake_addr_cu->address_size = elf_addr_size; result->fake_addr_cu->offset_size = 4; result->fake_addr_cu->version = 5; result->fake_addr_cu->split = NULL; + result->fake_addr_cu->locs_tree.root = NULL; } } @@ -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 ed8d27bea..cd9d04577 100644 --- a/libdw/dwarf_end.c +++ b/libdw/dwarf_end.c @@ -62,13 +62,12 @@ cu_free (void *arg) { struct Dwarf_CU *p = (struct Dwarf_CU *) arg; - tdestroy (p->locs, noop_free); - /* Only free the CU internals if its not a fake CU. */ - if(p != p->dbg->fake_loc_cu && p != p->dbg->fake_loclists_cu + if (p != p->dbg->fake_loc_cu && p != p->dbg->fake_loclists_cu && p != p->dbg->fake_addr_cu) { Dwarf_Abbrev_Hash_free (&p->abbrev_hash); + eu_search_tree_fini (&p->locs_tree, noop_free); /* Free split dwarf one way (from skeleton to split). */ if (p->unit_type == DW_UT_skeleton @@ -102,17 +101,17 @@ dwarf_end (Dwarf *dwarf) /* The search tree for the CUs. NB: the CU data itself is allocated separately, but the abbreviation hash tables need to be handled. */ - tdestroy (dwarf->cu_tree, cu_free); - tdestroy (dwarf->tu_tree, cu_free); + eu_search_tree_fini (&dwarf->cu_tree, cu_free); + eu_search_tree_fini (&dwarf->tu_tree, cu_free); /* Search tree for macro opcode tables. */ - tdestroy (dwarf->macro_ops, noop_free); + eu_search_tree_fini (&dwarf->macro_ops_tree, noop_free); /* Search tree for decoded .debug_lines units. */ - tdestroy (dwarf->files_lines, noop_free); + eu_search_tree_fini (&dwarf->files_lines_tree, noop_free); /* And the split Dwarf. */ - tdestroy (dwarf->split_tree, noop_free); + eu_search_tree_fini (&dwarf->split_tree, noop_free); /* Free the internally allocated memory. */ for (size_t i = 0; i < dwarf->mem_stacks; i++) diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c index 48ba81942..f8a51970c 100644 --- a/libdw/dwarf_formref_die.c +++ b/libdw/dwarf_formref_die.c @@ -92,7 +92,9 @@ dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *result) bool scan_debug_types = false; do { + rwlock_wrlock(attr->cu->dbg->dwarf_lock); cu = __libdw_intern_next_unit (attr->cu->dbg, scan_debug_types); + rwlock_unlock(attr->cu->dbg->dwarf_lock); if (cu == NULL) { if (scan_debug_types == false) diff --git a/libdw/dwarf_getalt.c b/libdw/dwarf_getalt.c index e3894c8c5..c4169df6b 100644 --- a/libdw/dwarf_getalt.c +++ b/libdw/dwarf_getalt.c @@ -44,10 +44,6 @@ #include #include -/* find_debug_altlink() modifies "dbg->alt_dwarf". - dwarf_getalt() reads "main->alt_dwarf". - Mutual exclusion is enforced to prevent a race. */ -rwlock_define(static, alt_dwarf_lock); char * internal_function @@ -156,9 +152,7 @@ find_debug_altlink (Dwarf *dbg) Dwarf *alt = dwarf_begin (fd, O_RDONLY); if (alt != NULL) { - rwlock_wrlock(alt_dwarf_lock); dbg->alt_dwarf = alt; - rwlock_unlock(alt_dwarf_lock); dbg->alt_fd = fd; } else @@ -166,36 +160,39 @@ 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) { - rwlock_rdlock(alt_dwarf_lock); - Dwarf *alt_dwarf_local = main->alt_dwarf; - rwlock_unlock(alt_dwarf_lock); + rwlock_rdlock(main->dwarf_lock); /* Only try once. */ - if (main == NULL || alt_dwarf_local == (void *) -1) - return NULL; + if (main == NULL || main->alt_dwarf == (void *) -1) + { + rwlock_unlock (main->dwarf_lock); + return NULL; + } - if (alt_dwarf_local != NULL) - return alt_dwarf_local; + if (main->alt_dwarf != NULL) + { + rwlock_unlock (main->dwarf_lock); + return main->alt_dwarf; + } find_debug_altlink (main); - rwlock_rdlock(alt_dwarf_lock); - alt_dwarf_local = main->alt_dwarf; - rwlock_unlock(alt_dwarf_lock); - /* If we found nothing, make sure we don't try again. */ - if (alt_dwarf_local == NULL) + if (main->alt_dwarf == NULL) { - rwlock_wrlock(alt_dwarf_lock); main->alt_dwarf = (void *) -1; - rwlock_unlock(alt_dwarf_lock); - + rwlock_unlock (main->dwarf_lock); return NULL; } - return alt_dwarf_local; + rwlock_unlock (main->dwarf_lock); + return main->alt_dwarf; } INTDEF (dwarf_getalt) diff --git a/libdw/dwarf_getcfi.c b/libdw/dwarf_getcfi.c index afa8a4607..a44971520 100644 --- a/libdw/dwarf_getcfi.c +++ b/libdw/dwarf_getcfi.c @@ -66,7 +66,10 @@ dwarf_getcfi (Dwarf *dbg) cfi->default_same_value = false; cfi->next_offset = 0; - cfi->cie_tree = cfi->fde_tree = cfi->expr_tree = NULL; + + eu_search_tree_init (&cfi->cie_tree); + eu_search_tree_init (&cfi->fde_tree); + eu_search_tree_init (&cfi->expr_tree); cfi->ebl = NULL; diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c index 35b1e626d..a6615aadf 100644 --- a/libdw/dwarf_getlocation.c +++ b/libdw/dwarf_getlocation.c @@ -34,7 +34,7 @@ #include #include #include - +#include #include @@ -139,7 +139,7 @@ loc_compare (const void *p1, const void *p2) This points us directly to the block data for later fetching. Returns zero on success, -1 on bad DWARF or 1 if eu_tsearch failed. */ static int -store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op) +store_implicit_value (Dwarf *dbg, search_tree *cache, Dwarf_Op *op) { if (dbg == NULL) return -1; @@ -167,7 +167,8 @@ dwarf_getlocation_implicit_value (Dwarf_Attribute *attr, const Dwarf_Op *op, return -1; struct loc_block_s fake = { .addr = (void *) op }; - struct loc_block_s **found = eu_tfind (&fake, &attr->cu->locs, loc_compare); + struct loc_block_s **found = eu_tfind (&fake, &attr->cu->locs_tree, + loc_compare); if (unlikely (found == NULL)) { __libdw_seterrno (DWARF_E_NO_BLOCK); @@ -211,7 +212,7 @@ is_constant_offset (Dwarf_Attribute *attr, /* Check whether we already cached this location. */ struct loc_s fake = { .addr = attr->valp }; - struct loc_s **found = eu_tfind (&fake, &attr->cu->locs, loc_compare); + struct loc_s **found = eu_tfind (&fake, &attr->cu->locs_tree, loc_compare); if (found == NULL) { @@ -235,7 +236,7 @@ is_constant_offset (Dwarf_Attribute *attr, newp->loc = result; newp->nloc = 1; - found = eu_tsearch (newp, &attr->cu->locs, loc_compare); + found = eu_tsearch (newp, &attr->cu->locs_tree, loc_compare); } assert ((*found)->nloc == 1); @@ -253,7 +254,7 @@ int internal_function __libdw_intern_expression (Dwarf *dbg, bool other_byte_order, unsigned int address_size, unsigned int ref_size, - void **cache, const Dwarf_Block *block, + search_tree *cache, const Dwarf_Block *block, bool cfap, bool valuep, Dwarf_Op **llbuf, size_t *listlen, int sec_index) { @@ -655,7 +656,7 @@ __libdw_intern_expression (Dwarf *dbg, bool other_byte_order, newp->addr = block->data; newp->loc = result; newp->nloc = *listlen; - (void) eu_tsearch (newp, cache, loc_compare); + eu_tsearch (newp, cache, loc_compare); /* We did it. */ return 0; @@ -677,7 +678,7 @@ getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block, cu->address_size, (cu->version == 2 ? cu->address_size : cu->offset_size), - &cu->locs, block, + &cu->locs_tree, block, false, false, llbuf, listlen, sec_index); } diff --git a/libdw/dwarf_getmacros.c b/libdw/dwarf_getmacros.c index 0118c7699..41d510a9d 100644 --- a/libdw/dwarf_getmacros.c +++ b/libdw/dwarf_getmacros.c @@ -317,7 +317,7 @@ cache_op_table (Dwarf *dbg, int sec_index, Dwarf_Off macoff, Dwarf_Die *cudie) { Dwarf_Macro_Op_Table fake = { .offset = macoff, .sec_index = sec_index }; - Dwarf_Macro_Op_Table **found = eu_tfind (&fake, &dbg->macro_ops, + Dwarf_Macro_Op_Table **found = eu_tfind (&fake, &dbg->macro_ops_tree, macro_op_compare); if (found != NULL) return *found; @@ -329,7 +329,7 @@ cache_op_table (Dwarf *dbg, int sec_index, Dwarf_Off macoff, if (table == NULL) return NULL; - Dwarf_Macro_Op_Table **ret = eu_tsearch (table, &dbg->macro_ops, + Dwarf_Macro_Op_Table **ret = eu_tsearch (table, &dbg->macro_ops_tree, macro_op_compare); if (unlikely (ret == NULL)) { diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c index bc717e53f..759b9c7ba 100644 --- a/libdw/dwarf_getsrclines.c +++ b/libdw/dwarf_getsrclines.c @@ -1320,7 +1320,7 @@ get_lines_or_files (Dwarf *dbg, Dwarf_Off debug_line_offset, Dwarf_Lines **linesp, Dwarf_Files **filesp) { struct files_lines_s fake = { .debug_line_offset = debug_line_offset }; - struct files_lines_s **found = eu_tfind (&fake, &dbg->files_lines, + struct files_lines_s **found = eu_tfind (&fake, &dbg->files_lines_tree, files_lines_compare); if (found == NULL) { @@ -1354,7 +1354,7 @@ get_lines_or_files (Dwarf *dbg, Dwarf_Off debug_line_offset, node->debug_line_offset = debug_line_offset; - found = eu_tsearch (node, &dbg->files_lines, files_lines_compare); + found = eu_tsearch (node, &dbg->files_lines_tree, files_lines_compare); if (found == NULL) { __libdw_seterrno (DWARF_E_NOMEM); diff --git a/libdw/dwarf_hasattr.c b/libdw/dwarf_hasattr.c index 92f8de685..d5dde5912 100644 --- a/libdw/dwarf_hasattr.c +++ b/libdw/dwarf_hasattr.c @@ -37,7 +37,6 @@ /* dwarf_hasattr() calls __libdw_dieabbrev() in libdwP.h. __libdw_dieabbrev() reads/writes "die->abbrev". Mutual exclusion is enforced around the call to __libdw_dieabbrev to prevent a race. */ -rwlock_define(static, die_abbrev_lock); int dwarf_hasattr (Dwarf_Die *die, unsigned int search_name) @@ -45,12 +44,12 @@ dwarf_hasattr (Dwarf_Die *die, unsigned int search_name) if (die == NULL) return 0; - rwlock_wrlock(die_abbrev_lock); + //rwlock_wrlock(die_abbrev_lock); /* Find the abbreviation entry. */ Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL); - rwlock_unlock(die_abbrev_lock); + //rwlock_unlock(die_abbrev_lock); if (unlikely (abbrevp == DWARF_END_ABBREV)) { diff --git a/libdw/dwarf_setalt.c b/libdw/dwarf_setalt.c index dc9b61cb0..f7d70d9dc 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,7 @@ dwarf_setalt (Dwarf *main, Dwarf *alt) } main->alt_dwarf = alt; + + rwlock_unlock(main->dwarf_lock); } INTDEF (dwarf_setalt) diff --git a/libdw/fde.c b/libdw/fde.c index 55065528a..5dc4ad026 100644 --- a/libdw/fde.c +++ b/libdw/fde.c @@ -123,6 +123,7 @@ intern_fde (Dwarf_CFI *cache, const Dwarf_FDE *entry) /* Add the new entry to the search tree. */ struct dwarf_fde **tres = eu_tsearch (fde, &cache->fde_tree, &compare_fde); + if (tres == NULL) { free (fde); diff --git a/libdw/frame-cache.c b/libdw/frame-cache.c index 683f7f17a..6c89858a3 100644 --- a/libdw/frame-cache.c +++ b/libdw/frame-cache.c @@ -60,10 +60,10 @@ void internal_function __libdw_destroy_frame_cache (Dwarf_CFI *cache) { - /* Most of the data is in our two search trees. */ - tdestroy (cache->fde_tree, free_fde); - tdestroy (cache->cie_tree, free_cie); - tdestroy (cache->expr_tree, free_expr); + /* Most of the data is in our three search trees. */ + eu_search_tree_fini (&cache->fde_tree, free_fde); + eu_search_tree_fini (&cache->cie_tree, free_cie); + eu_search_tree_fini (&cache->expr_tree, free_expr); if (cache->ebl != NULL && cache->ebl != (void *) -1l) ebl_closebackend (cache->ebl); diff --git a/libdw/libdw.h b/libdw/libdw.h index d53dc7871..54dfc9c10 100644 --- a/libdw/libdw.h +++ b/libdw/libdw.h @@ -125,7 +125,8 @@ typedef struct /* The offset can be computed from the address. */ void *addr; struct Dwarf_CU *cu; - Dwarf_Abbrev *abbrev; + //_Atomic Dwarf_Abbrev * abbrev; + Dwarf_Abbrev * abbrev; // XXX We'll see what other information will be needed. long int padding__; } Dwarf_Die; diff --git a/libdw/libdwP.h b/libdw/libdwP.h index e55ff50ac..a84ba7f5c 100644 --- a/libdw/libdwP.h +++ b/libdw/libdwP.h @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -215,22 +216,22 @@ struct Dwarf size_t pubnames_nsets; /* Search tree for the CUs. */ - void *cu_tree; + search_tree cu_tree; Dwarf_Off next_cu_offset; /* Search tree and sig8 hash table for .debug_types type units. */ - void *tu_tree; + search_tree tu_tree; Dwarf_Off next_tu_offset; Dwarf_Sig8_Hash sig8_hash; /* Search tree for split Dwarf associated with CUs in this debug. */ - void *split_tree; + search_tree split_tree; /* Search tree for .debug_macro operator tables. */ - void *macro_ops; + search_tree macro_ops_tree; /* Search tree for decoded .debug_line units. */ - void *files_lines; + search_tree files_lines_tree; /* Address ranges read from .debug_aranges. */ Dwarf_Aranges *aranges; @@ -263,6 +264,12 @@ 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 Dwarf objects. It guards against concurrent access issues by allowing multiple threads + to read or a single thread to write, thereby preventing data races and ensuring consistency + in multithreaded environments. */ + 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. */ @@ -423,7 +430,7 @@ struct Dwarf_CU Dwarf_Files *files; /* Known location lists. */ - void *locs; + search_tree locs_tree; /* Base address for use with ranges and locs. Don't access directly, call __libdw_cu_base_address. */ @@ -799,9 +806,14 @@ __libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp) /* Get the abbreviation code. */ unsigned int code; const unsigned char *addr = die->addr; + if (unlikely (die->cu == NULL || addr >= (const unsigned char *) die->cu->endp)) - return die->abbrev = DWARF_END_ABBREV; + { + die->abbrev = DWARF_END_ABBREV; + return DWARF_END_ABBREV; + } + get_uleb128 (code, addr, die->cu->endp); if (readp != NULL) *readp = addr; @@ -810,7 +822,7 @@ __libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp) if (die->abbrev == NULL) die->abbrev = __libdw_findabbrev (die->cu, code); } - return die->abbrev; + return (Dwarf_Abbrev *) die->abbrev; } /* Helper functions for form handling. */ @@ -912,7 +924,8 @@ extern int __libdw_intern_expression (Dwarf *dbg, bool other_byte_order, unsigned int address_size, unsigned int ref_size, - void **cache, const Dwarf_Block *block, + search_tree *cache, + const Dwarf_Block *block, bool cfap, bool valuep, Dwarf_Op **llbuf, size_t *listlen, int sec_index) diff --git a/libdw/libdw_find_split_unit.c b/libdw/libdw_find_split_unit.c index a17eac506..323579cc0 100644 --- a/libdw/libdw_find_split_unit.c +++ b/libdw/libdw_find_split_unit.c @@ -64,20 +64,16 @@ try_split_file (Dwarf_CU *cu, const char *dwo_path) && cu->unit_id8 == split->unit_id8) { if (eu_tsearch (split->dbg, &cu->dbg->split_tree, - __libdw_finddbg_cb) == NULL) + __libdw_finddbg_cb) == NULL) { /* Something went wrong. Don't link. */ __libdw_seterrno (DWARF_E_NOMEM); break; } - rwlock_wrlock(cu_split_lock); - /* Link skeleton and split compile units. */ __libdw_link_skel_split (cu, split); - rwlock_unlock(cu_split_lock); - /* We have everything we need from this ELF file. And we are going to close the fd to not run out of file descriptors. */ @@ -86,12 +82,8 @@ try_split_file (Dwarf_CU *cu, const char *dwo_path) } } - rwlock_rdlock(cu_split_lock); - if (cu->split == (Dwarf_CU *) -1) dwarf_end (split_dwarf); - - rwlock_unlock(cu_split_lock); } /* Always close, because we don't want to run out of file descriptors. See also the elf_fcntl ELF_C_FDDONE call @@ -147,8 +139,8 @@ try_dwp_file (Dwarf_CU *cu) cu->unit_id8); if (split != NULL) { - if (tsearch (split->dbg, &cu->dbg->split_tree, - __libdw_finddbg_cb) == NULL) + if (eu_tsearch (split->dbg, &cu->dbg->split_tree, + __libdw_finddbg_cb) == NULL) { /* Something went wrong. Don't link. */ __libdw_seterrno (DWARF_E_NOMEM); @@ -165,13 +157,14 @@ Dwarf_CU * internal_function __libdw_find_split_unit (Dwarf_CU *cu) { - rwlock_rdlock(cu_split_lock); - Dwarf_CU *cu_split_local = cu->split; rwlock_unlock(cu_split_lock); /* Only try once. */ - if (cu_split_local != (Dwarf_CU *) -1) - return cu_split_local; + if (cu->split != (Dwarf_CU *) -1) + { + rwlock_unlock(cu_split_lock); + return cu->split; + } /* We need a skeleton unit with a comp_dir and [GNU_]dwo_name attributes. The split unit will be the first in the dwo file and should have the @@ -200,11 +193,7 @@ __libdw_find_split_unit (Dwarf_CU *cu) free (dwo_path); } - rwlock_rdlock(cu_split_lock); - cu_split_local = cu->split; - rwlock_unlock(cu_split_lock); - - if (cu_split_local == (Dwarf_CU *) -1) + if (cu->split == (Dwarf_CU *) -1) { /* Try compdir plus dwo_name. */ Dwarf_Attribute compdir; @@ -230,11 +219,8 @@ __libdw_find_split_unit (Dwarf_CU *cu) /* If we found nothing, make sure we don't try again. */ if (cu->split == (Dwarf_CU *) -1) - { cu->split = NULL; - cu_split_local = cu->split; - } rwlock_unlock(cu_split_lock); - return cu_split_local; + return cu->split; } diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c index c9c433e78..93ed2570a 100644 --- a/libdw/libdw_findcu.c +++ b/libdw/libdw_findcu.c @@ -37,7 +37,7 @@ /* __libdw_findcu modifies "&dbg->next_tu_offset : &dbg->next_cu_offset". May read or write, so mutual exclusion is enforced to prevent a race. */ -rwlock_define(static, next_tucu_offset_lock); +//rwlock_define(static, next_tucu_offset_lock); static int findcu_cb (const void *arg1, const void *arg2) @@ -105,7 +105,7 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types) { Dwarf_Off *const offsetp = debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset; - void **tree = debug_types ? &dbg->tu_tree : &dbg->cu_tree; + search_tree *tree = debug_types ? &dbg->tu_tree : &dbg->cu_tree; Dwarf_Off oldoff = *offsetp; uint16_t version; @@ -171,7 +171,8 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types) newp->orig_abbrev_offset = newp->last_abbrev_offset = abbrev_offset; newp->files = NULL; newp->lines = NULL; - newp->locs = NULL; + newp->locs_tree.root = NULL; + rwlock_init (newp->locs_tree.lock); newp->split = (Dwarf_CU *) -1; newp->base_address = (Dwarf_Addr) -1; newp->addr_base = (Dwarf_Off) -1; @@ -240,7 +241,7 @@ struct Dwarf_CU * internal_function __libdw_findcu (Dwarf *dbg, Dwarf_Off start, bool v4_debug_types) { - void **tree = v4_debug_types ? &dbg->tu_tree : &dbg->cu_tree; + search_tree *tree = v4_debug_types ? &dbg->tu_tree : &dbg->cu_tree; Dwarf_Off *next_offset = v4_debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset; @@ -252,7 +253,7 @@ __libdw_findcu (Dwarf *dbg, Dwarf_Off start, bool v4_debug_types) if (found != NULL) return *found; - rwlock_wrlock(next_tucu_offset_lock); + rwlock_wrlock(dbg->dwarf_lock); if (start < *next_offset) __libdw_seterrno (DWARF_E_INVALID_DWARF); @@ -278,7 +279,7 @@ __libdw_findcu (Dwarf *dbg, Dwarf_Off start, bool v4_debug_types) } } - rwlock_unlock(next_tucu_offset_lock); + rwlock_unlock(dbg->dwarf_lock); return result; } @@ -286,7 +287,7 @@ struct Dwarf_CU * internal_function __libdw_findcu_addr (Dwarf *dbg, void *addr) { - void **tree; + search_tree *tree; Dwarf_Off start; if (addr >= dbg->sectiondata[IDX_debug_info]->d_buf && addr < (dbg->sectiondata[IDX_debug_info]->d_buf diff --git a/libdwfl/cu.c b/libdwfl/cu.c index ff8b2607a..d10c562af 100644 --- a/libdwfl/cu.c +++ b/libdwfl/cu.c @@ -151,8 +151,7 @@ less_lazy (Dwfl_Module *mod) return; /* We know about all the CUs now, we don't need this table. */ - tdestroy (mod->lazy_cu_root, nofree); - mod->lazy_cu_root = NULL; + eu_tdestroy (&mod->lazy_cu_tree, nofree); } static inline Dwarf_Off @@ -198,7 +197,8 @@ intern_cu (Dwfl_Module *mod, Dwarf_Off cuoff, struct dwfl_cu **result) struct dwfl_cu key; key.die.cu = die->cu; - struct dwfl_cu **found = eu_tsearch (&key, &mod->lazy_cu_root, &compare_cukey); + struct dwfl_cu **found = eu_tsearch (&key, &mod->lazy_cu_tree, + &compare_cukey); if (unlikely (found == NULL)) return DWFL_E_NOMEM; diff --git a/libdwfl/dwfl_module.c b/libdwfl/dwfl_module.c index c4d872d49..b4ddf8067 100644 --- a/libdwfl/dwfl_module.c +++ b/libdwfl/dwfl_module.c @@ -61,8 +61,7 @@ void internal_function __libdwfl_module_free (Dwfl_Module *mod) { - if (mod->lazy_cu_root != NULL) - tdestroy (mod->lazy_cu_root, nofree); + eu_search_tree_fini (&mod->lazy_cu_tree, nofree); if (mod->aranges != NULL) free (mod->aranges); @@ -200,6 +199,7 @@ dwfl_report_module (Dwfl *dwfl, const char *name, mod->low_addr = start; mod->high_addr = end; mod->dwfl = dwfl; + eu_search_tree_init (&mod->lazy_cu_tree); return use (mod, tailp, dwfl); } diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h index b3dfea1d1..bfb4bf275 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -37,6 +37,7 @@ #include #include #include +#include #include "libdwP.h" /* We need its INTDECLs. */ #include "libdwelfP.h" @@ -199,7 +200,7 @@ struct Dwfl_Module /* Known CU's in this module. */ struct dwfl_cu *first_cu, **cu; - void *lazy_cu_root; /* Table indexed by Dwarf_Off of CU. */ + search_tree lazy_cu_tree; /* Table indexed by Dwarf_Off of CU. */ struct dwfl_arange *aranges; /* Mapping of addresses in module to CUs. */ diff --git a/libelf/common.h b/libelf/common.h index 9b2a856d1..10b53e93e 100644 --- a/libelf/common.h +++ b/libelf/common.h @@ -92,9 +92,9 @@ allocate_elf (int fildes, void *map_address, int64_t offset, size_t maxsize, /* Acquire lock for the descriptor and all children. */ static void __attribute__ ((unused)) -libelf_acquire_all (Elf *elf) +libelf_acquire_all_children (Elf *elf) { - rwlock_wrlock (elf->lock); +// rwlock_wrlock (elf->lock); if (elf->kind == ELF_K_AR) { @@ -103,7 +103,10 @@ libelf_acquire_all (Elf *elf) while (child != NULL) { if (child->ref_count != 0) - libelf_acquire_all (child); + { + rwlock_wrlock(child->lock); + libelf_acquire_all_children (child); + } child = child->next; } } @@ -112,7 +115,7 @@ libelf_acquire_all (Elf *elf) /* Release own lock and those of the children. */ static void __attribute__ ((unused)) -libelf_release_all (Elf *elf) +libelf_release_all_children (Elf *elf) { if (elf->kind == ELF_K_AR) { @@ -121,12 +124,15 @@ libelf_release_all (Elf *elf) while (child != NULL) { if (child->ref_count != 0) - libelf_release_all (child); + { + rwlock_unlock (child->lock); + libelf_release_all_children (child); + } child = child->next; } } - rwlock_unlock (elf->lock); +// rwlock_unlock (elf->lock); } diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c index 8a49f3512..2b3b465f6 100644 --- a/libelf/elf_begin.c +++ b/libelf/elf_begin.c @@ -439,6 +439,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, /* So far only one block with sections. */ elf->state.elf32.scns_last = &elf->state.elf32.scns; + eu_search_tree_init (&elf->state.elf32.rawchunk_tree); } else { @@ -536,6 +537,7 @@ file_read_elf (int fildes, void *map_address, unsigned char *e_ident, /* So far only one block with sections. */ elf->state.elf64.scns_last = &elf->state.elf64.scns; + eu_search_tree_init (&elf->state.elf64.rawchunk_tree); } return elf; diff --git a/libelf/elf_cntl.c b/libelf/elf_cntl.c index 64087c7d6..cf5a59d06 100644 --- a/libelf/elf_cntl.c +++ b/libelf/elf_cntl.c @@ -53,11 +53,9 @@ elf_cntl (Elf *elf, Elf_Cmd cmd) switch (cmd) { case ELF_C_FDREAD: - rwlock_rdlock (elf->lock); - int addr_isnull = elf->map_address == NULL; - rwlock_unlock(elf->lock); + /* If not all of the file is in the memory read it now. */ - if (addr_isnull && __libelf_readall (elf) == NULL) + if (__libelf_readall (elf) == NULL) { /* We were not able to read everything. */ result = -1; diff --git a/libelf/elf_end.c b/libelf/elf_end.c index 80f4d13fa..da8f3a206 100644 --- a/libelf/elf_end.c +++ b/libelf/elf_end.c @@ -126,13 +126,14 @@ elf_end (Elf *elf) case ELF_K_ELF: { - void *rawchunks + search_tree *rawchunk_tree = (elf->class == ELFCLASS32 - || (offsetof (struct Elf, state.elf32.rawchunks) - == offsetof (struct Elf, state.elf64.rawchunks)) - ? elf->state.elf32.rawchunks - : elf->state.elf64.rawchunks); - tdestroy (rawchunks, free_chunk); + || (offsetof (struct Elf, state.elf32.rawchunk_tree) + == offsetof (struct Elf, state.elf64.rawchunk_tree)) + ? &elf->state.elf32.rawchunk_tree + : &elf->state.elf64.rawchunk_tree); + + eu_search_tree_fini (rawchunk_tree, free_chunk); Elf_ScnList *list = (elf->class == ELFCLASS32 || (offsetof (struct Elf, state.elf32.scns) diff --git a/libelf/elf_getdata_rawchunk.c b/libelf/elf_getdata_rawchunk.c index 1751878d6..3269dc6c7 100644 --- a/libelf/elf_getdata_rawchunk.c +++ b/libelf/elf_getdata_rawchunk.c @@ -33,8 +33,7 @@ #include #include -#include -#include +#include #include #include "libelfP.h" @@ -95,8 +94,9 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type) key.offset = offset; key.data.d.d_size = size; key.data.d.d_type = type; - Elf_Data_Chunk **found = tsearch (&key, &elf->state.elf.rawchunks, - &chunk_compare); + Elf_Data_Chunk **found + = eu_tsearch (&key, &elf->state.elf.rawchunk_tree, &chunk_compare); + if (found == NULL) goto nomem; @@ -136,7 +136,7 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type) if (rawchunk == NULL) { nomem: - tdelete (&key, &elf->state.elf.rawchunks, &chunk_compare); + eu_tdelete (&key, &elf->state.elf.rawchunk_tree, &chunk_compare); __libelf_seterrno (ELF_E_NOMEM); goto out; } @@ -147,7 +147,7 @@ elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type) != size)) { /* Something went wrong. */ - tdelete (&key, &elf->state.elf.rawchunks, &chunk_compare); + eu_tdelete (&key, &elf->state.elf.rawchunk_tree, &chunk_compare); free (rawchunk); __libelf_seterrno (ELF_E_READ_ERROR); goto out; diff --git a/libelf/elf_readall.c b/libelf/elf_readall.c index 2d62d4471..a804cd85e 100644 --- a/libelf/elf_readall.c +++ b/libelf/elf_readall.c @@ -84,8 +84,7 @@ __libelf_readall (Elf *elf) /* If this is an archive and we have derived descriptors get the locks for all of them. */ - rwlock_unlock(elf->lock); // lock will be reacquired next line - libelf_acquire_all (elf); + libelf_acquire_all_children (elf); if (elf->maximum_size == ~((size_t) 0)) { @@ -117,6 +116,7 @@ __libelf_readall (Elf *elf) { /* Something went wrong. */ read_error: + rwlock_unlock (elf->lock); __libelf_seterrno (ELF_E_READ_ERROR); free (mem); } @@ -142,8 +142,9 @@ __libelf_readall (Elf *elf) __libelf_seterrno (ELF_E_NOMEM); /* Free the locks on the children. */ - libelf_release_all (elf); // lock is released + libelf_release_all_children (elf); } + rwlock_unlock (elf->lock); return (char *) elf->map_address; } diff --git a/libelf/libelfP.h b/libelf/libelfP.h index bdd2cc6ac..3e4ab2f3e 100644 --- a/libelf/libelfP.h +++ b/libelf/libelfP.h @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -323,7 +324,8 @@ struct Elf Elf_ScnList *scns_last; /* Last element in the section list. If NULL the data has not yet been read from the file. */ - void *rawchunks; /* Tree of elf_getdata_rawchunk results. */ + search_tree rawchunk_tree; /* Tree and lock for elf_getdata_rawchunk + results. */ unsigned int scnincr; /* Number of sections allocate the last time. */ int ehdr_flags; /* Flags (dirty) for ELF header. */ @@ -342,7 +344,8 @@ struct Elf Elf_ScnList *scns_last; /* Last element in the section list. If NULL the data has not yet been read from the file. */ - void *rawchunks; /* Tree of elf_getdata_rawchunk results. */ + search_tree rawchunk_tree; /* Tree and lock for + elf_getdata_rawchunk results. */ unsigned int scnincr; /* Number of sections allocate the last time. */ int ehdr_flags; /* Flags (dirty) for ELF header. */ @@ -367,7 +370,8 @@ struct Elf Elf_ScnList *scns_last; /* Last element in the section list. If NULL the data has not yet been read from the file. */ - void *rawchunks; /* Tree of elf_getdata_rawchunk results. */ + search_tree rawchunk_tree; /* Tree and lock for + elf_getdata_rawchunk results. */ unsigned int scnincr; /* Number of sections allocate the last time. */ int ehdr_flags; /* Flags (dirty) for ELF header. */ diff --git a/tests/.Makefile.am.rej.swp b/tests/.Makefile.am.rej.swp deleted file mode 100644 index e2cc8cc7101973ec2aeef69d8b97ac24cc3658eb..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc-jL100001 literal 12288 zc-rk+&u`;I6rQexM1bYz331@=q_$JWf4 zG#5A^#F^vX;r~D@A@K(wZX7spLxK}$o`0oHTCx`^gqTnI>hbe?pWl4ru@u##*2nz= z_@LP$h}Q}EV{6y{^X|JVlc$8xh)Fgj&xOytSkmX`eO3r=u+UF657mZdN~?_nddhqr zvL=n1l06{?1_sxHn`EIkr2B^^8f!=zyF`TMhHXRN8UjG{3;<&kzXOd zMD~%t-6Z5&d(nwicg3?@`)&@p6RLV^w$gnWbv5HRX7seq1YR-a!| zQ>9r{)Rze;L)Ka9C`P3lI1zPateio&)9u22SY1OkZ&JUQ5^}*VXA}cep3C((TdL*y zeEvF1FDPAEGV3t+DzD={{_%OJnS@k$%*PJB#_C!u`Irkh8TOpPqrH!Y^?JifbRco! znRe%(Qn_+|*QH;0a$V|$qyMNnh)=o4sl(1RLj^B)D58mzFV4dH%`F>ba!x8}$j5lw zrKuqs+3lTWDGwfiwbR;aY{UAF-D=odfRQoNN#IG5MoZP%SrSVPy}|y;aepv$y8U5i zchGZo`<|$6_gjUiQz4*u7@#rOsvaM0&_8M zV)?O*EG|4QnX9w9?7GsDCss)1nB_JVdPQwvyj2-*mBw57tSW)OODb<%>8-9&6*03x z3L|qn1Lk%iEbMt$e97d#p~lkZzez)I8}A>7l>MD00000 -- 2.47.3