I am compiling a C program on linux with gcc. The program itself links libc (and not much else) at build-time, so that ldd gives this output :
$ ldd myprogram
linux-vdso.so.1 => (0x00007fffd31fe000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7a991c0000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7a99bba000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f7a98fbb000)
At run-time this program dlopen()s library B, which dependes on a library A, which of course dlopen also loads before returning. A exports a function called re_exec, which B invokes (B is linked against A). libc also exports a function called re_exec. readelf output :
$ readelf -as A.so | grep re_exec
104: 00000000000044ff 803 FUNC GLOBAL PROTECTED 11 re_exec
469: 00000000000044ff 803 FUNC GLOBAL PROTECTED 11 re_exec
$ readelf -as /lib/x86_64-linux-gnu/libc.so.6 | grep re_exec
2165: 00000000000e4ae0 39 FUNC WEAK DEFAULT 12 re_exec@@GLIBC_2.2.5
The problem is that when B invokes re_exec, the re_exec inside libc is called, NOT the re_exc inside of A.
If, when I invoke the program, I include LD_LIBRARY_PRELOAD=/path/to/A.so, then everything works as expected : Bs invocation of re_exec correctly calls A, and not libc.
The dlopen call passes RTLD_NOW | RTLD_GLOBAL. I have tried with and without DEEPBIND, and get the same behavior in either case.
I have also tried dlopen()ing A directly, before B, both with and without DEEPBIND, which did not affect the behavior.
The question : is it possible to dlopen A/B with higher precedence than libraries that were included at link-time (libc, in this case) ?
(please don't suggest that I rename the call to something other than re_exec ; not useful)