From f1a67a4e992db7e93592393b266c6bff347c4725 Mon Sep 17 00:00:00 2001 From: Andrew Bernal Date: Tue, 4 Aug 2026 14:13:07 -0400 Subject: [PATCH] create-diff-object: don't mark prefix symbols as changed When a symbol moves between sections -- out of an ignored section, or between text subsections -- kpatch_compare_correlated_symbol() marks it CHANGED. A function's __pfx_/__cfi_ prefix symbol moves along with its parent, so it gets marked CHANGED as well. Prefix symbols are padding, not independently patchable functions. kpatch_find_func_profiling_calls() already skips them, so they never have has_func_profiling set, and kpatch_check_func_profiling_calls() then rejects the build: function __pfx_foo has no fentry/mcount call, unable to patch Marking them CHANGED also emits a klp_func entry pointing at the padding instead of the function. This shows up on x86_64 with CONFIG_CALL_PADDING when patching a function in a section that doesn't honor -ffunction-sections, such as .sched.text: dropping __sched from the function and adding KPATCH_IGNORE_SECTION(".sched.text") moves both the function and its prefix symbol out of the shared section. Leave the prefix symbol's status alone. It is still carried into the output through its parent function's sym->pfx link. Signed-off-by: Andrew Bernal Co-Authored-By: Claude Opus 5 --- kpatch-build/create-diff-object.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index 051f8e82..0bf9dbcf 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -1048,14 +1048,18 @@ static void kpatch_compare_correlated_symbol(struct symbol *sym) * If two symbols are correlated but their sections are not, then the * symbol has changed sections. This is only allowed if the symbol is * moving out of an ignored section, or moving between normal/hot/unlikely - * subsections. + * subsections. A prefix symbol moves along with its parent function, + * but it's padding rather than a patchable function, so leave its status + * alone; it's included via the parent's sym->pfx link. */ if (sym1->sec && sym2->sec && sym1->sec->twin != sym2->sec) { if ((sym2->sec->twin && sym2->sec->twin->ignore) || - kpatch_subsection_changed(sym1->sec, sym2->sec)) - sym->status = CHANGED; - else + kpatch_subsection_changed(sym1->sec, sym2->sec)) { + if (!sym->is_pfx) + sym->status = CHANGED; + } else { DIFF_FATAL("symbol changed sections: %s", sym1->name); + } } if (sym1->type == STT_OBJECT &&