[15/15,v4] Add tests/run-eu-search-die.sh

Message ID 20250120032041.280173-15-amerey@redhat.com
State Superseded
Headers
Series [01/15] Add eu_search_tree_init |

Commit Message

Aaron Merey Jan. 20, 2025, 3:20 a.m. UTC
  From: Heather McIntyre <hsm2@rice.edu>

        * 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 <hsm2@rice.edu>
Signed-off-by: Aaron Merey <amerey@redhat.com>
Signed-off-by: Mark Wielaard <mark@klomp.org>

---
v3: https://patchwork.sourceware.org/project/elfutils/patch/20240802233847.690564-9-amerey@redhat.com/

Changes in v4: 
run-eu-search-tests.sh dropped and die search_tree tests moved to
run-eu-search-die.sh.
Formatting changes and improved lock contention in eu_search_die.c.

 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
  

Comments

Mark Wielaard Jan. 24, 2025, 3:07 p.m. UTC | #1
Hi Aaron,

On Sun, 2025-01-19 at 22:20 -0500, Aaron Merey wrote:
> From: Heather McIntyre <hsm2@rice.edu>
> 
>         * 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.

Another nice test. Good that it handles alt files and split dwarf.
Same nitpick as before. But you may ignore that.

Cheers,

Mark
  

Patch

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 570d5f72..8f8972cb 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
@@ -880,9 +880,11 @@  declfiles_LDADD = $(libdw)
 eu_search_cfi_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_die_LDFLAGS = $(if $(filter undefined,$(origin USE_LOCKS)),-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 00000000..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<http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include ELFUTILS_HEADER(dw)
+#include <dwarf.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <pthread.h>
+
+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 %" PRIx64 "\n",
+	     dwarf_dieoffset (die));
+      res = -1;
+    }
+
+  if (dwarf_cuoffset (die) != dwarf_cuoffset (&die2))
+    {
+      printf ("CU offsets differ for die at offset %" PRIx64 "\n",
+	     dwarf_dieoffset (die));
+      res = -1;
+    }
+
+  Dwarf_Die child;
+  if (dwarf_child (die, &child) == 0)
+    res |= check_die (&child, dbg);
+
+  Dwarf_Die sibling;
+  if (dwarf_siblingof (die, &sibling) == 0)
+    res |= check_die (&sibling, dbg);
+
+  return res;
+}
+
+static int check_dbg (Dwarf *dbg)
+{
+  int res = 0;
+  Dwarf_Off off = 0;
+  Dwarf_Off old_off = 0;
+  size_t hsize;
+  Dwarf_Off abbrev;
+  uint8_t addresssize;
+  uint8_t offsetsize;
+
+  while (dwarf_nextcu (dbg, off, &off, &hsize, &abbrev,
+		      &addresssize, &offsetsize) == 0)
+    {
+      Dwarf_Die die;
+      if (dwarf_offdie (dbg, old_off + hsize, &die) != NULL)
+	{
+	  printf ("checking CU at %" PRIx64 "\n", old_off);
+	  res |= check_die (&die, dbg);
+	}
+
+      old_off = off;
+    }
+
+  // Same for type...
+  Dwarf_Half version;
+  uint64_t typesig;
+  Dwarf_Off typeoff;
+  off = 0;
+  old_off = 0;
+
+  while (dwarf_next_unit (dbg, off, &off, &hsize, &version,
+	 &abbrev, &addresssize, &offsetsize, &typesig, &typeoff) == 0)
+    {
+      Dwarf_Die die;
+      if (dwarf_offdie_types (dbg, old_off + hsize, &die) != NULL)
+	{
+	  printf ("checking TU at %" PRIx64 "\n", old_off);
+	  res |= check_die (&die, dbg);
+	}
+
+      // We should have seen this already, but double check...
+      if (dwarf_offdie_types (dbg, old_off + typeoff, &die) != NULL)
+	{
+	  printf ("checking Type DIE at %" PRIx64 "\n",
+		 old_off + hsize + typeoff);
+	  res |= check_die (&die, dbg);
+	}
+
+      old_off = off;
+    }
+
+  Dwarf *alt = dwarf_getalt (dbg);
+
+  if (alt != NULL)
+    {
+      printf ("checking alt debug\n");
+      res |= check_dbg (alt);
+    }
+
+  // Split or Type Dwarf_Dies gotten through dwarf_get_units.
+  Dwarf_CU *cu = NULL;
+  Dwarf_Die subdie;
+  uint8_t unit_type;
+  while (dwarf_get_units (dbg, cu, &cu, NULL, &unit_type, NULL, &subdie) == 0)
+    {
+      if (dwarf_tag (&subdie) != DW_TAG_invalid)
+	{
+	  printf ("checking %" PRIx8 " subdie\n", unit_type);
+	  res |= check_die (&subdie, dbg);
+	}
+    }
+
+  return res;
+}
+
+int main (int argc, char *argv[])
+{
+  if (argc < 2)
+    {
+      printf ("No file given.\n");
+      return -1;
+    }
+
+  const char *name = argv[1];
+  int fd = open (name, O_RDONLY);
+  if (fd < 0)
+    {
+      printf ("Cannot open '%s': %s\n", name, strerror (errno));
+      return -1;
+    }
+
+  dwarf = dwarf_begin (fd, DWARF_C_READ);
+  if (dwarf == NULL)
+    {
+      printf ("Not a Dwarf file '%s': %s\n", name, dwarf_errmsg (-1));
+      close (fd);
+      return -1;
+    }
+
+  printf ("checking %s\n", name);
+
+  int num_threads = 4;
+  pthread_t threads[num_threads];
+  int thread_results[num_threads];
+
+  for (int i = 0; i < num_threads; i++)
+    {
+      if (pthread_create (&threads[i], NULL, thread_work,
+			  &thread_results[i]) != 0)
+	{
+	  perror ("Failed to create thread");
+	  for (int j = 0; j < i; j++)
+	    pthread_cancel (threads[j]);
+
+	  dwarf_end (dwarf);
+	  close (fd);
+	  return 1;
+	}
+    }
+
+  int res = 0;
+  for (int i = 0; i < num_threads; i++)
+    {
+      if (pthread_join (threads[i], NULL) != 0)
+	{
+	  perror ("Failed to join thread");
+	  res = 1;
+	  break;
+	}
+
+      res |= thread_results[i];
+    }
+
+  dwarf_end (dwarf);
+  close (fd);
+
+  return res;
+}
diff --git a/tests/run-eu-search-die.sh b/tests/run-eu-search-die.sh
new file mode 100755
index 00000000..bc8a5959
--- /dev/null
+++ b/tests/run-eu-search-die.sh
@@ -0,0 +1,34 @@ 
+#! /bin/sh
+# Data race test for parallelized dwarf-die-addr-die
+# Copyright (C) 2015, 2018 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 <http://www.gnu.org/licenses/>.
+
+. $srcdir/thread-safety-subr.sh
+
+check_thread_safety_enabled
+
+die_test_files=("testfile-debug-types"
+                "testfile_multi_main" "testfile_multi.dwz"
+                "testfilebazdbgppc64.debug"
+                "testfile-dwarf-4" "testfile-dwarf-5"
+                "testfile-splitdwarf-4" "testfile-hello4.dwo" "testfile-world4.dwo"
+                "testfile-splitdwarf-5" "testfile-hello5.dwo" "testfile-world5.dwo")
+
+testfiles "${die_test_files[@]}"
+
+for file in "${die_test_files[@]}"; do
+    testrun ${abs_builddir}/eu_search_die $file
+done