// write one histogram from low_pc ... high_pc
uint32_t num_buckets = (high_pc-low_pc)/alignment + 1;
double result_scale = (double)((high_pc-low_pc)/sizeof(uint16_t))/num_buckets;
- clog << format("DEBUG +hist {:x}..{:x} (alignment {}) of {} buckets @scale {}\n",
- low_pc, high_pc, alignment, num_buckets, result_scale);
+ if (verbose > 2)
+ clog << format("DEBUG +hist {:x}..{:x} (alignment {}) of {} buckets @scale {}\n",
+ low_pc, high_pc, alignment, num_buckets, result_scale);
/* TODO(PROBLEM): It's the @scale value that must be kept within
0.000001 of 0.5 to keep gprof from complaining. */
}
string target_path = buildid_to_mainfile[buildid];
- if (symlink(target_path.c_str(), exe_symlink_path.c_str()) == -1) {
- // Handle error, e.g., print errno or throw exception
- cerr << "symlink failed: " << strerror(errno) << endl;
- //return; /* TODO: We may want to re-create the symlink on repeated runs. */
- }
+ if (target_path != unknown_comm) // skip .exe symlink if there's no path
+ if (symlink(target_path.c_str(), exe_symlink_path.c_str()) == -1) {
+ // Handle error, e.g., print errno or throw exception
+ cerr << "symlink failed: " << strerror(errno) << endl;
+ //return; /* TODO: We may want to re-create the symlink on repeated runs. */
+ }
// TODO(REVIEW.4): plop buildid_to_{mainfile,debugfile} bits into per-gmon-out json files
json_object *metadata = json_object_new_object();
if (buildid_to_debugfile.count(buildid) != 0)
debugfile = buildid_to_debugfile[buildid].c_str();
if (show_summary)
- clog << format(N_("buildid {} ({} {}{}) -- received {} distinct pcs, {} callgraph arcs\n"), /* TODO also count samples / estimated histogram size? */
+ clog << format(N_("buildid {} ({}{}{}) -- received {} distinct pcs, {} callgraph arcs\n"), /* TODO also count samples / estimated histogram size? */
buildid.c_str(),
mainfile == NULL ? "<unknown>" : mainfile,
debugfile == NULL ? "" : " +debugfile ",
TESTS += run-funcretval-struct-native.sh
if ENABLE_STACKPROF
-TESTS += run-stackprof-user.sh run-stackprof-user-gprof.sh
+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
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
--- /dev/null
+#!/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/>.
+
+set -x
+
+. $srcdir/test-subr.sh
+
+# prerequisites
+type timeout 2>/dev/null || (echo "no timeout installed"; exit 77)
+expr `whoami` = "root" || (echo "run as root"; exit 77)
+
+# run systemwide scan
+tempfiles test.out
+# produce gprof data
+testrun timeout -p -sINT 10 ${abs_top_builddir}/src/stackprof -v -v 2>&1 | tee test.out
+
+grep "^perf_event_attr configuration" test.out
+grep "Starting stack profile collection systemwide" test.out
+grep -E "^[0-9]+ " test.out
+
+# run it again, producing gprof data
+testrun timeout -p -sINT 10 ${abs_top_builddir}/src/stackprof -v -v -g 2>&1 | tee test.out
+tempfiles test.out
+tempfiles gmon.*
+grep "^perf_event_attr configuration type=1 config=0 sample_freq=" test.out
+grep "Starting stack profile collection systemwide" test.out
+grep -E "^buildid [0-9a-f]+" test.out
+
+export DEBUGINFOD_URLS=https://debuginfod.elfutils.org/
+
+for f in gmon.*.out
+do
+ exe="`basename "$f" .out`.exe"
+ if [ ! -f "$exe" ];
+ then
+ echo "NOTE: finding $f executable by buildid"
+ buildid=`echo "$f" | cut -f2 -d.`
+ if testrun ${abs_top_builddir}/debuginfod/debuginfod-find -v executable $buildid; then
+ ln -s "`${abs_top_builddir}/debuginfod/debuginfod-find executable $buildid`" "$exe"
+ else
+ echo "SKIPPING: executable not found"
+ continue
+ fi
+ fi
+ tempfiles "$exe"
+ echo "NOTE: analyzing $exe `readlink $exe`"
+ tempfiles gprof_output.txt
+ # Try a plain gprof attempt on the executable
+ if gprof "$exe" "$f" > gprof_output.txt 2>&1; then
+ # Success, use the output
+ cat gprof_output.txt
+ else
+ # Fall back to debuginfod if necessary (e.g., if debug info is missing)
+ echo "NOTE: stripped binary found, attempting to find debuginfo"
+ if testrun ${abs_top_builddir}/debuginfod/debuginfod-find -v debuginfo $exe; then
+ debuginfo="`${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $exe`"
+ gprof "$debuginfo" "$f"
+ else
+ echo "SKIPPING: debuginfo not found"
+ continue
+ fi
+ fi
+done
+
+exit 0
--- /dev/null
+#!/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/>.
+
+set -x
+
+. $srcdir/test-subr.sh
+
+# prerequisites
+type timeout 2>/dev/null || (echo "no timeout installed"; exit 77)
+expr `whoami` = "root" || (echo "run as root"; exit 77)
+
+# run systemwide scan
+tempfiles test.out
+testrun timeout -p -sINT 10 ${abs_top_builddir}/src/stackprof -v -v 2>&1 | tee test.out
+
+grep "^perf_event_attr configuration" test.out
+grep "Starting stack profile collection systemwide" test.out
+grep -E "^[0-9]+ " test.out
+
+# run it again, producing gprof data
+testrun timeout -p -sINT 10 ${abs_top_builddir}/src/stackprof -v -v -g 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 systemwide" test.out
+grep -E "^buildid [0-9a-f]+" test.out
+
+
+exit 0
# produce gprof data
testrun ${abs_top_builddir}/src/stackprof -v -v -g -- timeout 2 /bin/sh -c "while true; do true; done" 2>&1 | tee test.out
tempfiles test.out
-
tempfiles gmon.*
grep "^perf_event_attr configuration" test.out
grep "Starting stack profile collection pid" test.out
for f in gmon.*.out
do
exe="`basename "$f" .out`.exe"
+ if [ ! -f "$exe" ];
+ then
+ echo "NOTE: finding $f executable by buildid"
+ buildid=`echo "$f" | cut -f2 -d.`
+ if testrun ${abs_top_builddir}/debuginfod/debuginfod-find -v executable $buildid; then
+ ln -s "`${abs_top_builddir}/debuginfod/debuginfod-find executable $buildid`" "$exe"
+ else
+ echo "SKIPPING: executable not found"
+ continue
+ fi
+ fi
+ tempfiles "$exe"
echo "NOTE: analyzing $exe `readlink $exe`"
tempfiles gprof_output.txt
# Try a plain gprof attempt on the executable
- if gprof "$exe" > gprof_output.txt 2>&1; then
+ if gprof "$exe" "$f" > gprof_output.txt 2>&1; then
# Success, use the output
cat gprof_output.txt
else
# Fall back to debuginfod if necessary (e.g., if debug info is missing)
echo "NOTE: stripped binary found, attempting to find debuginfo"
- if testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $exe; then
- debuginfo="`debuginfod-find debuginfo $exe`"
+ if testrun ${abs_top_builddir}/debuginfod/debuginfod-find -v debuginfo $exe; then
+ debuginfo="`${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $exe`"
gprof "$debuginfo" "$f"
else
echo "SKIPPING: debuginfo not found"
+ continue
fi
fi
done