On Wed, 24 Aug 2016, Alan Modra wrote:
> Given a hidden visibility function declaration, the toolchain can say
> that the function is local to the module.  This generally means that a
> call to the function can be direct, ie. doesn't need to go via the PLT
> even in a shared library.  However, ifunc breaks this promise.  GNU
> indirect functions may resolve non-locally, and are implemented by
> always using a PLT call.
> 
> This causes trouble for targets like ppc32 where the -msecure-plt PIC
> PLT call stub needs a valid GOT pointer.  Any call that potentially
> might be to an ifunc therefore requires a GOT pointer, and can't be a
> sibling call (because the GOT pointer on ppc32 is a caller saved reg).

The same issue exists on 32-bit x86: PLT calls require that %ebx holds the
address of GOT (and the sibcall issue arises as well).  I've just confirmed
using a simple testcase that the scenario you describe leads to a runtime error
on i386, and even LD_BIND_NOW=1 doesn't help, as it doesn't trigger early
resolution of ifuncs.

> So unless we require that all ifuncs are declared as ifunc,

(note, that would be impossible with today's GCC because the ifunc attribute
requires designating the resolver, and the resolver cannot be extern -- so
ultimately you cannot declare an extern-ifunc symbol)

> it seems that ppc32 can't assume extern or weak functions are local.

It doesn't seem nice to penalize all normal calls due to this issue. I think a
solution without this cost is possible: have ld synthesize a forwarder function
when it sees a non-plt call to an ifunc symbol. The forwarder can push the GOT
register, load the GOT address, call the ifunc symbol, pop the GOT register and
return. Does this sound right?

HTH.
Alexander

Reply via email to