#ifndef EU_CONFIG_H
#define EU_CONFIG_H 1
+#include <stdio.h>
+
#ifdef USE_LOCKS
# include <pthread.h>
# include <assert.h>
({ 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
#include <config.h>
#endif
-#include <stdlib.h>
#include "eu-search.h"
-rwlock_define(static, search_find_lock);
+#include <stdio.h>
-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);
+}
#ifndef EU_SEARCH_H
#define EU_SEARCH_H 1
+#include <stdlib.h>
#include <search.h>
+#include <eu-config.h>
-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
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");
}
|
;
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;
}
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");
}
}
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'",
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'",
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)
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);
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);
}
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;
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];
}
}
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;
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;
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;
__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;
__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);
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;
}
}
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;
}
}
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;
}
}
__libdw_seterrno (DWARF_E_NOMEM); /* no memory. */
return NULL;
}
+ rwlock_init(result->dwarf_lock);
result->mem_stacks = 0;
result->mem_tails = NULL;
{
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
/* 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++)
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)
#include <sys/types.h>
#include <sys/stat.h>
-/* 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
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
}
}
+/* 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)
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;
#include <eu-search.h>
#include <stdlib.h>
#include <assert.h>
-
+#include <cfi.h>
#include <libdwP.h>
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;
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);
/* 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)
{
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);
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)
{
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;
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);
}
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;
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))
{
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)
{
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);
/* 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)
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))
{
void
dwarf_setalt (Dwarf *main, Dwarf *alt)
{
+ rwlock_wrlock(main->dwarf_lock);
+
if (main->alt_fd != -1)
{
INTUSE(dwarf_end) (main->alt_dwarf);
}
main->alt_dwarf = alt;
+
+ rwlock_unlock(main->dwarf_lock);
}
INTDEF (dwarf_setalt)
/* 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);
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);
/* 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;
#include <stdbool.h>
#include <pthread.h>
+#include <eu-search.h>
#include <libdw.h>
#include <dwarf.h>
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;
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. */
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. */
/* 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;
if (die->abbrev == NULL)
die->abbrev = __libdw_findabbrev (die->cu, code);
}
- return die->abbrev;
+ return (Dwarf_Abbrev *) die->abbrev;
}
/* Helper functions for form handling. */
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)
&& 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. */
}
}
- 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
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);
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
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;
/* 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;
}
/* __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)
{
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;
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;
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;
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);
}
}
- rwlock_unlock(next_tucu_offset_lock);
+ rwlock_unlock(dbg->dwarf_lock);
return result;
}
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
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
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;
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);
mod->low_addr = start;
mod->high_addr = end;
mod->dwfl = dwfl;
+ eu_search_tree_init (&mod->lazy_cu_tree);
return use (mod, tailp, dwfl);
}
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
+#include <eu-search.h>
#include "libdwP.h" /* We need its INTDECLs. */
#include "libdwelfP.h"
/* 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. */
/* 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)
{
while (child != NULL)
{
if (child->ref_count != 0)
- libelf_acquire_all (child);
+ {
+ rwlock_wrlock(child->lock);
+ libelf_acquire_all_children (child);
+ }
child = child->next;
}
}
/* 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)
{
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);
}
/* 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
{
/* 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;
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;
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)
#include <assert.h>
#include <errno.h>
-#include <search.h>
-#include <stdlib.h>
+#include <eu-search.h>
#include <string.h>
#include "libelfP.h"
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;
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;
}
!= 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;
/* 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))
{
{
/* Something went wrong. */
read_error:
+ rwlock_unlock (elf->lock);
__libelf_seterrno (ELF_E_READ_ERROR);
free (mem);
}
__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;
}
#include <ar.h>
#include <gelf.h>
+#include <eu-search.h>
#include <errno.h>
#include <stdbool.h>
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. */
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. */
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. */