mirror of https://github.com/dynup/kpatch
Merge pull request #1102 from joe-lawrence/jp-ppc-mcount
create-diff-object: Add ppc64le mcount support
This commit is contained in:
commit
5331463768
|
@ -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
|
Loading…
Reference in New Issue