From: Song Liu <song@kernel.org>
To: live-patching@vger.kernel.org
Cc: jpoimboe@kernel.org, peterz@infradead.org, jikos@kernel.org,
mbenes@suse.cz, pmladek@suse.com, joe.lawrence@redhat.com,
puranjay@kernel.org, kernel-team@meta.com,
Song Liu <song@kernel.org>
Subject: [PATCH 02/58] objtool/klp: Check the klp test environment once, before any test
Date: Fri, 11 Sep 2026 11:42:09 -0700 [thread overview]
Message-ID: <20260911184305.1457308-3-song@kernel.org> (raw)
In-Reply-To: <20260911184305.1457308-1-song@kernel.org>
Every test checked for itself that objtool exists, was built with klp
support, and that $CC runs. Three problems with that: it is the same work
done 40 times, a missing objtool reads as a per-test skip rather than as a
suite which cannot run, and a run in which everything skipped still exits
0.
Do it once, before any test, in preflight.sh, and record the answers where
the tests can read them. If the suite cannot run the whole run fails and
says why; a test which gets as far as running can assume its environment.
The recorded file is required, not optional: a test which cannot tell where
objtool is or which architecture it is on should say so rather than guess
at an empty value. It also records which compiler it describes, so a
single test run by hand with a different CC after a full run cannot quietly
inherit the other one's environment.
preflight answers only whether the suite can run at all -- not what the
compiler is capable of. A test needing a particular compiler feature
probes for it and skips; that costs one compile and keeps the reason next
to the test that has to justify it.
Assisted-by: Claude:claude-opus-5
Signed-off-by: Song Liu <song@kernel.org>
---
tools/objtool/Makefile | 3 +-
tools/objtool/tests/lib.sh | 114 ++++++++++++++++++++++++++-----
tools/objtool/tests/run-tests.sh | 7 ++
3 files changed, 106 insertions(+), 18 deletions(-)
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index f4ec9f813a20..2c200d05c276 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -152,7 +152,8 @@ mrproper: clean
$(call QUIET_CLEAN, objtool) $(RM) $(OBJTOOL)
tests: $(OBJTOOL)
- $(Q)OBJTOOL=$(abspath $(OBJTOOL)) $(srctree)/tools/objtool/tests/run-tests.sh
+ $(Q)OBJTOOL=$(abspath $(OBJTOOL)) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) \
+ $(srctree)/tools/objtool/tests/run-tests.sh
FORCE:
diff --git a/tools/objtool/tests/lib.sh b/tools/objtool/tests/lib.sh
index 714371232fa3..6e4e54b10865 100644
--- a/tools/objtool/tests/lib.sh
+++ b/tools/objtool/tests/lib.sh
@@ -11,8 +11,98 @@
TESTS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
FIXTURES_DIR="$TESTS_DIR/fixtures"
+# The kernel's convention: CROSS_COMPILE is the one knob, with per-tool
+# overrides for what it does not cover. objtool itself is always a host binary
+# -- it is built with HOSTCC and only reads ELF -- so an arm64 machine can run
+# the x86 tests against x86 objects given a compiler that emits them.
+#
+# readelf reads any target, so it rarely needs overriding -- and it must stay
+# GNU readelf, whose column layout the assertions parse; llvm-readelf spaces
+# them differently. BFD's objcopy is usually built for the host's target
+# alone, and llvm-objcopy is the target-agnostic replacement.
+CROSS_COMPILE="${CROSS_COMPILE:-}"
+CC="${CC:-${CROSS_COMPILE}gcc}"
+LD="${LD:-${CROSS_COMPILE}ld}"
+READELF="${READELF:-${CROSS_COMPILE}readelf}"
+OBJCOPY="${OBJCOPY:-${CROSS_COMPILE}objcopy}"
+
OBJTOOL="${OBJTOOL:-$TESTS_DIR/../objtool}"
-CC="${CC:-gcc}"
+
+# klp_preflight
+#
+# Check the environment once, before any test runs, and report what was found.
+#
+klp_preflight()
+{
+ local tmp tool cc_version host cc_arch
+
+ bail() { echo "Bail out! $*" >&2; exit 1; }
+
+ # A relative $OBJTOOL is relative to the objtool directory, not tests/.
+ [ -x "$OBJTOOL" ] || [ ! -x "$TESTS_DIR/../$OBJTOOL" ] ||
+ OBJTOOL="$TESTS_DIR/../$OBJTOOL"
+
+ [ -x "$OBJTOOL" ] ||
+ bail "objtool not found at '$OBJTOOL' -- build it first"
+
+ "$OBJTOOL" klp 2>&1 | grep -q checksum ||
+ bail "objtool was built without klp support; install libxxhash (>= 0.8) and rebuild"
+
+ command -v "${CC%% *}" >/dev/null || bail "compiler not found: $CC"
+
+ for tool in "$READELF" "$OBJCOPY" "$LD"; do
+ command -v "$tool" >/dev/null || bail "$tool not found"
+ done
+
+ tmp="$(mktemp -d)" || bail "mktemp failed"
+ echo 'int probe(void) { return 0; }' > "$tmp/probe.c"
+ $CC -c -o "$tmp/probe.o" "$tmp/probe.c" 2>/dev/null ||
+ { rm -rf "$tmp"; bail "$CC cannot compile a trivial object"; }
+
+ # $CC, $ARCH and objtool have to agree about the target, and cross runs
+ # are where they stop agreeing: plain "CC=clang ARCH=x86_64" on an arm64
+ # box selects the x86 tests and then builds arm64 objects, because clang
+ # needs --target= to emit anything but the host's.
+ #
+ # Ask objtool rather than comparing machine names. It rejects an object
+ # it was not built for -- "unexpected ELF machine type" -- so one check
+ # covers every way the three can disagree, and says so once instead of
+ # failing every test for the same reason.
+ "$OBJTOOL" klp checksum "$tmp/probe.o" >/dev/null 2>&1 ||
+ { rm -rf "$tmp"
+ bail "objtool rejects an object built by '$CC'; they target" \
+ "different architectures (set CROSS_COMPILE, or" \
+ "--target= for clang)"; }
+
+ # BFD objcopy is usually built for the host's target alone, and
+ # checksum_of() needs it to read the object under test.
+ $OBJCOPY -O binary --only-section=.text "$tmp/probe.o" "$tmp/probe.bin" 2>/dev/null ||
+ { rm -rf "$tmp"
+ bail "$OBJCOPY cannot read objects built by '$CC'; install" \
+ "binutils-multiarch or set OBJCOPY=llvm-objcopy"; }
+ # $ARCH only chooses which directory of tests runs, so it can disagree
+ # with what $CC builds without objtool noticing -- and the result is the
+ # wrong set of tests, quietly.
+ case "$($READELF -hW "$tmp/probe.o" | sed -n 's/.*Machine: *//p')" in
+ *X86-64*|*Intel*80386*) cc_arch=x86 ;;
+ *AArch64*) cc_arch=arm64 ;;
+ *) cc_arch= ;;
+ esac
+ rm -rf "$tmp"
+
+ KLP_TEST_PREFLIGHT=done
+ export OBJTOOL CC KLP_TEST_PREFLIGHT
+
+ cc_version="$($CC --version 2>/dev/null | head -1)"
+ cat <<EOF
+# preflight
+# objtool $OBJTOOL (klp: yes)
+# compiler $cc_version
+# arch $KLP_TEST_ARCH$([ "$arch" = "$host" ] || echo " (host $host, cross)")
+EOF
+}
+
+[ -n "${KLP_TEST_PREFLIGHT:-}" ] || klp_preflight
# klp-build compiles the kernel this way; klp diff needs per-symbol sections to
# extract individual functions.
@@ -30,19 +120,9 @@ cleanup() { [ -n "$workdir" ] && rm -rf "$workdir"; }
# setup [exported symbol...]
setup()
{
- # A relative $OBJTOOL is relative to the objtool directory, not to the
- # tests which run from tests/.
- [ -x "$OBJTOOL" ] || [ ! -x "$TESTS_DIR/../$OBJTOOL" ] ||
- OBJTOOL="$TESTS_DIR/../$OBJTOOL"
-
- # Not finding objtool is a broken invocation, not an environment which
- # cannot run the test. Skipping here would read as a pass.
- [ -x "$OBJTOOL" ] || fail "objtool not found at '$OBJTOOL', build it first"
-
- "$OBJTOOL" klp 2>&1 | grep -q checksum ||
- skip "objtool built without klp support (needs libxxhash)"
- command -v "${CC%% *}" >/dev/null || skip "no compiler ($CC)"
-
+ # The environment was checked once when this file was sourced, so there
+ # is nothing to verify here: objtool exists at the resolved path, has
+ # klp support, and $CC works.
workdir="$(mktemp -d)" || fail "mktemp failed"
trap cleanup EXIT
@@ -151,9 +231,9 @@ find_thinlto_toolchain()
return 1
}
-out_sections() { readelf -S -W "$workdir/out.o" 2>/dev/null; }
-out_relocs() { readelf -r -W "$workdir/out.o" 2>/dev/null; }
-out_symbols() { readelf -s -W "$workdir/out.o" 2>/dev/null; }
+out_sections() { $READELF -S -W "$workdir/out.o" 2>/dev/null; }
+out_relocs() { $READELF -r -W "$workdir/out.o" 2>/dev/null; }
+out_symbols() { $READELF -s -W "$workdir/out.o" 2>/dev/null; }
diff_log() { cat "$workdir/diff.log"; }
assert_section()
diff --git a/tools/objtool/tests/run-tests.sh b/tools/objtool/tests/run-tests.sh
index ab1dea58811e..f6a3e1b7677e 100755
--- a/tools/objtool/tests/run-tests.sh
+++ b/tools/objtool/tests/run-tests.sh
@@ -2,6 +2,9 @@
# SPDX-License-Identifier: GPL-2.0
#
# Run the objtool klp tests. Each test-*.sh prints one TAP result line.
+#
+# The harness checks the environment once up front and fails the run if the
+# suite cannot execute, rather than letting every test skip and exit 0.
set -u
@@ -10,6 +13,10 @@ cd "$(dirname "$0")" || exit 1
tests=( test-*.sh )
[ "${tests[0]}" = "test-*.sh" ] && { echo "1..0 # SKIP no tests found"; exit 0; }
+# Sourcing the harness runs its preflight, and exports what it found so the
+# tests inherit it rather than working it out again.
+. ./lib.sh
+
echo "1..${#tests[@]}"
rc=0
--
2.53.0-Meta
next prev parent reply other threads:[~2026-09-11 18:43 UTC|newest]
Thread overview: 77+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 18:42 [PATCH 00/58] Unit test framework for klp-build toolchain Song Liu
2026-09-11 18:42 ` [PATCH 01/58] objtool: Add test harness for the klp subcommands Song Liu
2026-09-11 18:42 ` Song Liu [this message]
2026-09-11 19:02 ` [PATCH 02/58] objtool/klp: Check the klp test environment once, before any test sashiko-bot
2026-09-11 18:42 ` [PATCH 03/58] objtool/klp: Group the klp tests by architecture Song Liu
2026-09-11 18:42 ` [PATCH 04/58] objtool/klp: Classify klp test outcomes Song Liu
2026-09-11 18:42 ` [PATCH 05/58] objtool/klp: Build klp test fixtures through the harness Song Liu
2026-09-11 18:42 ` [PATCH 06/58] objtool/klp: Grow the klp test harness vocabulary Song Liu
2026-09-11 19:03 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 07/58] objtool/klp: Give each run one working directory, one per test inside it Song Liu
2026-09-11 18:42 ` [PATCH 08/58] objtool/klp: Run the klp tests under set -u Song Liu
2026-09-11 18:42 ` [PATCH 09/58] objtool/klp: Document the klp test harness Song Liu
2026-09-11 19:00 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 10/58] objtool: Keep failing test workdirs by default Song Liu
2026-09-11 19:07 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 11/58] objtool: Forward toolchain variables to the klp test runner Song Liu
2026-09-11 18:42 ` [PATCH 12/58] objtool/klp: Add test for rejecting changed data Song Liu
2026-09-11 18:42 ` [PATCH 13/58] objtool/klp: Add test for newly introduced data Song Liu
2026-09-11 19:07 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 14/58] objtool/klp: Add test for newly introduced functions Song Liu
2026-09-11 18:42 ` [PATCH 15/58] objtool/klp: Add test for static local correlation Song Liu
2026-09-11 18:42 ` [PATCH 16/58] objtool/klp: Add test for cold function halves Song Liu
2026-09-11 19:07 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 17/58] objtool/klp: Add test for special section extraction Song Liu
2026-09-11 18:42 ` [PATCH 18/58] objtool/klp: Add test for selective " Song Liu
2026-09-11 18:42 ` [PATCH 19/58] objtool/klp: Add test for jump table key relocations Song Liu
2026-09-11 18:42 ` [PATCH 20/58] objtool/klp: Add test for rejecting module-owned static branch keys Song Liu
2026-09-11 18:42 ` [PATCH 21/58] objtool/klp: Add test for rejecting module-owned static call keys Song Liu
2026-09-11 18:42 ` [PATCH 22/58] objtool/klp: Add test for symids in discarded sections Song Liu
2026-09-11 18:42 ` [PATCH 23/58] objtool/klp: Add test for rejecting references to init code/data Song Liu
2026-09-11 19:18 ` sashiko-bot
2026-09-11 18:42 ` [PATCH 24/58] objtool/klp: Add test for correlation across ThinLTO name mangling Song Liu
2026-09-11 18:42 ` [PATCH 25/58] objtool/klp: Add test for objects without .modinfo Song Liu
2026-09-11 18:49 ` [PATCH 26/58] objtool/klp: Add test for unchecksummed input Song Liu
2026-09-11 18:50 ` [PATCH 27/58] objtool/klp: Add klp diff and post-link regression tests Song Liu
2026-09-11 18:50 ` [PATCH 28/58] objtool/klp: Add test for klp reloc section naming in module objects Song Liu
2026-09-11 18:50 ` [PATCH 29/58] objtool/klp: Add test for vmlinux relocs in a patched module Song Liu
2026-09-11 18:50 ` [PATCH 30/58] objtool/klp: Add test for Module.symvers path normalization Song Liu
2026-09-11 18:50 ` [PATCH 31/58] objtool/klp: Add test for the contents of the klp_funcs list Song Liu
2026-09-11 18:50 ` [PATCH 32/58] objtool/klp: Add test for EXPORT_SYMBOL_FOR_MODULES references Song Liu
2026-09-11 18:50 ` [PATCH 33/58] objtool/klp: Add test for new references to exported symbols Song Liu
2026-09-11 18:50 ` [PATCH 34/58] objtool/klp: Add test for empty x86 alternative replacements Song Liu
2026-09-11 18:50 ` [PATCH 35/58] objtool/klp: Add test for recorded checksum values Song Liu
2026-09-11 18:50 ` [PATCH 36/58] objtool/klp: Add test for position-independent checksums Song Liu
2026-09-11 19:16 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 37/58] objtool/klp: Add test for sympos in module objects Song Liu
2026-09-11 19:21 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 38/58] objtool/klp: Add test for sympos resolved against a linked vmlinux Song Liu
2026-09-11 18:50 ` [PATCH 39/58] objtool/klp: Add test for static locals which must not be correlated Song Liu
2026-09-11 18:50 ` [PATCH 40/58] objtool/klp: Add test for __bug_table, __ex_table and __mcount_loc extraction Song Liu
2026-09-11 19:20 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 41/58] objtool/klp: Add test for kCFI prefix symbols and traps Song Liu
2026-09-11 19:21 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 42/58] objtool/klp: Add test for symbols whose linkage the patch changes Song Liu
2026-09-11 18:50 ` [PATCH 43/58] objtool/klp: Test rejection of a file-local static branch key Song Liu
2026-09-11 18:50 ` [PATCH 44/58] objtool/klp: Test a hand-built livepatch module's static call keys Song Liu
2026-09-11 18:50 ` [PATCH 45/58] objtool/klp: Test text annotations on alternative replacements Song Liu
2026-09-11 18:50 ` [PATCH 46/58] objtool/klp: Add test for data object checksums Song Liu
2026-09-11 18:50 ` [PATCH 47/58] objtool/klp: Add test for symbols with no checksum entry of their own Song Liu
2026-09-11 19:23 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 48/58] objtool/klp: Add test for a static branch introduced by the patch Song Liu
2026-09-11 18:50 ` [PATCH 49/58] objtool/klp: Add test for tracepoint and pr_debug static branch keys Song Liu
2026-09-11 18:50 ` [PATCH 50/58] objtool/klp: Add test for a static call introduced by the patch Song Liu
2026-09-11 19:25 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 51/58] objtool/klp: Add test for instruction operand checksums Song Liu
2026-09-11 18:50 ` [PATCH 52/58] objtool/klp: Add test for alternative replacement code in checksums Song Liu
2026-09-11 19:30 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 53/58] objtool/klp: Add test for the alignment of cloned data sections Song Liu
2026-09-11 18:50 ` [PATCH 54/58] objtool/klp: Add test for a patch which strips a data annotation Song Liu
2026-09-11 19:24 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 55/58] objtool/klp: Add test for absolute and __ADDRESSABLE symbols Song Liu
2026-09-11 18:50 ` [PATCH 56/58] objtool/klp: Add test for UBSAN metadata in an unchanged function Song Liu
2026-09-11 18:50 ` [PATCH 57/58] objtool/klp: Add test for Clang switch jump tables Song Liu
2026-09-11 19:27 ` sashiko-bot
2026-09-11 18:50 ` [PATCH 58/58] objtool/klp: Add test for ThinLTO symbols sharing a demangled name Song Liu
2026-09-11 19:28 ` sashiko-bot
2026-09-13 1:53 ` [PATCH 00/58] Unit test framework for klp-build toolchain Josh Poimboeuf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260911184305.1457308-3-song@kernel.org \
--to=song@kernel.org \
--cc=jikos@kernel.org \
--cc=joe.lawrence@redhat.com \
--cc=jpoimboe@kernel.org \
--cc=kernel-team@meta.com \
--cc=live-patching@vger.kernel.org \
--cc=mbenes@suse.cz \
--cc=peterz@infradead.org \
--cc=pmladek@suse.com \
--cc=puranjay@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox