Re: [PATCH] backends: allocate enough stace for null terminator

2024-07-17 Thread Mark Wielaard
Hi Sergei,

On Mon, 2024-07-15 at 22:23 +0100, Sergei Trofimovich wrote:
> `gcc-15` added a new warning in https://gcc.gnu.org/PR115185:
> 
> i386_regs.c:88:11: error: initializer-string for array of 'char' is too 
> long [-Werror=unterminated-string-initialization]
>88 |   "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "ip"
>   |   ^~~~

OK, I see why you want to warn for this. There is a real chance you use
those char array's with some str functions and then there is trouble.

> `elfutils` does not need to store '\0'. We could either initialize the
> arrays with individual bytes or allocate extra byte for null.

With initialize with individual bytes you mean:

diff --git a/backends/i386_regs.c b/backends/i386_regs.c
index 7ec93bb9fc13..ead55ef7f931 100644
--- a/backends/i386_regs.c
+++ b/backends/i386_regs.c
@@ -85,7 +85,15 @@ i386_register_info (Ebl *ebl __attribute__
((unused)),
 {
   static const char baseregs[][2] =
{
- "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "ip"
+ {'a', 'x'},
+ {'c', 'x'},
+ {'d', 'x'},
+ {'b', 'x'},
+ {'s', 'p'},
+ {'b', 'p'},
+ {'s', 'i'},
+ {'d', 'i'},
+ {'i', 'p'},
};
 
 case 4:

?

Since the use of this array is basically just:

  name[0] = 'r';
  name[1] = baseregs[regno][0];
  name[2] = baseregs[regno][1];

I think I prefer the individual bytes init way. It makes more clear
what we really use these arrays for. imho.

Thanks,

Mark


[PATCH v2] backends: allocate enough stace for null terminator

2024-07-17 Thread Sergei Trofimovich
`gcc-15` added a new warning in https://gcc.gnu.org/PR115185:

i386_regs.c:88:11: error: initializer-string for array of 'char' is too 
long [-Werror=unterminated-string-initialization]
   88 |   "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "ip"
  |   ^~~~

`elfutils` does not need to store '\0'. We could either initialize the
arrays with individual bytes or allocate extra byte for null.

This change initializes the array bytewise.

* backends/i386_regs.c (i386_register_info): Initialize the
array bytewise to fix gcc-15 warning.
* backends/x86_64_regs.c (x86_64_register_info): Ditto.

Signed-off-by: Sergei Trofimovich 
---
 backends/i386_regs.c   | 10 +-
 backends/x86_64_regs.c |  9 -
 2 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/backends/i386_regs.c b/backends/i386_regs.c
index 7ec93bb9..ead55ef7 100644
--- a/backends/i386_regs.c
+++ b/backends/i386_regs.c
@@ -85,7 +85,15 @@ i386_register_info (Ebl *ebl __attribute__ ((unused)),
 {
   static const char baseregs[][2] =
{
- "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "ip"
+ {'a', 'x'},
+ {'c', 'x'},
+ {'d', 'x'},
+ {'b', 'x'},
+ {'s', 'p'},
+ {'b', 'p'},
+ {'s', 'i'},
+ {'d', 'i'},
+ {'i', 'p'},
};
 
 case 4:
diff --git a/backends/x86_64_regs.c b/backends/x86_64_regs.c
index ef987daf..dab8f27f 100644
--- a/backends/x86_64_regs.c
+++ b/backends/x86_64_regs.c
@@ -82,7 +82,14 @@ x86_64_register_info (Ebl *ebl __attribute__ ((unused)),
 {
   static const char baseregs[][2] =
{
- "ax", "dx", "cx", "bx", "si", "di", "bp", "sp"
+ {'a', 'x'},
+ {'d', 'x'},
+ {'c', 'x'},
+ {'b', 'x'},
+ {'s', 'i'},
+ {'d', 'i'},
+ {'b', 'p'},
+ {'s', 'p'},
};
 
 case 6 ... 7:
-- 
2.45.2



[PATCH 0/9 v2] Fix thread-safety for elfutils

2024-07-17 Thread Aaron Merey
v1 can be found at
https://sourceware.org/pipermail/elfutils-devel/2023q3/006329.html

Heather McIntyre is the original author of v1 of these patches.
Heather and myself co-wrote v2.

Aaron Merey (9):
  libelf: Fix deadlock in __libelf_readall
  libelf: Fix deadlock in elf_cntl
  lib: Add eu_tsearch, eu_tfind, eu_tdelete and eu_tdestroy
  libdw: make dwarf_getalt thread-safe
  libdwP.h: Add locking to __libdw_dieabbrev
  libdw: Make libdw_find_split_unit thread-safe
  libdw: Make libdw_findcu thread-safe
  tests: Add eu-search tests
  configure: No longer mark --enable-thread-safety as EXPERIMENTAL

 configure.ac  |   6 +-
 lib/Makefile.am   |   5 +-
 lib/eu-config.h   |  30 +---
 lib/eu-search.c   |  85 +++
 lib/eu-search.h   |  64 +
 lib/locks.h   |  62 
 libdw/cfi.h   |   6 +-
 libdw/cie.c   |  10 +-
 libdw/dwarf_begin_elf.c   |   7 +-
 libdw/dwarf_end.c |  17 +--
 libdw/dwarf_formref_die.c |   2 +
 libdw/dwarf_getalt.c  |  18 ++-
 libdw/dwarf_getcfi.c  |   5 +-
 libdw/dwarf_getlocation.c |  24 ++--
 libdw/dwarf_getmacros.c   |   6 +-
 libdw/dwarf_getsrclines.c |   8 +-
 libdw/dwarf_setalt.c  |   4 +
 libdw/fde.c   |   6 +-
 libdw/frame-cache.c   |   8 +-
 libdw/libdwP.h|  49 +--
 libdw/libdw_find_split_unit.c |  18 ++-
 libdw/libdw_findcu.c  |  65 +
 libdwfl/cu.c  |   8 +-
 libdwfl/dwfl_module.c |   4 +-
 libdwfl/libdwflP.h|   3 +-
 libelf/common.h   |  16 +--
 libelf/elf_begin.c|   2 +
 libelf/elf_cntl.c |   7 +-
 libelf/elf_end.c  |  13 +-
 libelf/elf_getdata_rawchunk.c |  12 +-
 libelf/elf_readall.c  |   4 +-
 libelf/libelfP.h  |  10 +-
 tests/.gitignore  |   4 +
 tests/Makefile.am |  19 ++-
 tests/eu_search_cfi.c | 234 ++
 tests/eu_search_die.c | 262 ++
 tests/eu_search_lines.c   | 228 +
 tests/eu_search_macros.c  | 216 
 tests/run-eu-search-tests.sh  | 168 ++
 39 files changed, 1553 insertions(+), 162 deletions(-)
 create mode 100644 lib/eu-search.c
 create mode 100644 lib/eu-search.h
 create mode 100644 lib/locks.h
 create mode 100644 tests/eu_search_cfi.c
 create mode 100644 tests/eu_search_die.c
 create mode 100644 tests/eu_search_lines.c
 create mode 100644 tests/eu_search_macros.c
 create mode 100755 tests/run-eu-search-tests.sh

-- 
2.45.2



[PATCH 2/9 v2] libelf: Fix deadlock in elf_cntl

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

* libelf/elf_cntl.c (elf_cntl): Move rwlock_wrlock, rwlock_unlock,
inside case switch statements.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---
v2 changes:
Remove unnecessary locking and checking of elf->map_address

 libelf/elf_cntl.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/libelf/elf_cntl.c b/libelf/elf_cntl.c
index 04aa9132..3fbc7d97 100644
--- a/libelf/elf_cntl.c
+++ b/libelf/elf_cntl.c
@@ -48,13 +48,12 @@ elf_cntl (Elf *elf, Elf_Cmd cmd)
   return -1;
 }
 
-  rwlock_wrlock (elf->lock);
 
   switch (cmd)
 {
 case ELF_C_FDREAD:
   /* If not all of the file is in the memory read it now.  */
-  if (elf->map_address == NULL && __libelf_readall (elf) == NULL)
+  if (__libelf_readall (elf) == NULL)
{
  /* We were not able to read everything.  */
  result = -1;
@@ -64,7 +63,9 @@ elf_cntl (Elf *elf, Elf_Cmd cmd)
 
 case ELF_C_FDDONE:
   /* Mark the file descriptor as not usable.  */
+  rwlock_wrlock (elf->lock);
   elf->fildes = -1;
+  rwlock_unlock (elf->lock);
   break;
 
 default:
@@ -73,7 +74,5 @@ elf_cntl (Elf *elf, Elf_Cmd cmd)
   break;
 }
 
-  rwlock_unlock (elf->lock);
-
   return result;
 }
-- 
2.45.2



[PATCH 1/9 v2] libelf: Fix deadlock in __libelf_readall

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

Apply locking during __libelf_readall.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---
v2 changes:

Add locking for all early returns in __libelf_readall.

libelf_{acquire,release}_all have been renamed to
libelf_{acquire,release}_all_children.  These functions also no longer
acquire/release the parent's lock.  This is done in order to simplify
lock management in __libelf_readall.

 libelf/common.h  | 16 
 libelf/elf_readall.c |  4 ++--
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/libelf/common.h b/libelf/common.h
index 9b2a856d..b7226ee8 100644
--- a/libelf/common.h
+++ b/libelf/common.h
@@ -92,10 +92,8 @@ 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);
-
   if (elf->kind == ELF_K_AR)
 {
   Elf *child = elf->state.ar.children;
@@ -103,7 +101,9 @@ libelf_acquire_all (Elf *elf)
   while (child != NULL)
{
  if (child->ref_count != 0)
-   libelf_acquire_all (child);
+   libelf_acquire_all_children (child);
+
+ rwlock_wrlock(child->lock);
  child = child->next;
}
 }
@@ -112,7 +112,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 +121,12 @@ libelf_release_all (Elf *elf)
   while (child != NULL)
{
  if (child->ref_count != 0)
-   libelf_release_all (child);
+   libelf_release_all_children (child);
+
+ rwlock_unlock (child->lock);
  child = child->next;
}
 }
-
-  rwlock_unlock (elf->lock);
 }
 
 
diff --git a/libelf/elf_readall.c b/libelf/elf_readall.c
index d0f9a28c..4ef8fe97 100644
--- a/libelf/elf_readall.c
+++ b/libelf/elf_readall.c
@@ -84,7 +84,7 @@ __libelf_readall (Elf *elf)
 
   /* If this is an archive and we have derived descriptors get the
 locks for all of them.  */
-  libelf_acquire_all (elf);
+  libelf_acquire_all_children (elf);
 
   if (elf->maximum_size == ~((size_t) 0))
{
@@ -141,7 +141,7 @@ __libelf_readall (Elf *elf)
__libelf_seterrno (ELF_E_NOMEM);
 
   /* Free the locks on the children.  */
-  libelf_release_all (elf);
+  libelf_release_all_children (elf);
 }
 
   rwlock_unlock (elf->lock);
-- 
2.45.2



[PATCH 4/9 v2] libdw: make dwarf_getalt thread-safe

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

* libdw/dwarf_getalt.c (dwarf_getalt): Add locking.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

v2 changes:

Write lock now applies to all of dwarf_getalt.
---
 libdw/dwarf_getalt.c | 18 --
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/libdw/dwarf_getalt.c b/libdw/dwarf_getalt.c
index 0a12dfae..3b827d0b 100644
--- a/libdw/dwarf_getalt.c
+++ b/libdw/dwarf_getalt.c
@@ -160,15 +160,27 @@ 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_wrlock(main->dwarf_lock);
+
   /* Only try once.  */
   if (main == NULL || main->alt_dwarf == (void *) -1)
-return NULL;
+{
+  rwlock_unlock (main->dwarf_lock);
+  return NULL;
+}
 
   if (main->alt_dwarf != NULL)
-return main->alt_dwarf;
+{
+  rwlock_unlock (main->dwarf_lock);
+  return main->alt_dwarf;
+}
 
   find_debug_altlink (main);
 
@@ -176,9 +188,11 @@ dwarf_getalt (Dwarf *main)
   if (main->alt_dwarf == NULL)
 {
   main->alt_dwarf = (void *) -1;
+  rwlock_unlock (main->dwarf_lock);
   return NULL;
 }
 
+  rwlock_unlock (main->dwarf_lock);
   return main->alt_dwarf;
 }
 INTDEF (dwarf_getalt)
-- 
2.45.2



[PATCH 6/9 v2] libdw: Make libdw_find_split_unit thread-safe

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

* (__libdw_find_split_unit): Add lock for cu->split.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---

v2 changes:
Locking applied to __libdw_find_split_unit instead of try_split_file.

 libdw/libdw_find_split_unit.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/libdw/libdw_find_split_unit.c b/libdw/libdw_find_split_unit.c
index 67d31a9c..eb3d88d7 100644
--- a/libdw/libdw_find_split_unit.c
+++ b/libdw/libdw_find_split_unit.c
@@ -150,9 +150,14 @@ Dwarf_CU *
 internal_function
 __libdw_find_split_unit (Dwarf_CU *cu)
 {
+  rwlock_wrlock(cu->split_lock);
+
   /* Only try once.  */
   if (cu->split != (Dwarf_CU *) -1)
-return cu->split;
+{
+  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
@@ -207,5 +212,6 @@ __libdw_find_split_unit (Dwarf_CU *cu)
   if (cu->split == (Dwarf_CU *) -1)
 cu->split = NULL;
 
+  rwlock_unlock(cu->split_lock);
   return cu->split;
 }
-- 
2.45.2



[PATCH 5/9 v2] libdwP.h: Add locking to __libdw_dieabbrev,

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---

v2 changes:
This replaces patch "libdw: Add locking around __libdw_dieabbrev for
dwarf_hasattr".  Mark suggested that we remove lazy abbrev reading
in order to simplify the locking of __libdw_dieabbrev.  This is
a fair bit of work so for now lets just put a write lock around all
of __libdw_dieabbrev.  The removal of lazy reading of abbrev will be
done in a future patch.

 libdw/dwarf_formref_die.c |  2 ++
 libdw/dwarf_setalt.c  |  4 
 libdw/libdwP.h| 23 +++
 3 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c
index 48ba8194..f8a51970 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_setalt.c b/libdw/dwarf_setalt.c
index dc9b61cb..f7d70d9d 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/libdwP.h b/libdw/libdwP.h
index a4f26b82..9dce10e5 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -804,15 +804,28 @@ static inline Dwarf_Abbrev *
 __nonnull_attribute__ (1)
 __libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp)
 {
+  if (unlikely (die->cu == NULL))
+{
+  die->abbrev = DWARF_END_ABBREV;
+  return DWARF_END_ABBREV;
+}
+
+  rwlock_wrlock (die->cu->abbrev_lock);
+
   /* Do we need to get the abbreviation, or need to read after the code?  */
   if (die->abbrev == NULL || readp != NULL)
 {
   /* 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;
+
+  if (addr >= (const unsigned char *) die->cu->endp)
+   {
+ die->abbrev = DWARF_END_ABBREV;
+ rwlock_unlock (die->cu->abbrev_lock);
+ return DWARF_END_ABBREV;
+   }
+
   get_uleb128 (code, addr, die->cu->endp);
   if (readp != NULL)
*readp = addr;
@@ -821,7 +834,9 @@ __libdw_dieabbrev (Dwarf_Die *die, const unsigned char 
**readp)
   if (die->abbrev == NULL)
die->abbrev = __libdw_findabbrev (die->cu, code);
 }
-  return die->abbrev;
+
+  rwlock_unlock (die->cu->abbrev_lock);
+  return (Dwarf_Abbrev *) die->abbrev;
 }
 
 /* Helper functions for form handling.  */
-- 
2.45.2



[PATCH 8/9 v2] tests: Add eu-search tests

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

* tests/eu_search_cfi.c: New file.
* tests/eu_search_die.c: New file.
* tests/eu_search_lines.c: New file.
* tests/eu_search_macros.c: New file.
* tests/run-eu-search-tests.sh: New test.
* tests/Makefile.am: Add USE_LOCKS condition for -pthread.
(check_PROGRAMS): Add eu_search_cfi, eu_search_die,
eu_search_lines, and eu_search_macros.
(TESTS, EXTRA_DIST): Add run-eu-search-tests.sh
(eu_search_cfi_LDADD): New variable.
(eu_search_die_LDADD): New variable.
(eu_search_lines_LDADD): New variable.
(eu_search_macros_LDADD): New variable.
(eu_search_cfi_LDFLAGS): New variable.
Add -pthread if USE_LOCKS is not defined.
(eu_search_die_LDFLAGS): Likewise.
(eu_search_lines_LDFLAGS): Likewise.
(eu_search_macros_LDFLAGS): Likewise.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 
---
v2 changes:

Rebase and add run-eu-search-tests.sh to EXTRA_DIST.

The elfutils testsuite (including the tests added in this patch) passes
for me on the sourceware buildbots.  However the buildbots do not configure
elfutils with --enable-thread-safety.  I think we should include this
configure option when the buildbots run elfutils tests.

 tests/.gitignore |   4 +
 tests/Makefile.am|  19 ++-
 tests/eu_search_cfi.c| 234 +++
 tests/eu_search_die.c| 262 +++
 tests/eu_search_lines.c  | 228 ++
 tests/eu_search_macros.c | 216 +
 tests/run-eu-search-tests.sh | 168 ++
 7 files changed, 1129 insertions(+), 2 deletions(-)
 create mode 100644 tests/eu_search_cfi.c
 create mode 100644 tests/eu_search_die.c
 create mode 100644 tests/eu_search_lines.c
 create mode 100644 tests/eu_search_macros.c
 create mode 100755 tests/run-eu-search-tests.sh

diff --git a/tests/.gitignore b/tests/.gitignore
index 30f5800b..360c13a3 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -67,6 +67,10 @@
 /elfstrtab
 /elf-print-reloc-syms
 /emptyfile
+/eu_search_cfi
+/eu_search_die
+/eu_search_lines
+/eu_search_macros
 /fillfile
 /find-prologues
 /funcretval
diff --git a/tests/Makefile.am b/tests/Makefile.am
index cfed54b7..1642d4e9 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -32,6 +32,10 @@ else
 tests_rpath = no
 endif
 
+if USE_LOCKS
+  AM_CFLAGS += -pthread
+endif
+
 check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
  showptable update1 update2 update3 update4 test-nlist \
  show-die-info get-files next-files get-lines next-lines \
@@ -64,6 +68,7 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames 
sectiondump \
  msg_tst system-elf-libelf-test system-elf-gelf-test \
  nvidia_extended_linemap_libdw elf-print-reloc-syms \
  cu-dwp-section-info declfiles \
+ eu_search_cfi eu_search_die eu_search_lines eu_search_macros \
  $(asm_TESTS)
 
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
@@ -216,7 +221,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile 
test-nlist \
run-readelf-dw-form-indirect.sh run-strip-largealign.sh \
run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh 
\
run-declfiles.sh \
-   run-sysroot.sh
+   run-sysroot.sh run-eu-search-tests.sh
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
@@ -669,7 +674,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 testfile-dwp-4-cu-index-overflow.dwp.bz2 \
 testfile-dwp-cu-index-overflow.source \
 testfile-define-file.bz2 \
-testfile-sysroot.tar.bz2 run-sysroot.sh
+testfile-sysroot.tar.bz2 run-sysroot.sh \
+run-eu-search-tests.sh
 
 
 if USE_VALGRIND
@@ -849,6 +855,15 @@ nvidia_extended_linemap_libdw_LDADD = $(libelf) $(libdw)
 elf_print_reloc_syms_LDADD = $(libelf)
 cu_dwp_section_info_LDADD = $(libdw)
 declfiles_LDADD = $(libdw)
+eu_search_cfi_LDFLAGS = $(if $(filter undefined,$(origin USE_LOCKS)),-pthread) 
$(AM_LDFLAGS)
+eu_search_die_LDFLAGS = $(if $(filter undefined,$(origin USE_LOCKS)),-pthread) 
$(AM_LDFLAGS)
+eu_search_lines_LDFLAGS = $(if $(filter undefined,$(origin 
USE_LOCKS)),-pthread) $(AM_LDFLAGS)
+eu_search_macros_LDFLAGS = $(if $(filter undefined,$(origin 
USE_LOCKS)),-pthread) $(AM_LDFLAGS)
+eu_search_cfi_LDADD = $(libeu) $(libelf) $(libdw)
+eu_search_die_LDADD = $(libdw)
+eu_search_lines_LDADD = $(libdw) $(libelf)
+eu_search_macros_LDADD = $(libdw)
 
 # We want to test the libelf headers against the system elf.h header.
 # Don't include any -I CPPFLAGS. Except when we install our own elf.h.
diff --git a/tests/eu_search_cfi.c b/tests/eu_search_cfi.c
new file mode 100644
index ..

[PATCH 3/9 v2] lib: Add eu_tsearch, eu_tfind, eu_tdelete and eu_tdestroy

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

Add new struct search_tree to hold tree root and lock.  Add new eu_t*
functions for ensuring synchronized tree access.

Replace tsearch, tfind, etc with eu_t* equivalents.

Move the rwlock_* macros out of eu-config.h and into a new header file
locks.h.  This was done so that the rwlock_* macros can be included
in libdwP.h without having to also include the rest of eu-config.h.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

v2 changes:

This patch replaces v1 03/16 and 14/16.
---
 lib/Makefile.am   |  5 ++-
 lib/eu-config.h   | 30 +
 lib/eu-search.c   | 85 +++
 lib/eu-search.h   | 64 ++
 lib/locks.h   | 62 +
 libdw/cfi.h   |  6 +--
 libdw/cie.c   | 10 +++--
 libdw/dwarf_begin_elf.c   |  7 +--
 libdw/dwarf_end.c | 17 +++
 libdw/dwarf_getcfi.c  |  5 ++-
 libdw/dwarf_getlocation.c | 24 +-
 libdw/dwarf_getmacros.c   |  6 +--
 libdw/dwarf_getsrclines.c |  8 ++--
 libdw/fde.c   |  6 +--
 libdw/frame-cache.c   |  8 ++--
 libdw/libdwP.h| 26 ---
 libdw/libdw_find_split_unit.c | 10 ++---
 libdw/libdw_findcu.c  | 18 
 libdwfl/cu.c  |  8 ++--
 libdwfl/dwfl_module.c |  4 +-
 libdwfl/libdwflP.h|  3 +-
 libelf/elf_begin.c|  2 +
 libelf/elf_end.c  | 13 +++---
 libelf/elf_getdata_rawchunk.c | 12 ++---
 libelf/libelfP.h  | 10 +++--
 25 files changed, 331 insertions(+), 118 deletions(-)
 create mode 100644 lib/eu-search.c
 create mode 100644 lib/eu-search.h
 create mode 100644 lib/locks.h

diff --git a/lib/Makefile.am b/lib/Makefile.am
index b3bb929f..e324c18d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -34,10 +34,11 @@ AM_CPPFLAGS += -I$(srcdir)/../libelf
 noinst_LIBRARIES = libeu.a
 
 libeu_a_SOURCES = xasprintf.c xstrdup.c xstrndup.c xmalloc.c next_prime.c \
- crc32.c crc32_file.c \
+ crc32.c crc32_file.c eu-search.c \
  color.c error.c printversion.c
 
 noinst_HEADERS = fixedsizehash.h libeu.h system.h dynamicsizehash.h list.h \
 eu-config.h color.h printversion.h bpf.h \
-atomics.h stdatomic-fbsd.h dynamicsizehash_concurrent.h
+atomics.h stdatomic-fbsd.h dynamicsizehash_concurrent.h \
+eu-search.h locks.h
 EXTRA_DIST = dynamicsizehash.c dynamicsizehash_concurrent.c
diff --git a/lib/eu-config.h b/lib/eu-config.h
index feb079db..a38d75da 100644
--- a/lib/eu-config.h
+++ b/lib/eu-config.h
@@ -29,35 +29,7 @@
 #ifndef EU_CONFIG_H
 #define EU_CONFIG_H1
 
-#ifdef USE_LOCKS
-# include 
-# include 
-# define rwlock_define(class,name) class pthread_rwlock_t name
-# define once_define(class,name)  class pthread_once_t name = PTHREAD_ONCE_INIT
-# define RWLOCK_CALL(call) \
-  ({ int _err = pthread_rwlock_ ## call; assert_perror (_err); })
-# define ONCE_CALL(call)  \
-  ({ 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 once(once_control, init_routine)  \
-  ONCE_CALL (once (&once_control, init_routine))
-#else
-/* Eventually we will allow multi-threaded applications to use the
-   libraries.  Therefore we will add the necessary locking although
-   the macros used expand to nothing for now.  */
-# define rwlock_define(class,name) class int name
-# define rwlock_init(lock) ((void) (lock))
-# define rwlock_fini(lock) ((void) (lock))
-# define rwlock_rdlock(lock) ((void) (lock))
-# define rwlock_wrlock(lock) ((void) (lock))
-# define rwlock_unlock(lock) ((void) (lock))
-# define once_define(class,name)
-# define once(once_control, init_routine)  init_routine()
-#endif /* USE_LOCKS */
+#include 
 
 #include 
 /* gettext helper macros.  */
diff --git a/lib/eu-search.c b/lib/eu-search.c
new file mode 100644
index ..b7256eba
--- /dev/null
+++ b/lib/eu-search.c
@@ -0,0 +1,85 @@
+/* Definitions for thread-safe tsearch/tfind
+   Copyright (C) 2023 Rice University
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+ * the GNU Lesser General Public License as published by the Free
+   Software Foundation; either version 3 of the License, or (at
+   your option) any later version
+
+   or
+
+ * the GNU General Public License as published by the Free
+   Software Foundation; either version

[PATCH 7/9 v2] libdw: Make libdw_findcu thread-safe

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

* libdw/libdw_findcu.c (__libdw_findcu): Use eu_tfind
and dwarf_lock
(__libdw_intern_next_unit): Use per-Dwarf_CU locks.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 

---
v2 changes:
Use per-Dwarf_CU lock instead of a global lock.

 libdw/libdw_findcu.c | 47 
 1 file changed, 30 insertions(+), 17 deletions(-)

diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
index 72cf261c..8acff448 100644
--- a/libdw/libdw_findcu.c
+++ b/libdw/libdw_findcu.c
@@ -177,6 +177,8 @@ __libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
   newp->startp = data->d_buf + newp->start;
   newp->endp = data->d_buf + newp->end;
   eu_search_tree_init (&newp->locs_tree);
+  rwlock_init (newp->abbrev_lock);
+  rwlock_init (newp->split_lock);
 
   /* v4 debug type units have version == 4 and unit_type == DW_UT_type.  */
   if (debug_types)
@@ -243,27 +245,38 @@ __libdw_findcu (Dwarf *dbg, Dwarf_Off start, bool 
v4_debug_types)
   /* Maybe we already know that CU.  */
   struct Dwarf_CU fake = { .start = start, .end = 0 };
   struct Dwarf_CU **found = eu_tfind (&fake, tree, findcu_cb);
+  struct Dwarf_CU *result = NULL;
   if (found != NULL)
 return *found;
 
-  if (start < *next_offset)
-{
-  __libdw_seterrno (DWARF_E_INVALID_DWARF);
-  return NULL;
-}
+  rwlock_wrlock (dbg->dwarf_lock);
 
-  /* No.  Then read more CUs.  */
-  while (1)
-{
-  struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, v4_debug_types);
-  if (newp == NULL)
-   return NULL;
-
-  /* Is this the one we are looking for?  */
-  if (start < *next_offset || start == newp->start)
-   return newp;
-}
-  /* NOTREACHED */
+  if (start < *next_offset)
+__libdw_seterrno (DWARF_E_INVALID_DWARF);
+  else
+{   
+  /* No.  Then read more CUs.  */
+  while (1) 
+{   
+  struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg,
+v4_debug_types);
+  if (newp == NULL)
+{   
+  result = NULL;
+  break;
+}
+
+  /* Is this the one we are looking for?  */
+  if (start < *next_offset || start == newp->start)
+{
+  result = newp;
+  break;
+}
+}
+}   
+
+  rwlock_unlock (dbg->dwarf_lock);
+  return result;
 }
 
 struct Dwarf_CU *
-- 
2.45.2



[PATCH 9/9 v2] configure: No longer mark --enable-thread-safety as EXPERIMENTAL

2024-07-17 Thread Aaron Merey
From: Heather McIntyre 

* configure.ac (--enable-thread-safety): Remove experimental
warning.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 
---

No changes in v2.  However PR31967 (datarace in elf_compress[_gnu])
was recently filed and this patch set does not address it.  Maybe
we should hold off on merging this patch and keep thread safety
"experimental" until PR31967 is fixed.

 configure.ac | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/configure.ac b/configure.ac
index 24e68d94..2c885c8a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,12 +79,10 @@ AC_DEFINE_UNQUOTED(DEFAULT_AR_DETERMINISTIC, 
$default_ar_deterministic,
 
 AC_ARG_ENABLE([thread-safety],
 AS_HELP_STRING([--enable-thread-safety],
-   [enable thread safety of libraries EXPERIMENTAL]),
+   [enable thread safety of libraries]),
use_locks=$enableval, use_locks=no)
 AM_CONDITIONAL(USE_LOCKS, test "$use_locks" = yes)
 AS_IF([test "$use_locks" = yes], [AC_DEFINE(USE_LOCKS)])
-AS_IF([test "$use_locks" = yes],
-  [AC_MSG_WARN([thread-safety is EXPERIMENTAL tests might fail.])])
 
 AH_TEMPLATE([USE_LOCKS], [Defined if libraries should be thread-safe.])
 
@@ -939,10 +937,10 @@ AC_MSG_NOTICE([
 Symbol versioning  : ${enable_symbol_versioning}
 
   NOT RECOMMENDED FEATURES (should all be no)
-Experimental thread safety : ${use_locks}
 install elf.h  : ${install_elfh}
 
   OTHER FEATURES
+Enable thread safety   : ${use_locks}
 Deterministic archives by default  : ${default_ar_deterministic}
 Native language support: ${USE_NLS}
 Extra Valgrind annotations : ${use_vg_annotations}
-- 
2.45.2