Force dynamic linker to load library at runtime in Linux

前提是你 提交于 2019-12-02 20:57:14

问题


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 dlopens

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!