[PATCH 1/6] RISC-V bfd port
Andrew Waterman
andrew@sifive.com
Wed Oct 12 23:59:00 GMT 2016
On Wed, Oct 12, 2016 at 4:41 PM, Alan Modra <amodra@gmail.com> wrote:
> 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.
I'm glad we concur!
>
> 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.
I didn't realize another port had to address a similar issue. Thanks
for the pointer.
The indirect approach is tolerant to intervening linker relaxations,
because the delta between hi and lo doesn't factor into the final
computation; in the end, it's just the LSBs of (sym - hi). The power9
approach seems cleaner if the delta can be computed at assembly time,
but relaxation does preclude that.
>
> --
> Alan Modra
> Australia Development Lab, IBM
More information about the Binutils
mailing list