[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