forked from TencentOS/TencentOS-kernel
tkernel: add the kpatch kmod support
Add the kpatch and write relocations support. Signed-off-by: Kaixu Xia <kaixuxia@tencent.com>
This commit is contained in:
parent
de046697ad
commit
d2290bb348
|
|
@ -197,6 +197,184 @@ static int reloc_insn_imm(enum aarch64_reloc_op op, __le32 *place, u64 val,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int static_relocate(struct module *me, int type, void *loc,
|
||||
unsigned long val)
|
||||
{
|
||||
int ovf = 0;
|
||||
bool overflow_check = true;
|
||||
/* Perform the static relocation. */
|
||||
switch (type) {
|
||||
/* Null relocations. */
|
||||
case R_ARM_NONE:
|
||||
case R_AARCH64_NONE:
|
||||
ovf = 0;
|
||||
break;
|
||||
|
||||
/* Data relocations. */
|
||||
case R_AARCH64_ABS64:
|
||||
overflow_check = false;
|
||||
ovf = reloc_data(RELOC_OP_ABS, loc, val, 64);
|
||||
break;
|
||||
case R_AARCH64_ABS32:
|
||||
ovf = reloc_data(RELOC_OP_ABS, loc, val, 32);
|
||||
break;
|
||||
case R_AARCH64_ABS16:
|
||||
ovf = reloc_data(RELOC_OP_ABS, loc, val, 16);
|
||||
break;
|
||||
case R_AARCH64_PREL64:
|
||||
overflow_check = false;
|
||||
ovf = reloc_data(RELOC_OP_PREL, loc, val, 64);
|
||||
break;
|
||||
case R_AARCH64_PREL32:
|
||||
ovf = reloc_data(RELOC_OP_PREL, loc, val, 32);
|
||||
break;
|
||||
case R_AARCH64_PREL16:
|
||||
ovf = reloc_data(RELOC_OP_PREL, loc, val, 16);
|
||||
break;
|
||||
|
||||
/* MOVW instruction relocations. */
|
||||
case R_AARCH64_MOVW_UABS_G0_NC:
|
||||
overflow_check = false;
|
||||
case R_AARCH64_MOVW_UABS_G0:
|
||||
ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0,
|
||||
AARCH64_INSN_IMM_MOVKZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_UABS_G1_NC:
|
||||
overflow_check = false;
|
||||
case R_AARCH64_MOVW_UABS_G1:
|
||||
ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16,
|
||||
AARCH64_INSN_IMM_MOVKZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_UABS_G2_NC:
|
||||
overflow_check = false;
|
||||
case R_AARCH64_MOVW_UABS_G2:
|
||||
ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32,
|
||||
AARCH64_INSN_IMM_MOVKZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_UABS_G3:
|
||||
/* We're using the top bits so we can't overflow. */
|
||||
overflow_check = false;
|
||||
ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 48,
|
||||
AARCH64_INSN_IMM_MOVKZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_SABS_G0:
|
||||
ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 0,
|
||||
AARCH64_INSN_IMM_MOVNZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_SABS_G1:
|
||||
ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 16,
|
||||
AARCH64_INSN_IMM_MOVNZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_SABS_G2:
|
||||
ovf = reloc_insn_movw(RELOC_OP_ABS, loc, val, 32,
|
||||
AARCH64_INSN_IMM_MOVNZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_PREL_G0_NC:
|
||||
overflow_check = false;
|
||||
ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 0,
|
||||
AARCH64_INSN_IMM_MOVKZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_PREL_G0:
|
||||
ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 0,
|
||||
AARCH64_INSN_IMM_MOVNZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_PREL_G1_NC:
|
||||
overflow_check = false;
|
||||
ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 16,
|
||||
AARCH64_INSN_IMM_MOVKZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_PREL_G1:
|
||||
ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 16,
|
||||
AARCH64_INSN_IMM_MOVNZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_PREL_G2_NC:
|
||||
overflow_check = false;
|
||||
ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 32,
|
||||
AARCH64_INSN_IMM_MOVKZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_PREL_G2:
|
||||
ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 32,
|
||||
AARCH64_INSN_IMM_MOVNZ);
|
||||
break;
|
||||
case R_AARCH64_MOVW_PREL_G3:
|
||||
/* We're using the top bits so we can't overflow. */
|
||||
overflow_check = false;
|
||||
ovf = reloc_insn_movw(RELOC_OP_PREL, loc, val, 48,
|
||||
AARCH64_INSN_IMM_MOVNZ);
|
||||
break;
|
||||
|
||||
/* Immediate instruction relocations. */
|
||||
case R_AARCH64_LD_PREL_LO19:
|
||||
ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 19,
|
||||
AARCH64_INSN_IMM_19);
|
||||
break;
|
||||
case R_AARCH64_ADR_PREL_LO21:
|
||||
ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 0, 21,
|
||||
AARCH64_INSN_IMM_ADR);
|
||||
break;
|
||||
#ifndef CONFIG_ARM64_ERRATUM_843419
|
||||
case R_AARCH64_ADR_PREL_PG_HI21_NC:
|
||||
overflow_check = false;
|
||||
case R_AARCH64_ADR_PREL_PG_HI21:
|
||||
ovf = reloc_insn_imm(RELOC_OP_PAGE, loc, val, 12, 21,
|
||||
AARCH64_INSN_IMM_ADR);
|
||||
break;
|
||||
#endif
|
||||
case R_AARCH64_ADD_ABS_LO12_NC:
|
||||
case R_AARCH64_LDST8_ABS_LO12_NC:
|
||||
overflow_check = false;
|
||||
ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 0, 12,
|
||||
AARCH64_INSN_IMM_12);
|
||||
break;
|
||||
case R_AARCH64_LDST16_ABS_LO12_NC:
|
||||
overflow_check = false;
|
||||
ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 1, 11,
|
||||
AARCH64_INSN_IMM_12);
|
||||
break;
|
||||
case R_AARCH64_LDST32_ABS_LO12_NC:
|
||||
overflow_check = false;
|
||||
ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 2, 10,
|
||||
AARCH64_INSN_IMM_12);
|
||||
break;
|
||||
case R_AARCH64_LDST64_ABS_LO12_NC:
|
||||
overflow_check = false;
|
||||
ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 3, 9,
|
||||
AARCH64_INSN_IMM_12);
|
||||
break;
|
||||
case R_AARCH64_LDST128_ABS_LO12_NC:
|
||||
overflow_check = false;
|
||||
ovf = reloc_insn_imm(RELOC_OP_ABS, loc, val, 4, 8,
|
||||
AARCH64_INSN_IMM_12);
|
||||
break;
|
||||
case R_AARCH64_TSTBR14:
|
||||
ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 14,
|
||||
AARCH64_INSN_IMM_14);
|
||||
break;
|
||||
case R_AARCH64_CONDBR19:
|
||||
ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 19,
|
||||
AARCH64_INSN_IMM_19);
|
||||
break;
|
||||
case R_AARCH64_JUMP26:
|
||||
case R_AARCH64_CALL26:
|
||||
ovf = reloc_insn_imm(RELOC_OP_PREL, loc, val, 2, 26,
|
||||
AARCH64_INSN_IMM_26);
|
||||
break;
|
||||
default:
|
||||
pr_err("module %s: unsupported RELA relocation: %d\n",
|
||||
me->name, type);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (overflow_check && ovf == -ERANGE) {
|
||||
pr_err("module %s: overflow in relocation type %d val %lx\n",
|
||||
me->name, type, val);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(static_relocate);
|
||||
|
||||
int apply_relocate_add(Elf64_Shdr *sechdrs,
|
||||
const char *strtab,
|
||||
unsigned int symindex,
|
||||
|
|
|
|||
|
|
@ -1945,6 +1945,7 @@ void module_disable_ro(const struct module *mod)
|
|||
frob_text(&mod->init_layout, set_memory_rw);
|
||||
frob_rodata(&mod->init_layout, set_memory_rw);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(module_disable_ro);
|
||||
|
||||
void module_enable_ro(const struct module *mod, bool after_init)
|
||||
{
|
||||
|
|
@ -1959,6 +1960,7 @@ void module_enable_ro(const struct module *mod, bool after_init)
|
|||
if (after_init)
|
||||
frob_ro_after_init(&mod->core_layout, set_memory_ro);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(module_enable_ro);
|
||||
|
||||
static void module_enable_nx(const struct module *mod)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
obj-y = base.o netbind.o shield_mounts.o
|
||||
obj-m += kpatch/
|
||||
|
|
|
|||
Loading…
Reference in New Issue