问题
So a little bit of history, I have 3 libs:
- "lib1.so" with no dependencies
- "lib2.so" which is linked with "lib1.so"
- "test" executable program with no dependencies
What I need is to dynamically load "lib2.so" during runtime from "test" executable via "dlopen" method. The problem is that "lib1.so" cannot be loaded automatically due to linker doesn't know where to find it.
I've tried to load "lib1.so" at first like that:
void* ptr_lib1 = dlopen("/usr/local/test/lib1.so", RTLD_NOW | RTLD_GLOBAL);
void* ptr_lib2 = dlopen("/usr/local/test/lib2.so", RTLD_NOW | RTLD_GLOBAL);
But that's not working by some reason, it gives me error after calling second dlopen (text from dlerror):
"lib1.so: cannot open shared object file: No such file or directory"
It means that "lib1.so" is trying to be loaded twice: first time when I call dlopen for "lib1.so", and second when I call dlopen for "lib2.so".
Can anyone explain why and what to do to fix that? Please, don't advise to modify LD_LIBRARY_PATH before starting executable. Also don't advise to modify linker flags of executable. I need to be able load that libs at runtime from any folder.
UPDATE. After some research I did this:
LD_DEBUG=all ./test
And found that library lib1.so is trying to be loaded twice (first when I call dlopen, second when LD trying to resolve dependency for lib2.so"):
add /usr/local/test/lib1.so [0] to global scope
opening file=/usr/local/test/lib1.so [0]; direct_opencount=1
...
30031: file=lib1.so [0]; needed by /usr/local/test/lib2.so [0]
30031: find library=lib1.so [0]; searching
30031: search path=./tls/x86_64:./tls:./x86_64:. (RPATH from file ./test)
30031: trying file=./tls/x86_64/lib1.so
30031: trying file=./tls/lib1.so
30031: trying file=./x86_64/lib1.so
30031: trying file=./lib1.so
30031: search cache=/etc/ld.so.cache
30031: search path=/lib64/tls/x86_64:/lib64/tls:/lib64/x86_64:/lib64:/usr/lib64/tls/x86_64:/usr/lib64/tls:/usr/lib64/x86_64:/usr/lib64 (system search path)
30031: trying file=/lib64/tls/x86_64/lib1.so
30031: trying file=/lib64/tls/lib1.so
30031: trying file=/lib64/x86_64/lib1.so
30031: trying file=/lib64/lib1.so
30031: trying file=/usr/lib64/tls/x86_64/lib1.so
30031: trying file=/usr/lib64/tls/lib1.so
30031: trying file=/usr/lib64/x86_64/lib1.so
30031: trying file=/usr/lib64/lib1.so
30031:
30031:
30031: file=/usr/local/test/lib2.so [0]; destroying link map
Still don't understand what is going on...
UPDATE2. There is full LD_DEBUG log
Note: there is another library lib_other.so, just ignore it
回答1:
When dlopen(3) fails, you should use dlerror(3) to get some useful message.
So code at least:
void* ptr_lib1
= dlopen("/usr/local/test/lib1.so", RTLD_NOW | RTLD_GLOBAL);
if (!ptr_lib1) {
fprintf(stderr, "dlopen lib1 failure: %s\n", dlerror());
exit(EXIT_FAILURE);
}
and likewise for other dlopen
s
Notice that dlerror
is giving a detailed error message. If you don't understand it, put it in your question.
You probably forgot to set some rpath when linking lib1.so
or lib2.so
. Or you need to set explicitly LD_LIBRARY_PATH
, or run ldconfig
Read Drepper's How To Write Shared Libraries paper for details. Read carefully ld-linux(8)
dlopen
of lib2
fails because its dependency lib1
is not found. You need to fix that (thru rpath, LD_LIBRARY_PATH
, ldconfig
etc...)
You could add some -Wl,-rpath,/usr/local/test/lib1.so
in lib1
options, etc
You could also (more simply) decide that all your shared libraries go into /usr/local/lib/
which you would mention in /etc/ld.so.conf
. Then you need to run ldconfig
after every library addition there.
回答2:
The root cause of this problem seems to be that lib1.so
is NEEDED
by lib2.so
, which happens because you linked it at build time. So simply don't link it at build time--don't mention lib1
at all when building lib2
. Then you can load it with dlopen()
as you wish, and lib2
won't try to load it independently.
回答3:
I have similar issue, but it just works. I just use with "RTLD_LAZY" instead of "RTLD_NOW".
You can try it.
来源:https://stackoverflow.com/questions/49490555/force-dynamic-linker-to-load-library-at-runtime-in-linux