From ce8ca2cf681df73ab934f867cb51c401f5a43b2c Mon Sep 17 00:00:00 2001 From: Puranjay Mohan Date: Fri, 7 Feb 2025 17:30:05 +0000 Subject: [PATCH] create-diff-object: don't mangle .rela.__patchable_function_entries kpatch_replace_sections_syms() substitutes the object/function symbols for the section symbol in the relocation sections. But relocations in .rela.__patchable_function_entries can point to an instruction ouside the function. This is because with CALL_OPS enabled, two NOPs are added before the function entry. __patchable_function_entries needs the address of the first NOP above the function. We anyway generate __patchable_function_entries again in kpatch_create_ftrace_callsite_sections() so we can skip mangling these relocations Signed-off-by: Puranjay Mohan --- kpatch-build/create-diff-object.c | 7 +++++++ kpatch-build/kpatch-elf.c | 12 ++++++++++++ kpatch-build/kpatch-elf.h | 1 + 3 files changed, 20 insertions(+) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index 7f2c7b95..a10617fc 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -1639,6 +1639,13 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf) if (!is_rela_section(relasec) || is_debug_section(relasec)) continue; + /* + * We regenerate __patchable_function_entries from scratch so + * don't bother replacing section symbols in its relasec. + */ + if (is_patchable_function_entries_section(relasec)) + continue; + list_for_each_entry(rela, &relasec->relas, list) { if (rela->sym->type != STT_SECTION || !rela->sym->sec) diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c index a7f62c01..954db594 100755 --- a/kpatch-build/kpatch-elf.c +++ b/kpatch-build/kpatch-elf.c @@ -65,6 +65,18 @@ bool is_text_section(struct section *sec) (sec->sh.sh_flags & SHF_EXECINSTR)); } +bool is_patchable_function_entries_section(struct section *sec) +{ + char *name; + + if (is_rela_section(sec)) + name = sec->base->name; + else + name = sec->name; + + return !strncmp(name, "__patchable_function_entries", 28); +} + bool is_debug_section(struct section *sec) { char *name; diff --git a/kpatch-build/kpatch-elf.h b/kpatch-build/kpatch-elf.h index 3722a5cf..9484c495 100644 --- a/kpatch-build/kpatch-elf.h +++ b/kpatch-build/kpatch-elf.h @@ -136,6 +136,7 @@ struct kpatch_elf { char *status_str(enum status status); bool is_rela_section(struct section *sec); bool is_text_section(struct section *sec); +bool is_patchable_function_entries_section(struct section *sec); bool is_debug_section(struct section *sec); struct section *find_section_by_index(struct list_head *list, unsigned int index);