Merge pull request #1102 from joe-lawrence/jp-ppc-mcount

create-diff-object: Add ppc64le mcount support
This commit is contained in:
Joe Lawrence 2020-05-18 09:20:40 -04:00 committed by GitHub
commit 5331463768
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 32 deletions

View File

@ -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 * This function basically reimplements the functionality of the Linux
* recordmcount script, so that patched functions can be recognized by ftrace. * 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; int nr, index;
struct section *sec, *relasec; struct section *sec, *relasec;
struct symbol *sym; struct symbol *sym;
struct rela *rela; struct rela *rela, *mcount_rela;
void *newdata; void **funcs;
unsigned char *insn; unsigned long insn_offset;
nr = 0; nr = 0;
list_for_each_entry(sym, &kelf->symbols, list) list_for_each_entry(sym, &kelf->symbols, list)
@ -3363,36 +3360,40 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
continue; continue;
} }
/* add rela in .rela__mcount_loc to fill in function pointer */ #ifdef __x86_64__
ALLOC_LINK(rela, &relasec->relas);
rela->sym = sym; rela = list_first_entry(&sym->sec->rela->relas, struct rela, list);
rela->type = R_X86_64_64;
rela->addend = 0;
rela->offset = (unsigned int)(index * sizeof(void*));
/* /*
* Modify the first instruction of the function to "callq * For "call fentry", the relocation points to 1 byte past the
* __fentry__" so that ftrace will be happy. * beginning of the instruction.
*/ */
newdata = malloc(sym->sec->data->d_size); insn_offset = rela->offset - 1;
if (!newdata)
ERROR("malloc");
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); memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
sym->sec->data->d_buf = newdata; sym->sec->data->d_buf = newdata;
insn = 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 * Replace the NOP with a call to fentry. The fentry
* which use the mcount script. * rela symbol is already there, just need to change
* the relocation type accordingly.
*/ */
if (rela->type == R_X86_64_NONE) { insn = sym->sec->data->d_buf;
if (insn[0] != 0xf) if (insn[0] != 0xf)
ERROR("%s: unexpected instruction at the start of the function", ERROR("%s: unexpected instruction at the start of the function", sym->name);
sym->name);
insn[0] = 0xe8; insn[0] = 0xe8;
insn[1] = 0; insn[1] = 0;
insn[2] = 0; insn[2] = 0;
@ -3402,6 +3403,33 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
rela->type = R_X86_64_PC32; 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++; index++;
} }
@ -3409,7 +3437,6 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
if (index != nr) if (index != nr)
ERROR("size mismatch in funcs sections"); ERROR("size mismatch in funcs sections");
} }
#endif
/* /*
* This function strips out symbols that were referenced by changed rela * This function strips out symbols that were referenced by changed rela

@ -1 +1 @@
Subproject commit 42df5fbc85632c4bab836e104210fe5fd52ae1e5 Subproject commit 59b5841598dc2d01e750a2b21547ffa243a09894