Live Patching
 help / color / mirror / Atom feed
From: Puranjay Mohan <puranjay@kernel.org>
To: live-patching@vger.kernel.org
Cc: Puranjay Mohan <puranjay@kernel.org>,
	Josh Poimboeuf <jpoimboe@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>, Song Liu <song@kernel.org>,
	Miroslav Benes <mbenes@suse.cz>,
	Joe Lawrence <joe.lawrence@redhat.com>
Subject: [PATCH 1/3] objtool/klp: Build test fixtures with ftrace
Date: Thu, 22 Oct 2026 05:25:36 -0700	[thread overview]
Message-ID: <20261022122544.125305-2-puranjay@kernel.org> (raw)
In-Reply-To: <20261022122544.125305-1-puranjay@kernel.org>

Livepatch depends on ftrace, so the kernel klp-build operates on always
has __mcount_loc, but the test fixtures are built without it.

On x86, build them with -pg -mfentry and generate __mcount_loc like the
kernel does: with -mrecord-mcount -mnop-mcount if the compiler supports
it (FTRACE_MCOUNT_USE_CC), otherwise with objtool --mcount --mnop
(FTRACE_MCOUNT_USE_OBJTOOL).

test-checksum-alt ran objtool --mcount only to get insn->alts, which
"klp checksum" builds by itself, and that now warns about the existing
__mcount_loc.  Remove it.

test-special-sections can now check the real __mcount_loc instead of a
hand-written one.

Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
---
 .../objtool/Documentation/klp-write-tests.txt |  9 ++--
 .../tests/generic/test-thinlto-ambiguity.sh   |  3 +-
 .../tests/generic/test-thinlto-local.sh       |  5 ++-
 tools/objtool/tests/lib.sh                    | 42 +++++++++++++++++--
 tools/objtool/tests/x86/test-checksum-alt.sh  |  4 --
 .../tests/x86/test-special-sections.sh        | 23 ++++++----
 6 files changed, 64 insertions(+), 22 deletions(-)

diff --git a/tools/objtool/Documentation/klp-write-tests.txt b/tools/objtool/Documentation/klp-write-tests.txt
index eb2cacaf57207..7cc2148083cc2 100644
--- a/tools/objtool/Documentation/klp-write-tests.txt
+++ b/tools/objtool/Documentation/klp-write-tests.txt
@@ -116,9 +116,12 @@ Traps that have bitten before
   section entsize or annotations".  Their targets need real (global) symbols,
   or it reports "failed to convert reloc sym".
 * **Prefer letting objtool generate what objtool generates.**
-  ``.static_call_sites``, ``.mcount_loc``, ``.ibt_endbr_seal`` and ORC come
-  from its check pass.  Call ``run_objtool_check --mcount`` and let it build
-  them; a hand-written copy tests your reading of the format, not the format.
+  ``.static_call_sites``, ``.ibt_endbr_seal`` and ORC come from its check
+  pass.  Call ``run_objtool_check`` with the option for what you need and let
+  it build them; a hand-written copy tests your reading of the format, not the
+  format.
+* **Fixtures are built with ftrace.**  Objects not built with ``build_one``
+  need ``$FTRACE_CFLAGS`` and ``record_mcount`` too.
 
   Write one by hand only when the test needs a shape objtool will not produce,
   and say so in the fixture.  generic/fixtures/static_call.c does: objtool
diff --git a/tools/objtool/tests/generic/test-thinlto-ambiguity.sh b/tools/objtool/tests/generic/test-thinlto-ambiguity.sh
index 34f4f3a58e201..73740c804d54f 100755
--- a/tools/objtool/tests/generic/test-thinlto-ambiguity.sh
+++ b/tools/objtool/tests/generic/test-thinlto-ambiguity.sh
@@ -38,12 +38,13 @@ build_thinlto()		# $1 output object, $2 extra flags
 {
 	local t
 	for t in "" -DTU_B -DTU_C; do
-		$THIN_CC -flto=thin -O2 -ffunction-sections -fdata-sections \
+		$THIN_CC -flto=thin -O2 -ffunction-sections -fdata-sections $FTRACE_CFLAGS \
 			$2 $t -c "$FIXTURES_DIR/thinlto_ambiguity.c" \
 			-o "$workdir/tu$t.o" 2>/dev/null || return 1
 	done
 	"$THIN_LD" -r "$workdir/tu.o" "$workdir/tu-DTU_B.o" "$workdir/tu-DTU_C.o" \
 		-o "$1" 2>/dev/null || return 1
+	record_mcount "$1"
 }
 
 build_thinlto "$workdir/orig.o" "" ||
diff --git a/tools/objtool/tests/generic/test-thinlto-local.sh b/tools/objtool/tests/generic/test-thinlto-local.sh
index a266263676ed5..090c6df75ad64 100755
--- a/tools/objtool/tests/generic/test-thinlto-local.sh
+++ b/tools/objtool/tests/generic/test-thinlto-local.sh
@@ -15,11 +15,12 @@ find_thinlto_toolchain ||
 
 build_thinlto()		# $1 output object, $2 extra flags
 {
-	$THIN_CC -flto=thin -O2 -ffunction-sections -fdata-sections $2 \
+	$THIN_CC -flto=thin -O2 -ffunction-sections -fdata-sections $FTRACE_CFLAGS $2 \
 		-c "$FIXTURES_DIR/thinlto_local.c" -o "$workdir/tu_a.o" 2>/dev/null || return 1
-	$THIN_CC -flto=thin -O2 -ffunction-sections -fdata-sections $2 -DTU_B \
+	$THIN_CC -flto=thin -O2 -ffunction-sections -fdata-sections $FTRACE_CFLAGS $2 -DTU_B \
 		-c "$FIXTURES_DIR/thinlto_local.c" -o "$workdir/tu_b.o" 2>/dev/null || return 1
 	"$THIN_LD" -r "$workdir/tu_a.o" "$workdir/tu_b.o" -o "$1" 2>/dev/null || return 1
+	record_mcount "$1"
 }
 
 build_thinlto "$workdir/orig.o" "" ||
diff --git a/tools/objtool/tests/lib.sh b/tools/objtool/tests/lib.sh
index 4da168d0ddca3..d07eb07d15611 100644
--- a/tools/objtool/tests/lib.sh
+++ b/tools/objtool/tests/lib.sh
@@ -41,7 +41,7 @@ OBJTOOL="${OBJTOOL:-$TESTS_DIR/../objtool}"
 #
 klp_preflight()
 {
-	local tmp tool cc_version arch host cc_arch
+	local tmp tool cc_version arch host cc_arch mcount=
 
 	bail() { echo "Bail out! $*" >&2; exit 1; }
 
@@ -99,6 +99,16 @@ klp_preflight()
 	*AArch64*)		cc_arch=arm64 ;;
 	*)			cc_arch= ;;
 	esac
+
+	# Same test as FTRACE_MCOUNT_USE_CC.
+	if [ "$cc_arch" = x86 ]; then
+		if $CC -pg -mfentry -mrecord-mcount -mnop-mcount -c \
+			-o "$tmp/probe.o" "$tmp/probe.c" 2>/dev/null; then
+			mcount=cc
+		else
+			mcount=objtool
+		fi
+	fi
 	rm -rf "$tmp"
 
 	# Normalize to the kernel's SRCARCH.
@@ -119,8 +129,9 @@ klp_preflight()
 		     "the $arch tests would run against the wrong architecture"
 
 	KLP_TEST_ARCH="$arch"
+	KLP_TEST_MCOUNT="$mcount"
 	KLP_TEST_PREFLIGHT=done
-	export OBJTOOL CC KLP_TEST_ARCH KLP_TEST_PREFLIGHT
+	export OBJTOOL CC KLP_TEST_ARCH KLP_TEST_MCOUNT KLP_TEST_PREFLIGHT
 
 	cc_version="$($CC --version 2>/dev/null | head -1)"
 	cat <<EOF
@@ -128,6 +139,7 @@ klp_preflight()
 #   objtool   $OBJTOOL (klp: yes)
 #   compiler  $cc_version
 #   arch      $KLP_TEST_ARCH$([ "$arch" = "$host" ] || echo "  (host $host, cross)")
+#   mcount    ${KLP_TEST_MCOUNT:-n/a}
 #   tmpdir    ${TMPDIR:-/tmp}  (each test builds in a fresh directory here)
 EOF
 }
@@ -153,6 +165,16 @@ EOF
 FIXTURE_CFLAGS="-O2 -ffunction-sections -fdata-sections -fno-common \
 		-fno-asynchronous-unwind-tables"
 
+# Build with ftrace, which livepatch depends on.  Objects not built with
+# build_one() need FTRACE_CFLAGS and record_mcount() too.
+FTRACE_CFLAGS=
+if [ "$KLP_TEST_ARCH" = x86 ]; then
+	FTRACE_CFLAGS="-pg -mfentry"
+	[ "$KLP_TEST_MCOUNT" = cc ] &&
+		FTRACE_CFLAGS="$FTRACE_CFLAGS -mrecord-mcount -mnop-mcount"
+fi
+FIXTURE_CFLAGS="$FIXTURE_CFLAGS $FTRACE_CFLAGS"
+
 test_name="$(basename "$0" .sh)"
 workdir=
 
@@ -343,6 +365,20 @@ build_one()
 
 	$CC -c $FIXTURE_CFLAGS "$@" -o "$out" "$fixture" 2>"$workdir/cc.log" ||
 		fail "$(basename "$fixture") does not build: $(tail -1 "$workdir/cc.log")"
+
+	record_mcount "$out"
+}
+
+# record_mcount <object>
+#
+# FTRACE_MCOUNT_USE_OBJTOOL.  CONFIG_KLP_BUILD always runs objtool with --link.
+record_mcount()
+{
+	[ "$KLP_TEST_MCOUNT" = objtool ] || return 0
+
+	"$OBJTOOL" --mcount --mnop --link "$1" 2>"$workdir/objtool.log" ||
+		fail "objtool --mcount failed on $(basename "$1"):" \
+		     "$(tail -1 "$workdir/objtool.log")"
 }
 
 # build_pair <fixture.c> [cflags...]
@@ -365,7 +401,7 @@ build_pair()
 # Run objtool's ordinary check pass over the pair, as the kernel build does.
 #
 # Some of what klp diff consumes is produced by this pass rather than by the
-# compiler: .static_call_sites, .mcount_loc, .ibt_endbr_seal, ORC.
+# compiler: .static_call_sites, .ibt_endbr_seal, ORC.
 #
 # Only module objects see it before klp-build -- with CONFIG_KLP_BUILD the
 # per-object pass is deferred, so built-in objects reach klp diff exactly as
diff --git a/tools/objtool/tests/x86/test-checksum-alt.sh b/tools/objtool/tests/x86/test-checksum-alt.sh
index 74ebfca2b3ff3..eb9864c4bf825 100755
--- a/tools/objtool/tests/x86/test-checksum-alt.sh
+++ b/tools/objtool/tests/x86/test-checksum-alt.sh
@@ -16,9 +16,6 @@
 # the feature bit, so the failure looks like a machine-specific bug rather than
 # a missing patch.
 #
-# insn->alts exists only after objtool's check pass, so the pair goes through
-# that first -- the compiler emits none of this structure itself.
-#
 # Covers the same ground as corpus/x86_64/checksum-alt-group,
 # checksum-alt-no-group and checksum-alt-recursion-guard in Joe Lawrence's
 # klp-build unit test corpus.
@@ -31,7 +28,6 @@ check()
 {
 	build_pair checksum_alt.c "-D$1"
 	assert_input_section .altinstructions
-	run_objtool_check --mcount
 	run_checksum
 
 	assert_checksum_differs target
diff --git a/tools/objtool/tests/x86/test-special-sections.sh b/tools/objtool/tests/x86/test-special-sections.sh
index 8dfaa4fc9a360..b05d43cdc8aa4 100755
--- a/tools/objtool/tests/x86/test-special-sections.sh
+++ b/tools/objtool/tests/x86/test-special-sections.sh
@@ -15,26 +15,31 @@
 
 
 # section, entry size, relocations per entry
-for spec in "__bug_table 12 1" "__ex_table 12 2" "__mcount_loc 8 1"; do
+for spec in "__bug_table 12 1" "__ex_table 12 2"; do
 	set -- $spec
-	sec=$1
 
 	# A fresh workdir per section: run_diff caches its checksums.
 	setup
 	build_pair special_sections.c \
 		-DSPECIAL_SEC="\"$1\"" -DSPECIAL_ENTSIZE="$2" -DSPECIAL_RELOCS="$3"
 
-	assert_input_section "$sec"
+	# __mcount_loc comes from FTRACE_CFLAGS, not from the fixture.
+	for sec in "$1" __mcount_loc; do
+		assert_input_section "$sec"
+	done
 	run_diff
 
-	# Extracted, and pointing at the function that was patched.
-	assert_section "$sec"
-	assert_reloc_sym "$sec" target
 	assert_patched target
-
-	# Nothing belonging to the function that was not.
 	assert_not_patched other
-	assert_no_reloc_sym "$sec" other
+
+	for sec in "$1" __mcount_loc; do
+		# Extracted, and pointing at the function that was patched.
+		assert_section "$sec"
+		assert_reloc_sym "$sec" target
+
+		# Nothing belonging to the function that was not.
+		assert_no_reloc_sym "$sec" other
+	done
 
 	cleanup
 done
-- 
2.53.0-Meta


  reply	other threads:[~2026-10-22 12:26 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-22 12:25 [PATCH 0/3] objtool/klp: Reject changed functions without an ftrace call site Puranjay Mohan
2026-10-22 12:25 ` Puranjay Mohan [this message]
2026-10-22 14:46   ` [PATCH 1/3] objtool/klp: Build test fixtures with ftrace Joe Lawrence
2026-10-22 16:43     ` Puranjay Mohan
2026-10-22 12:25 ` [PATCH 2/3] objtool/klp: Reject changed functions without an ftrace call site Puranjay Mohan
2026-10-22 15:55   ` Joe Lawrence
2026-10-22 12:25 ` [PATCH 3/3] objtool/klp: Add test for " Puranjay Mohan
2026-10-22 16:02   ` Joe Lawrence

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=20261022122544.125305-2-puranjay@kernel.org \
    --to=puranjay@kernel.org \
    --cc=joe.lawrence@redhat.com \
    --cc=jpoimboe@kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mbenes@suse.cz \
    --cc=peterz@infradead.org \
    --cc=song@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