Skip to content

Commit 6f0ecd5

Browse files
dylanbhatchpuranjaymohan
authored andcommitted
create-diff-object: Add support for arm64 DYNAMIC_FTRACE_WITH_CALL_OPS
For arm64 this option uses -fpatchable-function-entry=M,2, so 2 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 two NOPs, and adjust the padding size by 8 if they are found. This was merged in the upstream kernel in v6.8 with: baaf553d3bc3 ("arm64: Implement HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS") With this into the equation, the entry of a function can look like one of: 1. Without DYNAMIC_FTRACE_WITH_CALL_OPS and CONFIG_ARM64_BTI_KERNEL ------------------------------------------------------------------- Disassembly of section .text.cmdline_proc_show: 0000000000000008 <cmdline_proc_show>: 8: d503201f nop c: d503201f nop 2. Without DYNAMIC_FTRACE_WITH_CALL_OPS and with CONFIG_ARM64_BTI_KERNEL ------------------------------------------------------------------------ Disassembly of section .text.cmdline_proc_show: 0000000000000008 <cmdline_proc_show>: 0: d503245f bti c 4: d503201f nop 8: d503201f nop 3. With DYNAMIC_FTRACE_WITH_CALL_OPS and without CONFIG_ARM64_BTI_KERNEL ------------------------------------------------------------------------ Disassembly of section .text.cmdline_proc_show: 0000000000000000 <cmdline_proc_show-0x8>: 0: d503201f nop 4: d503201f nop 0000000000000008 <cmdline_proc_show>: 8: d503201f nop c: d503201f nop 4. With DYNAMIC_FTRACE_WITH_CALL_OPS and with CONFIG_ARM64_BTI_KERNEL --------------------------------------------------------------------- Disassembly of section .text.cmdline_proc_show: 0000000000000000 <cmdline_proc_show-0x8>: 0: d503201f nop 4: d503201f nop 0000000000000008 <cmdline_proc_show>: 8: d503245f bti c c: d503201f nop 10: d503201f nop make create-diff-object aware of DYNAMIC_FTRACE_WITH_CALL_OPS and its quirks. Signed-off-by: Dylan Hatch <dylanbhatch@google.com> Signed-off-by: Puranjay Mohan <pjy@amazon.com>
1 parent 01db546 commit 6f0ecd5

File tree

1 file changed

+47
-1
lines changed

1 file changed

+47
-1
lines changed

kpatch-build/create-diff-object.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,42 @@ static bool kpatch_is_mapping_symbol(struct kpatch_elf *kelf, struct symbol *sym
255255
return false;
256256
}
257257

258+
static unsigned int function_padding_size(struct kpatch_elf *kelf, struct symbol *sym)
259+
{
260+
unsigned int size = 0;
261+
262+
switch (kelf->arch) {
263+
case AARCH64:
264+
{
265+
uint8_t *insn = sym->sec->data->d_buf;
266+
unsigned int i;
267+
void *insn_end = sym->sec->data->d_buf + sym->sym.st_value;
268+
269+
/*
270+
* If the arm64 kernel is compiled with CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
271+
* then there are two NOPs before the function and a `BTI C` + 2 NOPs at the
272+
* start of the function. Verify the presence of the two NOPs before the
273+
* function entry.
274+
*/
275+
for (i = 0; (void *)insn < insn_end; i++, insn += 4)
276+
if (insn[0] != 0x1f || insn[1] != 0x20 ||
277+
insn[2] != 0x03 || insn[3] != 0xd5)
278+
break;
279+
280+
if (i == 2)
281+
size = 8;
282+
else if (i != 0)
283+
log_error("function %s within section %s has invalid padding\n", sym->name, sym->sec->name);
284+
285+
break;
286+
}
287+
default:
288+
break;
289+
}
290+
291+
return size;
292+
}
293+
258294
/*
259295
* When compiling with -ffunction-sections and -fdata-sections, almost every
260296
* symbol gets its own dedicated section. We call such symbols "bundled"
@@ -271,6 +307,8 @@ static void kpatch_bundle_symbols(struct kpatch_elf *kelf)
271307
expected_offset = sym->pfx->sym.st_size;
272308
else if (is_gcc6_localentry_bundled_sym(kelf, sym))
273309
expected_offset = 8;
310+
else if (sym->type == STT_FUNC)
311+
expected_offset = function_padding_size(kelf, sym);
274312
else
275313
expected_offset = 0;
276314

@@ -3898,8 +3936,15 @@ static void kpatch_create_ftrace_callsite_sections(struct kpatch_elf *kelf)
38983936
switch(kelf->arch) {
38993937
case AARCH64: {
39003938
unsigned char *insn = sym->sec->data->d_buf;
3939+
int padding;
39013940
int i;
39023941

3942+
/*
3943+
* Skip the padding NOPs added by CALL_OPS.
3944+
*/
3945+
padding = function_padding_size(kelf, sym);
3946+
insn += padding;
3947+
39033948
/*
39043949
* If BTI (Branch Target Identification) is enabled then there
39053950
* might be an additional 'BTI C' instruction before the two
@@ -3909,7 +3954,8 @@ static void kpatch_create_ftrace_callsite_sections(struct kpatch_elf *kelf)
39093954
if (insn[0] == 0x5f) {
39103955
if (insn[1] != 0x24 || insn[2] != 0x03 || insn[3] != 0xd5)
39113956
ERROR("%s: unexpected instruction in patch section of function\n", sym->name);
3912-
insn_offset += 4;
3957+
if (!padding)
3958+
insn_offset += 4;
39133959
insn += 4;
39143960
}
39153961
for (i = 0; i < 8; i += 4) {

0 commit comments

Comments
 (0)