[Mips}Using DT tags for handling local ifuncs

Jack Carter Jack.Carter@imgtec.com
Wed Dec 18 21:31:00 GMT 2013


This is what I think you want:

*) A region in the GOT that only is fixed up by the relocation mechanism, not by
   implicit fixup rules.

*) This new region will come after the special GOT entries, but before the traditional
    implicit local entries.

*) This new region will have some type of DT pointers and count.

*) This new region will be visability neutral. It will contain both global and local 
    symbols.

*) I am assuming that this new region will be sorted to put gp relative entries towards
   the back to reduce multigot triggers.

*) I am assuming that this new region will be counted as part of DT_MIPS_LOCAL_GOTNO
   since the special first entries are also a part of it.

If I this is so, I will start implementation.

This discussion has been very useful to me. I am unlearning what I did at sgi and 
starting to understand how things are done for gcc. Many of my assumptions come
from my past and don't apply here.

Cheers,

Jack

On 12/18/2013 12:37 PM, Richard Sandiford wrote:> Jack Carter <Jack.Carter@imgtec.com> writes:
>> On 12/14/2013 02:06 AM, Richard Sandiford wrote:> "Maciej W. Rozycki"
>> <macro@codesourcery.com> writes:
>>>> On Thu, 12 Dec 2013, Richard Sandiford wrote:
>>>>
>>>>>>    Hmm, thanks for reminding me that, that rules out the space before the
>>>>>> ABI GOT.  We still have space afterwards for things like this (or e.g. for
>>>>>> a small-data area if we ever implement it) though.
>>>>>
>>>>> Yeah, putting it afterwards is what we already do for TLS relocs.
>>>>> The problem with that is that the ABI global GOT has to include all
>>>>> symbols that have a relocation against them, even if there's no need
>>>>> for a $gp-relative GOT access.  And there can be quite a lot of symbols
>>>>> like that, especially for things like vtables in C++ code.
>>
>> I am missing this part of the ABI. If a symbol has a relocation
>> against it why does it have to be in the GOT? TLS symbols that are
>> referenced through the PLT are specified to be in the GOT, but
>> otherwise?
> 
> TLS symbols don't need to be in the ABI global GOT.  They're treated
> as a special case.
> 
>>>>> So if we put the relocations after the ABI GOT we would end up forcing
>>>>> the use of multigots even though the number of "real" GOT entries
>>>>> (those that need to be accessed $gp-relative) is small enough for
>>>>> a single GOT.  The idea of the tag is to avoid that.
>>>>
>>>>    I see, that makes sense to me.  Do we already care to sort GOT entries
>>>> appropriately?
>>>
>>> Yeah, this is GGA_NORMAL vs. GGA_RELOC_ONLY in elfxx-mips.cs
>>
>> I don't understand this either. Local GOT and global GOT both are GP
>> relative.  Don't you have to include both along with any other GP
>> relative section in the multigot accounting? And if so, don't you have
>> to include pieces of both the local and global GOT in each multigot
>> region that needs it?
>>
>> In my mind it shouldn't matter where you put a GOT entry in terms of multigot
>> threshold accounting.
> 
> The point is that if foo binds globally:
> 
> 	.word	foo
> 
> requires a GOT entry for foo.  But this .word doesn't on its own require
> the GOT entry to be within range of a $gp-relative access.  It could be at
> $gp+0x8000, say, without breaking anything.  So we sort the GOT entries
> that do need to be accessed $gp-relative from those that don't.
> The ones that don't go after the ones that do.
> 
> Therefore, when creating multigots for normal local and global entries,
> we can ignore the entries that don't need to be $gp-relative, because
> they will always come later.  The problem is that TLS GOT entries need
> to be after _all_ global GOT entries.  So if the last entry of the
> global GOT is out of range of $gp, a single TLS reloc in an input bfd
> will force that bfd to use multigot, even if the last entry of the
> global GOT doesn't itself need to be accessed $gp-relative.

Okay, this legal in the abi, but SGI/Mips just put gp relative stuff in the GOT
making it a pure SHF_MIPS_GPREL section. I'll get over it ;-)

If you cluster the non-gp relative GOT entries at the beginning and end of the
the initial GOT, one can potentially prevent triggering multigot by ignoring them.

Is that what binutils does now? Put all the local non-gp relative entries first 
and all the global non-gp relative entries last?

> 
>> Is there a way that I can reduce the multigot threshold in binutils for
>> testing purposes?
> 
> Well, for testsuite tests we want the real threshold to be used.  .rept is
> your friend here.

Why wouldn't you want a linktime option to reduce the multigot threshold?
It could be used for testing as well. Have one test that uses the full blown
threshold and all the others with reduced ones. That's what I did at sgi and
it saved a lot of time and effort. But this is a digression from ifunc.

It's also a benefit to the customer in case there is a bug and we don't get it 
quite right and don't trigger multigot when we should. The customer could just
lower the threshold a bit and workaround the problem until we get a fix in.

> 
> For local testing you could hack elfxx-mips.c though.
> 
>>>>    Also let's make sure old ld.so binaries fail in a sensible way with ifunc
>>>> binaries though, i.e. no segfault or suchlike.
>>>
>>> I agree it's worth checking, but in this case it should do, because we'll
>>> only be using the new area for R_MIPS_IRELATIVE, which is a new relocation
>>> type.  ld.so does complain about types it doesn't understand.
>>>
>>
>> Is there no versioning or features list that is currently checked? How
>> do you currently
>> deal with forward incompatibility in ld.so?
> 
> There is no versioning system, unfortunately.

Okay, something for later.

> 
>>>>    For executables using traditional SVR4 PIC code we could use the absolute
>>>> sequence indeed.  However I checked the ifunc ABI description again and no
>>>> lazy binding is proposed for ifuncs so no stub of any kind will be
>>>> required for PIC code (be it an executables or a shared library) as all
>>>> calls are made through the GOT there anyway and this will have been
>>>> relocated by the time any ifunc call is reached.
>>>
>>> OK, once we start using the new GOT region then I agree we can make
>>> that the case.  In terms of the ABI and patch as posted though, we used
>>> IPLTs for all ifuncs defined in executables:
>>>
>>>     Dynamically linked executables with ifunc definitions are for the most
>>>     part the same as static executables, with the following exceptions:
>>>
>>>       *) No __rel_iplt_start/end symbols. The dynamic linker handles dynamic
>>>          relocations.
>>>       *) Generate STT_GNU_IFUNC symbols in the .dynsym section with the value
>>>          being the iplt entry for this IFUNC and transform them into
>>>          STT_FUNC symbols. Any references to this IFUNC have to go through
>>>          the stub. The dynamic linker (ld.so) will be doing the fixup at start-
>>>          up.
>>
>> If the dso LOCAL/INTERNAL/HIDDEN IIfunc GOT entry has a symbol
>> associated with it,
>> it does not need to go through an iplt stub since the call is referenced
>> through the GOT
>> value which will be fixed up by ld.so.
>>
>> The only time I would see a dso defined ifunc call going through the
>> iplt is for local calls that
>> go through the local got offset table. That is, the offset in the GOT is
>> shared among multiple
>> addresses and the call needs an additional addend to get the final
>> address. Does this occur
>> for function calls in GCC/binutils or do all function addresses get
>> their own GOT entry?
> 
> Either we should disallow GOT page accesses for ifuncs or the static linker
> should treat them in the same way as globals (i.e. by directing the GOT
> reloc to the function's own GOT slot and making the offset reloc resolve
> to 0).

I don't see your logic. These same functions w/o ifunc are in the local GOT.
What's changed? Only the fixup.

> 
>> Getting back to using dynsym symbols:
>>
>> But symbol lookups are expensive. That is why we have implicit fixups
>> in the GOT. If we are going to sequester these "local" ifunc entries
>> in their own GOT partition, why make them look up a symbol?
> 
> Not sure what you mean.  We're adding the new area so that we can create
> R_MIPS_IRELATIVE relocs.  R_MIPS_IRELATIVE doesn't take a symbol
> (or more accurately, it takes symbol 0).  It's a base-relative
> relocation, like R_MIPS_REL32.

This is what I think you want:

*) A region in the GOT that only is fixed up by the relocation mechanism, not by
   implicit fixup rules.

*) This new region will come after the special GOT entries, but before the traditional
    implicit local entries.

*) This new region will have some type of DT pointers and count.

*) This new region will be visability neutral. It will contain both global and local 
    symbols.

*) I am assuming that this new region will be sorted to put gp relative entries towards
   the back to reduce multigot triggers.

If I this is so, I will start implementation.

Thanks,
Jack



More information about the Binutils mailing list