Together with the stackprof tool we add some test cases to exercise it, and the underlying libdwfl_stacktrace functionality as well.
* tests/stackprof-subr.sh: Common subroutines for checking perf_events availability and verifying gmon.*.out files. * tests/run-stackprof-system.sh: New file. * tests/run-stackprof-system-gprof.sh: New file. * tests/run-stackprof-user.sh: New file. * tests/run-stackprof-user-gprof.sh: New file. * tests/Makefile.am (TESTS): add the new testcases. Co-authored-by: <[email protected]> Signed-off-by: <[email protected]> --- tests/Makefile.am | 14 +++++- tests/run-stackprof-system-gprof.sh | 49 +++++++++++++++++++++ tests/run-stackprof-system.sh | 45 ++++++++++++++++++++ tests/run-stackprof-user-gprof.sh | 41 ++++++++++++++++++ tests/run-stackprof-user.sh | 57 +++++++++++++++++++++++++ tests/stackprof-subr.sh | 66 +++++++++++++++++++++++++++++ 6 files changed, 270 insertions(+), 2 deletions(-) create mode 100755 tests/run-stackprof-system-gprof.sh create mode 100755 tests/run-stackprof-system.sh create mode 100755 tests/run-stackprof-user-gprof.sh create mode 100755 tests/run-stackprof-user.sh create mode 100644 tests/stackprof-subr.sh diff --git a/tests/Makefile.am b/tests/Makefile.am index 8ae7d126..f098d31f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to create Makefile.in ## -## Copyright (C) 1996-2019 Red Hat, Inc. +## Copyright (C) 1996-2026 Red Hat, Inc. ## This file is part of elfutils. ## ## This file is free software; you can redistribute it and/or modify @@ -313,7 +313,7 @@ TESTS += run-debuginfod-ima-verification.sh endif endif -if HAVE_CXX11 +if HAVE_CXX20 check_PROGRAMS += funcretval_test++11 funcretval_test__11_SOURCES = funcretval_test++11.cxx TESTS += run-funcretval++11.sh @@ -323,6 +323,14 @@ check_PROGRAMS += funcretval_test_struct funcretval_test_struct_SOURCES = funcretval_test_struct.c TESTS += run-funcretval-struct-native.sh +if ENABLE_STACKPROF +TESTS += run-stackprof-user.sh run-stackprof-user-gprof.sh +TESTS += run-stackprof-system.sh run-stackprof-system-gprof.sh +endif +if HAVE_LIBPFM +export HAVE_LIBPFM = 1 +endif + EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ run-ar-N.sh \ run-show-die-info.sh run-get-files.sh run-get-lines.sh \ @@ -717,6 +725,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ testfile-sysroot.tar.bz2 run-sysroot.sh \ run-test-manyfuncs.sh manyfuncs.c \ run-debuginfod-seekable.sh thread-safety-subr.sh \ + run-stackprof-user.sh run-stackprof-user-gprof.sh \ + run-stackprof-system.sh run-stackprof-system-gprof.sh \ run-eu-search-cfi.sh run-eu-search-macros.sh \ run-eu-search-lines.sh run-eu-search-die.sh diff --git a/tests/run-stackprof-system-gprof.sh b/tests/run-stackprof-system-gprof.sh new file mode 100755 index 00000000..c281167c --- /dev/null +++ b/tests/run-stackprof-system-gprof.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2026 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/stackprof-subr.sh + +set -x +unset VALGRIND_CMD + +# prerequisites +type timeout 2>/dev/null || (echo "no timeout installed"; exit 77) +type gprof 2>/dev/null || (echo "no gprof installed"; exit 77) +check_perf_event_open || (echo "perf_event_open fails (check kernel.perf_event_paranoid + kernel config)"; exit 77) +expr `whoami` = "root" || (echo "not running as root"; exit 77) + +tempfiles test.out + +# run systemwide scan, no gprof output +testrun timeout -p --kill-after=5 10 ${abs_top_builddir}/src/stackprof -v 2>&1 | tee test.out +grep "^perf_event_attr configuration" test.out +grep "Starting stack profile collection systemwide" test.out || (grep "ERROR: Unsupported architecture" test.out && echo "unsupported arch" && exit 77) +grep -E "^[0-9]+ " test.out # -- pid / sample counts entries + +# run systemwide scan again, with gprof output +# reduce verbosity, bump post-processing timeout compared to the first run +testrun timeout -p --kill-after=10 10 ${abs_top_builddir}/src/stackprof -g 2>&1 | tee test.out +tempfiles gmon.* +grep "^perf_event_attr configuration" test.out +grep "Starting stack profile collection systemwide" test.out +grep -E "^buildid [0-9a-f]+" test.out + +stackprof_debuginfod_setup +stackprof_check_gmon_out + +exit 0 diff --git a/tests/run-stackprof-system.sh b/tests/run-stackprof-system.sh new file mode 100755 index 00000000..cb796a71 --- /dev/null +++ b/tests/run-stackprof-system.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2026 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/stackprof-subr.sh + +set -x +unset VALGRIND_CMD + +# prerequisites +type timeout 2>/dev/null || (echo "no timeout installed"; exit 77) +check_perf_event_open || (echo "perf_event_open fails (check kernel.perf_event_paranoid + kernel config)"; exit 77) +expr `whoami` = "root" || (echo "not running as root"; exit 77) + +tempfiles test.out + +# run systemwide scan, no gprof output +testrun timeout -p --kill-after=5 10 ${abs_top_builddir}/src/stackprof -v 2>&1 | tee test.out +grep "^perf_event_attr configuration" test.out +grep "Starting stack profile collection systemwide" test.out || (grep "ERROR: Unsupported architecture" test.out && echo "unsupported arch" && exit 77) +grep -E "^[0-9]+ " test.out # -- pid / sample counts entries + +# run systemwide scan again, with gprof output +# reduce verbosity, bump post-processing timeout compared to the first run +testrun timeout -p --kill-after=10 15 ${abs_top_builddir}/src/stackprof -g 2>&1 | tee test.out +tempfiles gmon.* +grep "^perf_event_attr configuration" test.out +grep "Starting stack profile collection systemwide" test.out +grep -E "^buildid [0-9a-f]+" test.out + +exit 0 diff --git a/tests/run-stackprof-user-gprof.sh b/tests/run-stackprof-user-gprof.sh new file mode 100755 index 00000000..9360f8b8 --- /dev/null +++ b/tests/run-stackprof-user-gprof.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2026 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/stackprof-subr.sh + +set -x +unset VALGRIND_CMD + +# prerequisites +type timeout 2>/dev/null || (echo "no timeout installed"; exit 77) +type gprof 2>/dev/null || (echo "no gprof installed"; exit 77) +check_perf_event_open || (echo "perf_event_open fails (check kernel.perf_event_paranoid + kernel config)"; exit 77) + +tempfiles test.out + +# run on single executable, with gprof output +testrun ${abs_top_builddir}/src/stackprof -v -g -- timeout 2 /bin/sh -c "while true; do true; done" 2>&1 | tee test.out +tempfiles gmon.* +grep "^perf_event_attr configuration" test.out +grep "Starting stack profile collection pid" test.out || (grep "ERROR: Unsupported architecture" test.out && echo "unsupported arch" && exit 77) +grep -E "^buildid [0-9a-f]+" test.out + +stackprof_debuginfod_setup +stackprof_check_gmon_out + +exit 0 diff --git a/tests/run-stackprof-user.sh b/tests/run-stackprof-user.sh new file mode 100755 index 00000000..722b7b02 --- /dev/null +++ b/tests/run-stackprof-user.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# +# Copyright (C) 2026 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/stackprof-subr.sh + +set -x +unset VALGRIND_CMD + +# prerequisites +type timeout 2>/dev/null || (echo "no timeout installed"; exit 77) +check_perf_event_open || (echo "perf_event_open fails (check kernel.perf_event_paranoid + kernel config)"; exit 77) + +tempfiles test.out + +# run on single executable, no gprof output +testrun ${abs_top_builddir}/src/stackprof -v -- timeout 2 /bin/sh -c "while true; do true; done" 2>&1 | tee test.out +grep "^perf_event_attr configuration" test.out +grep "Starting stack profile collection pid" test.out || (grep "ERROR: Unsupported architecture" test.out && echo "unsupported arch" && exit 77) +grep -E "^[0-9]+ sh --" test.out # -- pid / sample counts entries + +# run on single executable again, with gprof output +testrun ${abs_top_builddir}/src/stackprof -g -- timeout 2 /bin/sh -c "while true; do true; done" 2>&1 | tee test.out +tempfiles gmon.* +grep "^perf_event_attr configuration type=1 config=0 sample_freq=" test.out +grep "Starting stack profile collection pid" test.out +grep -E "^buildid [0-9a-f]+" test.out +rm -f gmon.* + +# test libpfm event listing +if [ "x$HAVE_LIBPFM" = "x1" ]; then + testrun ${abs_top_builddir}/src/stackprof --event-list 2>&1 | tee test.out + grep "^perf::BRANCHES" test.out + + # run on single executable, with libpfm + testrun ${abs_top_builddir}/src/stackprof -v -e perf::BRANCHES:freq=4000 -g -- timeout 2 /bin/sh -c "while true; do true; done" 2>&1 | tee test out + tempfiles gmon.* + grep "^perf_event_attr configuration type=0 config=4 sample_freq=4000" test.out + grep "Starting stack profile collection pid" test.out + grep -E "^buildid [0-9a-f]+" test.out +fi + +exit 0 diff --git a/tests/stackprof-subr.sh b/tests/stackprof-subr.sh new file mode 100644 index 00000000..729053dd --- /dev/null +++ b/tests/stackprof-subr.sh @@ -0,0 +1,66 @@ +# Copyright (C) 2021 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/>. + +# sourced from run-stackprof-*.sh tests (must be bash scripts) + +. $srcdir/test-subr.sh + +check_perf_event_open() { + tempfiles perf-test.out + if ! testrun timeout 2 ${abs_top_builddir}/src/stackprof -v -- /bin/true > perf-test.out 2>&1; then + if grep -q "perf_event_open.*failed\|Operation not permitted\|Permission denied"; then + return 77 + fi + fi + return 0 +} + +stackprof_debuginfod_setup() { + # uncomment to test with networked debuginfod + #export DEBUGINFOD_URLS=https://debuginfod.elfutils.org/ + return 0 +} + +stackprof_check_gmon_out() { + for f in gmon.*.out + do + exe="`basename "$f" .out`.exe" + if [ ! -f "$exe" ]; then + buildid=`echo "$f" | cut -f2 -d.` + if ! testrun ${abs_top_builddir}/debuginfod/debuginfod-find -v executable $buildid; then + echo "$exe not found, skipping" + continue + fi + ln -s "`${abs_top_builddir}/debuginfod/debuginfod-find executable $buildid`" "$exe" + fi + tempfiles "$exe" gprof_output.txt + exe_info="$exe (`readlink $exe`)" + # try a plain gprof run on the executable + if gprof "$exe" "$f" > gprof_output.txt 2>&1; then + echo "$exe_info" + cat gprof_output.txt + continue + fi + # else fall back to debuginfod + if ! testrun ${abs_top_builddir}/debuginfod/debuginfod-find -v debuginfo $exe; then + echo "$exe_info is a stripped binary, debuginfo not found, skipping" + continue + fi + debuginfo="`${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $exe`" + echo "$exe_info" + gprof "$debuginfo" "$f" + done +} -- 2.54.0
