mirror of https://github.com/dynup/kpatch
create-diff-object: Add ppc64le mcount support
Add the __mcount_loc section on ppc64le. It has pointers to all the mcount calls. This will enable the ftrace hook to be used for patched functions. Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com> (rebased)
This commit is contained in:
parent
8e8707ed72
commit
b958ed601c
|
@ -3322,9 +3322,6 @@ static void kpatch_create_callbacks_objname_rela(struct kpatch_elf *kelf, char *
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef __powerpc64__
|
||||
void kpatch_create_mcount_sections(struct kpatch_elf *kelf) { }
|
||||
#else
|
||||
/*
|
||||
* This function basically reimplements the functionality of the Linux
|
||||
* recordmcount script, so that patched functions can be recognized by ftrace.
|
||||
|
@ -3337,9 +3334,9 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
|
|||
int nr, index;
|
||||
struct section *sec, *relasec;
|
||||
struct symbol *sym;
|
||||
struct rela *rela;
|
||||
void *newdata;
|
||||
unsigned char *insn;
|
||||
struct rela *rela, *mcount_rela;
|
||||
void **funcs;
|
||||
unsigned long insn_offset;
|
||||
|
||||
nr = 0;
|
||||
list_for_each_entry(sym, &kelf->symbols, list)
|
||||
|
@ -3363,36 +3360,40 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
|
|||
continue;
|
||||
}
|
||||
|
||||
/* add rela in .rela__mcount_loc to fill in function pointer */
|
||||
ALLOC_LINK(rela, &relasec->relas);
|
||||
rela->sym = sym;
|
||||
rela->type = R_X86_64_64;
|
||||
rela->addend = 0;
|
||||
rela->offset = (unsigned int)(index * sizeof(void*));
|
||||
#ifdef __x86_64__
|
||||
|
||||
rela = list_first_entry(&sym->sec->rela->relas, struct rela, list);
|
||||
|
||||
/*
|
||||
* Modify the first instruction of the function to "callq
|
||||
* __fentry__" so that ftrace will be happy.
|
||||
* For "call fentry", the relocation points to 1 byte past the
|
||||
* beginning of the instruction.
|
||||
*/
|
||||
newdata = malloc(sym->sec->data->d_size);
|
||||
if (!newdata)
|
||||
ERROR("malloc");
|
||||
insn_offset = rela->offset - 1;
|
||||
|
||||
memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
|
||||
sym->sec->data->d_buf = newdata;
|
||||
insn = newdata;
|
||||
|
||||
rela = list_first_entry(&sym->sec->rela->relas, struct rela,
|
||||
list);
|
||||
|
||||
/*
|
||||
* R_X86_64_NONE is only generated by older versions of kernel/gcc
|
||||
* which use the mcount script.
|
||||
*/
|
||||
if (rela->type == R_X86_64_NONE) {
|
||||
void *newdata;
|
||||
unsigned char *insn;
|
||||
|
||||
/*
|
||||
* R_X86_64_NONE is only generated by older versions of
|
||||
* kernel/gcc which use the mcount script. There's a
|
||||
* NOP instead of a call to fentry.
|
||||
*/
|
||||
|
||||
/* Make a writable copy of the text section data */
|
||||
newdata = malloc(sym->sec->data->d_size);
|
||||
memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
|
||||
sym->sec->data->d_buf = newdata;
|
||||
insn = newdata;
|
||||
|
||||
/*
|
||||
* Replace the NOP with a call to fentry. The fentry
|
||||
* rela symbol is already there, just need to change
|
||||
* the relocation type accordingly.
|
||||
*/
|
||||
insn = sym->sec->data->d_buf;
|
||||
if (insn[0] != 0xf)
|
||||
ERROR("%s: unexpected instruction at the start of the function",
|
||||
sym->name);
|
||||
ERROR("%s: unexpected instruction at the start of the function", sym->name);
|
||||
insn[0] = 0xe8;
|
||||
insn[1] = 0;
|
||||
insn[2] = 0;
|
||||
|
@ -3402,6 +3403,33 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
|
|||
rela->type = R_X86_64_PC32;
|
||||
}
|
||||
|
||||
#else /* __powerpc64__ */
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
list_for_each_entry(rela, &sym->sec->rela->relas, list)
|
||||
if (!strcmp(rela->sym->name, "_mcount")) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
ERROR("%s: unexpected missing call to _mcount()", __func__);
|
||||
|
||||
insn_offset = rela->offset;
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* 'rela' points to the mcount/fentry call.
|
||||
*
|
||||
* Create a .rela__mcount_loc entry which also points to it.
|
||||
*/
|
||||
ALLOC_LINK(mcount_rela, &relasec->relas);
|
||||
mcount_rela->sym = sym;
|
||||
mcount_rela->type = ABSOLUTE_RELA_TYPE;
|
||||
mcount_rela->addend = insn_offset - sym->sym.st_value;
|
||||
mcount_rela->offset = (unsigned int) (index * sizeof(*funcs));
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
|
@ -3409,7 +3437,6 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
|
|||
if (index != nr)
|
||||
ERROR("size mismatch in funcs sections");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function strips out symbols that were referenced by changed rela
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 42df5fbc85632c4bab836e104210fe5fd52ae1e5
|
||||
Subproject commit 59b5841598dc2d01e750a2b21547ffa243a09894
|
Loading…
Reference in New Issue