]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
objtool/klp: Fix extraction of text annotations for alternatives
authorJosh Poimboeuf <jpoimboe@kernel.org>
Fri, 3 Apr 2026 21:53:32 +0000 (14:53 -0700)
committerJosh Poimboeuf <jpoimboe@kernel.org>
Tue, 5 May 2026 04:16:01 +0000 (21:16 -0700)
Objtool is failing to extract text annotations which reference
.altinstr_replacement instructions:

  1) Alternative replacement fake symbols are NOTYPE rather than FUNC,
     and they don't have sym->included set, thus they aren't recognized
     by should_keep_special_sym().

  2) .discard.annotate_insn gets processed before .altinstr_replacement,
     so the referenced (fake) symbols don't have clones yet.

Fix the first issue by checking for a valid clone instead of
sym->included and by accepting NOTYPE symbols when processing
.discard.annotate_insn.

Fix the second issue by deferring text annotation processing until after
the other special sections have been cloned.

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 17a6146b9406bac414e84a33b5822d46efeac8ae..42970b38728f4bd4af660d74d2876ca3711291da 100644 (file)
@@ -1437,6 +1437,7 @@ entsize:
 /* Keep a special section entry if it references an included function */
 static bool should_keep_special_sym(struct elf *elf, struct symbol *sym)
 {
+       bool annotate_insn = !strcmp(sym->sec->name, ".discard.annotate_insn");
        struct reloc *reloc;
 
        if (is_sec_sym(sym) || !sym->sec->rsec)
@@ -1446,7 +1447,16 @@ static bool should_keep_special_sym(struct elf *elf, struct symbol *sym)
                if (convert_reloc_sym(elf, reloc))
                        continue;
 
-               if (is_func_sym(reloc->sym) && reloc->sym->included)
+               if (!reloc->sym->clone || is_undef_sym(reloc->sym->clone))
+                       continue;
+
+               /*
+                * Keep special section references to cloned functions.
+                * In some cases annotate_insn can also reference cloned alt
+                * replacement fake symbols; keep those references as well.
+                */
+               if (is_func_sym(reloc->sym) ||
+                   (annotate_insn && is_notype_sym(reloc->sym)))
                        return true;
        }
 
@@ -1590,15 +1600,28 @@ static int clone_special_section(struct elfs *e, struct section *patched_sec)
 /* Extract only the needed bits from special sections */
 static int clone_special_sections(struct elfs *e)
 {
-       struct section *patched_sec;
+       struct section *sec, *annotate_insn = NULL;
 
-       for_each_sec(e->patched, patched_sec) {
-               if (is_special_section(patched_sec)) {
-                       if (clone_special_section(e, patched_sec))
+       for_each_sec(e->patched, sec) {
+               if (is_special_section(sec)) {
+                       if (!strcmp(sec->name, ".discard.annotate_insn")) {
+                               annotate_insn = sec;
+                               continue;
+                       }
+                       if (clone_special_section(e, sec))
                                return -1;
                }
        }
 
+       /*
+        * Do .discard.annotate_insn last, it can reference other special
+        * sections (alt replacements) so they need to be cloned first.
+        */
+       if (annotate_insn) {
+               if (clone_special_section(e, annotate_insn))
+                       return -1;
+       }
+
        return 0;
 }