This is a followup question to What do %pcrel_hi and %pcrel_lo actually do?. I’m writing a simple Risc-V linker, and I’m trying to understand how, given an R_RISCV_PCREL_LO12I
relocation, the symbol of the corresponding R_RISCV_PCREL_HI20
relocation is found.
For concreteness, here is a RiscV instruction sequence, with relocations interleaved:
1: auipc x10,%pcrel_hi(some_symbol)
R_RISCV_PCREL_HI20 some_symbol
lw x11,%pcrel_lo(1b)(x10)
R_RISCV_PCREL_LO20I 1b // symbol refers to the auipc instruction above.
Imagine what the linker does when encountering the ...LO12I
relocation.
For this particular relocation type, it looks up the symbol 1b
, which gives it the location
of the auipc
instruction. However, the linker also needs the symbol some_symbol
associated
with the auipc
instruction. As far as I can tell, there is no direct way to
find that some_symbol
. The reason is that the ELF spec as far as I’m able to tell
doesn’t provide a mapping symbol => relocations_using_that_symbol
.
We only have a relocation => symbol
mapping.
There must be a function which, given a symbol (like 1b
) from a ...LO12I
relocation,
yields the corresponding ...HI20
relocation. How is this function typically
implemented? Does the linker need to build a special table of R_RISCV_PCREL_HI20
relocations, indexed by symbols? Or is there a more clever way of locating, for a
given ...LO12I
relocation, the corresponding ...HI20
relocation?
10