From 04d052bdfbc2e4a6c59ba3e6353bf51706659402 Mon Sep 17 00:00:00 2001 From: lu21253 Date: Thu, 4 Dec 2025 16:56:15 +0800 Subject: [PATCH] creatte-diff-object: Add support for x86_64 CONFIG_CALL_PADDING For x86_64 this option uses -fpatchable-function-entry=$(CONFIG_FUNCTION_PADDING_BYTES),$(CONFIG_FUNCTION_PADDING_BYTES), so CONFIG_FUNCTION_PADDING_BYTES NOPs are placed before the function entry point (in order to store a pointer to ftrace_ops).When calculating function padding, check for the presence of the CONFIG_FUNCTION_PADDING_BYTES NOPs, and adjust the padding size by CONFIG_FUNCTION_PADDING_BYTES if they are found. Signed-off-by: lu21253 Reviewed-by: w28894 Reviewed-by: z17497 --- kpatch-build/create-diff-object.c | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index 09160030..87e34d61 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -284,6 +284,43 @@ static unsigned int function_padding_size(struct kpatch_elf *kelf, struct symbol break; } + case X86_64: + { + uint8_t *insn = sym->sec->data->d_buf; + uint8_t *insn_end = sym->sec->data->d_buf + sym->sym.st_value; + + /* + * If the x86_64 kernel is compiled with CONFIG_CALL_PADDING + * then there are CONFIG_FUNCTION_PADDING_BYTES NOPs before the function.Verify the presence of the CONFIG_FUNCTION_PADDING_BYTES + * NOPs before the function entry. + * Possible padding patterns before X86 functions: + * 1. NOP instructions (0x90) for alignment. + * 2. Multi-byte NOPs that compilers may insert (e.g., 0x66 0x90). + * 3. Jump tables or special instructions may exist before functions (adjust according to actual scenarios). + */ + while (insn < insn_end) { + + if (*insn == 0x90) { + size++; + insn++; + } + else if (insn + 1 < insn_end && + insn[0] == 0x66 && insn[1] == 0x90) { + size += 2; + insn += 2; + } + else { + break; + } + } + + if (size > 16) { + log_error("function %s in section %s has excessive padding (%u bytes)\n", + sym->name, sym->sec->name, size); + size = 0; + } + break; + } default: break; }