kpatch-build: Add sym->has_func_profiling support for aarch64

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".

Signed-off-by: Suraj Jitindar Singh <surajjs@amazon.com>

---

V1->V2:
 - Make error message standard across architectures when no patchable entry
 - Don't store __patchable_function_entries section in
   kpatch_find_func_profiling_calls(), instead find it each time
This commit is contained in:
Suraj Jitindar Singh 2021-10-06 12:41:16 -07:00 committed by Mihails Strasuns
parent e0b20c9673
commit fcae79f54b
3 changed files with 23 additions and 1 deletions

View File

@ -1696,7 +1696,7 @@ static void kpatch_check_func_profiling_calls(struct kpatch_elf *kelf)
(sym->parent && sym->parent->status == CHANGED))
continue;
if (!sym->twin->has_func_profiling) {
log_normal("function %s has no fentry/mcount call, unable to patch\n",
log_normal("function %s doesn't have patchable function entry, unable to patch\n",
sym->name);
errs++;
}
@ -3976,6 +3976,24 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf)
continue;
switch(kelf->arch) {
case AARCH64: {
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;
list_for_each_entry(rela, &sec->rela->relas, list) {
if (rela->sym->sec && sym->sec == rela->sym->sec) {
sym->has_func_profiling = 1;
break;
}
}
break;
}
case PPC64:
list_for_each_entry(rela, &sym->sec->rela->relas, list) {
if (!strcmp(rela->sym->name, "_mcount")) {

View File

@ -604,6 +604,9 @@ struct kpatch_elf *kpatch_elf_open(const char *name)
if (!gelf_getehdr(kelf->elf, &ehdr))
ERROR("gelf_getehdr");
switch (ehdr.e_machine) {
case EM_AARCH64:
kelf->arch = AARCH64;
break;
case EM_PPC64:
kelf->arch = PPC64;
break;

View File

@ -115,6 +115,7 @@ enum architecture {
PPC64 = 0x1 << 0,
X86_64 = 0x1 << 1,
S390 = 0x1 << 2,
AARCH64 = 0x1 << 3,
};
struct kpatch_elf {