mirror of
https://github.com/ventoy/Ventoy.git
synced 2025-12-17 09:06:21 +00:00
loongarch: Add support for ELF psABI v2.00 relocations
A new set of relocation types was added in the LoongArch ELF psABI v2.00 spec [1], [2] to replace the stack-based scheme in v1.00. Toolchain support is available from binutils 2.40 and gcc 13 onwards. This patch adds support for the new relocation types, that are simpler to handle (in particular, stack operations are gone). Support for the v1.00 relocs are kept for now, for compatibility with older toolchains. [1] https://github.com/loongson/LoongArch-Documentation/pull/57 [2] https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html#_appendix_revision_history Signed-off-by: Xiaotian Wu <wuxiaotian@loongson.cn> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
This commit is contained in:
@@ -58,7 +58,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
|
||||
rel = (Elf_Rel *) ((char *) rel + s->sh_entsize))
|
||||
{
|
||||
Elf_Sym *sym;
|
||||
grub_uint64_t *place;
|
||||
void *place;
|
||||
grub_uint64_t sym_addr;
|
||||
|
||||
if (rel->r_offset >= seg->size)
|
||||
@@ -72,12 +72,19 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
|
||||
if (s->sh_type == SHT_RELA)
|
||||
sym_addr += ((Elf_Rela *) rel)->r_addend;
|
||||
|
||||
place = (grub_uint64_t *) ((grub_addr_t) seg->addr + rel->r_offset);
|
||||
place = (void *) ((grub_addr_t) seg->addr + rel->r_offset);
|
||||
|
||||
switch (ELF_R_TYPE (rel->r_info))
|
||||
{
|
||||
case R_LARCH_64:
|
||||
*place = sym_addr;
|
||||
{
|
||||
grub_uint64_t *abs_place = place;
|
||||
|
||||
grub_dprintf ("dl", "reloc_abs64 %p => 0x%016llx, %p\n",
|
||||
place, (unsigned long long) sym_addr, abs_place);
|
||||
|
||||
*abs_place += (grub_uint64_t) sym_addr;
|
||||
}
|
||||
break;
|
||||
case R_LARCH_MARK_LA:
|
||||
break;
|
||||
@@ -85,6 +92,47 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr,
|
||||
case R_LARCH_SOP_PUSH_PLT_PCREL:
|
||||
grub_loongarch64_sop_push (&stack, sym_addr - (grub_uint64_t)place);
|
||||
break;
|
||||
case R_LARCH_B26:
|
||||
{
|
||||
grub_uint32_t *abs_place = place;
|
||||
grub_ssize_t off = sym_addr - (grub_addr_t) place;
|
||||
|
||||
grub_loongarch64_b26 (abs_place, off);
|
||||
}
|
||||
break;
|
||||
case R_LARCH_ABS_HI20:
|
||||
{
|
||||
grub_uint32_t *abs_place = place;
|
||||
grub_loongarch64_xxx_hi20 (abs_place, sym_addr);
|
||||
}
|
||||
break;
|
||||
case R_LARCH_ABS64_LO20:
|
||||
{
|
||||
grub_uint32_t *abs_place = place;
|
||||
grub_loongarch64_xxx64_lo20 (abs_place, sym_addr);
|
||||
}
|
||||
break;
|
||||
case R_LARCH_ABS64_HI12:
|
||||
{
|
||||
grub_uint32_t *abs_place = place;
|
||||
grub_loongarch64_xxx64_hi12 (abs_place, sym_addr);
|
||||
}
|
||||
break;
|
||||
case R_LARCH_PCALA_HI20:
|
||||
{
|
||||
grub_uint32_t *abs_place = place;
|
||||
grub_int32_t off = (((sym_addr + 0x800) & ~0xfffULL) - ((grub_addr_t)place & ~0xfffULL));
|
||||
|
||||
grub_loongarch64_xxx_hi20 (abs_place, off);
|
||||
}
|
||||
break;
|
||||
case R_LARCH_ABS_LO12:
|
||||
case R_LARCH_PCALA_LO12:
|
||||
{
|
||||
grub_uint32_t *abs_place = place;
|
||||
grub_loongarch64_xxx_lo12 (abs_place, sym_addr);
|
||||
}
|
||||
break;
|
||||
GRUB_LOONGARCH64_RELOCATION (&stack, place, sym_addr)
|
||||
default:
|
||||
{
|
||||
|
||||
@@ -199,3 +199,62 @@ grub_loongarch64_sop_32_s_0_10_10_16_s2 (grub_loongarch64_stack_t stack,
|
||||
*place =(*place) | (((a >> 2) & 0xffff) << 10);
|
||||
*place =(*place) | ((a >> 18) & 0x3ff);
|
||||
}
|
||||
|
||||
void grub_loongarch64_b26 (grub_uint32_t *place, grub_int64_t offset)
|
||||
{
|
||||
grub_uint32_t val;
|
||||
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfc000000);
|
||||
|
||||
grub_dprintf ("dl", " reloc_xxxx64 %p %c= 0x%llx\n",
|
||||
place, offset > 0 ? '+' : '-',
|
||||
offset < 0 ? (long long) -(unsigned long long) offset : offset);
|
||||
|
||||
val = ((offset >> 18) & 0x3ff) | (((offset >> 2) & 0xffff) << 10);
|
||||
|
||||
*place &= insmask;
|
||||
*place |= grub_cpu_to_le32 (val) & ~insmask;
|
||||
}
|
||||
|
||||
void grub_loongarch64_xxx_hi20 (grub_uint32_t *place, grub_int64_t offset)
|
||||
{
|
||||
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfe00001f);
|
||||
grub_uint32_t val;
|
||||
|
||||
offset >>= 12;
|
||||
val = ((offset & 0xfffff) << 5);
|
||||
|
||||
*place &= insmask;
|
||||
*place |= grub_cpu_to_le32 (val) & ~insmask;
|
||||
}
|
||||
|
||||
void grub_loongarch64_xxx_lo12 (grub_uint32_t *place, grub_int64_t offset)
|
||||
{
|
||||
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff);
|
||||
|
||||
*place &= insmask;
|
||||
*place |= grub_cpu_to_le32 (offset << 10) & ~insmask;
|
||||
}
|
||||
|
||||
void grub_loongarch64_xxx64_hi12 (grub_uint32_t *place, grub_int64_t offset)
|
||||
{
|
||||
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xffc003ff);
|
||||
grub_uint32_t val;
|
||||
|
||||
offset >>= 52;
|
||||
val = ((offset & 0xfff) << 10);
|
||||
|
||||
*place &= insmask;
|
||||
*place |= grub_cpu_to_le32 (val) & ~insmask;
|
||||
}
|
||||
|
||||
void grub_loongarch64_xxx64_lo20 (grub_uint32_t *place, grub_int64_t offset)
|
||||
{
|
||||
const grub_uint32_t insmask = grub_cpu_to_le32_compile_time (0xfe00001f);
|
||||
grub_uint32_t val;
|
||||
|
||||
offset >>= 32;
|
||||
val = ((offset & 0xfffff) << 5);
|
||||
|
||||
*place &= insmask;
|
||||
*place |= grub_cpu_to_le32 (val) & ~insmask;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user