`-Wl,-z,now' works and the GNU-IFUNC resolver is called before `main'.
But RTLD_NOW returns handle and GNU-IFUNC gets called only after `dlsym'.
Even if the executable calling dlopen(, RTLD_NOW) uses -Wl,-z,-now.
The first part of the test below is correct:
But this part prints:
while I expect:
This behavior determines how the glibc Bug 2328 should be resolved in GDB.
cat >lc.c <<EOH
fi (int a)
return a + 1;
asm (".type f, @gnu_indirect_function");
f (void)) (int a)
cat >mc.c <<EOH
extern int f (int a);
return f (-1);
cat >mcd.c <<EOH
void *h = dlopen ("./lc.so", RTLD_NOW);
int (*fp) (int a) = (int (*) (int a)) dlsym (h, "f");
return fp (-1);
gcc -o lc.so lc.c -Wall -g -shared -fPIC; gcc -o mc mc.c -Wall -g -Wl,-z,now ./lc.so; gcc -o mcd mcd.c -Wall -g -Wl,-z,now -ldl; (set -x; ./mc; ./mcd)
Tested on Fedora 15:
There is nothing to change in the dynamic linker.
When you dynamically load the DSO this doesn't magically make a relocation appear. In your test, the symbol f doesn't have any relocation attached to it and this is correct. This is really the expected behavior. Without a relocation or returning the symbol address (as in dlsym) there is no place to store the result of the ifunc function call.
I agree now, there is no <f@plt> stub anywhere in the dlopen case, thanks.