Dlopen with higher priority than link time on linux
I am compiling a program on linux with gcc. The program itself links libc (and not much more) at build time, so 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)
During the execution of this program, the dlopen () s B library, which depends on the A library, which, of course, is loaded before returning. Exports the re_exec function that B calls (B is linked to A). libc also exports the re_exec function. 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 calls re_exec, re_exec inside libc is called, not re_exc inside A.
If I include LD_LIBRARY_PRELOAD = / path / to / A.so when I call the program, then everything works as expected: calling Bs re_exec correctly calls A, not libc.
Dlopen Calls Through RTLD_NOW | RTLD_GLOBAL. I tried with and without DEEPBIND and got the same behavior anyway.
I also tried dlopen () ing A directly before B, with or without DEEPBIND, which did not affect the behavior.
Question: is it possible to use dlopen A / B with a higher priority than the libraries that were included at the time of linking (libc, in this case)?
(please don't suggest renaming the call to something other than re_exec; not useful)
source to share
Well, you know, I cannot reproduce your error. Please have a look:
puts.c
:
#include <stdio.h>
int puts(const char* _s) {
return printf("custom puts: %s\n", _s);
}
built with
cc -Wall -fPIC -c puts.c -o puts.o
cc -shared -o libputs.so -fPIC -Wl,-soname,libputs.so puts.o
foo.c
:
#include <stdio.h>
void foo() {
puts("Hello, world! I'm foo!");
}
built with
cc -Wall -fPIC -c foo.c -o foo.o
cc -L`pwd` -shared -o libfoo.so -fPIC -Wl,-soname,libfoo.so foo.o -lputs
and rundl.c
:
#include <dlfcn.h>
#include <assert.h>
#include <stdio.h>
typedef void (*FooFunc)();
int main(void) {
void *foolib = dlopen("./libfoo.so", RTLD_NOW | RTLD_GLOBAL | RTLD_DEEPBIND);
assert(foolib != NULL);
FooFunc foo = (FooFunc)dlsym(foolib, "foo");
assert(foo != NULL);
foo();
return 0;
}
built with
cc -c -Wall rundl.c -o rundl.o
cc -o rundl rundl.o -ldl
we can now run rundl
with LD_LIBRARY_PATH=$(pwd)
(this is necessary because it is libputs.so
not in ld.so
known paths, so libfoo.so
w / dlopen()
and Co cannot be loaded ):
alex@rhyme ~/tmp/dynlib $ LD_LIBRARY_PATH=`pwd` ./rundl
custom puts: Hello, world! I'm foo!
alex@rhyme ~/tmp/dynlib $ _
if we move libputs.so to a directory known ld.so
and (re) run ldconfig
to refresh the caches, then the code runs without any special environment variables:
alex@rhyme ~/tmp/dynlib $ ldd ./libfoo.so
linux-vdso.so.1 (0x00007fff48db8000)
libputs.so => /usr/local/lib64/libputs.so (0x00007f8595450000)
libc.so.6 => /lib64/libc.so.6 (0x00007f85950a0000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8595888000)
alex@rhyme ~/tmp/dynlib $ ./rundl
custom puts: Hello, world! I'm foo!
If the link libfoo.so
w / o -lputs
foo()
calls the standard puts()
from libc. What is it.
source to share