Live Patching
 help / color / mirror / Atom feed
* Re: [PATCH v3 7/8] objtool/klp: Correlate locals to globals
From: Song Liu @ 2026-03-05 23:10 UTC (permalink / raw)
  To: Josh Poimboeuf
  Cc: live-patching, jikos, mbenes, pmladek, joe.lawrence, kernel-team
In-Reply-To: <4j5chvfnlugrpycrehextkinzfle7mokkos4ooa2ali2susov7@ncunycnjajtu>

On Thu, Mar 5, 2026 at 11:51 AM Josh Poimboeuf <jpoimboe@kernel.org> wrote:
>
> On Wed, Feb 25, 2026 at 04:54:35PM -0800, Song Liu wrote:
> > 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 | 34 ++++++++++++++++++++++++++++++++++
> >  1 file changed, 34 insertions(+)
> >
> > diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
> > index 92043da0ed0b..5cda965807a5 100644
> > --- a/tools/objtool/klp-diff.c
> > +++ b/tools/objtool/klp-diff.c
> > @@ -517,6 +517,40 @@ 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);
>
> I think this correlation is deterministic so there's no need for the
> warning?

Yes, we can remove this.

I also fixed 1/8 and 3/8. I will send v4 of patch 1/8 to 7/8, as we discuss
more with 8/8.

Thanks,
Song

^ permalink raw reply

* [PATCH] klp-build: Fix inconsistent kernel version
From: Josh Poimboeuf @ 2026-03-05 22:52 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: live-patching, Song Liu, Jiri Kosina, Miroslav Benes, Petr Mladek
In-Reply-To: <w6uwlcdd7eb247lj4r5khrliiymbpapshmaror3x3olfaamj6a@4ukxobzqj7fo>

If .config hasn't been synced with auto.conf, any recent changes to
CONFIG_LOCALVERSION* may not get reflected in the kernel version name.

Use "make syncconfig" to force them to sync, and "make kernelrelease" to
get the version instead of having to construct it manually.

Fixes: 24ebfcd65a87 ("livepatch/klp-build: Introduce klp-build script for generating livepatch modules")
Closes: https://lore.kernel.org/20260217160645.3434685-10-joe.lawrence@redhat.com
Reported-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 scripts/livepatch/klp-build | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index 809e198a561d..72f05c40b9f8 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -285,15 +285,14 @@ set_module_name() {
 # application from appending it with '+' due to a dirty git working tree.
 set_kernelversion() {
 	local file="$SRC/scripts/setlocalversion"
-	local localversion
+	local kernelrelease
 
 	stash_file "$file"
 
-	localversion="$(cd "$SRC" && make --no-print-directory kernelversion)"
-	localversion="$(cd "$SRC" && KERNELVERSION="$localversion" ./scripts/setlocalversion)"
-	[[ -z "$localversion" ]] && die "setlocalversion failed"
+	kernelrelease="$(cd "$SRC" && make syncconfig &>/dev/null && make kernelrelease)"
+	[[ -z "$kernelrelease" ]] && die "failed to get kernel version"
 
-	sed -i "2i echo $localversion; exit 0" scripts/setlocalversion
+	sed -i "2i echo $kernelrelease; exit 0" scripts/setlocalversion
 }
 
 get_patch_files() {
-- 
2.53.0


^ permalink raw reply related

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

On Mon, Mar 02, 2026 at 09:20:00PM -0500, Joe Lawrence wrote:
> I finally figured out why you couldn't reproduce, in my tests, I never
> built the original kernel, I jumped straight from a clean repo to
> starting up klp-build.  If I perform an initial make before running
> klp-build, then the sequence works as expected. 
> 
> - If skipping the initial vmlinux is an unsupported use-case, then we
>   can ignore and drop this patch,
> - or perhaps detect and warn/error out 
> - If this is something we need to support, then your suggested version
>   below didn't work out either...
> 
> The following change committed on top of v7.0-rc2:

Thanks, I was able to reproduce this and figure it out.  The problem is
that "make oldconfig" doesn't sync auto.conf, whereas a full make does.

So if you do "make kernelrelease" before the first build, it may be
wrong.

And apparently that's intentional:

  commit a29d4d8c5669a658b5a091b38205c13084967ce7
  Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  Date:   Fri Jul 20 16:46:35 2018 +0900
  
      kbuild: do not update config for 'make kernelrelease'
      
      'make kernelrelease' depends on CONFIG_LOCALVERSION(_AUTO), but
      for the same reason as install targets, we do not want to update
      the configuration just for printing the kernelrelease string.
      
      This is likely to happen when you compiled the kernel with
      CROSS_COMPILE, but forget to pass it to 'make kernelrelease'.
      
      Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
  
  diff --git a/Makefile b/Makefile
  index 8ca9e0b114f1..060874d85e0d 100644
  --- a/Makefile
  +++ b/Makefile
  @@ -225,7 +225,8 @@ no-dot-config-targets := $(clean-targets) \
   			 cscope gtags TAGS tags help% %docs check% coccicheck \
   			 $(version_h) headers_% archheaders archscripts \
   			 kernelversion %src-pkg
  -no-sync-config-targets := $(no-dot-config-targets) install %install
  +no-sync-config-targets := $(no-dot-config-targets) install %install \
  +			   kernelrelease
   
   config-targets  := 0
   mixed-targets   := 0



So the fix is just to do "make syncconfig" before the "make
kernelrelease".  Let me write up a proper patch.

-- 
Josh

^ permalink raw reply

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

On Mon, Mar 02, 2026 at 09:30:23PM -0500, Joe Lawrence wrote:
> On Mon, Feb 23, 2026 at 01:41:58PM -0800, Josh Poimboeuf wrote:
> > On Tue, Feb 17, 2026 at 11:06:44AM -0500, Joe Lawrence wrote:
> > > Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
> > > ---
> > >  scripts/livepatch/klp-build | 4 ++--
> > >  1 file changed, 2 insertions(+), 2 deletions(-)
> > 
> > Why?
> > 
> 
> I don't have a pithy repro captured here, so I can just drop this for
> now.  I was playing with building klp-build selftest modules and
> stashing the resulting .ko's under tools/testing/selftests.
> Occasionally subsequent klp-builds would get confused when seeing only a
> .ko and complaint about missing ancestor object files.  Which led me to
> ask, why does it look in directories that don't even include kernel
> build artifacts.

Yeah, I don't necessarily object to the change, but it would be nice to
have some kind of justification in the commit log.

-- 
Josh

^ permalink raw reply

* Re: [PATCH v3 11/13] livepatch/klp-build: add terminal color output
From: Josh Poimboeuf @ 2026-03-05 20:08 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: live-patching, Song Liu, Jiri Kosina, Miroslav Benes, Petr Mladek
In-Reply-To: <aaZGXPbyH3QmrcQs@redhat.com>

On Mon, Mar 02, 2026 at 09:24:28PM -0500, Joe Lawrence wrote:
> On Mon, Feb 23, 2026 at 01:32:09PM -0800, Josh Poimboeuf wrote:
> > On Mon, Feb 23, 2026 at 01:28:45PM -0800, Josh Poimboeuf wrote:
> > > On Tue, Feb 17, 2026 at 11:06:42AM -0500, Joe Lawrence wrote:
> > > > Improve the readability of klp-build output by implementing a basic
> > > > color scheme.  When the standard output and error are connected to a
> > > > terminal, highlight status messages in bold, warnings in yellow, and
> > > > errors in red.
> > > > 
> > > > Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
> > > > ---
> > > >  scripts/livepatch/klp-build | 15 ++++++++++++---
> > > >  1 file changed, 12 insertions(+), 3 deletions(-)
> > > > 
> > > > diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
> > > > index 80703ec4d775..fd104ace29e6 100755
> > > > --- a/scripts/livepatch/klp-build
> > > > +++ b/scripts/livepatch/klp-build
> > > > @@ -52,6 +52,15 @@ PATCH_TMP_DIR="$TMP_DIR/tmp"
> > > >  
> > > >  KLP_DIFF_LOG="$DIFF_DIR/diff.log"
> > > >  
> > > > +# Terminal output colors
> > > > +read -r COLOR_RESET COLOR_BOLD COLOR_ERROR COLOR_WARN <<< ""
> > > > +if [[ -t 1 && -t 2 ]]; then
> > > > +	COLOR_RESET="\033[0m"
> > > > +	COLOR_BOLD="\033[1m"
> > > > +	COLOR_ERROR="\033[0;31m"
> > > > +	COLOR_WARN="\033[0;33m"
> > > > +fi
> > > > +
> > > >  grep0() {
> > > >  	# shellcheck disable=SC2317
> > > >  	command grep "$@" || true
> > > > @@ -65,15 +74,15 @@ grep() {
> > > >  }
> > > >  
> > > >  status() {
> > > > -	echo "$*"
> > > > +	echo -e "${COLOR_BOLD}$*${COLOR_RESET}"
> > > >  }
> > > >  
> > > >  warn() {
> > > > -	echo "error: $SCRIPT: $*" >&2
> > > > +	echo -e "${COLOR_WARN}warn${COLOR_RESET}: $SCRIPT: $*" >&2
> > > 
> > > Shouldn't this reset the colors *after* printing out the whole message?
> > > 
> 
> Colorizing the "warn:" and "error:" was intended to look similar to gcc
> color output.  I can easily highlight the entire message if you prefer.

I guess I was confused because a) the commit log made it sound like the
entire warning is in color and b) the status messages are also for the
entire message.

I don't know if I have a preference either way, but at least the commit
log should make the intended behavior more clear.

-- 
Josh

^ permalink raw reply

* Re: [PATCH v3 7/8] objtool/klp: Correlate locals to globals
From: Josh Poimboeuf @ 2026-03-05 19:51 UTC (permalink / raw)
  To: Song Liu; +Cc: live-patching, jikos, mbenes, pmladek, joe.lawrence, kernel-team
In-Reply-To: <20260226005436.379303-8-song@kernel.org>

On Wed, Feb 25, 2026 at 04:54:35PM -0800, Song Liu wrote:
> 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 | 34 ++++++++++++++++++++++++++++++++++
>  1 file changed, 34 insertions(+)
> 
> diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c
> index 92043da0ed0b..5cda965807a5 100644
> --- a/tools/objtool/klp-diff.c
> +++ b/tools/objtool/klp-diff.c
> @@ -517,6 +517,40 @@ 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);

I think this correlation is deterministic so there's no need for the
warning?

> +		}
> +	}
> +
> +	/* 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->orig, 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);
> +		}

Ditto.

-- 
Josh

^ permalink raw reply

* Re: [PATCH v3 3/8] objtool/klp: Use sym->demangled_name for symbol_name hash
From: Josh Poimboeuf @ 2026-03-05 19:43 UTC (permalink / raw)
  To: Song Liu; +Cc: live-patching, jikos, mbenes, pmladek, joe.lawrence, kernel-team
In-Reply-To: <20260226005436.379303-4-song@kernel.org>

On Wed, Feb 25, 2026 at 04:54:31PM -0800, Song Liu wrote:
> +/*
> + * 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;
> +}

This actually returns the index of the last char rather than the length.
Should "len" be renamed to "idx" and then it can return "idx + 1"?

-- 
Josh

^ permalink raw reply

* Re: [PATCH v3 1/8] objtool/klp: Remove redundent strcmp in correlate_symbols
From: Josh Poimboeuf @ 2026-03-05 19:38 UTC (permalink / raw)
  To: Song Liu; +Cc: live-patching, jikos, mbenes, pmladek, joe.lawrence, kernel-team
In-Reply-To: <20260226005436.379303-2-song@kernel.org>

On Wed, Feb 25, 2026 at 04:54:29PM -0800, Song Liu wrote:
> 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;

Subject has a typo ("redundent"), and function names are missing "()":

  Remove redundant strcmp() in correlate_symbols()

-- 
Josh

^ permalink raw reply

* Re: [PATCH v3 8/8] livepatch: Add tests for klp-build toolchain
From: Josh Poimboeuf @ 2026-03-05 19:33 UTC (permalink / raw)
  To: Song Liu; +Cc: live-patching, jikos, mbenes, pmladek, joe.lawrence, kernel-team
In-Reply-To: <20260226005436.379303-9-song@kernel.org>

On Wed, Feb 25, 2026 at 04:54:36PM -0800, Song Liu wrote:
> 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>

This patch has some whitespace errors:

/tmp/a:505: space before tab in indent.
 	int i, sum = x;
/tmp/a:506: trailing whitespace.

/tmp/a:507: space before tab in indent.
 	for (i = 0; i < len; i++)
/tmp/a:510: space before tab in indent.
 	if (sum > 1000)
/tmp/a:511: space before tab in indent.
 		sum = 0;
warning: squelched 28 whitespace errors
warning: 33 lines add whitespace errors.


-- 
Josh

^ permalink raw reply

* Re: [PATCH v3 8/8] livepatch: Add tests for klp-build toolchain
From: Josh Poimboeuf @ 2026-03-05 18:50 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: Miroslav Benes, Song Liu, live-patching, jikos, pmladek,
	kernel-team
In-Reply-To: <aaiI7zv2JVgXZkPm@redhat.com>

On Wed, Mar 04, 2026 at 02:33:03PM -0500, Joe Lawrence wrote:
> On Mon, Mar 02, 2026 at 09:38:17AM +0100, Miroslav Benes wrote:
> > Him
> > 
> > > > We store test modules in tools/testing/selftests/livepatch/test_modules/
> > > > now. Could you move klp_test_module.c there, please? You might also reuse
> > > > existing ones for the purpose perhaps.
> > > 
> > > IIUC, tools/testing/selftests/livepatch/test_modules/ is more like an out
> > > of tree module. In the case of testing klp-build, we prefer to have it to
> > > work the same as in-tree modules. This is important because klp-build
> > > is a toolchain, and any changes of in-tree Makefiles may cause issues
> > > with klp-build. Current version can catch these issues easily. If we build
> > > the test module as an OOT module, we may miss some of these issues.
> > > In the longer term, we should consider adding klp-build support to build
> > > livepatch for OOT modules. But for now, good test coverage for in-tree
> > > modules are more important.
> > 
> > Ok. I thought it would not matter but it is a fair point.
> > 
> > > > What about vmlinux? I understand that it provides a lot more flexibility
> > > > to have separate functions for testing but would it be somehow sufficient
> > > > to use the existing (real) kernel functions? Like cmdline_proc_show() and
> > > > such which we use everywhere else? Or would it be to limited? I am fine if
> > > > you find it necessary in the end. I just think that reusing as much as
> > > > possible is generally a good approach.
> > > 
> > > I think using existing functions would be too limited, and Joe seems to
> > > agree with this based on his experience. To be able to test corner cases
> > > of the compiler/linker, such as LTO, we need special code patterns.
> > > OTOH, if we want to use an existing kernel function for testing, it needs
> > > to be relatively stable, i.e., not being changed very often. It is not always
> > > easy to find some known to be stable code that follows specific patterns.
> > > If we add dedicated code as test targets, things will be much easier
> > > down the road.
> > 
> > Fair enough.
> > 
> 
> I've been tinkering with ideas in this space, though I took it in a very
> different direction.
> 
> (First a disclaimer, this effort is largely the result of vibe coding
> with Claude to prototype testing concepts, so I don't believe any of it
> is reliable or upstream-worthy at this point.)
> 
> From a top-down perspective, I might start with the generated test
> reports:

Thanks Song and Joe, these are some great ideas.  Testing will be
extremely important for the success of klp-build.

Below are some back of napkin thoughts based on my experiences with
kpatch testing.  In my opinion the unit/integration test split for
kpatch was successful and we should try to continue that tradition with
klp-build.

- unit testing (.o diff)
  - great for preventing past regressions
  - nice and fast
  - tests the most fragile bits
  - catches 99% of bugs (almost everything except for new kernel/compiler features)
  - try to enforce a rule: one test for every regression
  - if we're storing binaries we may need to host the test suite elsewhere
  - extracting .o's could be more of a challenge now that vmlinux.o diff is the norm
    - the making of regression tests needs to be as easy as possible
  - or maybe they can be built on demand with .c and/or .S?
    - that *might* be more difficult
    - we'd need meta-tests to ensure the tests continue to test what they're supposed to

- integration testing: 
  - good for testing "this complex end-to-end operation still works"
  - good for finding issues with new toolchain versions and new kernel features
  - can be used for testing certain runtime-critical features like static branches/calls
  - not necessarily good for testing regressions, the underlying code is free to change at any time
  - I like Song's idea of adding a fake (yet stable) test component in vmlinux for which we can create .patch files to test
  - I also like Joe's idea of scripted patch generation (e.g., automatically patching meminfo_proc_show() somehow)

And in general, we may want to look to porting as many of the kpatch
unit/integration tests as possible so we can take advantage of all those
accumulated testing experiences.

-- 
Josh

^ permalink raw reply

* Re: [PATCH v3 8/8] livepatch: Add tests for klp-build toolchain
From: Petr Mladek @ 2026-03-05 15:20 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: Miroslav Benes, Song Liu, live-patching, jpoimboe, jikos,
	kernel-team
In-Reply-To: <aaiI7zv2JVgXZkPm@redhat.com>

On Wed 2026-03-04 14:33:03, Joe Lawrence wrote:
> On Mon, Mar 02, 2026 at 09:38:17AM +0100, Miroslav Benes wrote:
> > Him
> > 
> > > > We store test modules in tools/testing/selftests/livepatch/test_modules/
> > > > now. Could you move klp_test_module.c there, please? You might also reuse
> > > > existing ones for the purpose perhaps.
> > > 
> > > IIUC, tools/testing/selftests/livepatch/test_modules/ is more like an out
> > > of tree module. In the case of testing klp-build, we prefer to have it to
> > > work the same as in-tree modules. This is important because klp-build
> > > is a toolchain, and any changes of in-tree Makefiles may cause issues
> > > with klp-build. Current version can catch these issues easily. If we build
> > > the test module as an OOT module, we may miss some of these issues.
> > > In the longer term, we should consider adding klp-build support to build
> > > livepatch for OOT modules. But for now, good test coverage for in-tree
> > > modules are more important.
> > 
> > Ok. I thought it would not matter but it is a fair point.
> > 
> > > > What about vmlinux? I understand that it provides a lot more flexibility
> > > > to have separate functions for testing but would it be somehow sufficient
> > > > to use the existing (real) kernel functions? Like cmdline_proc_show() and
> > > > such which we use everywhere else? Or would it be to limited? I am fine if
> > > > you find it necessary in the end. I just think that reusing as much as
> > > > possible is generally a good approach.
> > > 
> > > I think using existing functions would be too limited, and Joe seems to
> > > agree with this based on his experience. To be able to test corner cases
> > > of the compiler/linker, such as LTO, we need special code patterns.
> > > OTOH, if we want to use an existing kernel function for testing, it needs
> > > to be relatively stable, i.e., not being changed very often. It is not always
> > > easy to find some known to be stable code that follows specific patterns.
> > > If we add dedicated code as test targets, things will be much easier
> > > down the road.
> > 
> > Fair enough.
> > 
> Do the helpers in functions.sh for safely loading and unloading
> livepatches (that wait for the transition, etc.) aid here?
> 
> > > > And a little bit of bikeshedding at the end. I think it would be more
> > > > descriptive if the new config options and tests (test modules) have
> > > > klp-build somewhere in the name to keep it clear. What do you think?
> > > 
> > > Technically, we can also use these tests to test other toolchains, for
> > > example, kpatch-build. I don't know ksplice or kGraft enough to tell
> > > whether they can benefit from these tests or not. OTOH, I am OK
> > > changing the name/description of these config options.
> > 
> > I would prefer it, thank you. Unless someone else objects of course.
> > 
> 
> To continue the bike shedding, in my branch, I had dumped this all under
> a new tools/testing/klp-build subdirectory as my focus was to put
> klp-build through the paces.  It does load the generated livepatches in
> the runtime testing, but as only as a sanity check.  With that, it
> didn't touch CONFIG or intermix testing with the livepatch/ set.

The question is what you expect from the klp-build testing.

My understanding is that the current test primary checks whether:

  + klp-build machinery is able to put together a working livepatch
  + "objtool klp diff" is able to find and match the right symbols

I assume this because the README contains a very simple steps:

    <paste>
    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
    </paste>

A separate directory would be perfectly fine in this case.

We could keep the existing selftests/livepatch as is for
testing the kernel/livepatch features, e.g. transition,
shadow variables, callbacks, cooperation with ftrace/kprobe.

An integration with the existing selftests/livepatch would be
better if you wanted to do more complicated tests. You
might want to reuse the existing framework for checking
the dmesg output.

Honestly, I guess that we would want to integrate both tests
sooner or later anyway. You might want to test how klp-build
handles the extra features, e.g. shadow variables, ...

But the integration might be non-trivial.

> If we do end up supplementing the livepatch/ with klp-build tests, then
> I agree that naming them (either filename prefix or subdirectory) would
> be nice.
> 
> But first, is it goal for klp-build to be the build tool (rather than
> simple module kbuild) for the livepatching .ko selftests?

Best Regards,
Petr

PS: Sigh, I hope that I'll find time to send v2 of the patchset reworking
    the callbacks, shadow variables, and states. It modifies/reworks
    the existing selftests modules a lot, see v1 at
    https://lore.kernel.org/all/20250115082431.5550-1-pmladek@suse.com/

^ permalink raw reply

* Re: [PATCH v3 8/8] livepatch: Add tests for klp-build toolchain
From: Joe Lawrence @ 2026-03-05 15:18 UTC (permalink / raw)
  To: Petr Mladek, Song Liu
  Cc: Miroslav Benes, live-patching, jpoimboe, jikos, kernel-team
In-Reply-To: <aamOXVxBXF8ivyVf@pathway.suse.cz>

On 3/5/26 9:08 AM, Petr Mladek wrote:
> On Wed 2026-03-04 21:03:41, Song Liu wrote:
>> On Wed, Mar 4, 2026 at 5:39 PM Joe Lawrence <joe.lawrence@redhat.com> wrote:
>>>>> (Tangent: kpatch-build implemented a unit test scheme that cached object
>>>>> files for even greater speed and fixed testing.  I haven't thought about
>>>>> how a similar idea might work for klp-build.)
>>>>
>>>> I think it is a good idea to have similar .o file tests for klp-diff
>>>> in klp-build.
>>>>
>>>
>>> kpatch-build uses a git submodule (a joy to work with /s), but maybe
>>> upstream tree can fetch the binary objects from some external
>>> (github/etc.) source?  I wonder if there is any kselftest precident for
>>> this, we'll need to investigate that.
>>
>> Ah, right. I forgot that carrying .o files in the upstream kernel is a bit
>> weird. That may indeed be a blocker.
> 
> I am afraind that caching .o files in the upstream git tree can't work
> in priniple. The upstream tree is generic. But .o files are comparable
> only when using the same toolchain, ...
> 
> Or do I miss anything, please?
> 

Hi Petr,

For kpatch-build, the cached object files were placed in a separate repo
away from the source code:

  https://github.com/dynup/kpatch-unit-test-objs/commits/master/

and its purpose is mostly to avoid regressions against known code
sequences (i.e. gcc omitting symbol section symbols, clang unnamed
sections, static call tests, etc.)  It only exercises the binary
comparison code and not full livepatch generation, so it never creates
or loads any .ko.

But you are right that the toolchain, optimization levels, etc. can all
contribute to generating unique code sequences.  The unit-test-objs were
 a (huge time) optimization to avoid building kernels just to check
things that should be generated 99% of the time -- or perhaps never,
given the toolchains we had on hand.  For example, we've converted a few
user bug reports into unit tests as we didn't have a particular compiler
version or kernel config at the ready.

It's a nice tool to be able to run a `make unit` test against your
development branch and have an answer in a few minutes.  The full `make
integration` test takes at least a few coffee cups and dog walks to
complete :D

Hope that clarifies things?

Regards,

-- 
Joe


^ permalink raw reply

* Re: [PATCH v3 8/8] livepatch: Add tests for klp-build toolchain
From: Petr Mladek @ 2026-03-05 14:08 UTC (permalink / raw)
  To: Song Liu
  Cc: Joe Lawrence, Miroslav Benes, live-patching, jpoimboe, jikos,
	kernel-team
In-Reply-To: <CAPhsuW51ihr9mDv6Ov+vJAn_7feqTra2XFXUFm-cb4teE_4s8w@mail.gmail.com>

On Wed 2026-03-04 21:03:41, Song Liu wrote:
> On Wed, Mar 4, 2026 at 5:39 PM Joe Lawrence <joe.lawrence@redhat.com> wrote:
> > > > (Tangent: kpatch-build implemented a unit test scheme that cached object
> > > > files for even greater speed and fixed testing.  I haven't thought about
> > > > how a similar idea might work for klp-build.)
> > >
> > > I think it is a good idea to have similar .o file tests for klp-diff
> > > in klp-build.
> > >
> >
> > kpatch-build uses a git submodule (a joy to work with /s), but maybe
> > upstream tree can fetch the binary objects from some external
> > (github/etc.) source?  I wonder if there is any kselftest precident for
> > this, we'll need to investigate that.
> 
> Ah, right. I forgot that carrying .o files in the upstream kernel is a bit
> weird. That may indeed be a blocker.

I am afraind that caching .o files in the upstream git tree can't work
in priniple. The upstream tree is generic. But .o files are comparable
only when using the same toolchain, ...

Or do I miss anything, please?

Best Regards,
Petr

^ permalink raw reply

* Re: [PATCH v3 8/8] livepatch: Add tests for klp-build toolchain
From: Song Liu @ 2026-03-05  5:03 UTC (permalink / raw)
  To: Joe Lawrence
  Cc: Miroslav Benes, live-patching, jpoimboe, jikos, pmladek,
	kernel-team
In-Reply-To: <aajexDFNdFz_Lsrp@redhat.com>

On Wed, Mar 4, 2026 at 5:39 PM Joe Lawrence <joe.lawrence@redhat.com> wrote:
[...]
> >
>
> Gah, sorry about those internal links.
>
> Try:
>
> https://joe-lawrence.github.io/klp-build-selftest-artifacts/report.html
> https://joe-lawrence.github.io/klp-build-selftest-artifacts/report.txt

Thanks! These look pretty good!

[...]

> It is strange, but for my experiment, I wanted minimal disruption to the
> tree.  For the "real" changeset, upstream + some testing CONFIG_ sounds
> good to me.
>
> > > That said, patching a dummy patched-tree isn't be perfect either,
> > > particularly in the runtime sense.  You're not testing a release kernel,
> > > but something slightly different.
> >
> > This should not be a problem. The goal is to test the klp-build toolchain.
> >
>
> Right, perhaps klp-build testing always targets a slightly modified
> kernel (or at least CONFIG_) while livepatching testing operates against
> the stock tree?

Agreed.

> > > (Tangent: kpatch-build implemented a unit test scheme that cached object
> > > files for even greater speed and fixed testing.  I haven't thought about
> > > how a similar idea might work for klp-build.)
> >
> > I think it is a good idea to have similar .o file tests for klp-diff
> > in klp-build.
> >
>
> kpatch-build uses a git submodule (a joy to work with /s), but maybe
> upstream tree can fetch the binary objects from some external
> (github/etc.) source?  I wonder if there is any kselftest precident for
> this, we'll need to investigate that.

Ah, right. I forgot that carrying .o files in the upstream kernel is a bit
weird. That may indeed be a blocker.

[...]
> > >
> > > 8- Probably more I've already forgotten about :) Cross-compilation may
> > > be interesting for build testing in the future.  For the full AI created
> > > commentary, there's https://github.com/joe-lawrence/linux/blob/klp-build-selftests/README.md
> >
> > Yes, cross-compilation can be really useful.
> >
>
> Agreed (I think Josh may be working on arm64 klp-build?) how many
> dimensions of testing are we up to now :)

We currently cross compile arm64 livepatch on x86_64 hosts with
kpatch-build. We don't have to do the same with klp-build. But it is
good to have the option. :)

Thanks,
Song

^ permalink raw reply

* [PATCH 14/14] klp-build: Support cross-compilation
From: Josh Poimboeuf @ 2026-03-05  3:31 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Peter Zijlstra, Joe Lawrence,
	Song Liu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Mark Rutland, Nathan Chancellor, Nicolas Schier, Herbert Xu
In-Reply-To: <cover.1772681234.git.jpoimboe@kernel.org>

Add support for cross-compilation.  The user must export ARCH, and
either CROSS_COMPILE or LLVM.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 scripts/livepatch/klp-build | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/scripts/livepatch/klp-build b/scripts/livepatch/klp-build
index 809e198a561d..b6c057e2120f 100755
--- a/scripts/livepatch/klp-build
+++ b/scripts/livepatch/klp-build
@@ -404,6 +404,14 @@ validate_patches() {
 	revert_patches
 }
 
+cross_compile_init() {
+	if [[ -v LLVM ]]; then
+		OBJCOPY=llvm-objcopy
+	else
+		OBJCOPY="${CROSS_COMPILE:-}objcopy"
+	fi
+}
+
 do_init() {
 	# We're not yet smart enough to handle anything other than in-tree
 	# builds in pwd.
@@ -420,6 +428,7 @@ do_init() {
 	validate_config
 	set_module_name
 	set_kernelversion
+	cross_compile_init
 }
 
 # Refresh the patch hunk headers, specifically the line numbers and counts.
@@ -783,7 +792,7 @@ build_patch_module() {
 	cp -f "$kmod_file" "$kmod_file.orig"
 
 	# Work around issue where slight .config change makes corrupt BTF
-	objcopy --remove-section=.BTF "$kmod_file"
+	"$OBJCOPY" --remove-section=.BTF "$kmod_file"
 
 	# Fix (and work around) linker wreckage for klp syms / relocs
 	"$SRC/tools/objtool/objtool" klp post-link "$kmod_file" || die "objtool klp post-link failed"
-- 
2.53.0


^ permalink raw reply related

* [PATCH 13/14] objtool: Introduce objtool for arm64
From: Josh Poimboeuf @ 2026-03-05  3:31 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Peter Zijlstra, Joe Lawrence,
	Song Liu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Mark Rutland, Nathan Chancellor, Nicolas Schier, Herbert Xu
In-Reply-To: <cover.1772681234.git.jpoimboe@kernel.org>

Add basic support for arm64 on objtool.  Only --checksum is currently
supported.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 arch/arm64/Kconfig                            |   2 +
 tools/objtool/Makefile                        |   4 +
 tools/objtool/arch/arm64/Build                |   2 +
 tools/objtool/arch/arm64/decode.c             | 116 ++++++++++++++++++
 .../arch/arm64/include/arch/cfi_regs.h        |  11 ++
 tools/objtool/arch/arm64/include/arch/elf.h   |  13 ++
 .../objtool/arch/arm64/include/arch/special.h |  21 ++++
 tools/objtool/arch/arm64/special.c            |  21 ++++
 8 files changed, 190 insertions(+)
 create mode 100644 tools/objtool/arch/arm64/Build
 create mode 100644 tools/objtool/arch/arm64/decode.c
 create mode 100644 tools/objtool/arch/arm64/include/arch/cfi_regs.h
 create mode 100644 tools/objtool/arch/arm64/include/arch/elf.h
 create mode 100644 tools/objtool/arch/arm64/include/arch/special.h
 create mode 100644 tools/objtool/arch/arm64/special.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 38dba5f7e4d2..354aa80c5b4b 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -236,9 +236,11 @@ config ARM64
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_IOREMAP_PROT
 	select HAVE_IRQ_TIME_ACCOUNTING
+	select HAVE_KLP_BUILD
 	select HAVE_LIVEPATCH
 	select HAVE_MOD_ARCH_SPECIFIC
 	select HAVE_NMI
+	select HAVE_OBJTOOL
 	select HAVE_PERF_EVENTS
 	select HAVE_PERF_EVENTS_NMI if ARM64_PSEUDO_NMI
 	select HAVE_PERF_REGS
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index 6964175abdfd..288db5bc3002 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -11,6 +11,10 @@ ifeq ($(SRCARCH),loongarch)
 	BUILD_ORC	   := y
 endif
 
+ifeq ($(SRCARCH),arm64)
+	ARCH_HAS_KLP := y
+endif
+
 ifeq ($(ARCH_HAS_KLP),y)
 	HAVE_XXHASH = $(shell printf "$(pound)include <xxhash.h>\nXXH3_state_t *state;int main() {}" | \
 		      $(HOSTCC) -xc - -o /dev/null -lxxhash 2> /dev/null && echo y || echo n)
diff --git a/tools/objtool/arch/arm64/Build b/tools/objtool/arch/arm64/Build
new file mode 100644
index 000000000000..d24d5636a5b8
--- /dev/null
+++ b/tools/objtool/arch/arm64/Build
@@ -0,0 +1,2 @@
+objtool-y += decode.o
+objtool-y += special.o
diff --git a/tools/objtool/arch/arm64/decode.c b/tools/objtool/arch/arm64/decode.c
new file mode 100644
index 000000000000..ee93c096243f
--- /dev/null
+++ b/tools/objtool/arch/arm64/decode.c
@@ -0,0 +1,116 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <objtool/check.h>
+#include <objtool/disas.h>
+#include <objtool/elf.h>
+#include <objtool/arch.h>
+#include <objtool/warn.h>
+#include <objtool/builtin.h>
+
+const char *arch_reg_name[CFI_NUM_REGS] = {};
+
+int arch_ftrace_match(const char *name)
+{
+	return 0;
+}
+
+s64 arch_insn_adjusted_addend(struct instruction *insn, struct reloc *reloc)
+{
+	return reloc_addend(reloc);
+}
+
+bool arch_callee_saved_reg(unsigned char reg)
+{
+	return false;
+}
+
+int arch_decode_hint_reg(u8 sp_reg, int *base)
+{
+	exit(-1);
+}
+
+const char *arch_nop_insn(int len)
+{
+	exit(-1);
+}
+
+const char *arch_ret_insn(int len)
+{
+	exit(-1);
+}
+
+int arch_decode_instruction(struct objtool_file *file, const struct section *sec,
+			    unsigned long offset, unsigned int maxlen,
+			    struct instruction *insn)
+{
+	u32 i = *((u32 *)(sec->data->d_buf + offset));
+
+	insn->len = 4;
+
+	/*
+	 * These are the bare minimum needed for static branch detection and
+	 * checksum calculations.
+	 */
+	if (i == 0xd503201f || i == 0x2a1f03f7) {
+		/* For static branches */
+		insn->type = INSN_NOP;
+	} else if ((i & 0xfc000000) == 0x14000000) {
+		/* For static branches and intra-TU sibling calls */
+		insn->type = INSN_JUMP_UNCONDITIONAL;
+		insn->immediate = sign_extend64(i & 0x03ffffff, 25);
+	} else if ((i & 0xfc000000) == 0x94000000) {
+		/* For intra-TU calls */
+		insn->type = INSN_CALL;
+		insn->immediate = sign_extend64(i & 0x03ffffff, 25);
+	} else if ((i & 0xff000000) == 0x54000000) {
+		/* For intra-TU conditional sibling calls */
+		insn->type = INSN_JUMP_CONDITIONAL;
+		insn->immediate = sign_extend64((i & 0xffffe0) >> 5, 18);
+	} else {
+		insn->type = INSN_OTHER;
+	}
+
+	return 0;
+}
+
+u64 arch_adjusted_addend(struct reloc *reloc)
+{
+	return reloc_addend(reloc);
+}
+
+unsigned long arch_jump_destination(struct instruction *insn)
+{
+	return insn->offset + (insn->immediate << 2);
+}
+
+bool arch_pc_relative_reloc(struct reloc *reloc)
+{
+	return false;
+}
+
+void arch_initial_func_cfi_state(struct cfi_init_state *state)
+{
+	state->cfa.base = CFI_UNDEFINED;
+}
+
+unsigned int arch_reloc_size(struct reloc *reloc)
+{
+	switch (reloc_type(reloc)) {
+	case R_AARCH64_ABS64:
+	case R_AARCH64_PREL64:
+		return 8;
+	default:
+		return 4;
+	}
+}
+
+#ifdef DISAS
+int arch_disas_info_init(struct disassemble_info *dinfo)
+{
+	return disas_info_init(dinfo, bfd_arch_aarch64,
+			       bfd_mach_arm_unknown, bfd_mach_aarch64,
+			       NULL);
+}
+#endif /* DISAS */
diff --git a/tools/objtool/arch/arm64/include/arch/cfi_regs.h b/tools/objtool/arch/arm64/include/arch/cfi_regs.h
new file mode 100644
index 000000000000..49c81cbb6646
--- /dev/null
+++ b/tools/objtool/arch/arm64/include/arch/cfi_regs.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _OBJTOOL_ARCH_CFI_REGS_H
+#define _OBJTOOL_ARCH_CFI_REGS_H
+
+/* These aren't actually used for arm64 */
+#define CFI_BP 0
+#define CFI_SP 0
+#define CFI_RA 0
+#define CFI_NUM_REGS 2
+
+#endif /* _OBJTOOL_ARCH_CFI_REGS_H */
diff --git a/tools/objtool/arch/arm64/include/arch/elf.h b/tools/objtool/arch/arm64/include/arch/elf.h
new file mode 100644
index 000000000000..80a1bc479930
--- /dev/null
+++ b/tools/objtool/arch/arm64/include/arch/elf.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _OBJTOOL_ARCH_ELF_H
+#define _OBJTOOL_ARCH_ELF_H
+
+#define R_NONE		R_AARCH64_NONE
+#define R_ABS64		R_AARCH64_ABS64
+#define R_ABS32		R_AARCH64_ABS32
+#define R_DATA32	R_AARCH64_PREL32
+#define R_DATA64	R_AARCH64_PREL64
+#define R_TEXT32	R_AARCH64_PREL32
+#define R_TEXT64	R_AARCH64_PREL64
+
+#endif /* _OBJTOOL_ARCH_ELF_H */
diff --git a/tools/objtool/arch/arm64/include/arch/special.h b/tools/objtool/arch/arm64/include/arch/special.h
new file mode 100644
index 000000000000..8ae804a83ea4
--- /dev/null
+++ b/tools/objtool/arch/arm64/include/arch/special.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _OBJTOOL_ARCH_SPECIAL_H
+#define _OBJTOOL_ARCH_SPECIAL_H
+
+#define EX_ENTRY_SIZE 12
+#define EX_ORIG_OFFSET 0
+#define EX_NEW_OFFSET 4
+
+#define JUMP_ENTRY_SIZE 16
+#define JUMP_ORIG_OFFSET 0
+#define JUMP_NEW_OFFSET 4
+#define JUMP_KEY_OFFSET 8
+
+#define ALT_ENTRY_SIZE 12
+#define ALT_ORIG_OFFSET 0
+#define ALT_NEW_OFFSET 4
+#define ALT_FEATURE_OFFSET 8
+#define ALT_ORIG_LEN_OFFSET 10
+#define ALT_NEW_LEN_OFFSET 11
+
+#endif /* _OBJTOOL_ARCH_SPECIAL_H */
diff --git a/tools/objtool/arch/arm64/special.c b/tools/objtool/arch/arm64/special.c
new file mode 100644
index 000000000000..3c2b83d94939
--- /dev/null
+++ b/tools/objtool/arch/arm64/special.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#include <objtool/special.h>
+
+bool arch_support_alt_relocation(struct special_alt *special_alt,
+				 struct instruction *insn,
+				 struct reloc *reloc)
+{
+	return false;
+}
+
+struct reloc *arch_find_switch_table(struct objtool_file *file,
+				     struct instruction *insn,
+				     unsigned long *table_size)
+{
+	return NULL;
+}
+
+const char *arch_cpu_feature_name(int feature_number)
+{
+	return NULL;
+}
-- 
2.53.0


^ permalink raw reply related

* [PATCH 12/14] objtool: Reuse consecutive string references
From: Josh Poimboeuf @ 2026-03-05  3:31 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Peter Zijlstra, Joe Lawrence,
	Song Liu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Mark Rutland, Nathan Chancellor, Nicolas Schier, Herbert Xu
In-Reply-To: <cover.1772681234.git.jpoimboe@kernel.org>

For duplicate strings, elf_add_string() just blindly adds duplicates.

That can be a problem for arm64 which often uses two consecutive
instructions (and corresponding relocations) to put an address into a
register, like:

  d8:   90000001        adrp    x1, 0 <meminfo_proc_show>       d8: R_AARCH64_ADR_PREL_PG_HI21  .rodata.meminfo_proc_show.str1.8
  dc:   91000021        add     x1, x1, #0x0    dc: R_AARCH64_ADD_ABS_LO12_NC   .rodata.meminfo_proc_show.str1.8

Referencing two different string addresses in the adrp+add pair can
result in a corrupt string addresses.  Detect such consecutive reuses
and force them to use the same string.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/elf.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 3da90686350d..52ef991115fc 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -1321,6 +1321,8 @@ struct elf *elf_create_file(GElf_Ehdr *ehdr, const char *name)
 
 unsigned int elf_add_string(struct elf *elf, struct section *strtab, const char *str)
 {
+	static unsigned int last_off;
+	static const char *last_str;
 	unsigned int offset;
 
 	if (!strtab)
@@ -1329,17 +1331,22 @@ unsigned int elf_add_string(struct elf *elf, struct section *strtab, const char
 		ERROR("can't find .strtab section");
 		return -1;
 	}
-
 	if (!strtab->sh.sh_addralign) {
 		ERROR("'%s': invalid sh_addralign", strtab->name);
 		return -1;
 	}
 
+	if (last_str && !strcmp(last_str, str))
+		return last_off;
+
 	offset = ALIGN(strtab->sh.sh_size, strtab->sh.sh_addralign);
 
 	if (!elf_add_data(elf, strtab, str, strlen(str) + 1))
 		return -1;
 
+	last_str = str;
+	last_off = offset;
+
 	return offset;
 }
 
-- 
2.53.0


^ permalink raw reply related

* [PATCH 11/14] objtool: Allow empty alternatives
From: Josh Poimboeuf @ 2026-03-05  3:31 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Peter Zijlstra, Joe Lawrence,
	Song Liu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Mark Rutland, Nathan Chancellor, Nicolas Schier, Herbert Xu
In-Reply-To: <cover.1772681234.git.jpoimboe@kernel.org>

arm64 can have empty alternatives, which are effectively no-ops.  Ignore
them.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 23cde2de66b9..036adbd67488 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1994,10 +1994,8 @@ static int add_special_section_alts(struct objtool_file *file)
 		}
 
 		if (special_alt->group) {
-			if (!special_alt->orig_len) {
-				ERROR_INSN(orig_insn, "empty alternative entry");
+			if (!special_alt->orig_len)
 				continue;
-			}
 
 			if (handle_group_alt(file, special_alt, orig_insn, &new_insn))
 				return -1;
-- 
2.53.0


^ permalink raw reply related

* [PATCH 10/14] objtool: Ignore jumps to the end of the function for non-CFG arches
From: Josh Poimboeuf @ 2026-03-05  3:31 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Peter Zijlstra, Joe Lawrence,
	Song Liu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Mark Rutland, Nathan Chancellor, Nicolas Schier, Herbert Xu
In-Reply-To: <cover.1772681234.git.jpoimboe@kernel.org>

Sometimes Clang arm64 code jumps to the end of the function for UB.
No need to make that an error, arm64 doesn't reverse engineer the CFG
anyway.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index f73cf1382e5c..23cde2de66b9 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1630,10 +1630,12 @@ static int add_jump_destinations(struct objtool_file *file)
 			/*
 			 * GCOV/KCOV dead code can jump to the end of
 			 * the function/section.
+			 *
+			 * Clang on arm64 also does this sometimes for
+			 * undefined behavior.
 			 */
-			if (file->ignore_unreachables && func &&
-			    dest_sec == insn->sec &&
-			    dest_off == func->offset + func->len)
+			if ((file->ignore_unreachables || (!opts.stackval && !opts.orc)) &&
+			    func && dest_sec == insn->sec && dest_off == func->offset + func->len)
 				continue;
 
 			ERROR_INSN(insn, "can't find jump dest instruction at %s",
-- 
2.53.0


^ permalink raw reply related

* [PATCH 09/14] kbuild: Only run objtool if there is at least one command
From: Josh Poimboeuf @ 2026-03-05  3:31 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Peter Zijlstra, Joe Lawrence,
	Song Liu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Mark Rutland, Nathan Chancellor, Nicolas Schier, Herbert Xu
In-Reply-To: <cover.1772681234.git.jpoimboe@kernel.org>

Split the objtool args into commands and options, such that if no
commands have been enabled, objtool doesn't run.

This is in preparation in enabling objtool and klp-build for arm64.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 arch/x86/boot/startup/Makefile |  2 +-
 scripts/Makefile.build         |  4 +--
 scripts/Makefile.lib           | 46 ++++++++++++++++++----------------
 scripts/Makefile.vmlinux_o     | 15 ++++-------
 4 files changed, 33 insertions(+), 34 deletions(-)

diff --git a/arch/x86/boot/startup/Makefile b/arch/x86/boot/startup/Makefile
index 5e499cfb29b5..a08297829fc6 100644
--- a/arch/x86/boot/startup/Makefile
+++ b/arch/x86/boot/startup/Makefile
@@ -36,7 +36,7 @@ $(patsubst %.o,$(obj)/%.o,$(lib-y)): OBJECT_FILES_NON_STANDARD := y
 # relocations, even if other objtool actions are being deferred.
 #
 $(pi-objs): objtool-enabled	= 1
-$(pi-objs): objtool-args	= $(if $(delay-objtool),--dry-run,$(objtool-args-y)) --noabs
+$(pi-objs): objtool-args	= $(if $(delay-objtool),--dry-run,$(objtool-cmds-y) $(objtool-opts-y)) --noabs
 
 #
 # Confine the startup code by prefixing all symbols with __pi_ (for position
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 32e209bc7985..d2d0776df947 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -277,7 +277,7 @@ endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
 is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(target-stem).o)$(OBJECT_FILES_NON_STANDARD)n),$(is-kernel-object))
 
 ifdef CONFIG_OBJTOOL
-$(obj)/%.o: private objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y))
+$(obj)/%.o: private objtool-enabled = $(if $(is-standard-object),$(if $(objtool-cmds-y),$(if $(delay-objtool),$(is-single-obj-m),y)))
 endif
 
 ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)
@@ -499,7 +499,7 @@ define rule_ld_multi_m
 	$(call cmd,gen_objtooldep)
 endef
 
-$(multi-obj-m): private objtool-enabled := $(delay-objtool)
+$(multi-obj-m): private objtool-enabled := $(if $(objtool-cmds-y),$(delay-objtool))
 $(multi-obj-m): private part-of-module := y
 $(multi-obj-m): %.o: %.mod FORCE
 	$(call if_changed_rule,ld_multi_m)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0718e39cedda..40a462581666 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -183,27 +183,31 @@ ifdef CONFIG_OBJTOOL
 
 objtool := $(objtree)/tools/objtool/objtool
 
-objtool-args-$(CONFIG_HAVE_JUMP_LABEL_HACK)		+= --hacks=jump_label
-objtool-args-$(CONFIG_HAVE_NOINSTR_HACK)		+= --hacks=noinstr
-objtool-args-$(CONFIG_MITIGATION_CALL_DEPTH_TRACKING)	+= --hacks=skylake
-objtool-args-$(CONFIG_X86_KERNEL_IBT)			+= --ibt
-objtool-args-$(CONFIG_FINEIBT)				+= --cfi
-objtool-args-$(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL)	+= --mcount
-ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
-objtool-args-$(CONFIG_HAVE_OBJTOOL_NOP_MCOUNT)		+= --mnop
-endif
-objtool-args-$(CONFIG_UNWINDER_ORC)			+= --orc
-objtool-args-$(CONFIG_MITIGATION_RETPOLINE)		+= --retpoline
-objtool-args-$(CONFIG_MITIGATION_RETHUNK)		+= --rethunk
-objtool-args-$(CONFIG_MITIGATION_SLS)			+= --sls
-objtool-args-$(CONFIG_STACK_VALIDATION)			+= --stackval
-objtool-args-$(CONFIG_HAVE_STATIC_CALL_INLINE)		+= --static-call
-objtool-args-$(CONFIG_HAVE_UACCESS_VALIDATION)		+= --uaccess
-objtool-args-$(or $(CONFIG_GCOV_KERNEL),$(CONFIG_KCOV))	+= --no-unreachable
-objtool-args-$(CONFIG_PREFIX_SYMBOLS)			+= --prefix=$(CONFIG_FUNCTION_PADDING_BYTES)
-objtool-args-$(CONFIG_OBJTOOL_WERROR)			+= --werror
+# objtool commands
+objtool-cmds-$(CONFIG_HAVE_JUMP_LABEL_HACK)		+= --hacks=jump_label
+objtool-cmds-$(CONFIG_HAVE_NOINSTR_HACK)		+= --hacks=noinstr
+objtool-cmds-$(CONFIG_MITIGATION_CALL_DEPTH_TRACKING)	+= --hacks=skylake
+objtool-cmds-$(CONFIG_X86_KERNEL_IBT)			+= --ibt
+objtool-cmds-$(CONFIG_FINEIBT)				+= --cfi
+objtool-cmds-$(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL)	+= --mcount
+objtool-cmds-$(CONFIG_UNWINDER_ORC)			+= --orc
+objtool-cmds-$(CONFIG_MITIGATION_RETPOLINE)		+= --retpoline
+objtool-cmds-$(CONFIG_MITIGATION_RETHUNK)		+= --rethunk
+objtool-cmds-$(CONFIG_MITIGATION_SLS)			+= --sls
+objtool-cmds-$(CONFIG_STACK_VALIDATION)			+= --stackval
+objtool-cmds-$(CONFIG_HAVE_STATIC_CALL_INLINE)		+= --static-call
+objtool-cmds-$(CONFIG_HAVE_UACCESS_VALIDATION)		+= --uaccess
+objtool-cmds-$(CONFIG_PREFIX_SYMBOLS)			+= --prefix=$(CONFIG_FUNCTION_PADDING_BYTES)
+objtool-cmds-y						+= $(OBJTOOL_ARGS)
 
-objtool-args = $(objtool-args-y)					\
+# objtool options
+ifdef CONFIG_FTRACE_MCOUNT_USE_OBJTOOL
+objtool-opts-$(CONFIG_HAVE_OBJTOOL_NOP_MCOUNT)		+= --mnop
+endif
+objtool-opts-$(or $(CONFIG_GCOV_KERNEL),$(CONFIG_KCOV))	+= --no-unreachable
+objtool-opts-$(CONFIG_OBJTOOL_WERROR)			+= --werror
+
+objtool-args = $(objtool-cmds-y) $(objtool-opts-y)			\
 	$(if $(delay-objtool), --link)					\
 	$(if $(part-of-module), --module)
 
@@ -212,7 +216,7 @@ delay-objtool := $(or $(CONFIG_LTO_CLANG),$(CONFIG_X86_KERNEL_IBT),$(CONFIG_KLP_
 cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool-args) $@)
 cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd)
 
-objtool-enabled := y
+objtool-enabled = $(if $(objtool-cmds-y),y)
 
 endif # CONFIG_OBJTOOL
 
diff --git a/scripts/Makefile.vmlinux_o b/scripts/Makefile.vmlinux_o
index 527352c222ff..09af33203bd8 100644
--- a/scripts/Makefile.vmlinux_o
+++ b/scripts/Makefile.vmlinux_o
@@ -36,18 +36,13 @@ endif
 # For !delay-objtool + CONFIG_NOINSTR_VALIDATION, it runs on both translation
 # units and vmlinux.o, with the latter only used for noinstr/unret validation.
 
-objtool-enabled := $(or $(delay-objtool),$(CONFIG_NOINSTR_VALIDATION))
-
-ifeq ($(delay-objtool),y)
-vmlinux-objtool-args-y					+= $(objtool-args-y)
-else
-vmlinux-objtool-args-$(CONFIG_OBJTOOL_WERROR)		+= --werror
+ifneq ($(delay-objtool),y)
+objtool-cmds-y					 =
+objtool-opts-y					+= --link
 endif
 
-vmlinux-objtool-args-$(CONFIG_NOINSTR_VALIDATION)	+= --noinstr \
-							   $(if $(or $(CONFIG_MITIGATION_UNRET_ENTRY),$(CONFIG_MITIGATION_SRSO)), --unret)
-
-objtool-args = $(vmlinux-objtool-args-y) --link
+objtool-cmds-$(CONFIG_NOINSTR_VALIDATION)	+= --noinstr \
+						   $(if $(or $(CONFIG_MITIGATION_UNRET_ENTRY),$(CONFIG_MITIGATION_SRSO)), --unret)
 
 # Link of vmlinux.o used for section mismatch analysis
 # ---------------------------------------------------------------------------
-- 
2.53.0


^ permalink raw reply related

* [PATCH 08/14] objtool: Allow setting --mnop without --mcount
From: Josh Poimboeuf @ 2026-03-05  3:31 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Peter Zijlstra, Joe Lawrence,
	Song Liu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Mark Rutland, Nathan Chancellor, Nicolas Schier, Herbert Xu
In-Reply-To: <cover.1772681234.git.jpoimboe@kernel.org>

Instead of returning an error for --mnop without --mcount, just silently
ignore it.  This will help simplify kbuild's handling of objtool args.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/builtin-check.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index b780df513715..f528a58aca74 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -145,11 +145,6 @@ int cmd_parse_options(int argc, const char **argv, const char * const usage[])
 
 static bool opts_valid(void)
 {
-	if (opts.mnop && !opts.mcount) {
-		ERROR("--mnop requires --mcount");
-		return false;
-	}
-
 	if (opts.noinstr && !opts.link) {
 		ERROR("--noinstr requires --link");
 		return false;
-- 
2.53.0


^ permalink raw reply related

* [PATCH 07/14] objtool: Extricate checksum calculation from validate_branch()
From: Josh Poimboeuf @ 2026-03-05  3:31 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Peter Zijlstra, Joe Lawrence,
	Song Liu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Mark Rutland, Nathan Chancellor, Nicolas Schier, Herbert Xu
In-Reply-To: <cover.1772681234.git.jpoimboe@kernel.org>

In preparation for porting the checksum code to other arches, make its
functionality independent from validate_branch().

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 tools/objtool/check.c                    | 71 +++++++++++++++++-------
 tools/objtool/include/objtool/checksum.h |  6 +-
 2 files changed, 53 insertions(+), 24 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index a30379e4ff97..f73cf1382e5c 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -2633,8 +2633,7 @@ static bool validate_branch_enabled(void)
 {
 	return opts.stackval ||
 	       opts.orc ||
-	       opts.uaccess ||
-	       opts.checksum;
+	       opts.uaccess;
 }
 
 static int decode_sections(struct objtool_file *file)
@@ -3649,6 +3648,7 @@ static bool skip_alt_group(struct instruction *insn)
 	return alt_insn->type == INSN_CLAC || alt_insn->type == INSN_STAC;
 }
 
+#ifdef BUILD_KLP
 static int checksum_debug_init(struct objtool_file *file)
 {
 	char *dup, *s;
@@ -3691,9 +3691,30 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func,
 				 struct instruction *insn)
 {
 	struct reloc *reloc = insn_reloc(file, insn);
+	struct alternative *alt;
 	unsigned long offset;
 	struct symbol *sym;
 
+	for (alt = insn->alts; alt; alt = alt->next) {
+		struct alt_group *alt_group = alt->insn->alt_group;
+
+		checksum_update(func, insn, &alt->type, sizeof(alt->type));
+
+		if (alt_group && alt_group->orig_group) {
+			struct instruction *alt_insn;
+
+			checksum_update(func, insn, &alt_group->feature, sizeof(alt_group->feature));
+
+			for (alt_insn = alt->insn; alt_insn; alt_insn = next_insn_same_sec(file, alt_insn)) {
+				checksum_update_insn(file, func, alt_insn);
+				if (alt_insn == alt_group->last_insn)
+					break;
+			}
+		} else {
+			checksum_update(func, insn, &alt->insn->offset, sizeof(alt->insn->offset));
+		}
+	}
+
 	if (insn->fake)
 		return;
 
@@ -3702,9 +3723,11 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func,
 	if (!reloc) {
 		struct symbol *call_dest = insn_call_dest(insn);
 
-		if (call_dest)
+		if (call_dest) {
+			/* intra-TU call without reloc */
 			checksum_update(func, insn, call_dest->demangled_name,
 					strlen(call_dest->demangled_name));
+		}
 		return;
 	}
 
@@ -3731,6 +3754,29 @@ static void checksum_update_insn(struct objtool_file *file, struct symbol *func,
 	checksum_update(func, insn, &offset, sizeof(offset));
 }
 
+static int calculate_checksums(struct objtool_file *file)
+{
+	struct instruction *insn;
+	struct symbol *func;
+
+	if (checksum_debug_init(file))
+		return -1;
+
+	for_each_sym(file->elf, func) {
+		if (!is_func_sym(func))
+			continue;
+
+		checksum_init(func);
+
+		func_for_each_insn(file, func, insn)
+			checksum_update_insn(file, func, insn);
+
+		checksum_finish(func);
+	}
+	return 0;
+}
+#endif /* BUILD_KLP */
+
 static int validate_branch(struct objtool_file *file, struct symbol *func,
 			   struct instruction *insn, struct insn_state state);
 static int do_validate_branch(struct objtool_file *file, struct symbol *func,
@@ -4012,9 +4058,6 @@ static int do_validate_branch(struct objtool_file *file, struct symbol *func,
 		insn->trace = 0;
 		next_insn = next_insn_to_validate(file, insn);
 
-		if (opts.checksum && func && insn->sec)
-			checksum_update_insn(file, func, insn);
-
 		if (func && insn_func(insn) && func != insn_func(insn)->pfunc) {
 			/* Ignore KCFI type preambles, which always fall through */
 			if (is_prefix_func(func))
@@ -4080,9 +4123,6 @@ static int validate_unwind_hint(struct objtool_file *file,
 		struct symbol *func = insn_func(insn);
 		int ret;
 
-		if (opts.checksum)
-			checksum_init(func);
-
 		ret = validate_branch(file, func, insn, *state);
 		if (ret)
 			BT_INSN(insn, "<=== (hint)");
@@ -4525,9 +4565,6 @@ static int validate_symbol(struct objtool_file *file, struct section *sec,
 
 	func = insn_func(insn);
 
-	if (opts.checksum)
-		checksum_init(func);
-
 	if (opts.trace && !fnmatch(opts.trace, sym->name, 0)) {
 		trace_enable();
 		TRACE("%s: validation begin\n", sym->name);
@@ -4540,9 +4577,6 @@ static int validate_symbol(struct objtool_file *file, struct section *sec,
 	TRACE("%s: validation %s\n\n", sym->name, ret ? "failed" : "end");
 	trace_disable();
 
-	if (opts.checksum)
-		checksum_finish(func);
-
 	return ret;
 }
 
@@ -4997,10 +5031,6 @@ int check(struct objtool_file *file)
 	cfi_hash_add(&init_cfi);
 	cfi_hash_add(&func_cfi);
 
-	ret = checksum_debug_init(file);
-	if (ret)
-		goto out;
-
 	ret = decode_sections(file);
 	if (ret)
 		goto out;
@@ -5091,6 +5121,9 @@ int check(struct objtool_file *file)
 		warnings += check_abs_references(file);
 
 	if (opts.checksum) {
+		ret = calculate_checksums(file);
+		if (ret)
+			goto out;
 		ret = create_sym_checksum_section(file);
 		if (ret)
 			goto out;
diff --git a/tools/objtool/include/objtool/checksum.h b/tools/objtool/include/objtool/checksum.h
index 7fe21608722a..36a17688c716 100644
--- a/tools/objtool/include/objtool/checksum.h
+++ b/tools/objtool/include/objtool/checksum.h
@@ -32,11 +32,7 @@ static inline void checksum_finish(struct symbol *func)
 
 #else /* !BUILD_KLP */
 
-static inline void checksum_init(struct symbol *func) {}
-static inline void checksum_update(struct symbol *func,
-				   struct instruction *insn,
-				   const void *data, size_t size) {}
-static inline void checksum_finish(struct symbol *func) {}
+static inline int calculate_checksums(struct objtool_file *file) { return -ENOSYS; }
 
 #endif /* !BUILD_KLP */
 
-- 
2.53.0


^ permalink raw reply related

* [PATCH 06/14] crypto: arm64: Move data to .rodata
From: Josh Poimboeuf @ 2026-03-05  3:31 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Peter Zijlstra, Joe Lawrence,
	Song Liu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Mark Rutland, Nathan Chancellor, Nicolas Schier, Herbert Xu
In-Reply-To: <cover.1772681234.git.jpoimboe@kernel.org>

Data embedded in .text pollutes i-cache and confuses objtool and other
tools that try to disassemble it.  Move it to .rodata.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 lib/crypto/arm64/sha2-armv8.pl | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/lib/crypto/arm64/sha2-armv8.pl b/lib/crypto/arm64/sha2-armv8.pl
index 35ec9ae99fe1..8cd86768bf5c 100644
--- a/lib/crypto/arm64/sha2-armv8.pl
+++ b/lib/crypto/arm64/sha2-armv8.pl
@@ -237,7 +237,8 @@ $code.=<<___;
 	ldp	$E,$F,[$ctx,#4*$SZ]
 	add	$num,$inp,$num,lsl#`log(16*$SZ)/log(2)`	// end of input
 	ldp	$G,$H,[$ctx,#6*$SZ]
-	adr	$Ktbl,.LK$BITS
+	adrp	$Ktbl,.LK$BITS
+	add	$Ktbl,$Ktbl,:lo12:.LK$BITS
 	stp	$ctx,$num,[x29,#96]
 
 .Loop:
@@ -286,6 +287,7 @@ $code.=<<___;
 	ret
 .size	$func,.-$func
 
+.pushsection .rodata
 .align	6
 .type	.LK$BITS,%object
 .LK$BITS:
@@ -365,6 +367,7 @@ $code.=<<___;
 #endif
 .asciz	"SHA$BITS block transform for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
 .align	2
+.popsection
 ___
 
 if ($SZ==4) {
@@ -385,7 +388,8 @@ sha256_block_armv8:
 	add		x29,sp,#0
 
 	ld1.32		{$ABCD,$EFGH},[$ctx]
-	adr		$Ktbl,.LK256
+	adrp		$Ktbl,.LK256
+	add		$Ktbl,$Ktbl,:lo12:.LK256
 
 .Loop_hw:
 	ld1		{@MSG[0]-@MSG[3]},[$inp],#64
@@ -648,7 +652,8 @@ sha256_block_neon:
 	mov	x29, sp
 	sub	sp,sp,#16*4
 
-	adr	$Ktbl,.LK256
+	adrp	$Ktbl,.LK256
+	add	$Ktbl,$Ktbl,:lo12:.LK256
 	add	$num,$inp,$num,lsl#6	// len to point at the end of inp
 
 	ld1.8	{@X[0]},[$inp], #16
-- 
2.53.0


^ permalink raw reply related

* [PATCH 05/14] arm64: Fix EFI linking with -fdata-sections
From: Josh Poimboeuf @ 2026-03-05  3:31 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Peter Zijlstra, Joe Lawrence,
	Song Liu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Mark Rutland, Nathan Chancellor, Nicolas Schier, Herbert Xu
In-Reply-To: <cover.1772681234.git.jpoimboe@kernel.org>

When building with func-fdata-sections, the .init.bss section gets split
up into a bunch of .init.bss.<var> sections.  Make sure they get linked
into .init.data.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 arch/arm64/kernel/vmlinux.lds.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index ad6133b89e7a..1f5e4f996a21 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -269,7 +269,7 @@ SECTIONS
 		INIT_CALLS
 		CON_INITCALL
 		INIT_RAM_FS
-		*(.init.altinstructions .init.bss)	/* from the EFI stub */
+		*(.init.altinstructions .init.bss .init.bss.*)	/* from the EFI stub */
 	}
 	.exit.data : {
 		EXIT_DATA
-- 
2.53.0


^ permalink raw reply related

* [PATCH 04/14] arm64: head: Move boot header to .head.data
From: Josh Poimboeuf @ 2026-03-05  3:31 UTC (permalink / raw)
  To: x86
  Cc: linux-kernel, live-patching, Peter Zijlstra, Joe Lawrence,
	Song Liu, Catalin Marinas, Will Deacon, linux-arm-kernel,
	Mark Rutland, Nathan Chancellor, Nicolas Schier, Herbert Xu
In-Reply-To: <cover.1772681234.git.jpoimboe@kernel.org>

The arm64 boot header is mostly data.  Move it to a data section to
prevent objtool and other tools from trying to disassemble it.  The
final linked result is the same.

Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
---
 arch/arm64/kernel/head.S          | 2 +-
 include/asm-generic/vmlinux.lds.h | 2 +-
 include/linux/init.h              | 1 +
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 87a822e5c4ca..0681c6e50859 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -54,7 +54,7 @@
  * that are useful before the MMU is enabled. The allocations are described
  * in the entry routines.
  */
-	__HEAD
+	__HEADDATA
 	/*
 	 * DO NOT MODIFY. Image header expected by Linux boot-loaders.
 	 */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index eeb070f330bd..51a0e5974f41 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -663,7 +663,7 @@
 		__static_call_text_end = .;
 
 /* Section used for early init (in .S files) */
-#define HEAD_TEXT  KEEP(*(.head.text))
+#define HEAD_TEXT  KEEP(*(.head.data .head.text))
 
 #define HEAD_TEXT_SECTION							\
 	.head.text : AT(ADDR(.head.text) - LOAD_OFFSET) {		\
diff --git a/include/linux/init.h b/include/linux/init.h
index 40331923b9f4..91e16f3205e2 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -90,6 +90,7 @@
 
 /* For assembly routines */
 #define __HEAD		.section	".head.text","ax"
+#define __HEADDATA	.section	".head.data","aw"
 #define __INIT		.section	".init.text","ax"
 #define __FINIT		.previous
 
-- 
2.53.0


^ permalink raw reply related


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