mirror of https://github.com/dynup/kpatch
Merge pull request #525 from euspectre/no-reloc-fix
kpatch-build: revisit checking for fentry calls
This commit is contained in:
commit
2e4dea5236
|
@ -127,6 +127,7 @@ struct symbol {
|
|||
int include; /* used in the patched elf */
|
||||
int strip; /* used in the output elf */
|
||||
};
|
||||
int has_fentry_call;
|
||||
};
|
||||
|
||||
struct rela {
|
||||
|
@ -472,6 +473,24 @@ void kpatch_create_symbol_list(struct kpatch_elf *kelf)
|
|||
|
||||
}
|
||||
|
||||
/* Check which functions have fentry calls; save this info for later use. */
|
||||
static void kpatch_find_fentry_calls(struct kpatch_elf *kelf)
|
||||
{
|
||||
struct symbol *sym;
|
||||
struct rela *rela;
|
||||
list_for_each_entry(sym, &kelf->symbols, list) {
|
||||
if (sym->type != STT_FUNC || !sym->sec->rela)
|
||||
continue;
|
||||
|
||||
rela = list_first_entry(&sym->sec->rela->relas, struct rela,
|
||||
list);
|
||||
if (rela->type != R_X86_64_NONE ||
|
||||
strcmp(rela->sym->name, "__fentry__"))
|
||||
continue;
|
||||
|
||||
sym->has_fentry_call = 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct kpatch_elf *kpatch_elf_open(const char *name)
|
||||
{
|
||||
|
@ -510,6 +529,7 @@ struct kpatch_elf *kpatch_elf_open(const char *name)
|
|||
kpatch_create_rela_list(kelf, sec);
|
||||
}
|
||||
|
||||
kpatch_find_fentry_calls(kelf);
|
||||
return kelf;
|
||||
}
|
||||
|
||||
|
@ -1373,6 +1393,25 @@ next:
|
|||
}
|
||||
}
|
||||
|
||||
static void kpatch_check_fentry_calls(struct kpatch_elf *kelf)
|
||||
{
|
||||
struct symbol *sym;
|
||||
int errs = 0;
|
||||
|
||||
list_for_each_entry(sym, &kelf->symbols, list) {
|
||||
if (sym->type != STT_FUNC || sym->status != CHANGED)
|
||||
continue;
|
||||
if (!sym->twin->has_fentry_call) {
|
||||
log_normal("function %s has no fentry call, unable to patch\n",
|
||||
sym->name);
|
||||
errs++;
|
||||
}
|
||||
}
|
||||
|
||||
if (errs)
|
||||
DIFF_FATAL("%d function(s) can not be patched", errs);
|
||||
}
|
||||
|
||||
void kpatch_verify_patchability(struct kpatch_elf *kelf)
|
||||
{
|
||||
struct section *sec;
|
||||
|
@ -2658,7 +2697,8 @@ void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
|
|||
|
||||
nr = 0;
|
||||
list_for_each_entry(sym, &kelf->symbols, list)
|
||||
if (sym->type == STT_FUNC && sym->status != SAME)
|
||||
if (sym->type == STT_FUNC && sym->status != SAME &&
|
||||
sym->has_fentry_call)
|
||||
nr++;
|
||||
|
||||
/* create text/rela section pair */
|
||||
|
@ -2672,6 +2712,12 @@ void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
|
|||
if (sym->type != STT_FUNC || sym->status == SAME)
|
||||
continue;
|
||||
|
||||
if (!sym->has_fentry_call) {
|
||||
log_debug("function %s has no fentry call, no mcount record is needed\n",
|
||||
sym->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* add rela in .rela__mcount_loc to fill in function pointer */
|
||||
ALLOC_LINK(rela, &relasec->relas);
|
||||
rela->sym = sym;
|
||||
|
@ -2688,7 +2734,8 @@ void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
|
|||
sym->sec->data->d_buf = newdata;
|
||||
insn = newdata;
|
||||
if (insn[0] != 0xf)
|
||||
ERROR("function '%s' has no fentry call; unable to patch", sym->name);
|
||||
ERROR("%s: unexpected instruction at the start of the function",
|
||||
sym->name);
|
||||
insn[0] = 0xe8;
|
||||
insn[1] = 0;
|
||||
insn[2] = 0;
|
||||
|
@ -2697,9 +2744,6 @@ void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
|
|||
|
||||
rela = list_first_entry(&sym->sec->rela->relas, struct rela,
|
||||
list);
|
||||
if (rela->type != R_X86_64_NONE ||
|
||||
strcmp(rela->sym->name, "__fentry__"))
|
||||
ERROR("function '%s' has no fentry call; unable to patch", sym->name);
|
||||
rela->type = R_X86_64_PC32;
|
||||
|
||||
index++;
|
||||
|
@ -3019,6 +3063,7 @@ int main(int argc, char *argv[])
|
|||
*/
|
||||
kpatch_mark_ignored_sections(kelf_patched);
|
||||
kpatch_compare_correlated_elements(kelf_patched);
|
||||
kpatch_check_fentry_calls(kelf_patched);
|
||||
kpatch_elf_teardown(kelf_base);
|
||||
kpatch_elf_free(kelf_base);
|
||||
|
||||
|
|
Loading…
Reference in New Issue