This is the mail archive of the 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: IFUNC resolver scheduling (bugs 21041, 20019)

On 01/25/2017 05:28 PM, Szabolcs Nagy wrote:
On 25/01/17 13:57, Florian Weimer wrote:
One problem is that recording the relocations requires temporary memory allocations during relocation.  I have
a mmap-based pool allocator for that (currently very specific to the task at hand, but I will have to
generalize it a bit).  The allocations are required so that we do not have to walk through large parts of the
relocation list in the second pass.  The number of delayed relocations is significant: around 100 for simple
binaries, and more than 1,000 for complex ones.  The current delayed relocation record contains six words, so
we are talking about several KiB even for small binaries.  I'm not convinced it makes sense to add a large
static stack allocation (like scratch_buffer does) to avoid calling mmap because the stack memory remains dirty
and might not be reused by some programs.  Adding at least one mmap and munmap call to the start-up sequence is
likely visible in benchmarks, though.

why is it bad to walk over the relocation list again
in the second pass? (sounds simpler than the allocation)

The relocations are sorted by target address right now. This means that IFUNC-using relocations can be spaced quite far apart. I'm also not convinced that there is a single, contiguous relocation section, so we'd have to detect gaps which need skipping in the second pass, too.

(The alternative would be to rewrite the relocation processing in the way I sketched in my first message.)

Apart from the performance impact and complexity, there is another issue I worry about: What happens if an
IFUNC-based relocation is subject to a copy relocation?  Assuming we delay IFUNC relocations and copy
relocations and execute them in that order, the data produced by the copy relocation is correct because the
IFUNC relocation has been performed before the copy is made.  But what happens if the copy-relocated symbol is
accessed by the IFUNC resolver?  I think it will touch the object at its final location, and that has not been
relocated yet.  I suppose this is similar to the dependency bypass due to function interposition.  Maybe it's
sufficient to document this; it is certainly easier to avoid than the current restriction on accessing *any*
relocated data.  This looks like a circular dependency which is impossible to resolve in general (and rather
expensive to detect).

if by 'ifunc-based' relocation you mean that the
copy relocation refers to an STT_GNU_IFUNC type
symbol, then that should not happen and it is ok
to crash on it.

No, I meant copy relocations of data which is the result of IFUNC relocations. Something like this:

In a DSO:

void *global_data = (void *) memcpy;

In the main program:

extern void *global_data;
printf ("%p", global_data);

This should work once we delay copy relocations as well.

There is another case which is even more tricky.

In a DSO:

void f (void) { }

void *global_data = (void *)f;

void *g_resolve (void)
  return global_data;

In the main program (with BIND_NOW):

extern void *global_data;
void g (void); /* IFUNC with g_resolve as the resolver.  */
printf ("%p", global_data);
g ();

This complies with the rule that an IFUNC resolver may only access declarations defined in the same translation. But I expect that when g_resolve is run, it will load the address from the main program's copy of global_data, which has not been initialized yet because copy relocations are processed after IFUNC relocations.

i still think that it is invalid for an ifunc resolver
to return an object address but in case of copy relocs
it would not work anyway:

to do the copy the symbol size in the symbol table is
used but that's the size of the resolver function, not
the size of the object whose address is returned.

The function size is more or less unused, and I think the dynamic linker will just treat it as the size of the copy relocation.


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