]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
objtool/klp: Fix handling of zero-length .altinstr_replacement sections
authorJosh Poimboeuf <jpoimboe@kernel.org>
Fri, 10 Apr 2026 01:34:50 +0000 (18:34 -0700)
committerJosh Poimboeuf <jpoimboe@kernel.org>
Tue, 5 May 2026 04:16:00 +0000 (21:16 -0700)
When a section is empty (e.g. only zero-length alternative
replacements), there are no symbols to convert a section symbol
reference to.  Skip the reloc instead of erroring out.

Fixes: dd590d4d57eb ("objtool/klp: Introduce klp diff subcommand for diffing object files")
Acked-by: Song Liu <song@kernel.org>
Reviewed-by: Miroslav Benes <mbenes@suse.cz>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>
tools/objtool/klp-diff.c

index 30ce234e01a11d0076b30bcb581ac2583f27c90d..a226e99948b397027f62f152e57d3260858a354f 100644 (file)
@@ -1005,6 +1005,13 @@ static int convert_reloc_secsym_to_sym(struct elf *elf, struct reloc *reloc)
        /* No dedicated section; find the symbol manually */
        sym = find_symbol_containing(sec, arch_adjusted_addend(reloc));
        if (!sym) {
+               /*
+                * This is presumably an .altinstr_replacement section which is
+                * empty due to it only having zero-length replacement(s).
+                */
+               if (!sec_size(sec))
+                       return 1;
+
                /*
                 * This can happen for special section references to weak code
                 * whose symbol has been stripped by the linker.
@@ -1265,6 +1272,7 @@ static int clone_sym_relocs(struct elfs *e, struct symbol *patched_sym)
 
        for_each_reloc(patched_rsec, patched_reloc) {
                unsigned long offset;
+               int ret;
 
                if (reloc_offset(patched_reloc) < start ||
                    reloc_offset(patched_reloc) >= end)
@@ -1278,12 +1286,15 @@ static int clone_sym_relocs(struct elfs *e, struct symbol *patched_sym)
                    !strcmp(patched_reloc->sym->sec->name, ".altinstr_aux"))
                        continue;
 
-               if (convert_reloc_sym(e->patched, patched_reloc)) {
+               ret = convert_reloc_sym(e->patched, patched_reloc);
+               if (ret < 0) {
                        ERROR_FUNC(patched_rsec->base, reloc_offset(patched_reloc),
                                   "failed to convert reloc sym '%s' to its proper format",
                                   patched_reloc->sym->name);
                        return -1;
                }
+               if (ret > 0)
+                       continue;
 
                offset = out_sym->offset + (reloc_offset(patched_reloc) - patched_sym->offset);