Live Patching
 help / color / mirror / Atom feed
* [PATCH 2/2] selftests: livepatch: functions.sh: Workaround heredoc on older bash
From: Marcos Paulo de Souza @ 2026-02-20 14:12 UTC (permalink / raw)
  To: Josh Poimboeuf, Jiri Kosina, Miroslav Benes, Petr Mladek,
	Joe Lawrence, Shuah Khan
  Cc: live-patching, linux-kselftest, linux-kernel,
	Marcos Paulo de Souza
In-Reply-To: <20260220-lp-test-trace-v1-0-4b6703cd01a6@suse.com>

When running current selftests on older distributions like SLE12-SP5 that
contains an older bash trips over heredoc. Convert it to plain echo
calls, which ends up with the same result.

Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
---
 tools/testing/selftests/livepatch/functions.sh | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/livepatch/functions.sh b/tools/testing/selftests/livepatch/functions.sh
index 8ec0cb64ad94..45ed04c6296e 100644
--- a/tools/testing/selftests/livepatch/functions.sh
+++ b/tools/testing/selftests/livepatch/functions.sh
@@ -96,10 +96,8 @@ function pop_config() {
 }
 
 function set_dynamic_debug() {
-        cat <<-EOF > "$SYSFS_DEBUG_DIR/dynamic_debug/control"
-		file kernel/livepatch/* +p
-		func klp_try_switch_task -p
-		EOF
+	echo "file kernel/livepatch/* +p" > "$SYSFS_DEBUG_DIR/dynamic_debug/control"
+	echo "func klp_try_switch_task -p" > "$SYSFS_DEBUG_DIR/dynamic_debug/control"
 }
 
 function set_ftrace_enabled() {

-- 
2.52.0


^ permalink raw reply related

* [PATCH 1/2] selftests: livepatch: test-ftrace: livepatch a traced function
From: Marcos Paulo de Souza @ 2026-02-20 14:12 UTC (permalink / raw)
  To: Josh Poimboeuf, Jiri Kosina, Miroslav Benes, Petr Mladek,
	Joe Lawrence, Shuah Khan
  Cc: live-patching, linux-kselftest, linux-kernel,
	Marcos Paulo de Souza
In-Reply-To: <20260220-lp-test-trace-v1-0-4b6703cd01a6@suse.com>

This is basically the inverse case of commit 474eecc882ae
("selftests: livepatch: test if ftrace can trace a livepatched function")
but ensuring that livepatch would work on a traced function.

Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
---
 tools/testing/selftests/livepatch/test-ftrace.sh | 36 ++++++++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/tools/testing/selftests/livepatch/test-ftrace.sh b/tools/testing/selftests/livepatch/test-ftrace.sh
index 094176f1a46a..c6222cc037c5 100755
--- a/tools/testing/selftests/livepatch/test-ftrace.sh
+++ b/tools/testing/selftests/livepatch/test-ftrace.sh
@@ -95,4 +95,40 @@ livepatch: '$MOD_LIVEPATCH': completing unpatching transition
 livepatch: '$MOD_LIVEPATCH': unpatching complete
 % rmmod $MOD_LIVEPATCH"
 
+
+# - trace a function
+# - verify livepatch can load targgeting no the same traced function
+# - check if the livepatch is in effect
+# - reset trace and unload livepatch
+
+start_test "livepatch a traced function and check that the live patch remains in effect"
+
+FUNCTION_NAME="cmdline_proc_show"
+
+trace_function "$FUNCTION_NAME"
+load_lp $MOD_LIVEPATCH
+
+if [[ "$(cat /proc/cmdline)" == "$MOD_LIVEPATCH: this has been live patched" ]] ; then
+	log "livepatch: ok"
+fi
+
+check_traced_functions "$FUNCTION_NAME"
+
+disable_lp $MOD_LIVEPATCH
+unload_lp $MOD_LIVEPATCH
+
+check_result "% insmod test_modules/$MOD_LIVEPATCH.ko
+livepatch: enabling patch '$MOD_LIVEPATCH'
+livepatch: '$MOD_LIVEPATCH': initializing patching transition
+livepatch: '$MOD_LIVEPATCH': starting patching transition
+livepatch: '$MOD_LIVEPATCH': completing patching transition
+livepatch: '$MOD_LIVEPATCH': patching complete
+livepatch: ok
+% echo 0 > $SYSFS_KLP_DIR/$MOD_LIVEPATCH/enabled
+livepatch: '$MOD_LIVEPATCH': initializing unpatching transition
+livepatch: '$MOD_LIVEPATCH': starting unpatching transition
+livepatch: '$MOD_LIVEPATCH': completing unpatching transition
+livepatch: '$MOD_LIVEPATCH': unpatching complete
+% rmmod $MOD_LIVEPATCH"
+
 exit 0

-- 
2.52.0


^ permalink raw reply related

* [PATCH 0/2] kselftests: livepatch: One new test and one fix for older bash
From: Marcos Paulo de Souza @ 2026-02-20 14:12 UTC (permalink / raw)
  To: Josh Poimboeuf, Jiri Kosina, Miroslav Benes, Petr Mladek,
	Joe Lawrence, Shuah Khan
  Cc: live-patching, linux-kselftest, linux-kernel,
	Marcos Paulo de Souza

I found the bash issue when running this new test on a SLE12-SP5. There
are still other issues that would need to be addressed, but with this
change, test-ftrace.sh can run on SLE12-SP5 withou issues.

Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
---
Marcos Paulo de Souza (2):
      selftests: livepatch: test-ftrace: livepatch a traced function
      selftests: livepatch: functions.sh: Workaround heredoc on older bash

 tools/testing/selftests/livepatch/functions.sh   |  6 ++--
 tools/testing/selftests/livepatch/test-ftrace.sh | 36 ++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 4 deletions(-)
---
base-commit: 6d6ad32e22f028c525d5df471c5522616e645a6b
change-id: 20260220-lp-test-trace-73b2f607960a

Best regards,
--  
Marcos Paulo de Souza <mpdesouza@suse.com>


^ permalink raw reply

* [PATCH v2 8/8] livepatch: Add tests for klp-build toolchain
From: Song Liu @ 2026-02-19 22:22 UTC (permalink / raw)
  To: live-patching
  Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
	Song Liu
In-Reply-To: <20260219222239.3650400-1-song@kernel.org>

Add selftests for the klp-build toolchain. This includes kernel side test
code and .patch files. The tests cover both livepatch to vmlinux and kernel
modules.

Check tools/testing/selftests/livepatch/test_patches/README for
instructions to run these tests.

Signed-off-by: Song Liu <song@kernel.org>

---

AI was used to wrote the test code and .patch files in this.
---
 kernel/livepatch/Kconfig                      |  20 +++
 kernel/livepatch/Makefile                     |   2 +
 kernel/livepatch/tests/Makefile               |   6 +
 kernel/livepatch/tests/klp_test_module.c      | 111 ++++++++++++++
 kernel/livepatch/tests/klp_test_module.h      |   8 +
 kernel/livepatch/tests/klp_test_vmlinux.c     | 138 ++++++++++++++++++
 kernel/livepatch/tests/klp_test_vmlinux.h     |  16 ++
 kernel/livepatch/tests/klp_test_vmlinux_aux.c |  59 ++++++++
 .../selftests/livepatch/test_patches/README   |  15 ++
 .../test_patches/klp_test_hash_change.patch   |  30 ++++
 .../test_patches/klp_test_module.patch        |  18 +++
 .../klp_test_nonstatic_to_static.patch        |  40 +++++
 .../klp_test_static_to_nonstatic.patch        |  39 +++++
 .../test_patches/klp_test_vmlinux.patch       |  18 +++
 14 files changed, 520 insertions(+)
 create mode 100644 kernel/livepatch/tests/Makefile
 create mode 100644 kernel/livepatch/tests/klp_test_module.c
 create mode 100644 kernel/livepatch/tests/klp_test_module.h
 create mode 100644 kernel/livepatch/tests/klp_test_vmlinux.c
 create mode 100644 kernel/livepatch/tests/klp_test_vmlinux.h
 create mode 100644 kernel/livepatch/tests/klp_test_vmlinux_aux.c
 create mode 100644 tools/testing/selftests/livepatch/test_patches/README
 create mode 100644 tools/testing/selftests/livepatch/test_patches/klp_test_hash_change.patch
 create mode 100644 tools/testing/selftests/livepatch/test_patches/klp_test_module.patch
 create mode 100644 tools/testing/selftests/livepatch/test_patches/klp_test_nonstatic_to_static.patch
 create mode 100644 tools/testing/selftests/livepatch/test_patches/klp_test_static_to_nonstatic.patch
 create mode 100644 tools/testing/selftests/livepatch/test_patches/klp_test_vmlinux.patch

diff --git a/kernel/livepatch/Kconfig b/kernel/livepatch/Kconfig
index 4c0a9c18d0b2..852049601389 100644
--- a/kernel/livepatch/Kconfig
+++ b/kernel/livepatch/Kconfig
@@ -30,3 +30,23 @@ config KLP_BUILD
 	select OBJTOOL
 	help
 	  Enable klp-build support
+
+config KLP_TEST
+	bool "Livepatch test code"
+	depends on LIVEPATCH
+	help
+	  Dummy kernel code for testing the klp-build livepatch toolchain.
+	  Provides built-in vmlinux functions with sysfs interfaces for
+	  verifying livepatches.
+
+	  If unsure, say N.
+
+config KLP_TEST_MODULE
+	tristate "Livepatch test module (klp_test_module)"
+	depends on KLP_TEST && m
+	help
+	  Test module for livepatch testing. Dummy kernel module for
+	  testing the klp-build toolchain. Provides sysfs interfaces for
+	  verifying livepatches.
+
+	  If unsure, say N.
diff --git a/kernel/livepatch/Makefile b/kernel/livepatch/Makefile
index cf03d4bdfc66..751080a62cec 100644
--- a/kernel/livepatch/Makefile
+++ b/kernel/livepatch/Makefile
@@ -2,3 +2,5 @@
 obj-$(CONFIG_LIVEPATCH) += livepatch.o
 
 livepatch-objs := core.o patch.o shadow.o state.o transition.o
+
+obj-$(CONFIG_KLP_TEST) += tests/
diff --git a/kernel/livepatch/tests/Makefile b/kernel/livepatch/tests/Makefile
new file mode 100644
index 000000000000..82ae48f54abe
--- /dev/null
+++ b/kernel/livepatch/tests/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-y                           += klp_test_vmlinux_all.o
+obj-$(CONFIG_KLP_TEST_MODULE)   += klp_test_module.o
+
+klp_test_vmlinux_all-y := klp_test_vmlinux.o \
+			   klp_test_vmlinux_aux.o
diff --git a/kernel/livepatch/tests/klp_test_module.c b/kernel/livepatch/tests/klp_test_module.c
new file mode 100644
index 000000000000..25cefbe36a2b
--- /dev/null
+++ b/kernel/livepatch/tests/klp_test_module.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * klp_test_module.c - Single-file test module for livepatch/klp-build testing
+ *
+ * Copyright (C) 2026 Meta Platforms, Inc. and affiliates.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/string.h>
+#include "klp_test_module.h"
+#include "klp_test_vmlinux.h"
+
+static int klp_test_module_var1;
+static int klp_test_module_var2;
+
+static noinline ssize_t __klp_test_module_func1(char *buf, int len)
+{
+	ssize_t ret = 0;
+	int i;
+
+	for (i = 0; i < len; i++)
+		klp_test_module_var1 += i;
+
+	if (klp_test_module_var1 > 1000)
+		klp_test_module_var1 = 0;
+
+	ret = sysfs_emit(buf, "klp_test_module_func1 unpatched %d\n",
+			 klp_test_module_var1);
+	return ret;
+}
+
+ssize_t klp_test_module_func1(char *buf, int len)
+{
+	return __klp_test_module_func1(buf, len);
+}
+EXPORT_SYMBOL_GPL(klp_test_module_func1);
+
+static noinline ssize_t __klp_test_module_func2(char *buf, int len)
+{
+	ssize_t ret = 0;
+	int i;
+
+	for (i = 0; i < len; i++)
+		klp_test_module_var2 += i * 2;
+
+	if (klp_test_module_var2 > 1000)
+		klp_test_module_var2 = 0;
+
+	ret = sysfs_emit(buf, "klp_test_module_func2 unpatched %d\n",
+			 klp_test_module_var2);
+	return ret;
+}
+
+ssize_t klp_test_module_func2(char *buf, int len)
+{
+	return __klp_test_module_func2(buf, len);
+}
+EXPORT_SYMBOL_GPL(klp_test_module_func2);
+
+static ssize_t func1_show(struct kobject *kobj,
+			   struct kobj_attribute *attr, char *buf)
+{
+	return klp_test_module_func1(buf, 5);
+}
+
+static ssize_t func2_show(struct kobject *kobj,
+			   struct kobj_attribute *attr, char *buf)
+{
+	return klp_test_module_func2(buf, 5);
+}
+
+static struct kobj_attribute func1_attr = __ATTR_RO(func1);
+static struct kobj_attribute func2_attr = __ATTR_RO(func2);
+
+static struct attribute *klp_test_module_attrs[] = {
+	&func1_attr.attr,
+	&func2_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group klp_test_module_attr_group = {
+	.attrs = klp_test_module_attrs,
+};
+
+static struct kobject *klp_test_module_kobj;
+
+static int __init klp_test_module_init(void)
+{
+	klp_test_module_kobj = kobject_create_and_add("module",
+						      klp_test_kobj);
+	if (!klp_test_module_kobj)
+		return -ENOMEM;
+
+	return sysfs_create_group(klp_test_module_kobj,
+				  &klp_test_module_attr_group);
+}
+
+static void __exit klp_test_module_exit(void)
+{
+	sysfs_remove_group(klp_test_module_kobj, &klp_test_module_attr_group);
+	kobject_put(klp_test_module_kobj);
+}
+
+module_init(klp_test_module_init);
+module_exit(klp_test_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Livepatch single-file test module");
diff --git a/kernel/livepatch/tests/klp_test_module.h b/kernel/livepatch/tests/klp_test_module.h
new file mode 100644
index 000000000000..56a766f4744b
--- /dev/null
+++ b/kernel/livepatch/tests/klp_test_module.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _KLP_TEST_MODULE_H
+#define _KLP_TEST_MODULE_H
+
+ssize_t klp_test_module_func1(char *buf, int len);
+ssize_t klp_test_module_func2(char *buf, int len);
+
+#endif /* _KLP_TEST_MODULE_H */
diff --git a/kernel/livepatch/tests/klp_test_vmlinux.c b/kernel/livepatch/tests/klp_test_vmlinux.c
new file mode 100644
index 000000000000..bd4157ea97c0
--- /dev/null
+++ b/kernel/livepatch/tests/klp_test_vmlinux.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * klp_test_vmlinux.c - Dummy built-in code for livepatch/klp-build testing
+ *
+ * Copyright (C) 2026 Meta Platforms, Inc. and affiliates.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include "klp_test_vmlinux.h"
+
+static int klp_test_vmlinux_var1;
+static int klp_test_vmlinux_var2;
+
+static noinline int __helper(int x, int len)
+{
+	int i, sum = x;
+
+	for (i = 0; i < len; i++)
+		sum += i + 5;
+	if (sum > 1000)
+		sum = 0;
+	return sum;
+}
+
+static noinline ssize_t __klp_test_vmlinux_func1(char *buf, int len)
+{
+	ssize_t ret = 0;
+
+	klp_test_vmlinux_var1 = __helper(klp_test_vmlinux_var1, len);
+
+	ret = sysfs_emit(buf, "klp_test_vmlinux_func1 unpatched %d\n",
+			 klp_test_vmlinux_var1);
+	return ret;
+}
+
+ssize_t klp_test_vmlinux_func1(char *buf, int len)
+{
+	return __klp_test_vmlinux_func1(buf, len);
+}
+EXPORT_SYMBOL_GPL(klp_test_vmlinux_func1);
+
+static noinline ssize_t __klp_test_vmlinux_func2(char *buf, int len)
+{
+	ssize_t ret = 0;
+	int i;
+
+	for (i = 0; i < len; i++)
+		klp_test_vmlinux_var2 += i * 2;
+
+	if (klp_test_vmlinux_var2 > 1000)
+		klp_test_vmlinux_var2 = 0;
+
+	ret = sysfs_emit(buf, "klp_test_vmlinux_func2 unpatched %d\n",
+			 klp_test_vmlinux_var2);
+	return ret;
+}
+
+ssize_t klp_test_vmlinux_func2(char *buf, int len)
+{
+	return __klp_test_vmlinux_func2(buf, len);
+}
+EXPORT_SYMBOL_GPL(klp_test_vmlinux_func2);
+
+static ssize_t vmlinux_func1_show(struct kobject *kobj,
+				   struct kobj_attribute *attr, char *buf)
+{
+	return klp_test_vmlinux_func1(buf, 5);
+}
+
+static ssize_t vmlinux_func2_show(struct kobject *kobj,
+				   struct kobj_attribute *attr, char *buf)
+{
+	return klp_test_vmlinux_func2(buf, 5);
+}
+
+static struct kobj_attribute vmlinux_func1_attr = __ATTR_RO(vmlinux_func1);
+static struct kobj_attribute vmlinux_func2_attr = __ATTR_RO(vmlinux_func2);
+
+static struct attribute *klp_test_attrs[] = {
+	&vmlinux_func1_attr.attr,
+	&vmlinux_func2_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group klp_test_attr_group = {
+	.attrs = klp_test_attrs,
+};
+
+static struct kobject *klp_test_vmlinux_kobj;
+struct kobject *klp_test_kobj;
+EXPORT_SYMBOL_GPL(klp_test_kobj);
+
+static int __init klp_test_vmlinux_init(void)
+{
+	int ret;
+
+	klp_test_kobj = kobject_create_and_add("klp_test", kernel_kobj);
+	if (!klp_test_kobj)
+		return -ENOMEM;
+
+	klp_test_vmlinux_kobj = kobject_create_and_add("vmlinux", klp_test_kobj);
+	if (!klp_test_vmlinux_kobj) {
+		kobject_put(klp_test_kobj);
+		return -ENOMEM;
+	}
+
+	ret = sysfs_create_group(klp_test_vmlinux_kobj, &klp_test_attr_group);
+	if (ret)
+		goto err_group;
+
+	ret = klp_test_vmlinux_aux_init(klp_test_vmlinux_kobj);
+	if (ret)
+		goto err_aux;
+
+	return 0;
+
+err_aux:
+	sysfs_remove_group(klp_test_vmlinux_kobj, &klp_test_attr_group);
+err_group:
+	kobject_put(klp_test_vmlinux_kobj);
+	kobject_put(klp_test_kobj);
+	return ret;
+}
+
+static void __exit klp_test_vmlinux_exit(void)
+{
+	klp_test_vmlinux_aux_exit(klp_test_vmlinux_kobj);
+	sysfs_remove_group(klp_test_vmlinux_kobj, &klp_test_attr_group);
+	kobject_put(klp_test_vmlinux_kobj);
+	kobject_put(klp_test_kobj);
+}
+
+late_initcall(klp_test_vmlinux_init);
diff --git a/kernel/livepatch/tests/klp_test_vmlinux.h b/kernel/livepatch/tests/klp_test_vmlinux.h
new file mode 100644
index 000000000000..56d9f7b6d350
--- /dev/null
+++ b/kernel/livepatch/tests/klp_test_vmlinux.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _KLP_TEST_VMLINUX_H
+#define _KLP_TEST_VMLINUX_H
+
+#include <linux/kobject.h>
+
+extern struct kobject *klp_test_kobj;
+
+ssize_t klp_test_vmlinux_func1(char *buf, int len);
+ssize_t klp_test_vmlinux_func2(char *buf, int len);
+ssize_t klp_test_vmlinux_func3(char *buf, int len);
+
+int klp_test_vmlinux_aux_init(struct kobject *parent);
+void klp_test_vmlinux_aux_exit(struct kobject *parent);
+
+#endif /* _KLP_TEST_VMLINUX_H */
diff --git a/kernel/livepatch/tests/klp_test_vmlinux_aux.c b/kernel/livepatch/tests/klp_test_vmlinux_aux.c
new file mode 100644
index 000000000000..1d76b0308a11
--- /dev/null
+++ b/kernel/livepatch/tests/klp_test_vmlinux_aux.c
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * klp_test_vmlinux_aux.c - Auxiliary built-in code for livepatch/klp-build
+ *                          testing. This file has its own static __helper()
+ *                          to test ThinLTO .llvm.<hash> suffix handling.
+ *
+ * Copyright (C) 2026 Meta Platforms, Inc. and affiliates.
+ */
+
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+#include <linux/string.h>
+#include "klp_test_vmlinux.h"
+
+static int klp_test_vmlinux_var3;
+
+static noinline int __helper(int x, int len)
+{
+	int i, sum = x;
+
+	for (i = 0; i < len; i++)
+		sum += i + 10;
+	if (sum > 1000)
+		sum = 0;
+	return sum;
+}
+
+static noinline ssize_t __klp_test_vmlinux_func3(char *buf, int len)
+{
+	klp_test_vmlinux_var3 = __helper(klp_test_vmlinux_var3, len);
+
+	return sysfs_emit(buf, "klp_test_vmlinux_func3 unpatched %d\n",
+			 klp_test_vmlinux_var3);
+}
+
+ssize_t klp_test_vmlinux_func3(char *buf, int len)
+{
+	return __klp_test_vmlinux_func3(buf, len);
+}
+EXPORT_SYMBOL_GPL(klp_test_vmlinux_func3);
+
+static ssize_t vmlinux_func3_show(struct kobject *kobj,
+				   struct kobj_attribute *attr, char *buf)
+{
+	return klp_test_vmlinux_func3(buf, 5);
+}
+
+static struct kobj_attribute vmlinux_func3_attr = __ATTR_RO(vmlinux_func3);
+
+int klp_test_vmlinux_aux_init(struct kobject *parent)
+{
+	return sysfs_create_file(parent, &vmlinux_func3_attr.attr);
+}
+
+void klp_test_vmlinux_aux_exit(struct kobject *parent)
+{
+	sysfs_remove_file(parent, &vmlinux_func3_attr.attr);
+}
diff --git a/tools/testing/selftests/livepatch/test_patches/README b/tools/testing/selftests/livepatch/test_patches/README
new file mode 100644
index 000000000000..8266348aab57
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test_patches/README
@@ -0,0 +1,15 @@
+This is folder contains patches to test the klp-build toolchain.
+
+To run the test:
+
+1. Enable CONFIG_KLP_TEST and CONFIG_KLP_TEST_MODULE, and build the kernel.
+
+2. Build these patches with:
+
+  ./scripts/livepatch/klp-build tools/testing/selftests/livepatch/test_patches/*.patch
+
+3. Verify the correctness with:
+
+  modprobe klp_test_module
+  kpatch load livepatch-patch.ko
+  grep -q unpatched /sys/kernel/klp_test/*/* && echo FAIL || echo PASS
diff --git a/tools/testing/selftests/livepatch/test_patches/klp_test_hash_change.patch b/tools/testing/selftests/livepatch/test_patches/klp_test_hash_change.patch
new file mode 100644
index 000000000000..609d54d6d6f6
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test_patches/klp_test_hash_change.patch
@@ -0,0 +1,30 @@
+Test ThinLTO .llvm.<hash> suffix handling.
+
+Modify a static __helper() function whose body change causes its
+.llvm.<hash> suffix to change under ThinLTO. Both klp_test_vmlinux.c
+and klp_test_vmlinux_aux.c define static __helper() with different
+bodies, so ThinLTO promotes both to globals with different hashes.
+This patch changes the __helper() in the aux file, which changes its
+hash, and klp-build must correctly match the old and new symbols.
+
+diff --git i/kernel/livepatch/tests/klp_test_vmlinux_aux.c w/kernel/livepatch/tests/klp_test_vmlinux_aux.c
+--- i/kernel/livepatch/tests/klp_test_vmlinux_aux.c
++++ w/kernel/livepatch/tests/klp_test_vmlinux_aux.c
+@@ -20,7 +20,7 @@
+ 	int i, sum = x;
+ 
+ 	for (i = 0; i < len; i++)
+-		sum += i + 10;
++		sum += i * 2 + 10;
+ 	if (sum > 1000)
+ 		sum = 0;
+ 	return sum;
+@@ -30,7 +30,7 @@
+ {
+ 	klp_test_vmlinux_var3 = __helper(klp_test_vmlinux_var3, len);
+ 
+-	return sysfs_emit(buf, "klp_test_vmlinux_func3 unpatched %d\n",
++	return sysfs_emit(buf, "klp_test_vmlinux_func3 hash_patched %d\n",
+ 			 klp_test_vmlinux_var3);
+ }
+ 
diff --git a/tools/testing/selftests/livepatch/test_patches/klp_test_module.patch b/tools/testing/selftests/livepatch/test_patches/klp_test_module.patch
new file mode 100644
index 000000000000..d86e75618136
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test_patches/klp_test_module.patch
@@ -0,0 +1,18 @@
+Test basic module patching.
+
+Patch a loadable module function to verify that klp-build can generate
+a livepatch for module code. Changes __klp_test_module_func1() output
+from "unpatched" to "patched".
+
+diff --git i/kernel/livepatch/tests/klp_test_module.c w/kernel/livepatch/tests/klp_test_module.c
+--- i/kernel/livepatch/tests/klp_test_module.c
++++ w/kernel/livepatch/tests/klp_test_module.c
+@@ -27,7 +27,7 @@
+ 	if (klp_test_module_var1 > 1000)
+ 		klp_test_module_var1 = 0;
+ 
+-	ret = sysfs_emit(buf, "klp_test_module_func1 unpatched %d\n",
++	ret = sysfs_emit(buf, "klp_test_module_func1 patched %d\n",
+ 			 klp_test_module_var1);
+ 	return ret;
+ }
diff --git a/tools/testing/selftests/livepatch/test_patches/klp_test_nonstatic_to_static.patch b/tools/testing/selftests/livepatch/test_patches/klp_test_nonstatic_to_static.patch
new file mode 100644
index 000000000000..f26711c6bfac
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test_patches/klp_test_nonstatic_to_static.patch
@@ -0,0 +1,40 @@
+Test nonstatic-to-static symbol change.
+
+Change klp_test_module_func2() from nonstatic (global) to static and
+remove its EXPORT_SYMBOL_GPL. Also remove its declaration from the
+header file. This tests klp-build's ability to handle symbol visibility
+changes where a function that was originally global becomes static in
+the patched kernel.
+
+diff --git i/kernel/livepatch/tests/klp_test_module.c w/kernel/livepatch/tests/klp_test_module.c
+--- i/kernel/livepatch/tests/klp_test_module.c
++++ w/kernel/livepatch/tests/klp_test_module.c
+@@ -49,16 +49,15 @@
+ 	if (klp_test_module_var2 > 1000)
+ 		klp_test_module_var2 = 0;
+
+-	ret = sysfs_emit(buf, "klp_test_module_func2 unpatched %d\n",
++	ret = sysfs_emit(buf, "klp_test_module_func2 patched_nts %d\n",
+ 			 klp_test_module_var2);
+ 	return ret;
+ }
+
+-ssize_t klp_test_module_func2(char *buf, int len)
++static noinline ssize_t klp_test_module_func2(char *buf, int len)
+ {
+ 	return __klp_test_module_func2(buf, len);
+ }
+-EXPORT_SYMBOL_GPL(klp_test_module_func2);
+
+ static ssize_t func1_show(struct kobject *kobj,
+ 			   struct kobj_attribute *attr, char *buf)
+diff --git i/kernel/livepatch/tests/klp_test_module.h w/kernel/livepatch/tests/klp_test_module.h
+--- i/kernel/livepatch/tests/klp_test_module.h
++++ w/kernel/livepatch/tests/klp_test_module.h
+@@ -3,6 +3,5 @@
+ #define _KLP_TEST_MODULE_H
+
+ ssize_t klp_test_module_func1(char *buf, int len);
+-ssize_t klp_test_module_func2(char *buf, int len);
+
+ #endif /* _KLP_TEST_MODULE_H */
diff --git a/tools/testing/selftests/livepatch/test_patches/klp_test_static_to_nonstatic.patch b/tools/testing/selftests/livepatch/test_patches/klp_test_static_to_nonstatic.patch
new file mode 100644
index 000000000000..673f6c42f698
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test_patches/klp_test_static_to_nonstatic.patch
@@ -0,0 +1,39 @@
+Test static-to-nonstatic symbol change.
+
+Change __klp_test_vmlinux_func2() from static to nonstatic (global).
+This tests klp-build's ability to handle symbol visibility changes
+where a function that was originally static becomes globally visible
+in the patched kernel.
+
+diff --git i/kernel/livepatch/tests/klp_test_vmlinux.c w/kernel/livepatch/tests/klp_test_vmlinux.c
+--- i/kernel/livepatch/tests/klp_test_vmlinux.c
++++ w/kernel/livepatch/tests/klp_test_vmlinux.c
+@@ -44,7 +44,7 @@
+ }
+ EXPORT_SYMBOL_GPL(klp_test_vmlinux_func1);
+
+-static noinline ssize_t __klp_test_vmlinux_func2(char *buf, int len)
++noinline ssize_t __klp_test_vmlinux_func2(char *buf, int len)
+ {
+ 	ssize_t ret = 0;
+ 	int i;
+@@ -55,7 +55,7 @@
+ 	if (klp_test_vmlinux_var2 > 1000)
+ 		klp_test_vmlinux_var2 = 0;
+
+-	ret = sysfs_emit(buf, "klp_test_vmlinux_func2 unpatched %d\n",
++	ret = sysfs_emit(buf, "klp_test_vmlinux_func2 patched_stn %d\n",
+ 			 klp_test_vmlinux_var2);
+ 	return ret;
+ }
+diff --git i/kernel/livepatch/tests/klp_test_vmlinux.h w/kernel/livepatch/tests/klp_test_vmlinux.h
+--- i/kernel/livepatch/tests/klp_test_vmlinux.h
++++ w/kernel/livepatch/tests/klp_test_vmlinux.h
+@@ -9,6 +9,7 @@
+ ssize_t klp_test_vmlinux_func1(char *buf, int len);
+ ssize_t klp_test_vmlinux_func2(char *buf, int len);
+ ssize_t klp_test_vmlinux_func3(char *buf, int len);
++ssize_t __klp_test_vmlinux_func2(char *buf, int len);
+
+ int klp_test_vmlinux_aux_init(struct kobject *parent);
+ void klp_test_vmlinux_aux_exit(struct kobject *parent);
diff --git a/tools/testing/selftests/livepatch/test_patches/klp_test_vmlinux.patch b/tools/testing/selftests/livepatch/test_patches/klp_test_vmlinux.patch
new file mode 100644
index 000000000000..8b1d91381728
--- /dev/null
+++ b/tools/testing/selftests/livepatch/test_patches/klp_test_vmlinux.patch
@@ -0,0 +1,18 @@
+Test basic vmlinux patching.
+
+Patch a built-in vmlinux function to verify that klp-build can generate
+a livepatch for vmlinux code. Changes __klp_test_vmlinux_func1() output
+from "unpatched" to "patched".
+
+diff --git i/kernel/livepatch/tests/klp_test_vmlinux.c w/kernel/livepatch/tests/klp_test_vmlinux.c
+--- i/kernel/livepatch/tests/klp_test_vmlinux.c
++++ w/kernel/livepatch/tests/klp_test_vmlinux.c
+@@ -33,7 +33,7 @@
+ 
+ 	klp_test_vmlinux_var1 = __helper(klp_test_vmlinux_var1, len);
+ 
+-	ret = sysfs_emit(buf, "klp_test_vmlinux_func1 unpatched %d\n",
++	ret = sysfs_emit(buf, "klp_test_vmlinux_func1 patched %d\n",
+ 			 klp_test_vmlinux_var1);
+ 	return ret;
+ }
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 7/8] objtool/klp: Correlate locals to globals
From: Song Liu @ 2026-02-19 22:22 UTC (permalink / raw)
  To: live-patching
  Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
	Song Liu
In-Reply-To: <20260219222239.3650400-1-song@kernel.org>

Allow correlating original locals to patched globals, and vice versa.
This is needed when:

1. User adds/removes "static" for a function.
2. CONFIG_LTO_CLANG_THIN promotes local functions and objects to global
   and add .llvm.<hash> suffix.

Given this is a less common scenario, show warnings when this is needed.

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/objtool/klp-diff.c | 31 +++++++++++++++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 147e7e7176fb..07fcaca46160 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -519,6 +519,37 @@ static int correlate_symbols(struct elfs *e)
 		}
 	}
 
+	/* Correlate original locals with patched globals */
+	for_each_sym(e->orig, sym1) {
+		if (sym1->twin || dont_correlate(sym1) || !is_local_sym(sym1))
+			continue;
+		sym2 = find_global_symbol_by_name(e->patched, sym1->name);
+		if (!sym2 && find_global_symbol_by_demangled_name(e->patched, sym1, &sym2))
+			return -1;
+		if (sym2 && !sym2->twin) {
+			sym1->twin = sym2;
+			sym2->twin = sym1;
+			WARN("correlate LOCAL %s (original) to GLOBAL %s (patched)",
+			     sym1->name, sym2->name);
+		}
+	}
+
+	/* Correlate original globals with patched locals */
+	for_each_sym(e->patched, sym2) {
+		if (sym2->twin || dont_correlate(sym2) || !is_local_sym(sym2))
+			continue;
+		sym1 = find_global_symbol_by_name(e->orig, sym2->name);
+		if (!sym1 && find_global_symbol_by_demangled_name(e->patched, sym2, &sym1))
+			return -1;
+
+		if (sym1 && !sym1->twin) {
+			sym2->twin = sym1;
+			sym1->twin = sym2;
+			WARN("correlate GLOBAL %s (origial) to LOCAL %s (patched)",
+			     sym1->name, sym2->name);
+		}
+	}
+
 	for_each_sym(e->orig, sym1) {
 		if (sym1->twin || dont_correlate(sym1))
 			continue;
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 6/8] objtool/klp: Match symbols based on demangled_name for global variables
From: Song Liu @ 2026-02-19 22:22 UTC (permalink / raw)
  To: live-patching
  Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
	Song Liu
In-Reply-To: <20260219222239.3650400-1-song@kernel.org>

correlate_symbols will always try to match full name first. If there is no
match, try match only demangled_name.

In very rare cases, it is possible to have multiple foo.llvm.<hash> in
the same kernel. Whenever there is ambiguity like this, fail the klp diff.

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/objtool/elf.c                 | 13 +++++++
 tools/objtool/include/objtool/elf.h |  3 ++
 tools/objtool/klp-diff.c            | 59 +++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index efb13ec0a89d..5ddbfa8f8701 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -323,6 +323,19 @@ struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *nam
 	return NULL;
 }
 
+void iterate_global_symbol_by_demangled_name(const struct elf *elf,
+					     const char *demangled_name,
+					     void (*process)(struct symbol *sym, void *data),
+					     void *data)
+{
+	struct symbol *sym;
+
+	elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(demangled_name)) {
+		if (!strcmp(sym->demangled_name, demangled_name) && !is_local_sym(sym))
+			process(sym, data);
+	}
+}
+
 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
 				     unsigned long offset, unsigned int len)
 {
diff --git a/tools/objtool/include/objtool/elf.h b/tools/objtool/include/objtool/elf.h
index e12c516bd320..25573e5af76e 100644
--- a/tools/objtool/include/objtool/elf.h
+++ b/tools/objtool/include/objtool/elf.h
@@ -186,6 +186,9 @@ struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);
 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
 struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
 struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *name);
+void iterate_global_symbol_by_demangled_name(const struct elf *elf, const char *demangled_name,
+					     void (*process)(struct symbol *sym, void *data),
+					     void *data);
 struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset);
 int find_symbol_hole_containing(const struct section *sec, unsigned long offset);
 struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index 57606bc3390a..147e7e7176fb 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -355,6 +355,46 @@ static bool dont_correlate(struct symbol *sym)
 	       strstarts(sym->name, "__initcall__");
 }
 
+struct process_demangled_name_data {
+	struct symbol *ret;
+	int count;
+};
+
+static void process_demangled_name(struct symbol *sym, void *d)
+{
+	struct process_demangled_name_data *data = d;
+
+	if (sym->twin)
+		return;
+
+	data->count++;
+	data->ret = sym;
+}
+
+/*
+ * When there is no full name match, try match demangled_name. This would
+ * match original foo.llvm.123 to patched foo.llvm.456.
+ *
+ * Note that, in very rare cases, it is possible to have multiple
+ * foo.llvm.<hash> in the same kernel. When this happens, report error and
+ * fail the diff.
+ */
+static int find_global_symbol_by_demangled_name(struct elf *elf, struct symbol *sym,
+						struct symbol **out_sym)
+{
+	struct process_demangled_name_data data = {};
+
+	iterate_global_symbol_by_demangled_name(elf, sym->demangled_name,
+						process_demangled_name,
+						&data);
+	if (data.count > 1) {
+		ERROR("Multiple (%d) correlation candidates for %s", data.count, sym->name);
+		return -1;
+	}
+	*out_sym = data.ret;
+	return 0;
+}
+
 /*
  * For each symbol in the original kernel, find its corresponding "twin" in the
  * patched kernel.
@@ -453,8 +493,27 @@ static int correlate_symbols(struct elfs *e)
 			continue;
 
 		sym2 = find_global_symbol_by_name(e->patched, sym1->name);
+		if (sym2 && !sym2->twin) {
+			sym1->twin = sym2;
+			sym2->twin = sym1;
+		}
+	}
+
+	/*
+	 * Correlate globals with demangled_name.
+	 * A separate loop is needed because we want to finish all the
+	 * full name correlations first.
+	 */
+	for_each_sym(e->orig, sym1) {
+		if (sym1->bind == STB_LOCAL || sym1->twin)
+			continue;
+
+		if (find_global_symbol_by_demangled_name(e->patched, sym1, &sym2))
+			return -1;
 
 		if (sym2 && !sym2->twin) {
+			WARN("correlate %s (original) to %s (patched)",
+			     sym1->name, sym2->name);
 			sym1->twin = sym2;
 			sym2->twin = sym1;
 		}
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 5/8] objtool/klp: Remove .llvm suffix in demangle_name()
From: Song Liu @ 2026-02-19 22:22 UTC (permalink / raw)
  To: live-patching
  Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
	Song Liu
In-Reply-To: <20260219222239.3650400-1-song@kernel.org>

Remove .llvm suffix, so that we can correlate foo.llvm.<hash 1> and
foo.llvm.<hash 2>.

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/objtool/elf.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index d66452d66fb4..efb13ec0a89d 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -455,10 +455,15 @@ static int read_sections(struct elf *elf)
 static ssize_t demangled_name_len(const char *name)
 {
 	ssize_t len;
+	const char *p;
 
 	if (!strstarts(name, "__UNIQUE_ID_") && !strchr(name, '.'))
 		return strlen(name);
 
+	p = strstr(name, ".llvm.");
+	if (p)
+		return p - name;
+
 	for (len = strlen(name) - 1; len >= 0; len--) {
 		char c = name[len];
 
@@ -482,6 +487,9 @@ static ssize_t demangled_name_len(const char *name)
  *   __UNIQUE_ID_addressable___UNIQUE_ID_pci_invalid_bar_694_695
  *
  * to remove both trailing numbers, also remove trailing '_'.
+ *
+ * For symbols with llvm suffix, i.e., foo.llvm.<hash>, remove the
+ * .llvm.<hash> part.
  */
 static const char *demangle_name(struct symbol *sym)
 {
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 4/8] objtool/klp: Also demangle global objects
From: Song Liu @ 2026-02-19 22:22 UTC (permalink / raw)
  To: live-patching
  Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
	Song Liu
In-Reply-To: <20260219222239.3650400-1-song@kernel.org>

With CONFIG_LTO_CLANG_THIN, it is possible to have global __UNIQUE_ID,
such as:

   FUNC    GLOBAL HIDDEN  19745 __UNIQUE_ID_quirk_amd_nb_node_458

Also demangle global objects.

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/objtool/elf.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index c784a0484270..d66452d66fb4 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -488,9 +488,6 @@ static const char *demangle_name(struct symbol *sym)
 	char *str;
 	ssize_t len;
 
-	if (!is_local_sym(sym))
-		return sym->name;
-
 	if (!is_func_sym(sym) && !is_object_sym(sym))
 		return sym->name;
 
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 3/8] objtool/klp: Use sym->demangled_name for symbol_name hash
From: Song Liu @ 2026-02-19 22:22 UTC (permalink / raw)
  To: live-patching
  Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
	Song Liu
In-Reply-To: <20260219222239.3650400-1-song@kernel.org>

For klp-build with LTO, it is necessary to correlate demangled symbols,
e.g., correlate foo.llvm.<num 1> and foo.llvm.<num 2>. However, these two
symbols do not have the same str_hash(name). To be able to correlate the
two symbols, calculate hash based on demanged_name, so that these two
symbols have the same hash.

No functional changes intended.

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/objtool/elf.c | 58 +++++++++++++++++++++++++++++++--------------
 1 file changed, 40 insertions(+), 18 deletions(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 0d93e8496e8d..c784a0484270 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -26,11 +26,18 @@
 #include <objtool/elf.h>
 #include <objtool/warn.h>
 
+static ssize_t demangled_name_len(const char *name);
+
 static inline u32 str_hash(const char *str)
 {
 	return jhash(str, strlen(str), 0);
 }
 
+static inline u32 str_hash_demangled(const char *str)
+{
+	return jhash(str, demangled_name_len(str), 0);
+}
+
 #define __elf_table(name)	(elf->name##_hash)
 #define __elf_bits(name)	(elf->name##_bits)
 
@@ -294,7 +301,7 @@ static struct symbol *find_local_symbol_by_file_and_name(const struct elf *elf,
 {
 	struct symbol *sym;
 
-	elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(name)) {
+	elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash_demangled(name)) {
 		if (sym->bind == STB_LOCAL && sym->file == file &&
 		    !strcmp(sym->name, name)) {
 			return sym;
@@ -308,7 +315,7 @@ struct symbol *find_global_symbol_by_name(const struct elf *elf, const char *nam
 {
 	struct symbol *sym;
 
-	elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash(name)) {
+	elf_hash_for_each_possible(symbol_name, sym, name_hash, str_hash_demangled(name)) {
 		if (!strcmp(sym->name, name) && !is_local_sym(sym))
 			return sym;
 	}
@@ -441,6 +448,28 @@ static int read_sections(struct elf *elf)
 	return 0;
 }
 
+/*
+ * Returns desired length of the demangled name.
+ * If name doesn't need demangling, return strlen(name).
+ */
+static ssize_t demangled_name_len(const char *name)
+{
+	ssize_t len;
+
+	if (!strstarts(name, "__UNIQUE_ID_") && !strchr(name, '.'))
+		return strlen(name);
+
+	for (len = strlen(name) - 1; len >= 0; len--) {
+		char c = name[len];
+
+		if (!isdigit(c) && c != '.' && c != '_')
+			break;
+	}
+	if (len <= 0)
+		return strlen(name);
+	return len;
+}
+
 /*
  * Remove number suffix of a symbol.
  *
@@ -457,6 +486,7 @@ static int read_sections(struct elf *elf)
 static const char *demangle_name(struct symbol *sym)
 {
 	char *str;
+	ssize_t len;
 
 	if (!is_local_sym(sym))
 		return sym->name;
@@ -464,24 +494,16 @@ static const char *demangle_name(struct symbol *sym)
 	if (!is_func_sym(sym) && !is_object_sym(sym))
 		return sym->name;
 
-	if (!strstarts(sym->name, "__UNIQUE_ID_") && !strchr(sym->name, '.'))
+	len = demangled_name_len(sym->name);
+	if (len == strlen(sym->name))
 		return sym->name;
 
-	str = strdup(sym->name);
+	str = strndup(sym->name, len);
 	if (!str) {
 		ERROR_GLIBC("strdup");
 		return NULL;
 	}
 
-	for (int i = strlen(str) - 1; i >= 0; i--) {
-		char c = str[i];
-
-		if (!isdigit(c) && c != '.' && c != '_') {
-			str[i + 1] = '\0';
-			break;
-		}
-	}
-
 	return str;
 }
 
@@ -517,9 +539,13 @@ static int elf_add_symbol(struct elf *elf, struct symbol *sym)
 		entry = &sym->sec->symbol_list;
 	list_add(&sym->list, entry);
 
+	sym->demangled_name = demangle_name(sym);
+	if (!sym->demangled_name)
+		return -1;
+
 	list_add_tail(&sym->global_list, &elf->symbols);
 	elf_hash_add(symbol, &sym->hash, sym->idx);
-	elf_hash_add(symbol_name, &sym->name_hash, str_hash(sym->name));
+	elf_hash_add(symbol_name, &sym->name_hash, str_hash(sym->demangled_name));
 
 	if (is_func_sym(sym) &&
 	    (strstarts(sym->name, "__pfx_") ||
@@ -543,10 +569,6 @@ static int elf_add_symbol(struct elf *elf, struct symbol *sym)
 
 	sym->pfunc = sym->cfunc = sym;
 
-	sym->demangled_name = demangle_name(sym);
-	if (!sym->demangled_name)
-		return -1;
-
 	return 0;
 }
 
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 2/8] objtool/klp: Remove trailing '_' in demangle_name()
From: Song Liu @ 2026-02-19 22:22 UTC (permalink / raw)
  To: live-patching
  Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
	Song Liu
In-Reply-To: <20260219222239.3650400-1-song@kernel.org>

With CONFIG_LTO_CLANG_THIN, it is possible to have nested __UNIQUE_ID_,
such as:

  __UNIQUE_ID_addressable___UNIQUE_ID_pci_invalid_bar_694_695

To remove both trailing numbers, also remove trailing '_'.

Also add comments to demangle_name().

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/objtool/elf.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 2c02c7b49265..0d93e8496e8d 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -441,6 +441,19 @@ static int read_sections(struct elf *elf)
 	return 0;
 }
 
+/*
+ * Remove number suffix of a symbol.
+ *
+ * Specifically, remove trailing numbers for "__UNIQUE_ID_" symbols and
+ * symbols with '.'.
+ *
+ * With CONFIG_LTO_CLANG_THIN, it is possible to have nested __UNIQUE_ID_,
+ * such as
+ *
+ *   __UNIQUE_ID_addressable___UNIQUE_ID_pci_invalid_bar_694_695
+ *
+ * to remove both trailing numbers, also remove trailing '_'.
+ */
 static const char *demangle_name(struct symbol *sym)
 {
 	char *str;
@@ -463,7 +476,7 @@ static const char *demangle_name(struct symbol *sym)
 	for (int i = strlen(str) - 1; i >= 0; i--) {
 		char c = str[i];
 
-		if (!isdigit(c) && c != '.') {
+		if (!isdigit(c) && c != '.' && c != '_') {
 			str[i + 1] = '\0';
 			break;
 		}
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 1/8] objtool/klp: Remove redundent strcmp in correlate_symbols
From: Song Liu @ 2026-02-19 22:22 UTC (permalink / raw)
  To: live-patching
  Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
	Song Liu
In-Reply-To: <20260219222239.3650400-1-song@kernel.org>

find_global_symbol_by_name() already compares names of the two symbols,
so there is no need to compare them again.

Signed-off-by: Song Liu <song@kernel.org>
---
 tools/objtool/klp-diff.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
index a3198a63c2f0..57606bc3390a 100644
--- a/tools/objtool/klp-diff.c
+++ b/tools/objtool/klp-diff.c
@@ -454,7 +454,7 @@ static int correlate_symbols(struct elfs *e)
 
 		sym2 = find_global_symbol_by_name(e->patched, sym1->name);
 
-		if (sym2 && !sym2->twin && !strcmp(sym1->name, sym2->name)) {
+		if (sym2 && !sym2->twin) {
 			sym1->twin = sym2;
 			sym2->twin = sym1;
 		}
-- 
2.47.3


^ permalink raw reply related

* [PATCH v2 0/8] objtool/klp: klp-build LTO support and tests
From: Song Liu @ 2026-02-19 22:22 UTC (permalink / raw)
  To: live-patching
  Cc: jpoimboe, jikos, mbenes, pmladek, joe.lawrence, kernel-team,
	Song Liu

Add support for LTO in klp-build toolchain. The key changes are to the
symbol correlation logic.Basically, we want to:

1. Match symbols with differerent .llvm.<hash> suffixes, e.g., foo.llvm.123
   to foo.llvm.456.
2. Match local symbols with promoted global symbols, e.g., local foo
   with global foo.llvm.123.

1/8 and 2/8 are small cleanup/fix for existing code.
3/8 through 7/8 contains the core logic changes to correlate_symbols().
8/8 contains tests for klp-build toolchain.

Changes v1 => v2:
1. Error out on ambiguous .llvm.<hash>

Song Liu (8):
  objtool/klp: Remove redundent strcmp in correlate_symbols
  objtool/klp: Remove trailing '_' in demangle_name()
  objtool/klp: Use sym->demangled_name for symbol_name hash
  objtool/klp: Also demangle global objects
  objtool/klp: Remove .llvm suffix in demangle_name()
  objtool/klp: Match symbols based on demangled_name for global
    variables
  objtool/klp: Correlate locals to globals
  livepatch: Add tests for klp-build toolchain

 kernel/livepatch/Kconfig                      |  20 +++
 kernel/livepatch/Makefile                     |   2 +
 kernel/livepatch/tests/Makefile               |   6 +
 kernel/livepatch/tests/klp_test_module.c      | 111 ++++++++++++++
 kernel/livepatch/tests/klp_test_module.h      |   8 +
 kernel/livepatch/tests/klp_test_vmlinux.c     | 138 ++++++++++++++++++
 kernel/livepatch/tests/klp_test_vmlinux.h     |  16 ++
 kernel/livepatch/tests/klp_test_vmlinux_aux.c |  59 ++++++++
 tools/objtool/elf.c                           |  95 +++++++++---
 tools/objtool/include/objtool/elf.h           |   3 +
 tools/objtool/klp-diff.c                      |  92 +++++++++++-
 .../selftests/livepatch/test_patches/README   |  15 ++
 .../test_patches/klp_test_hash_change.patch   |  30 ++++
 .../test_patches/klp_test_module.patch        |  18 +++
 .../klp_test_nonstatic_to_static.patch        |  40 +++++
 .../klp_test_static_to_nonstatic.patch        |  39 +++++
 .../test_patches/klp_test_vmlinux.patch       |  18 +++
 17 files changed, 688 insertions(+), 22 deletions(-)
 create mode 100644 kernel/livepatch/tests/Makefile
 create mode 100644 kernel/livepatch/tests/klp_test_module.c
 create mode 100644 kernel/livepatch/tests/klp_test_module.h
 create mode 100644 kernel/livepatch/tests/klp_test_vmlinux.c
 create mode 100644 kernel/livepatch/tests/klp_test_vmlinux.h
 create mode 100644 kernel/livepatch/tests/klp_test_vmlinux_aux.c
 create mode 100644 tools/testing/selftests/livepatch/test_patches/README
 create mode 100644 tools/testing/selftests/livepatch/test_patches/klp_test_hash_change.patch
 create mode 100644 tools/testing/selftests/livepatch/test_patches/klp_test_module.patch
 create mode 100644 tools/testing/selftests/livepatch/test_patches/klp_test_nonstatic_to_static.patch
 create mode 100644 tools/testing/selftests/livepatch/test_patches/klp_test_static_to_nonstatic.patch
 create mode 100644 tools/testing/selftests/livepatch/test_patches/klp_test_vmlinux.patch

--
2.47.3

^ permalink raw reply

* Re: [PATCH 0/8] objtool/klp: klp-build LTO support and tests
From: Song Liu @ 2026-02-19 21:31 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: Joe Lawrence, live-patching, jikos, mbenes, pmladek, kernel-team
In-Reply-To: <5l3i26zkg7eoprhuyl7pdujrn2a4vyule423xqovnoea53tu3j@j4pbbgdy232c>

On Thu, Feb 19, 2026 at 12:51 PM Josh Poimboeuf <jpoimboe@kernel.org> wrote:
[...]
> >
> > Thanks for the test case. This one shows the worst case of the .llvm.
> > suffix issue.
> >
> > We have
> >   c_start.llvm.15251198824366928061
> >   c_start.llvm.1768504738091882651
> > in the original kernel, and
> >   c_start.llvm.14107081093236395767
> >   c_start.llvm.10047843810948474008
> > in the patched kernel.
> >
> > All of them are GLOBAL HIDDEN functions, so I don't think we can
> > reliably correlate them. Maybe we should fail the build in such cases.
>
> I'm thinking the "correlate <orig> to <patched>" warnings would need to
> be an error when there's ambiguity (i.e., two symbols with the same
> ".llvm.*" mangled name), as there's nothing preventing their symbols'
> orders from getting swapped.

Agreed. I changed the logic to error out when there is ambiguity.

> And note that changing a symbol from local to global (or vice versa) can
> do exactly that, as globals always come at the end.
>
> Also, this problem may be more widespread than the above, as there are a
> lot of duplicately named functions in the kernel, with
> CONFIG_DEBUG_SECTION_MISMATCH making the problem even worse in practice.
>
> I think we may need to figure out a way to map sym.llvm.<hash> back to
> its original FILE symbol so correlate_symbols() can reliably
> disambiguate.
>
> The hash seems to be file-specific.  I don't think there's a way for
> objtool to reverse engineer that.
>
> DWARF could be used to map the symbol to its original file name, but we
> can't necessarily rely on CONFIG_DEBUG_INFO.
>
> However, I did find that LLVM has a hidden option:
>
>   -mllvm -use-source-filename-for-promoted-locals
>
> which changes the hash to a file path:
>
>   c_start.llvm.arch_x86_kernel_cpu_proc_c
>
> That would be (almost) everything we'd need to match a symbol to its
> FILE symbol.

I am aware of this option. I think it makes kallsyms too ugly tough.
Also, at the moment, llvm adds these suffixes even when there is
no ambiguity. As a result, there are too many of them. Yonghong
is working on a LLVM change so that it only adds suffixes when
necessary (https://github.com/llvm/llvm-project/pull/178587). But
this won't be available until LLVM-23.

At the moment, I think error out on ambiguity is probably good
enough. This should not happen too often in real world patches.
Does this sound like a viable solution for now?

Thanks,
Song

[...]

^ permalink raw reply

* Re: [PATCH 0/8] objtool/klp: klp-build LTO support and tests
From: Josh Poimboeuf @ 2026-02-19 20:51 UTC (permalink / raw)
  To: Song Liu; +Cc: Joe Lawrence, live-patching, jikos, mbenes, pmladek, kernel-team
In-Reply-To: <CAPhsuW7zHDxct5OByqDH+i3m5xbqBrrRtEJ4xV=AC6rgFgbq3g@mail.gmail.com>

On Wed, Feb 18, 2026 at 07:08:55PM -0800, Song Liu wrote:
> On Wed, Feb 18, 2026 at 3:00 PM Joe Lawrence <joe.lawrence@redhat.com> wrote:
> >
> > On Thu, Feb 12, 2026 at 11:21:53AM -0800, Song Liu wrote:
> [...]
> > vmlinux.o: warning: objtool: correlate c_start.llvm.15251198824366928061 (origial) to c_start.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate c_stop.llvm.15251198824366928061 (origial) to c_stop.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate c_next.llvm.15251198824366928061 (origial) to c_next.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate show_cpuinfo.llvm.15251198824366928061 (origial) to show_cpuinfo.llvm.10047843810948474008 (patched)
> > vmlinux.o: warning: objtool: correlate .str.llvm.1768504738091882651 (origial) to .str.llvm.7814622528726587167 (patched)
> > vmlinux.o: warning: objtool: correlate crypto_seq_ops.llvm.1768504738091882651 (origial) to crypto_seq_ops.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate c_start.llvm.1768504738091882651 (origial) to c_start.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate c_stop.llvm.1768504738091882651 (origial) to c_stop.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate c_next.llvm.1768504738091882651 (origial) to c_next.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate c_show.llvm.1768504738091882651 (origial) to c_show.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_start.llvm.15251198824366928061 (origial) to __pfx_c_start.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_stop.llvm.15251198824366928061 (origial) to __pfx_c_stop.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_next.llvm.15251198824366928061 (origial) to __pfx_c_next.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_show_cpuinfo.llvm.15251198824366928061 (origial) to __pfx_show_cpuinfo.llvm.10047843810948474008 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_start.llvm.1768504738091882651 (origial) to __pfx_c_start.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_stop.llvm.1768504738091882651 (origial) to __pfx_c_stop.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_next.llvm.1768504738091882651 (origial) to __pfx_c_next.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_show.llvm.1768504738091882651 (origial) to __pfx_c_show.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: no correlation: c_start.llvm.1768504738091882651
> > vmlinux.o: warning: objtool: no correlation: c_stop.llvm.1768504738091882651
> > vmlinux.o: warning: objtool: no correlation: c_next.llvm.1768504738091882651
> > vmlinux.o: new function: c_start.llvm.10047843810948474008
> > vmlinux.o: new function: c_stop.llvm.10047843810948474008
> > vmlinux.o: new function: c_next.llvm.10047843810948474008
> > vmlinux.o: changed function: c_start.llvm.14107081093236395767
> > vmlinux.o: changed function: c_stop.llvm.14107081093236395767
> > vmlinux.o: changed function: c_next.llvm.14107081093236395767
> > Building patch module: livepatch-min.ko
> > SUCCESS
> 
> Thanks for the test case. This one shows the worst case of the .llvm.
> suffix issue.
> 
> We have
>   c_start.llvm.15251198824366928061
>   c_start.llvm.1768504738091882651
> in the original kernel, and
>   c_start.llvm.14107081093236395767
>   c_start.llvm.10047843810948474008
> in the patched kernel.
> 
> All of them are GLOBAL HIDDEN functions, so I don't think we can
> reliably correlate them. Maybe we should fail the build in such cases.

I'm thinking the "correlate <orig> to <patched>" warnings would need to
be an error when there's ambiguity (i.e., two symbols with the same
".llvm.*" mangled name), as there's nothing preventing their symbols'
orders from getting swapped.

And note that changing a symbol from local to global (or vice versa) can
do exactly that, as globals always come at the end.

Also, this problem may be more widespread than the above, as there are a
lot of duplicately named functions in the kernel, with
CONFIG_DEBUG_SECTION_MISMATCH making the problem even worse in practice.

I think we may need to figure out a way to map sym.llvm.<hash> back to
its original FILE symbol so correlate_symbols() can reliably
disambiguate.

The hash seems to be file-specific.  I don't think there's a way for
objtool to reverse engineer that.

DWARF could be used to map the symbol to its original file name, but we
can't necessarily rely on CONFIG_DEBUG_INFO.

However, I did find that LLVM has a hidden option:

  -mllvm -use-source-filename-for-promoted-locals

which changes the hash to a file path:

  c_start.llvm.arch_x86_kernel_cpu_proc_c

That would be (almost) everything we'd need to match a symbol to its
FILE symbol.

The only remaining ambiguity is that FILE symbols only have the
basename, not the full path.  So a duplicate "basename+sym" would still
be ambiguous.  But that seems much less likely.

We could possibly enforce a new requirement that "basename+sym" be
unique treewide.  Then we could maybe even base sympos on that.  That
also might help fix some of the other unique symbol headaches I remember
some people having with tracing and possibly elsewhere.

-- 
Josh

^ permalink raw reply

* Re: [PATCH 0/8] objtool/klp: klp-build LTO support and tests
From: Song Liu @ 2026-02-19 20:47 UTC (permalink / raw)
  To: Joe Lawrence; +Cc: live-patching, jpoimboe, jikos, mbenes, pmladek, kernel-team
In-Reply-To: <CAPhsuW7zHDxct5OByqDH+i3m5xbqBrrRtEJ4xV=AC6rgFgbq3g@mail.gmail.com>

On Wed, Feb 18, 2026 at 7:08 PM Song Liu <song@kernel.org> wrote:
>
> On Wed, Feb 18, 2026 at 3:00 PM Joe Lawrence <joe.lawrence@redhat.com> wrote:
> >
> > On Thu, Feb 12, 2026 at 11:21:53AM -0800, Song Liu wrote:
> [...]
> > vmlinux.o: warning: objtool: correlate c_start.llvm.15251198824366928061 (origial) to c_start.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate c_stop.llvm.15251198824366928061 (origial) to c_stop.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate c_next.llvm.15251198824366928061 (origial) to c_next.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate show_cpuinfo.llvm.15251198824366928061 (origial) to show_cpuinfo.llvm.10047843810948474008 (patched)
> > vmlinux.o: warning: objtool: correlate .str.llvm.1768504738091882651 (origial) to .str.llvm.7814622528726587167 (patched)
> > vmlinux.o: warning: objtool: correlate crypto_seq_ops.llvm.1768504738091882651 (origial) to crypto_seq_ops.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate c_start.llvm.1768504738091882651 (origial) to c_start.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate c_stop.llvm.1768504738091882651 (origial) to c_stop.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate c_next.llvm.1768504738091882651 (origial) to c_next.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate c_show.llvm.1768504738091882651 (origial) to c_show.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_start.llvm.15251198824366928061 (origial) to __pfx_c_start.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_stop.llvm.15251198824366928061 (origial) to __pfx_c_stop.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_next.llvm.15251198824366928061 (origial) to __pfx_c_next.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_show_cpuinfo.llvm.15251198824366928061 (origial) to __pfx_show_cpuinfo.llvm.10047843810948474008 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_start.llvm.1768504738091882651 (origial) to __pfx_c_start.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_stop.llvm.1768504738091882651 (origial) to __pfx_c_stop.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_next.llvm.1768504738091882651 (origial) to __pfx_c_next.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: correlate __pfx_c_show.llvm.1768504738091882651 (origial) to __pfx_c_show.llvm.14107081093236395767 (patched)
> > vmlinux.o: warning: objtool: no correlation: c_start.llvm.1768504738091882651
> > vmlinux.o: warning: objtool: no correlation: c_stop.llvm.1768504738091882651
> > vmlinux.o: warning: objtool: no correlation: c_next.llvm.1768504738091882651
> > vmlinux.o: new function: c_start.llvm.10047843810948474008
> > vmlinux.o: new function: c_stop.llvm.10047843810948474008
> > vmlinux.o: new function: c_next.llvm.10047843810948474008
> > vmlinux.o: changed function: c_start.llvm.14107081093236395767
> > vmlinux.o: changed function: c_stop.llvm.14107081093236395767
> > vmlinux.o: changed function: c_next.llvm.14107081093236395767
> > Building patch module: livepatch-min.ko
> > SUCCESS
>
> Thanks for the test case. This one shows the worst case of the .llvm.
> suffix issue.
>
> We have
>   c_start.llvm.15251198824366928061
>   c_start.llvm.1768504738091882651
> in the original kernel, and
>   c_start.llvm.14107081093236395767
>   c_start.llvm.10047843810948474008
> in the patched kernel.
>
> All of them are GLOBAL HIDDEN functions, so I don't think we can
> reliably correlate them. Maybe we should fail the build in such cases.
>
> Any comments and suggestions on this one? CC: Josh.

I fixed the correlation logic, with the min.patch from Joe that patches:
  arch/x86/kernel/cpu/proc.c
  crypto/proc.c
  fs/proc/consoles.c

we got the following failure:
Diffing objects
vmlinux.o: error: objtool: Multiple (2) correlation candidates for
c_start.llvm.18238767671416440194
error: klp-build: objtool klp diff failed

With a smaller patch, that only patches:
  arch/x86/kernel/cpu/proc.c
  fs/proc/consoles.c

There will be only one c_start.llvm.<hash>. klp-build fails with:
Diffing objects
vmlinux.o: warning: objtool: correlate
c_start.llvm.18238767671416440194 (original) to
c_start.llvm.4054753011035506728 (patched)
vmlinux.o: warning: objtool: correlate
c_stop.llvm.18238767671416440194 (original) to
c_stop.llvm.4054753011035506728 (patched)
vmlinux.o: warning: objtool: correlate
c_next.llvm.18238767671416440194 (original) to
c_next.llvm.4054753011035506728 (patched)
vmlinux.o: warning: objtool: correlate
show_cpuinfo.llvm.18238767671416440194 (original) to
show_cpuinfo.llvm.4054753011035506728 (patched)
Building patch module: livepatch-0001-min.ko
error: klp-build: no changes detected

This is the best solution I can think of at the moment. I will send v2
patches soon.

Thanks,
Song

^ permalink raw reply

* Re: [PATCH 0/8] objtool/klp: klp-build LTO support and tests
From: Song Liu @ 2026-02-19  3:08 UTC (permalink / raw)
  To: Joe Lawrence; +Cc: live-patching, jpoimboe, jikos, mbenes, pmladek, kernel-team
In-Reply-To: <aZZEjfxgLWTWODE7@redhat.com>

On Wed, Feb 18, 2026 at 3:00 PM Joe Lawrence <joe.lawrence@redhat.com> wrote:
>
> On Thu, Feb 12, 2026 at 11:21:53AM -0800, Song Liu wrote:
[...]
> vmlinux.o: warning: objtool: correlate c_start.llvm.15251198824366928061 (origial) to c_start.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate c_stop.llvm.15251198824366928061 (origial) to c_stop.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate c_next.llvm.15251198824366928061 (origial) to c_next.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate show_cpuinfo.llvm.15251198824366928061 (origial) to show_cpuinfo.llvm.10047843810948474008 (patched)
> vmlinux.o: warning: objtool: correlate .str.llvm.1768504738091882651 (origial) to .str.llvm.7814622528726587167 (patched)
> vmlinux.o: warning: objtool: correlate crypto_seq_ops.llvm.1768504738091882651 (origial) to crypto_seq_ops.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate c_start.llvm.1768504738091882651 (origial) to c_start.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate c_stop.llvm.1768504738091882651 (origial) to c_stop.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate c_next.llvm.1768504738091882651 (origial) to c_next.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate c_show.llvm.1768504738091882651 (origial) to c_show.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate __pfx_c_start.llvm.15251198824366928061 (origial) to __pfx_c_start.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate __pfx_c_stop.llvm.15251198824366928061 (origial) to __pfx_c_stop.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate __pfx_c_next.llvm.15251198824366928061 (origial) to __pfx_c_next.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate __pfx_show_cpuinfo.llvm.15251198824366928061 (origial) to __pfx_show_cpuinfo.llvm.10047843810948474008 (patched)
> vmlinux.o: warning: objtool: correlate __pfx_c_start.llvm.1768504738091882651 (origial) to __pfx_c_start.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate __pfx_c_stop.llvm.1768504738091882651 (origial) to __pfx_c_stop.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate __pfx_c_next.llvm.1768504738091882651 (origial) to __pfx_c_next.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: correlate __pfx_c_show.llvm.1768504738091882651 (origial) to __pfx_c_show.llvm.14107081093236395767 (patched)
> vmlinux.o: warning: objtool: no correlation: c_start.llvm.1768504738091882651
> vmlinux.o: warning: objtool: no correlation: c_stop.llvm.1768504738091882651
> vmlinux.o: warning: objtool: no correlation: c_next.llvm.1768504738091882651
> vmlinux.o: new function: c_start.llvm.10047843810948474008
> vmlinux.o: new function: c_stop.llvm.10047843810948474008
> vmlinux.o: new function: c_next.llvm.10047843810948474008
> vmlinux.o: changed function: c_start.llvm.14107081093236395767
> vmlinux.o: changed function: c_stop.llvm.14107081093236395767
> vmlinux.o: changed function: c_next.llvm.14107081093236395767
> Building patch module: livepatch-min.ko
> SUCCESS

Thanks for the test case. This one shows the worst case of the .llvm.
suffix issue.

We have
  c_start.llvm.15251198824366928061
  c_start.llvm.1768504738091882651
in the original kernel, and
  c_start.llvm.14107081093236395767
  c_start.llvm.10047843810948474008
in the patched kernel.

All of them are GLOBAL HIDDEN functions, so I don't think we can
reliably correlate them. Maybe we should fail the build in such cases.

Any comments and suggestions on this one? CC: Josh.

> And since we're here, it looks like there's a type:
> s/origial/original/g.

Fixed!

Thanks,
Song

^ permalink raw reply

* Re: [PATCH v3 13/13] livepatch/klp-build: don't look for changed objects in tools/
From: Song Liu @ 2026-02-19  2:55 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: live-patching, Josh Poimboeuf, Jiri Kosina, Miroslav Benes,
	Petr Mladek
In-Reply-To: <aZXYO5ZZPV72qOPD@redhat.com>

On Wed, Feb 18, 2026 at 7:18 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
>
> On Tue, Feb 17, 2026 at 11:29:13AM -0800, Song Liu wrote:
> > On Tue, Feb 17, 2026 at 8:07 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
> >
> > I guess we still need a short commit message.
> >
>
> Heh, checkpatch complained, but I didn't think such a trivial change
> needed a full body :)
>
> > Could you please share the patch that needs this change?
> >
>
> Sorry I don't have a specific patch or repro for this one.  I hit this
> during one of my -T, -T -S 2 short-circuiting testing runs.  I got an
> error like this:
>
>   error: klp-build: missing livepatch-cmdline-string.o for tools/testing/selftests/klp-build/artifacts/full-virtme-ng/cmdline-string/livepatch-cmdline-string.ko
>
> to which I wondered why are we even looking for changed kernel objects
> in tools/ ?  That directory may be stuffed with other weird stuff, a
> combination of user-space and kernel-test .o's, so why bother?
>
> I can drop this one until it becomes something required.

I don't have a strong preference either way. I was more curious
about the test case that triggered this.

Thanks,
Song

^ permalink raw reply

* Re: [PATCH v3 09/13] livepatch/klp-build: fix version mismatch when short-circuiting
From: Song Liu @ 2026-02-19  2:52 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: live-patching, Josh Poimboeuf, Jiri Kosina, Miroslav Benes,
	Petr Mladek
In-Reply-To: <aZXVCIuSdlk6f-1K@redhat.com>

On Wed, Feb 18, 2026 at 7:04 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
>
> On Tue, Feb 17, 2026 at 11:25:13AM -0800, Song Liu wrote:
> > On Tue, Feb 17, 2026 at 8:17 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
> > >
> > [...]
> > > > 2.53.0
> > > >
> > > >
> > >
> > > Maybe I'm starting to see things, but when running 'S 2' builds, I keep
> > > getting "vmlinux.o: changed function: override_release".  It could be
> > > considered benign for quick development work, or confusing.  Seems easy
> > > enough to stash and avoid.
> >
> > "-S 2" with a different set of patches is only needed in patch development,
> > but not used for official releases. Therefore, I agree this is not a real issue.
> >
>
> My use case was running a series of tests:
>
>   (test 1) - full build with -T
>   (test N) - short circuit with -S 2 -T
>   ...
>
> and where it confused me was that I had created tests which were
> designed to fail, specifically one wanted to verify no changes found
> for the recountdiff change in this set.
>
> Without this patch, that test will succeed as the version glitch gets
> picked up as:
>
>   vmlinux.o: changed function: override_release
>
> I could work around that in verification, but then I miss the *specific*
> failure report from klp-build.  I could also run each individual test as
> full, but each build was taking ~6 minutes on my machine.

Agreed that saving ~6 minutes per test is huge.

I think we can ship this.

Acked-by: Song Liu <song@kernel.org>

^ permalink raw reply

* Re: [PATCH 0/8] objtool/klp: klp-build LTO support and tests
From: Joe Lawrence @ 2026-02-18 23:00 UTC (permalink / raw)
  To: Song Liu; +Cc: live-patching, jpoimboe, jikos, mbenes, pmladek, kernel-team
In-Reply-To: <20260212192201.3593879-1-song@kernel.org>

On Thu, Feb 12, 2026 at 11:21:53AM -0800, Song Liu wrote:
> Add support for LTO in klp-build toolchain. The key changes are to the
> symbol correlation logic.Basically, we want to:
> 
> 1. Match symbols with differerent .llvm.<hash> suffixes, e.g., foo.llvm.123
>    to foo.llvm.456.
> 2. Match local symbols with promoted global symbols, e.g., local foo
>    with global foo.llvm.123.
> 
> 1/8 and 2/8 are small cleanup/fix for existing code.
> 3/8 through 7/8 contains the core logic changes to correlate_symbols().
> 8/8 contains tests for klp-build toolchain.
> 
> Song Liu (8):
>   objtool/klp: Remove redundent strcmp in correlate_symbols
>   objtool/klp: Remove trailing '_' in demangle_name()
>   objtool/klp: Use sym->demangled_name for symbol_name hash
>   objtool/klp: Also demangle global objects
>   objtool/klp: Remove .llvm suffix in demangle_name()
>   objtool/klp: Match symbols based on demangled_name for global
>     variables
>   objtool/klp: Correlate locals to globals
>   livepatch: Add tests for klp-build toolchain
> 

Hi Song,

One of the tests that Josh had suggested running to validate "no
changes" and git apply --recount / recountdiff was to touch most of the
.c files in the tree like so:

  $ find . -type f -name '*.c' ! -path "./lib/*" -print0 | xargs -0 sed -i '1iasm("nop");'
  $ git checkout tools arch/x86/lib/inat.c arch/x86/lib/insn.c kernel/configs.c
  $ git diff > /tmp/oneline.patch

which results in "klp-build: no changes detected" using gcc, but with
this patchset+llvm thin-LTO results in a few c_start/c_stop/c_next
uncorrelated variables.

Here is a minimal version of a reproducer:

$ grep LTO .config
CONFIG_LTO=y
CONFIG_LTO_CLANG=y
CONFIG_ARCH_SUPPORTS_LTO_CLANG=y
CONFIG_ARCH_SUPPORTS_LTO_CLANG_THIN=y
CONFIG_HAS_LTO_CLANG=y
# CONFIG_LTO_NONE is not set
# CONFIG_LTO_CLANG_FULL is not set
CONFIG_LTO_CLANG_THIN=y

$ cat ~/min.patch
diff --git a/arch/x86/kernel/cpu/proc.c b/arch/x86/kernel/cpu/proc.c
index 6571d432cbe3..96c6c8bb7228 100644
--- a/arch/x86/kernel/cpu/proc.c
+++ b/arch/x86/kernel/cpu/proc.c
@@ -1,3 +1,4 @@
+asm("nop");
 // SPDX-License-Identifier: GPL-2.0
 #include <linux/smp.h>
 #include <linux/timex.h>
diff --git a/crypto/proc.c b/crypto/proc.c
index 82f15b967e85..1474800162bf 100644
--- a/crypto/proc.c
+++ b/crypto/proc.c
@@ -1,3 +1,4 @@
+asm("nop");
 // SPDX-License-Identifier: GPL-2.0-or-later
 /*
  * Scatterlist Cryptographic API.
diff --git a/fs/proc/consoles.c b/fs/proc/consoles.c
index b7cab1ad990d..066e625ae14e 100644
--- a/fs/proc/consoles.c
+++ b/fs/proc/consoles.c
@@ -1,3 +1,4 @@
+asm("nop");
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2010 Werner Fink, Jiri Slaby

$ LLVM=1 ./scripts/livepatch/klp-build -T ~/min.patch 
Validating patch(es)
Building original kernel
Copying original object files
Fixing patch(es)
Building patched kernel
Copying patched object files
Diffing objects
vmlinux.o: warning: objtool: correlate c_start.llvm.15251198824366928061 (origial) to c_start.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate c_stop.llvm.15251198824366928061 (origial) to c_stop.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate c_next.llvm.15251198824366928061 (origial) to c_next.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate show_cpuinfo.llvm.15251198824366928061 (origial) to show_cpuinfo.llvm.10047843810948474008 (patched)
vmlinux.o: warning: objtool: correlate .str.llvm.1768504738091882651 (origial) to .str.llvm.7814622528726587167 (patched)
vmlinux.o: warning: objtool: correlate crypto_seq_ops.llvm.1768504738091882651 (origial) to crypto_seq_ops.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate c_start.llvm.1768504738091882651 (origial) to c_start.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate c_stop.llvm.1768504738091882651 (origial) to c_stop.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate c_next.llvm.1768504738091882651 (origial) to c_next.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate c_show.llvm.1768504738091882651 (origial) to c_show.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate __pfx_c_start.llvm.15251198824366928061 (origial) to __pfx_c_start.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate __pfx_c_stop.llvm.15251198824366928061 (origial) to __pfx_c_stop.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate __pfx_c_next.llvm.15251198824366928061 (origial) to __pfx_c_next.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate __pfx_show_cpuinfo.llvm.15251198824366928061 (origial) to __pfx_show_cpuinfo.llvm.10047843810948474008 (patched)
vmlinux.o: warning: objtool: correlate __pfx_c_start.llvm.1768504738091882651 (origial) to __pfx_c_start.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate __pfx_c_stop.llvm.1768504738091882651 (origial) to __pfx_c_stop.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate __pfx_c_next.llvm.1768504738091882651 (origial) to __pfx_c_next.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: correlate __pfx_c_show.llvm.1768504738091882651 (origial) to __pfx_c_show.llvm.14107081093236395767 (patched)
vmlinux.o: warning: objtool: no correlation: c_start.llvm.1768504738091882651
vmlinux.o: warning: objtool: no correlation: c_stop.llvm.1768504738091882651
vmlinux.o: warning: objtool: no correlation: c_next.llvm.1768504738091882651
vmlinux.o: new function: c_start.llvm.10047843810948474008
vmlinux.o: new function: c_stop.llvm.10047843810948474008
vmlinux.o: new function: c_next.llvm.10047843810948474008
vmlinux.o: changed function: c_start.llvm.14107081093236395767
vmlinux.o: changed function: c_stop.llvm.14107081093236395767
vmlinux.o: changed function: c_next.llvm.14107081093236395767
Building patch module: livepatch-min.ko
SUCCESS

And since we're here, it looks like there's a type:
s/origial/original/g.

--
Joe


^ permalink raw reply related

* Re: [PATCH v3 13/13] livepatch/klp-build: don't look for changed objects in tools/
From: Joe Lawrence @ 2026-02-18 15:18 UTC (permalink / raw)
  To: Song Liu
  Cc: live-patching, Josh Poimboeuf, Jiri Kosina, Miroslav Benes,
	Petr Mladek
In-Reply-To: <CAPhsuW6=9OUGdLBR1OhNDk2tbFncGfYe+z7HDr16si06g4AXGw@mail.gmail.com>

On Tue, Feb 17, 2026 at 11:29:13AM -0800, Song Liu wrote:
> On Tue, Feb 17, 2026 at 8:07 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
> 
> I guess we still need a short commit message.
> 

Heh, checkpatch complained, but I didn't think such a trivial change
needed a full body :)

> Could you please share the patch that needs this change?
> 

Sorry I don't have a specific patch or repro for this one.  I hit this
during one of my -T, -T -S 2 short-circuiting testing runs.  I got an
error like this:

  error: klp-build: missing livepatch-cmdline-string.o for tools/testing/selftests/klp-build/artifacts/full-virtme-ng/cmdline-string/livepatch-cmdline-string.ko

to which I wondered why are we even looking for changed kernel objects
in tools/ ?  That directory may be stuffed with other weird stuff, a
combination of user-space and kernel-test .o's, so why bother? 

I can drop this one until it becomes something required.

--
Joe

> Thanks,
> Song
> 
> > Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
> > ---
> >  scripts/livepatch/klp-build | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
> > index 5367d573b94b..9bbce09cfb74 100755
> > --- a/scripts/livepatch/klp-build
> > +++ b/scripts/livepatch/klp-build
> > @@ -564,8 +564,8 @@ find_objects() {
> >         local opts=("$@")
> >
> >         # Find root-level vmlinux.o and non-root-level .ko files,
> > -       # excluding klp-tmp/ and .git/
> > -       find "$OBJ" \( -path "$TMP_DIR" -o -path "$OBJ/.git" -o -regex "$OBJ/[^/][^/]*\.ko" \) -prune -o \
> > +       # excluding klp-tmp/, .git/, and tools/
> > +       find "$OBJ" \( -path "$TMP_DIR" -o -path "$OBJ/.git" -o -path "$OBJ/tools" -o -regex "$OBJ/[^/][^/]*\.ko" \) -prune -o \
> >                     -type f "${opts[@]}"                                \
> >                     \( -name "*.ko" -o -path "$OBJ/vmlinux.o" \)        \
> >                     -printf '%P\n'
> > --
> > 2.53.0
> >
> >
> 


^ permalink raw reply

* Re: [PATCH v3 12/13] livepatch/klp-build: report patch validation drift
From: Joe Lawrence @ 2026-02-18 15:09 UTC (permalink / raw)
  To: Song Liu
  Cc: live-patching, Josh Poimboeuf, Jiri Kosina, Miroslav Benes,
	Petr Mladek
In-Reply-To: <CAPhsuW4YN5PYp3iF8P3pBGF8vP62m0L-yEfD1pBut6fL+78N2Q@mail.gmail.com>

On Tue, Feb 17, 2026 at 11:42:21AM -0800, Song Liu wrote:
> On Tue, Feb 17, 2026 at 8:07 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
> >
> > Capture the output of the patch command to detect when a patch applies
> > with fuzz or line offsets.
> >
> > If such "drift" is detected during the validation phase, warn the user
> > and display the details.  This helps identify input patches that may need
> > refreshing against the target source tree.
> >
> > Ensure that internal patch operations (such as those in refresh_patch or
> > during the final build phase) can still run quietly.
> >
> > Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
> > ---
> >  scripts/livepatch/klp-build | 24 +++++++++++++++++++-----
> >  1 file changed, 19 insertions(+), 5 deletions(-)
> >
> > diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
> > index fd104ace29e6..5367d573b94b 100755
> > --- a/scripts/livepatch/klp-build
> > +++ b/scripts/livepatch/klp-build
> > @@ -369,11 +369,24 @@ check_unsupported_patches() {
> >
> >  apply_patch() {
> >         local patch="$1"
> > +       shift
> > +       local extra_args=("$@")
> > +       local drift_regex="with fuzz|offset [0-9]+ line"
> > +       local output
> > +       local status
> >
> >         [[ ! -f "$patch" ]] && die "$patch doesn't exist"
> > -       patch -d "$SRC" -p1 --dry-run --silent --no-backup-if-mismatch -r /dev/null < "$patch"
> > -       patch -d "$SRC" -p1 --silent --no-backup-if-mismatch -r /dev/null < "$patch"
> > +       status=0
> > +       output=$(patch -d "$SRC" -p1 --dry-run --no-backup-if-mismatch -r /dev/null "${extra_args[@]}" < "$patch" 2>&1) || status=$?
> > +       if [[ "$status" -ne 0 ]]; then
> > +               echo "$output"
> > +               die "$patch did not apply"
> > +       elif [[ "$output" =~ $drift_regex ]]; then
> > +               warn "$patch applied with drift"
> > +               echo "$output"
> > +       fi
> 
> It appears we only need the non-silent "patch" command and the reporting
> logic in validate_patches(). Maybe we can have a different version of
> apply_patches for validate_patches(), say apply_patches_verbose(), and
> keep existing apply_patch() and apply_patches as-is?
> 

Yes, you're right about the reporting cases.  Splitting might be
cleaner, I'll consider for v4.  This logic does get a little hairy to
handle the two cases of when we want to see output vs. not.  (set -o
errexit forces us to disarm anything that might throw an error and bring
down the whole show.) 

--
Joe


^ permalink raw reply

* Re: [PATCH v3 09/13] livepatch/klp-build: fix version mismatch when short-circuiting
From: Joe Lawrence @ 2026-02-18 15:04 UTC (permalink / raw)
  To: Song Liu
  Cc: live-patching, Josh Poimboeuf, Jiri Kosina, Miroslav Benes,
	Petr Mladek
In-Reply-To: <CAPhsuW55E-T0gg4zFitjVB81+y5wHPEQ0665MDPnznV9=9Y1+g@mail.gmail.com>

On Tue, Feb 17, 2026 at 11:25:13AM -0800, Song Liu wrote:
> On Tue, Feb 17, 2026 at 8:17 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
> >
> [...]
> > > 2.53.0
> > >
> > >
> >
> > Maybe I'm starting to see things, but when running 'S 2' builds, I keep
> > getting "vmlinux.o: changed function: override_release".  It could be
> > considered benign for quick development work, or confusing.  Seems easy
> > enough to stash and avoid.
> 
> "-S 2" with a different set of patches is only needed in patch development,
> but not used for official releases. Therefore, I agree this is not a real issue.
> 

My use case was running a series of tests:

  (test 1) - full build with -T
  (test N) - short circuit with -S 2 -T
  ...

and where it confused me was that I had created tests which were
designed to fail, specifically one wanted to verify no changes found
for the recountdiff change in this set.

Without this patch, that test will succeed as the version glitch gets
picked up as:

  vmlinux.o: changed function: override_release

I could work around that in verification, but then I miss the *specific*
failure report from klp-build.  I could also run each individual test as
full, but each build was taking ~6 minutes on my machine.

--
Joe


^ permalink raw reply

* Re: [PATCH v3 12/13] livepatch/klp-build: report patch validation drift
From: Song Liu @ 2026-02-17 19:42 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: live-patching, Josh Poimboeuf, Jiri Kosina, Miroslav Benes,
	Petr Mladek
In-Reply-To: <20260217160645.3434685-13-joe.lawrence@redhat.com>

On Tue, Feb 17, 2026 at 8:07 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
>
> Capture the output of the patch command to detect when a patch applies
> with fuzz or line offsets.
>
> If such "drift" is detected during the validation phase, warn the user
> and display the details.  This helps identify input patches that may need
> refreshing against the target source tree.
>
> Ensure that internal patch operations (such as those in refresh_patch or
> during the final build phase) can still run quietly.
>
> Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
> ---
>  scripts/livepatch/klp-build | 24 +++++++++++++++++++-----
>  1 file changed, 19 insertions(+), 5 deletions(-)
>
> diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
> index fd104ace29e6..5367d573b94b 100755
> --- a/scripts/livepatch/klp-build
> +++ b/scripts/livepatch/klp-build
> @@ -369,11 +369,24 @@ check_unsupported_patches() {
>
>  apply_patch() {
>         local patch="$1"
> +       shift
> +       local extra_args=("$@")
> +       local drift_regex="with fuzz|offset [0-9]+ line"
> +       local output
> +       local status
>
>         [[ ! -f "$patch" ]] && die "$patch doesn't exist"
> -       patch -d "$SRC" -p1 --dry-run --silent --no-backup-if-mismatch -r /dev/null < "$patch"
> -       patch -d "$SRC" -p1 --silent --no-backup-if-mismatch -r /dev/null < "$patch"
> +       status=0
> +       output=$(patch -d "$SRC" -p1 --dry-run --no-backup-if-mismatch -r /dev/null "${extra_args[@]}" < "$patch" 2>&1) || status=$?
> +       if [[ "$status" -ne 0 ]]; then
> +               echo "$output"
> +               die "$patch did not apply"
> +       elif [[ "$output" =~ $drift_regex ]]; then
> +               warn "$patch applied with drift"
> +               echo "$output"
> +       fi

It appears we only need the non-silent "patch" command and the reporting
logic in validate_patches(). Maybe we can have a different version of
apply_patches for validate_patches(), say apply_patches_verbose(), and
keep existing apply_patch() and apply_patches as-is?

Thanks,
Song

>
> +       patch -d "$SRC" -p1 --no-backup-if-mismatch -r /dev/null "${extra_args[@]}" --silent < "$patch"
>         APPLIED_PATCHES+=("$patch")
>  }
>
> @@ -392,10 +405,11 @@ revert_patch() {
>  }
>
>  apply_patches() {
> +       local extra_args=("$@")
>         local patch
>
>         for patch in "${PATCHES[@]}"; do
> -               apply_patch "$patch"
> +               apply_patch "$patch" "${extra_args[@]}"
>         done
>  }
>
> @@ -453,7 +467,7 @@ refresh_patch() {
>         ( cd "$SRC" && echo "${input_files[@]}" | xargs cp --parents --target-directory="$tmpdir/a" )
>
>         # Copy patched source files to 'b'
> -       apply_patch "$patch"
> +       apply_patch "$patch" "--silent"
>         ( cd "$SRC" && echo "${output_files[@]}" | xargs cp --parents --target-directory="$tmpdir/b" )
>         revert_patch "$patch"
>
> @@ -826,7 +840,7 @@ fi
>  if (( SHORT_CIRCUIT <= 2 )); then
>         status "Fixing patch(es)"
>         fix_patches
> -       apply_patches
> +       apply_patches "--silent"
>         status "Building patched kernel"
>         build_kernel "patched"
>         revert_patches
> --
> 2.53.0
>

^ permalink raw reply

* Re: [PATCH v3 13/13] livepatch/klp-build: don't look for changed objects in tools/
From: Song Liu @ 2026-02-17 19:29 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: live-patching, Josh Poimboeuf, Jiri Kosina, Miroslav Benes,
	Petr Mladek
In-Reply-To: <20260217160645.3434685-14-joe.lawrence@redhat.com>

On Tue, Feb 17, 2026 at 8:07 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:

I guess we still need a short commit message.

Could you please share the patch that needs this change?

Thanks,
Song

> Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
> ---
>  scripts/livepatch/klp-build | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
> index 5367d573b94b..9bbce09cfb74 100755
> --- a/scripts/livepatch/klp-build
> +++ b/scripts/livepatch/klp-build
> @@ -564,8 +564,8 @@ find_objects() {
>         local opts=("$@")
>
>         # Find root-level vmlinux.o and non-root-level .ko files,
> -       # excluding klp-tmp/ and .git/
> -       find "$OBJ" \( -path "$TMP_DIR" -o -path "$OBJ/.git" -o -regex "$OBJ/[^/][^/]*\.ko" \) -prune -o \
> +       # excluding klp-tmp/, .git/, and tools/
> +       find "$OBJ" \( -path "$TMP_DIR" -o -path "$OBJ/.git" -o -path "$OBJ/tools" -o -regex "$OBJ/[^/][^/]*\.ko" \) -prune -o \
>                     -type f "${opts[@]}"                                \
>                     \( -name "*.ko" -o -path "$OBJ/vmlinux.o" \)        \
>                     -printf '%P\n'
> --
> 2.53.0
>
>

^ permalink raw reply

* Re: [PATCH v3 09/13] livepatch/klp-build: fix version mismatch when short-circuiting
From: Song Liu @ 2026-02-17 19:25 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: live-patching, Josh Poimboeuf, Jiri Kosina, Miroslav Benes,
	Petr Mladek
In-Reply-To: <aZSUfFUfpUYIbuiA@redhat.com>

On Tue, Feb 17, 2026 at 8:17 AM Joe Lawrence <joe.lawrence@redhat.com> wrote:
>
[...]
> > 2.53.0
> >
> >
>
> Maybe I'm starting to see things, but when running 'S 2' builds, I keep
> getting "vmlinux.o: changed function: override_release".  It could be
> considered benign for quick development work, or confusing.  Seems easy
> enough to stash and avoid.

"-S 2" with a different set of patches is only needed in patch development,
but not used for official releases. Therefore, I agree this is not a real issue.

Thanks,
Song

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox