This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 1/2] [RFC] Add IFUNC support for MIPS (v4)


On 05/20/2016 07:01 PM, Faraz Shahbazker wrote:
>>> @@ -8398,7 +8885,8 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
>>>  	case R_MIPS_CALL16:
>>>  	case R_MIPS16_CALL16:
>>>  	case R_MICROMIPS_CALL16:
>>> -	  if (h == NULL)
>>> +	  /* Exclude local IFUNCs from check.  */
>>> +	  if (h == NULL && ih == NULL)
>>>  	    {
>>>  	      (*_bfd_error_handler)
>>>  		(_("%B: CALL16 reloc at 0x%lx not against global symbol"),
>>
>>  Under which circumstances does this condition trigger for local ifuncs?  
>> CALL16 relocations are used for lazy binding and are explicitly defined in 
>> the MIPS psABI for external symbols only.  Can the resolver for a local 
>> ifunc be external and bind lazily?
> 
> Local IFUNCs are treated like global symbols in that they get a full GOT 
> (or IGOT) entry each and all references must go through that GOT entry.
> This means that call16/got16 references can theoretically work for local
> IFUNCs, although not explicitly sanctioned by the ABI.
> 
> I just followed gcc's behaviour instead of referring to the ABI on this
> point. gcc does not consider IFUNCs to be locally bound, since the 
> resolved function could be external. The mips backend, using this criteria,
> considers all IFUNCs to be candidates for lazy evaluation and emits call16
> for all PIC IFUNC calls without caring about local vs. global binding.
> This trips up the error condition above.
> 
> Since you pointed it out, I tinkered around with gcc to force got16 to be
> generated for local IFUNCs instead of call16, but ran up against instances 
> where it is impossible to know that the symbol is a local IFUNC. For example,
> the glibc testsuite has IFUNC declarations like this:
> 
> 	extern int foo (void);
> 	static void * foo_ifunc (void) __asm__ ("foo");
> 	__asm__(".type foo, %gnu_indirect_function");
> 
> Both `static' and `ifunc' aspects of foo are hidden in inline assembly
> and hence not available to the compiler. I don't see a way around this.

Another problem with using got() instead of call16() is that we can't
distinguish call v. non-call PIC references in this case. In effect, all PIC
calls end up going through an IPLT stub, when they could have otherwise
directly used the GOT slot that the stub uses to get the resolved function.
This is referred to as case 3 in the spec document (excerpt below),
for locally bound IFUNCs.

==========
When an IFUNC symbol binds locally there are 6 cases:

    PIC relocs?  non-PIC relocs?  all call-only?   variant
    y            y                y                (3)

    (3) Need an IPLT.  The associated IRELATIVE GOT entry should go in .got
        so that it can be used by the PIC references.
==========

Regards,
Faraz Shahbazker


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]