1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-20 01:18:53 +03:00

Revert "[ELF][RISC-V] Do not assume HI20 relocs appear before LO12 relocs"

This reverts commit 990b0ac4cd.

This is what the RISC-V psABI says

> The R_RISCV_HI20 refers to an LUI instruction containing the high
> 20-bits to be relocated to an absolute symbol address. The LUI
> instruction is followed by an I-Type instruction (add immediate or
> load) with an R_RISCV_LO12_I relocation or an S-Type instruction
> (store) and an R_RISCV_LO12_S relocation. The addresses for pair of
> relocations are calculated like this:

I read LO12 is guaranteed to always appear after HI20.
This commit is contained in:
Rui Ueyama 2022-07-18 13:14:54 +08:00
parent 990b0ac4cd
commit f6a85acc07

View File

@ -285,10 +285,20 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
*(ul32 *)loc = S + A - P;
}
break;
case R_RISCV_PCREL_LO12_I:
assert(sym.get_input_section() == this);
assert(sym.value < r_offset);
write_itype(loc, *(ul32 *)(base + sym.value));
break;
case R_RISCV_LO12_I:
case R_RISCV_TPREL_LO12_I:
write_itype(loc, S + A);
break;
case R_RISCV_PCREL_LO12_S:
assert(sym.get_input_section() == this);
assert(sym.value < r_offset);
write_stype(loc, *(ul32 *)(base + sym.value));
break;
case R_RISCV_LO12_S:
case R_RISCV_TPREL_LO12_S:
write_stype(loc, S + A);
@ -352,10 +362,6 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
case R_RISCV_32_PCREL:
*(ul32 *)loc = S + A - P;
break;
case R_RISCV_PCREL_LO12_I:
case R_RISCV_PCREL_LO12_S:
// These relocations are handled in the next loop.
break;
default:
Error(ctx) << *this << ": unknown relocation: " << rel;
}
@ -367,33 +373,10 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
#undef GOT
}
// Handle LO12 relocations. In the above loop, PC-relative HI20
// relocations overwrote instructions with full 32-bit values to allow
// their corresponding LO12 relocations to read their values.
for (i64 i = 0; i < rels.size(); i++) {
const ElfRel<E> &r = rels[i];
if (r.r_type != R_RISCV_PCREL_LO12_I && r.r_type != R_RISCV_PCREL_LO12_S)
continue;
Symbol<E> &sym = *file.symbols[r.r_sym];
assert(sym.get_input_section() == this);
u8 *loc = base + r.r_offset + extra.r_deltas[i];
u32 val = *(ul32 *)(base + sym.value);
switch (r.r_type) {
case R_RISCV_PCREL_LO12_I:
write_itype(loc, val);
break;
case R_RISCV_PCREL_LO12_S:
write_stype(loc, val);
break;
default:
unreachable();
}
}
// Restore the original instructions HI20 relocations overwrote.
// In the above loop, PC-relative HI20 relocations overwrote
// instructions with full 32-bit values to allow their corresponding
// PCREL_LO12 relocations to read their values. This loop restore
// the original instructions.
for (i64 i = 0; i < rels.size(); i++) {
switch (rels[i].r_type) {
case R_RISCV_GOT_HI20: