From: Joe Lawrence <joe.lawrence@redhat.com>
To: Puranjay Mohan <puranjay@kernel.org>
Cc: live-patching@vger.kernel.org,
Josh Poimboeuf <jpoimboe@kernel.org>,
Peter Zijlstra <peterz@infradead.org>, Song Liu <song@kernel.org>,
Miroslav Benes <mbenes@suse.cz>
Subject: Re: [PATCH 1/3] objtool/klp: Build test fixtures with ftrace
Date: Thu, 22 Oct 2026 10:46:30 -0400 [thread overview]
Message-ID: <atohxvOb9MAxkhsg@redhat.com> (raw)
In-Reply-To: <20261022122544.125305-2-puranjay@kernel.org>
On Thu, Oct 22, 2026 at 05:25:36AM -0700, Puranjay Mohan wrote:
> 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
Nitpick: it looks a little odd that the __mcount_loc special case was
pushed inside the greater section loop (bug-tables, ex-table) so it runs
twice AFAICT. Would it be clearer to just pull this out as its own
block?
--
Joe
next prev parent reply other threads:[~2026-10-22 14:46 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 ` [PATCH 1/3] objtool/klp: Build test fixtures with ftrace Puranjay Mohan
2026-10-22 14:46 ` Joe Lawrence [this message]
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=atohxvOb9MAxkhsg@redhat.com \
--to=joe.lawrence@redhat.com \
--cc=jpoimboe@kernel.org \
--cc=live-patching@vger.kernel.org \
--cc=mbenes@suse.cz \
--cc=peterz@infradead.org \
--cc=puranjay@kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.