[PATCH 01/10 v2] Change type of dwarf_lock from rwlock to mutex

2025-02-04 Thread Aaron Merey
Change type of dwarf_lock to mutex in order to take advantage of
built-in support for recursive locking.

* lib/locks.h: Add macros for locking, unlocking, initializing
and destroying mutexes.
* libdw/dwarf_begin_elf.c (dwarf_end): Replace rwlock macro with
mutex macro.
* libdw/dwarf_end.c (dwarf_end): Ditto.
* libdw/dwarf_formref_die.c (dwarf_formref_die): Ditto.
* libdw/dwarf_getalt.c (dwarf_getalt): Ditto.
* libdw/dwarf_setalt.c (dwarf_setalt): Ditto.
* libdw/libdwP.h (struct Dwarf): Ditto.
* libdw/libdw_findcu.c (__libdw_findcu): Ditto.

Signed-off-by: Aaron Merey 
---
v2 changes: Add comments to libdwP.h locks describing which functions
they're intended to cover.

 lib/locks.h   | 16 
 libdw/dwarf_begin_elf.c   |  2 +-
 libdw/dwarf_end.c |  2 +-
 libdw/dwarf_formref_die.c |  4 ++--
 libdw/dwarf_getalt.c  | 10 +-
 libdw/dwarf_setalt.c  |  4 ++--
 libdw/libdwP.h| 12 +++-
 libdw/libdw_findcu.c  |  4 ++--
 8 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/lib/locks.h b/lib/locks.h
index 90fe3f1b..9c17eca7 100644
--- a/lib/locks.h
+++ b/lib/locks.h
@@ -43,6 +43,17 @@
 # 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 mutex_define(class,name)   class pthread_mutex_t name
+# define MUTEX_CALL(call)  \
+  ({ int _err = pthread_mutex_ ## call; assert_perror (_err); })
+# define mutex_init(lock) \
+  ({ pthread_mutexattr_t _attr;   \
+ pthread_mutexattr_init (&_attr); \
+ pthread_mutexattr_settype (&_attr, PTHREAD_MUTEX_RECURSIVE); \
+ MUTEX_CALL (init (&lock, &_attr)); })
+# define mutex_lock(_lock) MUTEX_CALL (lock (&_lock))
+# define mutex_unlock(lock)MUTEX_CALL (unlock (&lock))
+# define mutex_fini(lock)  MUTEX_CALL (destroy (&lock))
 # define once(once_control, init_routine)  \
   ONCE_CALL (once (&once_control, init_routine))
 #else
@@ -55,6 +66,11 @@
 # define rwlock_rdlock(lock) ((void) (lock))
 # define rwlock_wrlock(lock) ((void) (lock))
 # define rwlock_unlock(lock) ((void) (lock))
+# define mutex_define(class,name) class int name
+# define mutex_init(lock) ((void) (lock))
+# define mutex_lock(lock) ((void) (lock))
+# define mutex_unlock(lock) ((void) (lock))
+# define mutex_fini(lock) ((void) (lock))
 # define once_define(class,name)
 # define once(once_control, init_routine)   init_routine()
 #endif  /* USE_LOCKS */
diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
index c8292913..8a3a939b 100644
--- a/libdw/dwarf_begin_elf.c
+++ b/libdw/dwarf_begin_elf.c
@@ -579,7 +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);
+  mutex_init (result->dwarf_lock);
   eu_search_tree_init (&result->cu_tree);
   eu_search_tree_init (&result->tu_tree);
   eu_search_tree_init (&result->split_tree);
diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
index ee3ed74e..92389c07 100644
--- a/libdw/dwarf_end.c
+++ b/libdw/dwarf_end.c
@@ -129,7 +129,7 @@ dwarf_end (Dwarf *dwarf)
   if (dwarf->mem_tails != NULL)
 free (dwarf->mem_tails);
   pthread_rwlock_destroy (&dwarf->mem_rwl);
-  rwlock_fini (dwarf->dwarf_lock);
+  mutex_fini (dwarf->dwarf_lock);
 
   /* Free the pubnames helper structure.  */
   free (dwarf->pubnames_sets);
diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c
index 69d1bf1c..85c484f6 100644
--- a/libdw/dwarf_formref_die.c
+++ b/libdw/dwarf_formref_die.c
@@ -92,9 +92,9 @@ dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *result)
  bool scan_debug_types = false;
  do
{
- rwlock_wrlock(attr->cu->dbg->dwarf_lock);
+ mutex_lock (attr->cu->dbg->dwarf_lock);
  cu = __libdw_intern_next_unit (attr->cu->dbg, scan_debug_types);
- rwlock_unlock(attr->cu->dbg->dwarf_lock);
+ mutex_unlock (attr->cu->dbg->dwarf_lock);
 
  if (cu == NULL)
{
diff --git a/libdw/dwarf_getalt.c b/libdw/dwarf_getalt.c
index 26433b81..f4b8ad02 100644
--- a/libdw/dwarf_getalt.c
+++ b/libdw/dwarf_getalt.c
@@ -170,12 +170,12 @@ dwarf_getalt (Dwarf *main)
   if (main == NULL)
 return NULL;
 
-  rwlock_wrlock(main->dwarf_lock);
+  mutex_lock (main->dwarf_lock);
 
   /* Only try once.  */
   if (main->alt_dwarf == (void *) -1)
 {
-  rwlock_unlock (main->dwarf_lock);
+  mutex_unlock (main->dwarf_lock);
   return NULL;
 }
 
@@ -185,7 +185,7 @@ dwarf_getalt (Dwarf *main)
   if (main->alt_dwarf != NULL)
 {
   result 

[PATCH 02/10 v2] dwarf_filesrc.c: Add locking

2025-02-04 Thread Aaron Merey
* libdw/dwarf_getsrclines.c (read_srcfiles): Initialize Dwarf
member.
* libdw/dwarf_filesrc.c (dwarf_filesrc): Use dwarf_lock.
* libdw/libdwP.h (struct Dwarf_Files_s): Add Dwarf member.

Signed-off-by: Aaron Merey 
---
v2 changes: Combined v1 patches 03/15 and 06/15 into one patch.

 libdw/dwarf_filesrc.c | 13 +++--
 libdw/dwarf_getsrclines.c |  2 ++
 libdw/libdwP.h|  1 +
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/libdw/dwarf_filesrc.c b/libdw/dwarf_filesrc.c
index d866ce72..a0881f36 100644
--- a/libdw/dwarf_filesrc.c
+++ b/libdw/dwarf_filesrc.c
@@ -38,14 +38,23 @@ const char *
 dwarf_filesrc (Dwarf_Files *file, size_t idx, Dwarf_Word *mtime,
   Dwarf_Word *length)
 {
-  if (file == NULL || idx >= file->nfiles)
+  if (file == NULL)
 return NULL;
 
+  mutex_lock (file->dbg->dwarf_lock);
+  if (idx >= file->nfiles)
+{
+  mutex_unlock (file->dbg->dwarf_lock);
+  return NULL;
+}
+
   if (mtime != NULL)
 *mtime = file->info[idx].mtime;
 
   if (length != NULL)
 *length = file->info[idx].length;
 
-  return file->info[idx].name;
+  const char *res = file->info[idx].name;
+  mutex_unlock (file->dbg->dwarf_lock);
+  return res;
 }
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index da78db67..b0b5f2eb 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -717,6 +717,7 @@ read_srcfiles (Dwarf *dbg,
   if (unlikely (files == NULL))
 goto no_mem;
 
+  files->dbg = dbg;
   const char **dirs = (void *) &files->info[nfilelist];
 
   struct filelist *fileslist = filelist;
@@ -1198,6 +1199,7 @@ read_srclines (Dwarf *dbg,
+ (ndirs + 1) * sizeof (char *),
1);
 
+  newfiles->dbg = dbg;
 
   /* Copy prevfiles to newfiles.  */
   for (size_t n = 0; n < nprevfiles; n++)
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
index 9d2ffab0..a6bd7e5b 100644
--- a/libdw/libdwP.h
+++ b/libdw/libdwP.h
@@ -305,6 +305,7 @@ struct Dwarf_Abbrev
 /* Files in line information records.  */
 struct Dwarf_Files_s
   {
+Dwarf *dbg;
 unsigned int ndirs;
 unsigned int nfiles;
 struct Dwarf_Fileinfo_s
-- 
2.48.1



[PATCH] libelf: fix DEREF_OF_NULL.RET in objdump.c

2025-02-04 Thread Anton Moryakov
Report of the static analyzer:
Pointer, returned from function 'elf_getarhdr' at objdump.c:314,
may be NULL and is dereferenced at objdump.c:317. (CWE-476, CWE-690)

Corrections explained:
When processing archive elements, the code could dereference a NULL
pointer if 'elf_getarhdr' returns NULL. This patch adds a check to
ensure 'arhdr' is not NULL before using it. The fix ensures that the
function safely handles cases where 'elf_getarhdr' fails, avoiding
potential crashes.

Triggers found by static analyzer Svace.

Signed-off-by: Anton Moryakov 

---
 src/objdump.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/objdump.c b/src/objdump.c
index 1b38da23..d2b7c7b3 100644
--- a/src/objdump.c
+++ b/src/objdump.c
@@ -313,7 +313,8 @@ handle_ar (int fd, Elf *elf, const char *prefix, const char 
*fname,
   Elf_Arhdr *arhdr = elf_getarhdr (subelf);
 
   /* Skip over the index entries.  */
-  if (strcmp (arhdr->ar_name, "/") != 0
+  if (arhdr != NULL
+  && strcmp (arhdr->ar_name, "/") != 0
  && strcmp (arhdr->ar_name, "//") != 0)
{
  if (elf_kind (subelf) == ELF_K_ELF)
-- 
2.30.2



[PATCH 04/10 v2] dwarf_offdie.c: Add locking

2025-02-04 Thread Aaron Merey
* libdw/dwarf_offdie.c (__libdw_offdie): Use dwarf_lock.

Signed-off-by: Aaron Merey 
---
v2 changes: Lock only for the duration of __libdw_findcu.

 libdw/dwarf_offdie.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/libdw/dwarf_offdie.c b/libdw/dwarf_offdie.c
index 883720de..a9729947 100644
--- a/libdw/dwarf_offdie.c
+++ b/libdw/dwarf_offdie.c
@@ -58,7 +59,10 @@ __libdw_offdie (Dwarf *dbg, Dwarf_Off offset, Dwarf_Die 
*result,
   result->addr = (char *) data->d_buf + offset;
 
   /* Get the CU.  */
+  mutex_lock (dbg->dwarf_lock);
   result->cu = __libdw_findcu (dbg, offset, debug_types);
+  mutex_unlock (dbg->dwarf_lock);
+
   if (result->cu == NULL)
 {
   /* This should never happen.  The input file is malformed.  */
-- 
2.48.1



[PATCH 09/10 v5] Add tests/run-eu-search-lines.sh

2025-02-04 Thread Aaron Merey
* tests/.gitignore: Add eu_search-lines.
* tests/Makefile.am: Add eu_search_lines,
run-eu-search-lines.sh.
* tests/eu_search_lines.c: New file.
tests/run-eu-search-lines.sh: New file.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 
---
v5 changes: pthread added to eu_search_lines_LDFLAGS unconditionally.

A review for this patch was already posted by Mark:
https://sourceware.org/pipermail/elfutils-devel/2025q1/007795.html

 tests/.gitignore |   1 +
 tests/Makefile.am|   9 +-
 tests/eu_search_lines.c  | 211 +++
 tests/run-eu-search-lines.sh |  31 +
 4 files changed, 249 insertions(+), 3 deletions(-)
 create mode 100644 tests/eu_search_lines.c
 create mode 100755 tests/run-eu-search-lines.sh

diff --git a/tests/.gitignore b/tests/.gitignore
index 9fb56361..26bf6059 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -69,6 +69,7 @@
 /emptyfile
 /eu_search_cfi
 /eu_search_macros
+/eu_search_lines
 /fillfile
 /find-prologues
 /funcretval
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a38ed608..a448cd57 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -65,7 +65,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_macros \
+ eu_search_cfi eu_search_macros eu_search_lines \
  $(asm_TESTS)
 
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
@@ -218,7 +218,8 @@ 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-eu-search-cfi.sh run-eu-search-macros.sh
+   run-sysroot.sh run-eu-search-cfi.sh run-eu-search-macros.sh \
+   run-eu-search-lines.sh
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
@@ -690,7 +691,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 testfile-dwp-cu-index-overflow.source \
 testfile-define-file.bz2 \
 testfile-sysroot.tar.bz2 run-sysroot.sh run-debuginfod-seekable.sh 
\
-run-eu-search-cfi.sh run-eu-search-macros.sh \
+ run-eu-search-cfi.sh run-eu-search-macros.sh 
run-eu-search-lines.sh \
 thread-safety-subr.sh
 
 
@@ -878,7 +879,9 @@ cu_dwp_section_info_LDADD = $(libdw)
 declfiles_LDADD = $(libdw)
 eu_search_cfi_LDFLAGS = -pthread $(AM_LDFLAGS)
 eu_search_macros_LDFLAGS = -pthread $(AM_LDFLAGS)
+eu_search_lines_LDFLAGS = -pthread $(AM_LDFLAGS)
 eu_search_cfi_LDADD = $(libeu) $(libelf) $(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.
diff --git a/tests/eu_search_lines.c b/tests/eu_search_lines.c
new file mode 100644
index ..d5a7de6d
--- /dev/null
+++ b/tests/eu_search_lines.c
@@ -0,0 +1,211 @@
+/* Test program for eu_search_lines.
+   Copyright (C) 2023 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see.  */
+
+#include 
+#include 
+#include 
+#include 
+#include ELFUTILS_HEADER(dw)
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static Dwarf *dbg;
+
+static void *thread_work (void *arg)
+{
+  int *res = (int *) arg;
+
+  *res = 0;
+  Dwarf_Off cuoff = 0;
+  Dwarf_Off old_cuoff = 0;
+  size_t hsize;
+  Dwarf_Off ao;
+  uint8_t asz;
+  uint8_t osz;
+  while (dwarf_nextcu (dbg, cuoff, &cuoff, &hsize, &ao, &asz, &osz) == 0)
+{
+  printf ("cuhl = %zu, o = %llu, asz = %hhu, osz = %hhu, ncu = %llu\n",
+hsize, (unsigned long long int) ao,
+asz, osz, (unsigned long long int) cuoff);
+
+  // Get the DIE for the CU.
+  Dwarf_Die die;
+  if (dwarf_offdie (dbg, old_cuoff + hsize, &die) == NULL)
+   {
+ printf ("cannot get CU die\n");
+ *res = 1;
+ break;
+   }
+
+  old_cuoff = cuoff;
+
+  Dwarf_Lines *lb;
+  size_t nlb;
+  if (dwarf_getsrclines (&die, &lb, &nlb) != 0)
+  

[PATCH 08/10 v5] Add tests/run-eu-search-macros.sh

2025-02-04 Thread Aaron Merey
* tests/.gitignore: Add eu_search_macros.sh
* tests/Makefile.am: Add eu_search_macros,
run-eu-search-macros.sh.
* tests/eu_search_macros.c: New file.
* tests/run-eu-search-macros.sh: New file.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 
---
v5 changes: pthread added to eu_search_macros_LDFLAGS unconditionally.
Add missing error exit to thread_work.

A review for this patch has already been posted by Mark:
https://sourceware.org/pipermail/elfutils-devel/2025q1/007798.html

 tests/.gitignore  |   1 +
 tests/Makefile.am |   8 +-
 tests/eu_search_macros.c  | 175 ++
 tests/run-eu-search-macros.sh |  28 ++
 4 files changed, 209 insertions(+), 3 deletions(-)
 create mode 100644 tests/eu_search_macros.c
 create mode 100755 tests/run-eu-search-macros.sh

diff --git a/tests/.gitignore b/tests/.gitignore
index bf17d646..9fb56361 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -68,6 +68,7 @@
 /elf-print-reloc-syms
 /emptyfile
 /eu_search_cfi
+/eu_search_macros
 /fillfile
 /find-prologues
 /funcretval
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 3b37344d..a38ed608 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -65,7 +65,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_cfi eu_search_macros \
  $(asm_TESTS)
 
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
@@ -218,7 +218,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-eu-search-cfi.sh
+   run-sysroot.sh run-eu-search-cfi.sh run-eu-search-macros.sh
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
@@ -690,7 +690,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 testfile-dwp-cu-index-overflow.source \
 testfile-define-file.bz2 \
 testfile-sysroot.tar.bz2 run-sysroot.sh run-debuginfod-seekable.sh 
\
-run-eu-search-cfi.sh \
+run-eu-search-cfi.sh run-eu-search-macros.sh \
 thread-safety-subr.sh
 
 
@@ -877,7 +877,9 @@ elf_print_reloc_syms_LDADD = $(libelf)
 cu_dwp_section_info_LDADD = $(libdw)
 declfiles_LDADD = $(libdw)
 eu_search_cfi_LDFLAGS = -pthread $(AM_LDFLAGS)
+eu_search_macros_LDFLAGS = -pthread $(AM_LDFLAGS)
 eu_search_cfi_LDADD = $(libeu) $(libelf) $(libdw)
+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_macros.c b/tests/eu_search_macros.c
new file mode 100644
index ..0f70eef2
--- /dev/null
+++ b/tests/eu_search_macros.c
@@ -0,0 +1,175 @@
+/* Test program for eu_search_macros
+   Copyright (C) 2023 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see.  */
+
+#include 
+#include ELFUTILS_HEADER(dw)
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void *thread_work (void * arg);
+static int mac (Dwarf_Macro *macro, void *arg);
+static int include (Dwarf_Off macoff, ptrdiff_t token);
+
+static Dwarf *dbg;
+static ptrdiff_t cuoff;
+
+static void *thread_work (void *arg __attribute__ ((unused)))
+{
+  Dwarf_Die cudie_mem, *cudie = dwarf_offdie (dbg, cuoff, &cudie_mem);
+  for (ptrdiff_t off = DWARF_GETMACROS_START;
+   (off = dwarf_getmacros (cudie, mac, dbg, off));)
+{
+  if (off != 0)
+   {
+ error (EXIT_FAILURE, 0, "dwarf_getmacros: %s",
+dwarf_errmsg (dwarf_errno ()));
+   }
+}
+
+  return NULL;
+}
+
+static int include (Dwarf_Off macoff, ptrdiff_t token)
+{
+  while ((token = dwarf_getmacros_off (dbg, macoff, mac, dbg, token)) != 0)
+{
+  if (token == -1)
+   {
+ puts (dwarf_errmsg (dwarf_e

[PATCH 10/10 v5] Add tests/run-eu-search-die.sh

2025-02-04 Thread Aaron Merey
* tests/.gitignore: Add eu_search_die.
* tests/Makefile.am: Add eu_search_die, run-eu-search-die.sh.
* tests/eu_search_die.c: New file.
* tests/run-eu-search-die.sh: New file.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 
---
v5 changes: pthread added to eu_search_die_LDFLAGS unconditionally.

A review for this patch has already been posted by Mark:
https://sourceware.org/pipermail/elfutils-devel/2025q1/007796.html

 tests/.gitignore   |   1 +
 tests/Makefile.am  |   8 +-
 tests/eu_search_die.c  | 226 +
 tests/run-eu-search-die.sh |  34 ++
 4 files changed, 266 insertions(+), 3 deletions(-)
 create mode 100644 tests/eu_search_die.c
 create mode 100755 tests/run-eu-search-die.sh

diff --git a/tests/.gitignore b/tests/.gitignore
index 26bf6059..f8869b40 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -70,6 +70,7 @@
 /eu_search_cfi
 /eu_search_macros
 /eu_search_lines
+/eu_search_die
 /fillfile
 /find-prologues
 /funcretval
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a448cd57..710a4238 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -65,7 +65,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_macros eu_search_lines \
+ eu_search_cfi eu_search_macros eu_search_lines eu_search_die \
  $(asm_TESTS)
 
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
@@ -219,7 +219,7 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile 
test-nlist \
run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh 
\
run-declfiles.sh \
run-sysroot.sh run-eu-search-cfi.sh run-eu-search-macros.sh \
-   run-eu-search-lines.sh
+   run-eu-search-lines.sh run-eu-search-die.sh
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
@@ -692,7 +692,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 testfile-define-file.bz2 \
 testfile-sysroot.tar.bz2 run-sysroot.sh run-debuginfod-seekable.sh 
\
  run-eu-search-cfi.sh run-eu-search-macros.sh 
run-eu-search-lines.sh \
-thread-safety-subr.sh
+run-eu-search-die.sh thread-safety-subr.sh
 
 
 if USE_HELGRIND
@@ -879,10 +879,12 @@ cu_dwp_section_info_LDADD = $(libdw)
 declfiles_LDADD = $(libdw)
 eu_search_cfi_LDFLAGS = -pthread $(AM_LDFLAGS)
 eu_search_macros_LDFLAGS = -pthread $(AM_LDFLAGS)
+eu_search_die_LDFLAGS = -pthread $(AM_LDFLAGS)
 eu_search_lines_LDFLAGS = -pthread $(AM_LDFLAGS)
 eu_search_cfi_LDADD = $(libeu) $(libelf) $(libdw)
 eu_search_lines_LDADD = $(libdw) $(libelf)
 eu_search_macros_LDADD = $(libdw)
+eu_search_die_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_die.c b/tests/eu_search_die.c
new file mode 100644
index ..a4510d3b
--- /dev/null
+++ b/tests/eu_search_die.c
@@ -0,0 +1,226 @@
+/* Test program for eu_search_die.
+   Copyright (C) 2023 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see.  */
+
+#include 
+#include ELFUTILS_HEADER(dw)
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static int check_die (Dwarf_Die *die, Dwarf *dbg);
+static int check_dbg (Dwarf *dbg);
+
+static Dwarf *dwarf;
+
+static void *thread_work (void *arg)
+{
+  int *res = (int *) arg;
+  *res = check_dbg (dwarf);
+  return NULL;
+}
+
+static int check_die (Dwarf_Die *die, Dwarf *dbg)
+{
+  if (dwarf_tag (die) == DW_TAG_invalid)
+{
+  printf ("Invalid die\n");
+  return -1;
+}
+
+  int res = 0;
+  void *addr = die->addr;
+  Dwarf_Die die2;
+  if (dwarf_die_addr_die (dbg, addr, &die2) == NULL)
+{
+  printf ("Bad die addr die at offset %" PRIx64 "\n",
+ dwarf_dieoffset (die));
+  res = -1;
+}
+
+  if (dwarf_tag (die) != dwarf_tag (&die2))
+{
+  printf ("Tags differ for die at offset %" PRIx

[PATCH 07/10 v5] Add tests/run-eu-search-cfi.sh

2025-02-04 Thread Aaron Merey
From: Heather McIntyre 

* tests/.gitignore: Add eu_search_cfi.
* tests/Makefile.am: Add eu_search_cfi, run-eu-search-cfi.sh.
* tests/eu_search_cfi.c: New file.
* tests/run-eu-search-cfi.sh: New file.

Signed-off-by: Heather S. McIntyre 
Signed-off-by: Aaron Merey 
Signed-off-by: Mark Wielaard 
---
v5 changes: pthread added to eu_search_cfi_LDFLAGS unconditionally.

A review for this patch has already been posted by Mark:
https://sourceware.org/pipermail/elfutils-devel/2025q1/007797.html

 tests/.gitignore   |   1 +
 tests/Makefile.am  |   8 +-
 tests/eu_search_cfi.c  | 201 +
 tests/run-eu-search-cfi.sh |  31 ++
 4 files changed, 239 insertions(+), 2 deletions(-)
 create mode 100644 tests/eu_search_cfi.c
 create mode 100755 tests/run-eu-search-cfi.sh

diff --git a/tests/.gitignore b/tests/.gitignore
index 14620fc3..bf17d646 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -67,6 +67,7 @@
 /elfstrtab
 /elf-print-reloc-syms
 /emptyfile
+/eu_search_cfi
 /fillfile
 /find-prologues
 /funcretval
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9ca97b6f..3b37344d 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -65,6 +65,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 \
  $(asm_TESTS)
 
 asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
@@ -217,7 +218,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-cfi.sh
 
 if !BIARCH
 export ELFUTILS_DISABLE_BIARCH = 1
@@ -688,7 +689,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 run-debuginfod-seekable.sh
+testfile-sysroot.tar.bz2 run-sysroot.sh run-debuginfod-seekable.sh 
\
+run-eu-search-cfi.sh \
 thread-safety-subr.sh
 
 
@@ -874,6 +876,8 @@ 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 = -pthread $(AM_LDFLAGS)
+eu_search_cfi_LDADD = $(libeu) $(libelf) $(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 ..4a46ab1c
--- /dev/null
+++ b/tests/eu_search_cfi.c
@@ -0,0 +1,201 @@
+/* Test program for eu_search_cfi
+   Copyright (C) 2023 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see.  */
+
+#include 
+#include 
+#include 
+#include ELFUTILS_HEADER(dw)
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "system.h"
+#include 
+
+static void handle_section (char *name, const unsigned char e_ident[],
+  Elf_Scn *scn, const bool is_eh);
+static void *thread_work (void *arg);
+
+typedef struct
+{
+  char *name;
+  const unsigned char *e_ident;
+  Elf_Scn * scn;
+  bool is_eh;
+}
+ThreadData;
+
+static void *thread_work (void *arg)
+{
+  ThreadData *data = (ThreadData *) arg;
+  handle_section (data->name, data->e_ident, data->scn, data->is_eh);
+  return NULL;
+}
+
+static void handle_section (char *name, const unsigned char e_ident[],
+Elf_Scn *scn, const bool is_eh)
+{
+  if (is_eh)
+printf (".eh_frame\n");
+  else
+printf (".debug_frame\n");
+
+  GElf_Shdr mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &mem);
+
+  if (shdr == NULL)
+error (EXIT_FAILURE, 0, "Couldn't get section header: %s",
+ elf_errmsg (-1));
+
+  if ((shdr->sh_flags &SHF_COMPRESSED) != 0)
+{
+  if (elf_compress (scn,

[PATCH 03/10 v2] libdw: Add locking to dwarf_getsrcfiles and dwarf_getsrclines

2025-02-04 Thread Aaron Merey
* libdw/dwarf_getsrcfiles.c (dwarf_getsrcfiles): Use dwarf_lock.
* libdw/dwarf_getsrclines.c (dwarf_getsrclines): Use dwarf_lock.

Signed-off-by: Aaron Merey 
---
v2 changes: Combined from v1 patches 04/15 and 05/15.

 libdw/dwarf_getsrcfiles.c | 11 +++
 libdw/dwarf_getsrclines.c | 25 +++--
 2 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/libdw/dwarf_getsrcfiles.c b/libdw/dwarf_getsrcfiles.c
index 24e4b7d2..3029ce69 100644
--- a/libdw/dwarf_getsrcfiles.c
+++ b/libdw/dwarf_getsrcfiles.c
@@ -47,9 +47,10 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, 
size_t *nfiles)
 }
 
   int res = -1;
+  struct Dwarf_CU *const cu = cudie->cu;
+  mutex_lock (cudie->cu->dbg->dwarf_lock);
 
   /* Get the information if it is not already known.  */
-  struct Dwarf_CU *const cu = cudie->cu;
   if (cu->files == NULL)
 {
   /* For split units there might be a simple file table (without lines).
@@ -96,7 +97,10 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, 
size_t *nfiles)
  Dwarf_Off debug_line_offset;
  if (__libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE,
   NULL, &debug_line_offset) == NULL)
-   return -1;
+   {
+ mutex_unlock (cudie->cu->dbg->dwarf_lock);
+ return -1;
+   }
 
  res = __libdw_getsrcfiles (cu->dbg, debug_line_offset,
 __libdw_getcompdir (cudie),
@@ -115,8 +119,7 @@ dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, 
size_t *nfiles)
*nfiles = cu->files->nfiles;
 }
 
-  // XXX Eventually: unlocking here.
-
+  mutex_unlock (cudie->cu->dbg->dwarf_lock);
   return res;
 }
 INTDEF (dwarf_getsrcfiles)
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index b0b5f2eb..79b672dd 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -1444,8 +1444,10 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines 
**lines, size_t *nlines)
   return -1;
 }
 
-  /* Get the information if it is not already known.  */
   struct Dwarf_CU *const cu = cudie->cu;
+  mutex_lock (cu->dbg->dwarf_lock);
+
+  /* Get the information if it is not already known.  */
   if (cu->lines == NULL)
 {
   /* For split units always pick the lines from the skeleton.  */
@@ -1466,10 +1468,13 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines 
**lines, size_t *nlines)
  *lines = cu->lines;
  *nlines = cu->lines->nlines;
}
+
+ mutex_unlock (cu->dbg->dwarf_lock);
  return res;
}
 
  __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
+ mutex_unlock (cu->dbg->dwarf_lock);
  return -1;
}
 
@@ -1487,21 +1492,29 @@ dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines 
**lines, size_t *nlines)
   Dwarf_Off debug_line_offset;
   if (__libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE,
   NULL, &debug_line_offset) == NULL)
-   return -1;
+   {
+ mutex_unlock (cu->dbg->dwarf_lock);
+ return -1;
+   }
 
   if (__libdw_getsrclines (cu->dbg, debug_line_offset,
   __libdw_getcompdir (cudie),
   cu->address_size, &cu->lines, &cu->files) < 0)
-   return -1;
+   {
+ mutex_unlock (cu->dbg->dwarf_lock);
+ return -1;
+   }
 }
   else if (cu->lines == (void *) -1l)
-return -1;
+{
+  mutex_unlock (cu->dbg->dwarf_lock);
+  return -1;
+}
 
   *lines = cu->lines;
   *nlines = cu->lines->nlines;
 
-  // XXX Eventually: unlocking here.
-
+  mutex_unlock (cu->dbg->dwarf_lock);
   return 0;
 }
 INTDEF(dwarf_getsrclines)
-- 
2.48.1



Re: [PATCH 09/10 v5] Add tests/run-eu-search-lines.sh

2025-02-04 Thread Aaron Merey
Hi Mark,

On Mon, Feb 3, 2025 at 7:40 AM Mark Wielaard  wrote:
>
> Found the issue with the patches not showing up on the list.
> They were sent to elfutils-patches@ which doesn't exists...
> Add elfutils-devel to the CC now.

Apologies, I mixed up elfutils-devel@ and gdb-patches@.
I've reposted this series and included links to your reviews in patches 7 to 10.

Aaron



Re: [PATCH 4/5] tests/test-elf_cntl_gelf_getshdr.c: Close fd unconditionally

2025-02-04 Thread Aaron Merey
Hi Mark,

On Mon, Feb 3, 2025 at 8:36 AM Mark Wielaard  wrote:
>
> I think this subtly changes what is being tested here.  If I remember
> correctly this tests that gelf_getshdr works correctly even when the
> underlying fd is closed and the file is either mmapped or elf_cntl
> with ELF_C_FDREAD is called.
>
> The idea being that if the file is mmapped then everything needed for
> reading the ELF file is already in memory. And when elf_cntl is called
> with ELF_C_FDREAD then libelf must make sure the same is true.
>
> You could argue that the test should explicitly call elf_cntl with
> ELF_C_FDDONE after the close (fd) though.
>
> So I don't think close should be called unconditionally.  Maybe the
> correct solution is to do if (!close_fd) close (fd); after elf_end?

Thanks for the clarification. I think you're right about simply
including `if (!close_fd) close (fd)` at the end. The test still
passes for me with that change.

I've dropped this patch and instead included the `if (!close_fd)...`
change in patch 5/5 "tests: Avoid leaking file descriptors". Are you
ok with me pushing the series with this change or would you prefer I
repost the series?

Aaron



[PATCH 05/10 v2] Add configure option --enable-helgrind

2025-02-04 Thread Aaron Merey
Like --enable-valgrind but uses helgrind instead of memcheck.

If both --enable-valgrind and --enable-helgrind are given then
helgrind takes priority.

--enable-helgrind requires --enable-valgrind-annotations.

* configure.ac: Add --enable-helgrind option.
* tests/Makefile.am: If USE_HELGRIND is true, then include
--tool=helgrind in the valgrind command that tests are run
under.

Signed-off-by: Aaron Merey 
---
v2 changes: Enabing helgrind now requires enabling annotations

 configure.ac  | 16 ++--
 tests/Makefile.am |  6 +-
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/configure.ac b/configure.ac
index e57d3927..bb1788d4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -363,10 +363,15 @@ if test "$use_address" = yes; then
 fi
 AM_CONDITIONAL(USE_ADDRESS_SANITIZER, test "$use_address" = yes)
 
+AC_ARG_ENABLE([helgrind],
+AS_HELP_STRING([--enable-helgrind],[run all tests under the valgrind tool 
helgrind]),
+[use_helgrind=$enableval], [use_helgrind=no])
+
 AC_ARG_ENABLE([valgrind],
 AS_HELP_STRING([--enable-valgrind],[run all tests under valgrind]),
 [use_valgrind=$enableval], [use_valgrind=no])
-if test "$use_valgrind" = yes; then
+if test "$use_valgrind" = yes -o "$use_helgrind" = yes; then
+
   if test "$use_address" = yes; then
 AC_MSG_ERROR([cannot enable valgrind and sanitize address together])
   fi
@@ -375,7 +380,8 @@ if test "$use_valgrind" = yes; then
 AC_MSG_ERROR([valgrind not found])
   fi
 fi
-AM_CONDITIONAL(USE_VALGRIND, test "$use_valgrind" = yes)
+AM_CONDITIONAL(USE_VALGRIND, test "$use_valgrind" = yes -o "$use_helgrind" = 
yes)
+AM_CONDITIONAL(USE_HELGRIND, test "$use_helgrind" = yes)
 
 AC_ARG_WITH([valgrind],
 AS_HELP_STRING([--with-valgrind],[include directory for Valgrind headers]),
@@ -394,6 +400,12 @@ fi
 AC_ARG_ENABLE([valgrind-annotations],
 AS_HELP_STRING([--enable-valgrind-annotations],[insert extra annotations for 
better valgrind support]),
 [use_vg_annotations=$enableval], [use_vg_annotations=no])
+
+# Helgrind requires Valgrind annotations.
+if test "$use_vg_annotations" = no -a "$use_helgrind" = yes; then
+  AC_MSG_ERROR(["--enable-helgrind requires --enable-valgrind-annotations"])
+fi
+
 if test "$use_vg_annotations" = yes; then
 if test "x$HAVE_VALGRIND_HEADERS" != "xyes"; then
   AC_MSG_CHECKING([whether Valgrind headers are available])
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8f087798..e4fe72f0 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -691,8 +691,12 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 testfile-sysroot.tar.bz2 run-sysroot.sh run-debuginfod-seekable.sh
 
 
+if USE_HELGRIND
+valgrind_cmd=valgrind -q --tool=helgrind --error-exitcode=1
+else
 if USE_VALGRIND
-valgrind_cmd=valgrind -q --leak-check=full --error-exitcode=1
+valgrind_cmd=valgrind -q --leak-check=full --error-exitcode=1
+endif
 endif
 
 
-- 
2.48.1



[PATCH 06/10 v2] Add tests/thread-safety-subr.sh

2025-02-04 Thread Aaron Merey
thread-safety-subr.sh contains subroutine check_thread_safety_enabled
which skips further testing when USE_LOCKS is false.

* tests/Makefile.am (EXTRA_DIST): Add thread-safety-subr.sh.
* tests/thread-safety-subr.sh: New file.

Signed-off-by: Aaron Merey 
---
v2 changes: Removed checks for address and memory sanitizer in
check_thread_safety_enabled.

 tests/Makefile.am   |  1 +
 tests/thread-safety-subr.sh | 33 +
 2 files changed, 34 insertions(+)
 create mode 100644 tests/thread-safety-subr.sh

diff --git a/tests/Makefile.am b/tests/Makefile.am
index e4fe72f0..9ca97b6f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -689,6 +689,7 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
 testfile-dwp-cu-index-overflow.source \
 testfile-define-file.bz2 \
 testfile-sysroot.tar.bz2 run-sysroot.sh run-debuginfod-seekable.sh
+thread-safety-subr.sh
 
 
 if USE_HELGRIND
diff --git a/tests/thread-safety-subr.sh b/tests/thread-safety-subr.sh
new file mode 100644
index ..1024df02
--- /dev/null
+++ b/tests/thread-safety-subr.sh
@@ -0,0 +1,33 @@
+#! /bin/sh
+# Subroutines for thread safety testing
+# Copyright (C) 2024 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see .
+
+. $srcdir/test-subr.sh
+
+# Verify that thread safety tests can be run.  If not, skip further testing.
+check_thread_safety_enabled()
+{
+  # Extract lock setting.
+  USE_LOCKS=$(grep '^#define USE_LOCKS' \
+   ${abs_builddir}/../config.h | awk '{print $3}')
+
+  # Test will only be run if USE_LOCKS is defined. Otherwise, skip.
+  if [[ "$USE_LOCKS" != 1 ]]; then
+echo "USE_LOCKS is not defined. Skipping test."
+exit 77
+  fi
+}
-- 
2.48.1