Messages in this thread | | | From | Huacai Chen <> | Date | Mon, 29 Aug 2022 23:08:03 +0800 | Subject | Re: [PATCH v6 5/6] LoongArch: Support PC-relative relocations in modules |
| |
Hi, Ruoyao,
On Mon, Aug 29, 2022 at 9:35 PM Xi Ruoyao <xry111@xry111.site> wrote: > > Binutils >= 2.40 uses R_LARCH_B26 instead of R_LARCH_SOP_PUSH_PLT_PCREL, > and R_LARCH_PCALA* instead of R_LARCH_SOP_PUSH_PCREL. > > Handle R_LARCH_B26 and R_LARCH_PCALA* in the module loader. For > R_LARCH_B26, also create a PLT entry as needed. > > Signed-off-by: Xi Ruoyao <xry111@xry111.site> > --- > arch/loongarch/kernel/module-sections.c | 7 ++- > arch/loongarch/kernel/module.c | 75 +++++++++++++++++++++++++ > 2 files changed, 81 insertions(+), 1 deletion(-) > > diff --git a/arch/loongarch/kernel/module-sections.c b/arch/loongarch/kernel/module-sections.c > index 6d498288977d..c67b9cb220eb 100644 > --- a/arch/loongarch/kernel/module-sections.c > +++ b/arch/loongarch/kernel/module-sections.c > @@ -56,9 +56,14 @@ static void count_max_entries(Elf_Rela *relas, int num, unsigned int *plts) > > for (i = 0; i < num; i++) { > type = ELF_R_TYPE(relas[i].r_info); > - if (type == R_LARCH_SOP_PUSH_PLT_PCREL) { > + switch (type) { > + case R_LARCH_SOP_PUSH_PLT_PCREL: > + case R_LARCH_B26: > if (!duplicate_rela(relas, i)) > (*plts)++; > + break; > + default: > + /* Do nothing. */ > } > } > } > diff --git a/arch/loongarch/kernel/module.c b/arch/loongarch/kernel/module.c > index 755d91ef8d85..0024bc6c4af1 100644 > --- a/arch/loongarch/kernel/module.c > +++ b/arch/loongarch/kernel/module.c > @@ -281,6 +281,79 @@ static int apply_r_larch_add_sub(struct module *mod, u32 *location, Elf_Addr v, > } > } > > +static int apply_r_larch_b26(struct module *mod, u32 *location, Elf_Addr v, > + s64 *rela_stack, size_t *rela_stack_top, unsigned int type) > +{ > + ptrdiff_t offset = (void *)v - (void *)location; > + union loongarch_instruction *insn = (union loongarch_instruction *)location; > + > + if (offset >= SZ_128M) > + v = module_emit_plt_entry(mod, v); > + > + if (offset < -SZ_128M) > + v = module_emit_plt_entry(mod, v); > + > + offset = (void *)v - (void *)location; > + > + if (offset & 3) { > + pr_err("module %s: jump offset = 0x%llx unaligned! dangerous R_LARCH_B26 (%u) relocation\n", > + mod->name, (long long)offset, type); > + return -ENOEXEC; > + } > + > + if (!signed_imm_check(offset, 28)) { > + pr_err("module %s: jump offset = 0x%llx overflow! dangerous R_LARCH_B26 (%u) relocation\n", > + mod->name, (long long)offset, type); > + return -ENOEXEC; > + } > + > + offset >>= 2; > + insn->reg0i26_format.immediate_l = offset & 0xffff; > + insn->reg0i26_format.immediate_h = (offset >> 16) & 0x3ff; > + return 0; > +} > + > +static int apply_r_larch_pcala(struct module *mod, u32 *location, Elf_Addr v, > + s64 *rela_stack, size_t *rela_stack_top, unsigned int type) > +{ > + union loongarch_instruction *insn = (union loongarch_instruction *)location; > + /* Use s32 for a sign-extension deliberately. */ > + s32 offset_hi20 = (void *)((v + 0x800) & ~0xfff) - > + (void *)((Elf_Addr)location & ~0xfff); > + Elf_Addr anchor = (((Elf_Addr)location) & ~0xfff) + offset_hi20; > + ptrdiff_t offset_rem = (void *)v - (void *)anchor; > + > + switch (type) { > + case R_LARCH_PCALA_HI20: > + v = offset_hi20 >> 12; > + break; > + case R_LARCH_PCALA64_LO20: > + v = offset_rem >> 32; > + break; > + case R_LARCH_PCALA64_HI12: > + v = offset_rem >> 52; > + break; > + default: > + /* Do nothing. */ > + } > + > + switch (type) { > + case R_LARCH_PCALA_HI20: > + case R_LARCH_PCALA64_LO20: > + insn->reg1i20_format.immediate = v & 0xfffff; > + break; > + case R_LARCH_PCALA_LO12: > + case R_LARCH_PCALA64_HI12: > + insn->reg2i12_format.immediate = v & 0xfff; > + break; > + default: > + pr_err("%s: Unsupport relocation type %u\n", mod->name, type); > + return -EINVAL; > + } Can we merge the two switch here?
Huacai > + > + return 0; > +} > + > /* > * reloc_handlers_rela() - Apply a particular relocation to a module > * @mod: the module to apply the reloc to > @@ -310,6 +383,8 @@ static reloc_rela_handler reloc_rela_handlers[] = { > [R_LARCH_SOP_SUB ... R_LARCH_SOP_IF_ELSE] = apply_r_larch_sop, > [R_LARCH_SOP_POP_32_S_10_5 ... R_LARCH_SOP_POP_32_U] = apply_r_larch_sop_imm_field, > [R_LARCH_ADD32 ... R_LARCH_SUB64] = apply_r_larch_add_sub, > + [R_LARCH_B26] = apply_r_larch_b26, > + [R_LARCH_PCALA_HI20...R_LARCH_PCALA64_HI12] = apply_r_larch_pcala, > }; > > int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, > -- > 2.37.0 > >
| |