All of lore.kernel.org
 help / color / mirror / Atom feed
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 v4 27/58] objtool/klp: Add klp diff and post-link regression tests
Date: Tue, 15 Sep 2026 16:34:23 -0700	[thread overview]
Message-ID: <20260915233454.2405019-28-song@kernel.org> (raw)
In-Reply-To: <20260915233454.2405019-1-song@kernel.org>

Five tests covering behaviour the harness could reach but nothing
exercised.  Each was verified to fail against the code it guards, by
reverting the fix or sabotaging the exact line; where a first attempt
passed against broken code, the fixture was wrong and was rebuilt.

  post-link                    first coverage of the subcommand at all
  local-vs-export              local symbols must not match exports
  symvers-parse-error          Module.symvers parse error line numbers
  checksum-debug               the --debug-checksum format klp-build reads
  function-removal             the "no correlation" path

local-vs-export tests the behavior of commit 86a697572c62 ("objtool/klp:
Don't match local symbols against exports"), and symvers-parse-error that
of commit 51c1de134863 ("objtool/klp: Fix line numbers in Module.symvers
parse errors").

Assisted-by: Claude:claude-opus-5
Signed-off-by: Song Liu <song@kernel.org>
---
 .../tests/generic/fixtures/function_removal.c | 25 ++++++++++
 .../tests/generic/test-checksum-debug.sh      | 49 +++++++++++++++++++
 .../tests/generic/test-function-removal.sh    | 34 +++++++++++++
 .../tests/generic/test-local-vs-export.sh     | 32 ++++++++++++
 tools/objtool/tests/generic/test-post-link.sh | 42 ++++++++++++++++
 .../tests/generic/test-symvers-parse-error.sh | 23 +++++++++
 6 files changed, 205 insertions(+)
 create mode 100644 tools/objtool/tests/generic/fixtures/function_removal.c
 create mode 100755 tools/objtool/tests/generic/test-checksum-debug.sh
 create mode 100755 tools/objtool/tests/generic/test-function-removal.sh
 create mode 100755 tools/objtool/tests/generic/test-local-vs-export.sh
 create mode 100755 tools/objtool/tests/generic/test-post-link.sh
 create mode 100755 tools/objtool/tests/generic/test-symvers-parse-error.sh

diff --git a/tools/objtool/tests/generic/fixtures/function_removal.c b/tools/objtool/tests/generic/fixtures/function_removal.c
new file mode 100644
index 000000000000..d65ff604c2c5
--- /dev/null
+++ b/tools/objtool/tests/generic/fixtures/function_removal.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * A function the patch deletes, along with its only caller's use of it.  The
+ * original has a symbol which the patched object simply does not, so there is
+ * nothing to correlate it against.
+ */
+
+static const char __modinfo[]
+	__attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux";
+
+#ifndef PATCHED
+int going_away(int x)
+{
+	return x + 7;
+}
+#endif
+
+int caller(int x)
+{
+#ifdef PATCHED
+	return x + 1;
+#else
+	return going_away(x);
+#endif
+}
diff --git a/tools/objtool/tests/generic/test-checksum-debug.sh b/tools/objtool/tests/generic/test-checksum-debug.sh
new file mode 100755
index 000000000000..78856b191636
--- /dev/null
+++ b/tools/objtool/tests/generic/test-checksum-debug.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# "klp checksum --debug-checksum" prints a per-instruction checksum stream,
+# and klp-build -f (--show-first-changed) parses it to report where a function
+# first differs between the original and patched builds.
+#
+# It is a debugging aid, so nothing fails when it breaks: klp-build greps the
+# stream, and an unmatched grep just yields no output, which reads as "no
+# instruction changed".  That is exactly how the format drifted out from under
+# it once already.  Pin the shape klp-build depends on:
+#
+#   DEBUG: <object>: checksum: <func>(): <sym>+0x<offset> <16 hex digits>
+#
+# and that --dry-run leaves the object alone, since klp-build runs this against
+# objects it is going to checksum again for real.
+
+. "$(dirname "$0")/../lib.sh"
+
+setup
+build_pair basic.c
+
+before="$(md5sum < "$workdir/orig.o")"
+
+"$OBJTOOL" klp checksum --dry-run --debug-checksum=changed \
+	"$workdir/orig.o" > "$workdir/debug.log" 2>&1 ||
+	fail "klp checksum --debug-checksum failed"
+
+# --dry-run has to mean it: klp-build checksums these objects again afterwards,
+# and "already has .discard.sym_checksum, skipping" would lose the real run.
+[ "$(md5sum < "$workdir/orig.o")" = "$before" ] ||
+	fail "--dry-run modified the object"
+has_input_section orig.o .discard.sym_checksum &&
+	fail "--dry-run created .discard.sym_checksum"
+
+grep -qE '^DEBUG: .*: checksum: changed\(\): [^ ]+\+0x[0-9a-f]+ [0-9a-f]{16}$' \
+	"$workdir/debug.log" ||
+	fail "unexpected --debug-checksum format: $(head -1 "$workdir/debug.log")"
+
+# This is the pattern klp-build greps with.  Keep it working verbatim.
+grep -qE "^DEBUG: .*checksum: changed\(\): " "$workdir/debug.log" ||
+	fail "klp-build's --show-first-changed pattern no longer matches"
+
+# Only the requested function, or klp-build attributes instructions to the
+# wrong one.
+grep -qE 'checksum: untouched\(\)' "$workdir/debug.log" &&
+	fail "--debug-checksum=changed also dumped untouched()"
+
+pass "--debug-checksum format is the one klp-build -f parses"
diff --git a/tools/objtool/tests/generic/test-function-removal.sh b/tools/objtool/tests/generic/test-function-removal.sh
new file mode 100755
index 000000000000..df76e81e3936
--- /dev/null
+++ b/tools/objtool/tests/generic/test-function-removal.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# A patch which deletes a function leaves a symbol in the original with no
+# counterpart in the patched object.  klp diff cannot correlate it, and must
+# say so and carry on: livepatching cannot remove code from a running kernel,
+# so what matters is that the surviving caller is patched and the deleted
+# function is not dragged into the patch module.
+#
+# Cloning it would be worse than useless -- dead code in the patch, plus
+# whatever it references, resolved against a kernel where it may not exist.
+
+. "$(dirname "$0")/../lib.sh"
+
+setup
+build_pair function_removal.c
+
+# One-sided by construction: present in the original, gone from the patched.
+has_input_symbol orig.o going_away ||
+	fail "fixture has no going_away in the original"
+has_input_symbol patched.o going_away &&
+	fail "fixture still has going_away in the patched object"
+
+run_diff
+
+assert_diff_log 'no correlation: going_away'
+
+# The caller changed, so it is patched ...
+assert_patched caller
+# ... and the deleted function comes along in no form at all.
+assert_not_patched going_away
+assert_no_symbol going_away
+
+pass "deleted function reported as uncorrelated and left out of the patch"
diff --git a/tools/objtool/tests/generic/test-local-vs-export.sh b/tools/objtool/tests/generic/test-local-vs-export.sh
new file mode 100755
index 000000000000..5b91101dadd6
--- /dev/null
+++ b/tools/objtool/tests/generic/test-local-vs-export.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# find_export() matched on symbol name alone, so a static function or variable
+# sharing a name with an export was mistaken for a reference to that export.
+# For a vmlinux export that means no klp relocation at all: the normal
+# relocation left behind is resolved by the module loader to the vmlinux
+# symbol, and the patched code quietly reads and writes the wrong object.
+#
+# Exports are always global, so a local symbol is never one.
+
+. "$(dirname "$0")/../lib.sh"
+
+setup
+build_pair static_local.c
+
+# The static the fixture uses.  Compilers mangle statics variously -- gcc says
+# counter.0, clang says target.counter -- so find what this one produced rather
+# than assuming a shape.
+local_sym="$(in_symbols orig.o |
+	awk '$4 == "OBJECT" && $5 == "LOCAL" && $8 ~ /counter/ { print $8; exit }')"
+[ -n "$local_sym" ] ||
+	fail "fixture produced no local 'counter' symbol"
+
+# Contrive the collision: something else exports that same name.
+export_syms "$local_sym" counter
+run_diff
+
+# Still treated as the local it is, not as the export.
+assert_klp_sym "$local_sym" vmlinux
+
+pass "local symbol not mistaken for an export of the same name"
diff --git a/tools/objtool/tests/generic/test-post-link.sh b/tools/objtool/tests/generic/test-post-link.sh
new file mode 100755
index 000000000000..a6d40ae1b18d
--- /dev/null
+++ b/tools/objtool/tests/generic/test-post-link.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# klp post-link converts the intermediate __klp_relocs.* sections into the
+# .klp.rela.* form the kernel applies at patch load.  Getting this wrong is
+# invisible at build time: the module links and loads, and the relocations are
+# simply never applied.
+
+. "$(dirname "$0")/../lib.sh"
+
+setup
+build_pair static_local.c
+
+# An unexported symbol is what produces a klp relocation in the first place.
+# The static local is renamed by the compiler -- counter.0 with gcc -- so the
+# fixture's premise is that some local of that shape exists, not that a symbol
+# called "counter" does.  Find it first; everything below names it.
+local_sym="$(in_symbols orig.o |
+	     awk '$4 == "OBJECT" && $5 == "LOCAL" && $8 ~ /counter/ { print $8; exit }')"
+[ -n "$local_sym" ] || fail "fixture produced no local 'counter' symbol"
+
+run_diff
+assert_section __klp_relocs.vmlinux
+
+# Nothing has converted them yet.
+assert_no_section ".klp.rela.vmlinux..text.target"
+
+# The original relocation is neutralised by pointing it at a tombstone, which
+# is what stops the module loader resolving it behind livepatch's back.
+#
+# Compilers mangle a static local differently -- gcc says counter.0, clang
+# target.counter -- so find what this one produced rather than assuming.
+assert_tombstone "$local_sym"
+
+run_post_link
+
+# One .klp.rela section per base section, carrying SHF_RELA_LIVEPATCH, against
+# a symbol in SHN_LIVEPATCH for the kernel to resolve.
+assert_klp_rela vmlinux .text.target
+assert_livepatch_sym "$local_sym"
+
+pass "klp relocations converted to .klp.rela with SHN_LIVEPATCH symbols"
diff --git a/tools/objtool/tests/generic/test-symvers-parse-error.sh b/tools/objtool/tests/generic/test-symvers-parse-error.sh
new file mode 100755
index 000000000000..d597f28e5617
--- /dev/null
+++ b/tools/objtool/tests/generic/test-symvers-parse-error.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+#
+# A malformed Module.symvers has to be reported against the line it is on.
+# Module.symvers has tens of thousands of lines and is generated, so a wrong
+# line number sends whoever has to fix it to the wrong place, and "line 1" is
+# wrong in a way that looks plausible.
+
+. "$(dirname "$0")/../lib.sh"
+
+setup
+build_pair basic.c
+
+# Three well-formed lines, then one with no tabs at all.
+export_syms a b c
+echo 'this line has no fields' >> "$workdir/Module.symvers"
+
+run_diff 255
+
+assert_diff_log 'malformed Module.symvers'
+assert_diff_log 'at line 4'
+
+pass "malformed Module.symvers reported against the offending line"
-- 
2.53.0-Meta


  parent reply	other threads:[~2026-09-15 23:37 UTC|newest]

Thread overview: 69+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-15 23:33 [PATCH v4 00/58] Unit test framework for klp-build toolchain Song Liu
2026-09-15 23:33 ` [PATCH v4 01/58] objtool: Add test harness for the klp subcommands Song Liu
2026-09-15 23:33 ` [PATCH v4 02/58] objtool/klp: Check the klp test environment once, before any test Song Liu
2026-09-15 23:33 ` [PATCH v4 03/58] objtool/klp: Group the klp tests by architecture Song Liu
2026-09-15 23:34 ` [PATCH v4 04/58] objtool/klp: Classify klp test outcomes Song Liu
2026-09-15 23:34 ` [PATCH v4 05/58] objtool/klp: Build klp test fixtures through the harness Song Liu
2026-09-15 23:34 ` [PATCH v4 06/58] objtool/klp: Grow the klp test harness vocabulary Song Liu
2026-09-15 23:50   ` sashiko-bot
2026-09-16 17:33     ` Song Liu
2026-09-15 23:34 ` [PATCH v4 07/58] objtool/klp: Give each run one working directory, one per test inside it Song Liu
2026-09-15 23:34 ` [PATCH v4 08/58] objtool/klp: Run the klp tests under set -u Song Liu
2026-09-15 23:34 ` [PATCH v4 09/58] objtool/klp: Document the klp test harness Song Liu
2026-09-15 23:34 ` [PATCH v4 10/58] objtool: Keep failing test workdirs by default Song Liu
2026-09-15 23:34 ` [PATCH v4 11/58] objtool: Forward toolchain variables to the klp test runner Song Liu
2026-09-15 23:34 ` [PATCH v4 12/58] objtool/klp: Add test for rejecting changed data Song Liu
2026-09-15 23:34 ` [PATCH v4 13/58] objtool/klp: Add test for newly introduced data Song Liu
2026-09-15 23:34 ` [PATCH v4 14/58] objtool/klp: Add test for newly introduced functions Song Liu
2026-09-15 23:34 ` [PATCH v4 15/58] objtool/klp: Add test for static local correlation Song Liu
2026-09-15 23:46   ` sashiko-bot
2026-09-16 17:45     ` Song Liu
2026-09-15 23:34 ` [PATCH v4 16/58] objtool/klp: Add test for cold function halves Song Liu
2026-09-15 23:34 ` [PATCH v4 17/58] objtool/klp: Add test for special section extraction Song Liu
2026-09-15 23:34 ` [PATCH v4 18/58] objtool/klp: Add test for selective " Song Liu
2026-09-15 23:34 ` [PATCH v4 19/58] objtool/klp: Add test for jump table key relocations Song Liu
2026-09-15 23:34 ` [PATCH v4 20/58] objtool/klp: Add test for rejecting module-owned static branch keys Song Liu
2026-09-15 23:34 ` [PATCH v4 21/58] objtool/klp: Add test for rejecting module-owned static call keys Song Liu
2026-09-15 23:34 ` [PATCH v4 22/58] objtool/klp: Add test for symids in discarded sections Song Liu
2026-09-15 23:34 ` [PATCH v4 23/58] objtool/klp: Add test for rejecting references to init code/data Song Liu
2026-09-15 23:34 ` [PATCH v4 24/58] objtool/klp: Add test for correlation across ThinLTO name mangling Song Liu
2026-09-15 23:34 ` [PATCH v4 25/58] objtool/klp: Add test for objects without .modinfo Song Liu
2026-09-15 23:34 ` [PATCH v4 26/58] objtool/klp: Add test for unchecksummed input Song Liu
2026-09-15 23:34 ` Song Liu [this message]
2026-09-15 23:34 ` [PATCH v4 28/58] objtool/klp: Add test for klp reloc section naming in module objects Song Liu
2026-09-15 23:34 ` [PATCH v4 29/58] objtool/klp: Add test for vmlinux relocs in a patched module Song Liu
2026-09-15 23:34 ` [PATCH v4 30/58] objtool/klp: Add test for Module.symvers path normalization Song Liu
2026-09-15 23:34 ` [PATCH v4 31/58] objtool/klp: Add test for the contents of the klp_funcs list Song Liu
2026-09-15 23:34 ` [PATCH v4 32/58] objtool/klp: Add test for EXPORT_SYMBOL_FOR_MODULES references Song Liu
2026-09-15 23:34 ` [PATCH v4 33/58] objtool/klp: Add test for new references to exported symbols Song Liu
2026-09-15 23:48   ` sashiko-bot
2026-09-16 17:40     ` Song Liu
2026-09-15 23:34 ` [PATCH v4 34/58] objtool/klp: Add test for empty x86 alternative replacements Song Liu
2026-09-15 23:34 ` [PATCH v4 35/58] objtool/klp: Add test for recorded checksum values Song Liu
2026-09-15 23:34 ` [PATCH v4 36/58] objtool/klp: Add test for position-independent checksums Song Liu
2026-09-15 23:34 ` [PATCH v4 37/58] objtool/klp: Add test for sympos in module objects Song Liu
2026-09-15 23:34 ` [PATCH v4 38/58] objtool/klp: Add test for sympos resolved against a linked vmlinux Song Liu
2026-09-15 23:34 ` [PATCH v4 39/58] objtool/klp: Add test for static locals which must not be correlated Song Liu
2026-09-15 23:51   ` sashiko-bot
2026-09-16 17:51     ` Song Liu
2026-09-15 23:34 ` [PATCH v4 40/58] objtool/klp: Add test for __bug_table, __ex_table and __mcount_loc extraction Song Liu
2026-09-15 23:34 ` [PATCH v4 41/58] objtool/klp: Add test for kCFI prefix symbols and traps Song Liu
2026-09-15 23:34 ` [PATCH v4 42/58] objtool/klp: Add test for symbols whose linkage the patch changes Song Liu
2026-09-15 23:34 ` [PATCH v4 43/58] objtool/klp: Test rejection of a file-local static branch key Song Liu
2026-09-15 23:34 ` [PATCH v4 44/58] objtool/klp: Test a hand-built livepatch module's static call keys Song Liu
2026-09-15 23:34 ` [PATCH v4 45/58] objtool/klp: Test text annotations on alternative replacements Song Liu
2026-09-15 23:34 ` [PATCH v4 46/58] objtool/klp: Add test for data object checksums Song Liu
2026-09-15 23:53   ` sashiko-bot
2026-09-16  7:00     ` Song Liu
2026-09-15 23:34 ` [PATCH v4 47/58] objtool/klp: Add test for symbols with no checksum entry of their own Song Liu
2026-09-15 23:34 ` [PATCH v4 48/58] objtool/klp: Add test for a static branch introduced by the patch Song Liu
2026-09-15 23:34 ` [PATCH v4 49/58] objtool/klp: Add test for tracepoint and pr_debug static branch keys Song Liu
2026-09-15 23:34 ` [PATCH v4 50/58] objtool/klp: Add test for a static call introduced by the patch Song Liu
2026-09-15 23:34 ` [PATCH v4 51/58] objtool/klp: Add test for instruction operand checksums Song Liu
2026-09-15 23:34 ` [PATCH v4 52/58] objtool/klp: Add test for alternative replacement code in checksums Song Liu
2026-09-15 23:34 ` [PATCH v4 53/58] objtool/klp: Add test for the alignment of cloned data sections Song Liu
2026-09-15 23:34 ` [PATCH v4 54/58] objtool/klp: Add test for a patch which strips a data annotation Song Liu
2026-09-15 23:34 ` [PATCH v4 55/58] objtool/klp: Add test for absolute and __ADDRESSABLE symbols Song Liu
2026-09-15 23:34 ` [PATCH v4 56/58] objtool/klp: Add test for UBSAN metadata in an unchanged function Song Liu
2026-09-15 23:34 ` [PATCH v4 57/58] objtool/klp: Add test for Clang switch jump tables Song Liu
2026-09-15 23:34 ` [PATCH v4 58/58] objtool/klp: Add test for ThinLTO symbols sharing a demangled name Song Liu

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=20260915233454.2405019-28-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 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.