[PATCH 1/6] RISC-V bfd port
Alan Modra
amodra@gmail.com
Wed Oct 12 23:41:00 GMT 2016
On Wed, Oct 12, 2016 at 11:47:26AM -0700, Andrew Waterman wrote:
> On Tue, Oct 11, 2016 at 6:57 PM, Alan Modra <amodra@gmail.com> wrote:
> > On Tue, Oct 11, 2016 at 06:17:59PM -0700, Andrew Waterman wrote:
> >> On Tuesday, October 11, 2016, Alan Modra <amodra@gmail.com> wrote:
> >>
> >> > On Tue, Oct 11, 2016 at 04:46:06PM -0700, Andrew Waterman wrote:
> >> > > +/* Remember all PC-relative high-part relocs we've encountered to help
> >> > us
> >> > > + later resolve the corresponding low-part relocs. */
> >> >
> >> > Why? This sort of thing is usually only needed on REL targets.
> >>
> >> We'll expound on this comment to explain our strategy. Of course, a simpler
> >> approach might suffice.
> >
> > It's not a matter of explaining. I think you have something seriously
> > wrong here. You most likely need to remove all of the hi/lo recording
> > and use of high value to apply low relocs, or you have a broken ABI.
> > If the latter then it would pay to fix it sooner rather than later.
> >
> > The reason hi/lo matching is needed on REL targets is that with the
> > addend stored in the insn you can only fit a partial addend in an
> > insn. You need to read both insns and combine the addends to create a
> > full addend (which is needed to properly perform pc subtraction).
> > With RELA targets you should have the full addend in the reloc.
>
> It's not that a partial addend is being stored anywhere; it's that
> there is a level of indirection. The PC-relative addressing scheme is
> relative to the address of the high-part reloc, because of how the ISA
> works. So, the value of the low-part reloc depends both on the
> address of the high-part reloc and the symbol being referenced. The
> alternative would be to put two relocs on the low-part (one for the
> symbol being referenced and one for the high-part reloc). The
> indirect approach seems cleaner to me.
>
> An example might clarify:
>
> 0x1234: auipc t0, %pcrel_hi(sym)
> ...
> 0x1338: addi t0, t0, %prcrel_lo(0x1234)
> ...
> sym = 0x45678
>
> The %pcrel_lo needs to be filled in with ((0x45678 - 0x1234) & 0xFFF).
>
> This approach is perhaps unconventional, but it is hard to see why it
> is "seriously wrong."
I see. Yes, if you explicitly reference the hi reloc from the lo one
that's not so bad. I thought you may have been trying to associate
the two in the linker, which has lots of ways to go wrong.
Note that power9 has something similar with addpcis/addi pairs where
we write:
.L0:
addpcis 9,(sym - .L0)@ha
...
addi 9,9,(sym - .L0)@l
producing (... is two nops in this example)
0000000000000000 <.text>:
0: 04 00 20 4d addpcis r9,0
0: R_PPC64_REL16DX_HA sym
4: 00 00 00 60 nop
8: 00 00 00 60 nop
c: 00 00 29 39 addi r9,r9,0
c: R_PPC64_REL16_LO sym+0xc
This way both addpcis and addi insns have exactly the same reloc
symbol and each can be relocated independently. The addpcis insn
reloc has an addend of -.L0, zero in this case, while the addi insn
reloc addend is the difference between the two insn addresses.
Things get a little tricky with linker relaxation involving deletion
or insertion of insns (which powerpc64 ld doesn't support), but I
imagine you might have similar problems if linker relaxation moves
your auipc insn.
--
Alan Modra
Australia Development Lab, IBM
More information about the Binutils
mailing list