Skip to content

Commit

Permalink
kpatch-build: Add sym->has_func_profiling support for aarch64
Browse files Browse the repository at this point in the history
The "has_function_profiling" support field in the symbol struct is used to show
that a function symbol is able to be patched. This is necessary to check that
functions which need to be patched are able to be.

On arm64 this means the presence of 2 NOP instructions at function entry
which are patched by ftrace to call the ftrace handling code. These 2 NOPs
are inserted by the compiler and the location of them is recorded in a
section called "__patchable_function_entries". Check whether a symbol has a
corresponding entry in the "__patchable_function_entries" section and if so
mark it as "has_func_profiling".

Additionally updated the error message in kpatch_check_func_profiling_calls()
to accurately reflect the cause of the failure.

Signed-off-by: Suraj Jitindar Singh <[email protected]>
  • Loading branch information
Suraj Jitindar Singh committed Nov 3, 2021
1 parent 61fc3f1 commit 2a21437
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
5 changes: 5 additions & 0 deletions kpatch-build/create-diff-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -1632,8 +1632,13 @@ static void kpatch_check_func_profiling_calls(struct kpatch_elf *kelf)
(sym->parent && sym->parent->status == CHANGED))
continue;
if (!sym->twin->has_func_profiling) {
#ifdef __aarch64__
log_normal("function %s doesn't have patchable_function_entry,"
" unable to patch\n", sym->name);
#else
log_normal("function %s has no fentry/mcount call, unable to patch\n",
sym->name);
#endif
errs++;
}
}
Expand Down
25 changes: 24 additions & 1 deletion kpatch-build/kpatch-elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,9 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf)
{
struct symbol *sym;
struct rela *rela;
#ifdef __aarch64__
struct section *patchable_sec = NULL;
#endif
list_for_each_entry(sym, &kelf->symbols, list) {
if (sym->type != STT_FUNC || !sym->sec || !sym->sec->rela)
continue;
Expand All @@ -332,7 +335,27 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf)
break;
}
}
#else
#elif defined(__aarch64__)
if (!patchable_sec) {
struct section *sec = find_section_by_name(&kelf->sections,
"__patchable_function_entries");
/*
* If we can't find the __patchable_function_entries
* section or there are no relocations in it then not
* patchable.
*/
if (!sec || !sec->rela)
return;
patchable_sec = sec->rela;
}
list_for_each_entry(rela, &patchable_sec->relas,
list) {
if (rela->sym->sec && sym->sec == rela->sym->sec) {
sym->has_func_profiling = 1;
break;
}
}
#else /* x86_64 */
rela = list_first_entry(&sym->sec->rela->relas, struct rela,
list);
if ((rela->type != R_X86_64_NONE &&
Expand Down

0 comments on commit 2a21437

Please sign in to comment.