This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc 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: Are ifuncs intended to be allowed to resolve to symbols in another DSO?


On 2020-02-03, Carlos O'Donell wrote:
On 2/3/20 3:06 PM, Florian Weimer wrote:
* Carlos O'Donell:

If an IFUNC resolver calls a function which is not yet resolved then
isn't that a defect in the IFUNC resolver?

There is a position that an IFUNC resolver must not use any non-local
relocations.  (We must support some relocations for IFUNCs on
!PI_STATIC_AND_HIDDEN targets.)  In this case, yes, such a dependencies
would be a bug because all external dependencies are bugs.

Just so I understand the position is, to simplify the implementation, that
IFUNC resolvers must not use any non-local relocations?

What does non-local relocations mean? Are we saying the target of all
relocations must be within the same linkmap as the resolver? Are we saying
then that resolvers can only manipulate local data and make local function
calls?

I don't think that would be useful since you'd want to call many libc functions
from the resolver itself and so you would have calls in the resolver that
could call through a GOT entry that has a relocation against an external
symbol in another DSO e.g. libc.so.6.

If an IFUNC resolver has relocations that against non-local symbols
then those symbols must have been a dependency of the object and listed
in DT_NEEDED and therefore relocated before the current IFUNC resolver
is running.

On the other hand, in glibc, we could get rid of many IFUNC resolvers
which violate this rule only after changing the loader that eliminated
their need for them.  Other IFUNCs that do not follow this rule do not
have this luxury.

I don't quite parse your first setnence here, could you expand on that please?

When you speak about luxury, you mean to say that IFUNCs in other projects
would not have the same possibility to solve such a problem like we do in
glibc?

The code which contains such an IFUNC should have had a DT_NEEDED entry
on all objects to which the resolver called into?

This does not help with symbol interposition.

What exact problem does symbol interposition cause?

I like solutions that ensure that IFUNC resolvers, which are just foreign
functions, run@a stage *after* their own dependencies have been resolved,
but before their own initializers have run.

Lazy binding achieves this because it implicitly tracks this dependency
information.  For eager binding, we simply do not have this information.
Hence my patch for delayed relocation processing.  But it does not solve
the problem completely, of course.

The dependencies are explicitly tracked by DT_NEEDED.

Then when we have underlinked libraries we try to suppliment this and reorder
by relocation dependencies. This may be causing more problems than it solves?

If we had good visibility into the load order manipulations because of the
relocations I think users would understand the consequences of these problems
and we would also be able to better identify underlinked applications and file
bugs to fix them (if possible).

On powerpc64: A is in one module, B and C are in another module. C is a
non-preemptible ifunc. A calls B, B tail calls C.

The GNU ld generated IPLT code sequence starts with `std r2,24(r1)` .
When B tail calls C, it has popped its stack frame. `std r2,24(r1)`
overwrites the TOC pointer from A's module with the TOC pointer from
B,C's module. When C returns to the call site in A, the TOC pointer
incorrectly restores to the value from B,C's module.

The lld generated IPLT code sequence does not use `std r2,24(r1)`.
The above scenario works, but the resolver and the implementation cannot
be in different modules.

So for powerpc64, an IFUNC resolver returning the implementation in
another module may be unreliable.


On powerpc32 Secure PLT: A is in one translation unit, B and C are in
another translation units.  A, B and C are in the same module. C is a
non-preemptible ifunc. B takes the address of C and passes it to A. A
calls the function pointer.

The IPLT code sequence assumes r30 = .got2(B)+0x8000. Calling it from A
(.got2(A)!=.got2(B)) will be wrong.

So for powerpc, even different translation units can be unreliable.


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