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:
parent
990b0ac4cd
commit
f6a85acc07
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user