This is the mail archive of the glibc-bugs@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]

[Bug dynamic-link/16585] dlsym() shouldn't be declared as leaf


https://sourceware.org/bugzilla/show_bug.cgi?id=16585

--- Comment #10 from Carlos O'Donell <carlos at redhat dot com> ---
(In reply to Alexander Monakov from comment #9)
> Carlos, if you agree that the documentation can be adjusted to explicitely
> mention this, can the summary be changed accordingly (suggest: "document
> that leaf attribute assumes no interposition", or more generally "document
> constraints for LD_PRELOAD interposers") and the bug reopened?

Sounds good to me.

> This:
> 
> > IFUNCs are AFAIK never processed lazily, the IRELATIVE relocs in the ports I've looked at are all handled at startup.
> 
> is confusing, IFUNC and IRELATIVE are not the same.  IFUNCs are resolved
> lazily, and moreover, repeated calls to dlsym trigger the resolver
> repeatedly.  Here's a testcase:

Sorry, that's implementor speak.

STT_GNU_IFUNC is the symbol type and the relocation used is R_*_IRELATIVE.

The IRELATIVE relocations are, AFAIK, processed upfront.

> $ cat test.c 
> #define _GNU_SOURCE
> #include <dlfcn.h>
> #include <stdio.h>
> 
> static int counter;
> 
> void bar(void) __attribute__((ifunc("bar_resolver")));
> 
> static void *bar_resolver(void)
> {
>   printf("bar_resolver(): counter == %d\n", counter);
>   return NULL;
> }
> 
> int main(void)
> {
>   counter++;
>   dlsym(RTLD_DEFAULT, "bar");
>   counter++;
>   dlsym(RTLD_DEFAULT, "bar");
>   counter++;
>   return counter;
> }
> $ gcc -O test.c -ldl -rdynamic 
> $ ./a.out ; echo $?
> bar_resolver(): counter == 0
> bar_resolver(): counter == 0
> 3

This is not an indication of lazy resolution in the sense of relocation
processing.

The dlsym code does re-run the resolver function just to ensure that it is
using the most up to date version of the function that should be called.

If you change the code slightly to this:
#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>

static int counter;

void bar(void) __attribute__((ifunc("bar_resolver")));

void foo(void)
{
  printf("foo!\n");
}

static void *bar_resolver(void)
{
  printf("bar_resolver(): counter == %d\n", counter);
  return foo;
}

int main(void)
{
  printf ("In main...\n");
  bar();
  counter++;
  dlsym(RTLD_DEFAULT, "bar");
  counter++;
  dlsym(RTLD_DEFAULT, "bar");
  counter++;
  return counter;
}

bar_resolver(): counter == 0
In main...
foo!
bar_resolver(): counter == 1
bar_resolver(): counter == 2

You see the IRELATIVE reloc is resolved non-lazily at startup (running the
resolver function to resolve the reocation) before passing control to the
application. Later the use of dlsym forces a re-running of the resolver to
ensure it is correct before potentially being called through a function
pointer.

WARING: The IFUNC resolver restrictions are pretty tight and while the loader
tries hard to ensure you can do as much as possible in the resolver, the
community hasn't yet worked out exactly what is and is not allowed. Since it
happens non-lazily at startup you might get in trouble referencing other
objects not yet relocated.

Cheers,
Carlos.

-- 
You are receiving this mail because:
You are on the CC list for the bug.


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