* 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 <h...@rice.edu> Signed-off-by: Aaron Merey <ame...@redhat.com> Signed-off-by: Mark Wielaard <m...@klomp.org> --- 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 00000000..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<http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include <fcntl.h> +#include <inttypes.h> +#include <libelf.h> +#include ELFUTILS_HEADER(dw) +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> +#include <pthread.h> + +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) + { + printf ("cannot get lines\n"); + *res = 1; + break; + } + + printf (" %zu lines\n", nlb); + + for (size_t i = 0; i < nlb; ++i) + { + Dwarf_Line *l = dwarf_onesrcline (lb, i); + if (l == NULL) + { + printf ("cannot get individual line\n"); + *res = 1; + break; + } + + Dwarf_Addr addr; + if (dwarf_lineaddr (l, &addr) != 0) + addr = 0; + + const char *file = dwarf_linesrc (l, NULL, NULL); + int line; + + if (dwarf_lineno (l, &line) != 0) + line = 0; + + printf ("%" PRIx64 ": %s:%d:", (uint64_t) addr, file ? : "???", line); + + // Getting the file path through the Dwarf_Files should + // result in the same path. + Dwarf_Files *files; + size_t idx; + if (dwarf_line_file (l, &files, &idx) != 0) + { + printf ("cannot get file from line (%zd): %s\n", + i, dwarf_errmsg (-1)); + *res = 1; + break; + } + + const char *path = dwarf_filesrc (files, idx, NULL, NULL); + if ((path == NULL && file != NULL) || + (path != NULL && file == NULL) || + (strcmp (file, path) != 0)) + { + printf ("line %zd srcline (%s) != file srcline (%s)\n", + i, file ? : "???", path ? : "???"); + *res = 1; + break; + } + + int column; + + if (dwarf_linecol (l, &column) != 0) + column = 0; + if (column >= 0) + printf ("%d:", column); + + bool is_stmt; + if (dwarf_linebeginstatement (l, &is_stmt) != 0) + is_stmt = false; + bool end_sequence; + if (dwarf_lineendsequence (l, &end_sequence) != 0) + end_sequence = false; + bool basic_block; + if (dwarf_lineblock (l, &basic_block) != 0) + basic_block = false; + bool prologue_end; + if (dwarf_lineprologueend (l, &prologue_end) != 0) + prologue_end = false; + bool epilogue_begin; + if (dwarf_lineepiloguebegin (l, &epilogue_begin) != 0) + epilogue_begin = false; + + printf (" is_stmt:%s, end_seq:%s, bb:%s, prologue:%s, epilogue:%s\n", + is_stmt ? "yes" : "no", end_sequence ? "yes" : "no", + basic_block ? "yes" : "no", prologue_end ? "yes" : "no", + epilogue_begin ? "yes" : "no"); + } + } + + return NULL; +} + +int main (int argc, char *argv[]) +{ + if (argc != 2) + { + printf ("Usage: %s <filename>\n", argv[0]); + return 1; + } + + char *name = argv[1]; + int fd = open (name, O_RDONLY); + if (fd < 0) + { + printf ("%s not usable: %s\n", name, dwarf_errmsg (-1)); + return 1; + } + + dbg = dwarf_begin (fd, DWARF_C_READ); + if (dbg == NULL) + { + printf ("%s not usable: %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 (dbg); + 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 (dbg); + close (fd); + + return res; +} diff --git a/tests/run-eu-search-lines.sh b/tests/run-eu-search-lines.sh new file mode 100755 index 00000000..2108ab8f --- /dev/null +++ b/tests/run-eu-search-lines.sh @@ -0,0 +1,31 @@ +#! /bin/sh +# Data race test for parallelized get-lines +# 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 + +lines_testfiles=("testfile" "testfile2" "testfilenolines") + +testfiles "${lines_testfiles[@]}" + +for file in "${lines_testfiles[@]}"; do + testrun ${abs_builddir}/eu_search_lines $file +done + +exit 0 -- 2.48.1