From: Josh Poimboeuf Date: Fri, 3 Apr 2026 21:53:32 +0000 (-0700) Subject: objtool/klp: Fix extraction of text annotations for alternatives X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=62a7a01fde87c99926cd7e9670b4226c4c79ebaf;p=thirdparty%2Fkernel%2Flinux.git objtool/klp: Fix extraction of text annotations for alternatives 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 Reviewed-by: Miroslav Benes Signed-off-by: Josh Poimboeuf --- diff --git a/tools/objtool/klp-diff.c b/tools/objtool/klp-diff.c index 17a6146b9406b..42970b38728f4 100644 --- a/tools/objtool/klp-diff.c +++ b/tools/objtool/klp-diff.c @@ -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; }