Error loading shared libraries using dlopen ()

I am working on a program that downloads user-created plugins using dlopen on CentOS. I had a problem with a plugin that has dependencies on shared libraries, which also have dependencies:

libplugin.so → libservices.so → libconfig.so

Our program first loads the dependencies into memory, starting from the leaves of the dependency tree and moving to the plugin (the verification error was not indicated in this example):

dlopen("/path_to_plugin/libconfig.so", RTLD_NOW | RTLD_GLOBAL)
dlopen("/path_to_plugin/libservices.so", RTLD_NOW | RTLD_GLOBAL)
dlopen("/path_to_plugin/libplugin.so", RTLD_NOW | RTLD_GLOBAL)

We use this approach, so the end user should not change their LD_LIBRARY_PATH to point to the directory with the plugins. This approach has worked successfully for several different plugins.

We recently got a new plugin for which this approach does not work. We can load libconfig.so successfully, but when we try to download libservices.so, we get the following error message:

Exception libconfig.so: cannot open shared object file: No such file or directory

I know that the correspondence between the characters between the libraries is fulfilled, because when I set LD_LIBRARY_PATH to contain the path to the plugin, the plugin loads and runs correctly.

When I run strace in my program, I see that the system is looking for libconfig.so, as described in the dlopen man page. It seems that for some reason, dlopen does not detect that libconfig.so is already loaded. What conditions can cause this behavior?

+4
source share
1 answer

?

dlopen("/path_to_plugin/libservices.so", ...), :

  • , ELF .
  • . DT_NEEDED (libconfig.so ),
  • DSO, ( ),
    • ,
    • .

3 , , - DSO - dlclose libconfig.so.

GDB info shared - libconfig.so 3, . , .

, _r_debug->r_map GDB GDB info shared.

, VDSO (, libc.so.6 libdl.so.2). libconfig.so, , l_name, , - .

, , , dlopen("/path/to/libconfig.so",...), , r_map , , .

, dlclose -, dlclose .

Update:

, _r_debug->r_map

:

  • debuginfo GLIBC. Ubuntu, apt-get install libc6-dbg ,
  • , _r_debug. :

    cat t.c
    int main() { return 0; }
    
    gcc -g t.c && gdb -q ./a.out
    (gdb) start
    Temporary breakpoint 1 at 0x4004e1: file t.c, line 1.
    Starting program: /tmp/a.out
    
    Temporary breakpoint 1, main () at t.c:1
    1   int main() { return 0; }
    (gdb) p _r_debug
    $1 = 1    # The program does not reference _r_debug itself,
              # and debuginfo is not installed. This is probably what you see.
    

:

cat t2.c
#include <link.h>

int main() { return _r_debug.r_version; }  // reference needed for debug info

gcc -g t2.c && gdb -q ./a.out
(gdb) start
Temporary breakpoint 1 at 0x400561: file t2.c, line 3.
Starting program: /tmp/a.out

Temporary breakpoint 1, main () at t2.c:3
3   int main() { return _r_debug.r_version; }
(gdb) p _r_debug
$1 = {r_version = 1, r_map = 0x7ffff7ffe1c8, r_brk = 140737351960640, r_state = RT_CONSISTENT, r_ldbase = 140737351884800}
(gdb) p _r_debug.r_map[0]
$2 = {l_addr = 0, l_name = 0x7ffff7df6c3d "", l_ld = 0x600e18, l_next = 0x7ffff7ffe758, l_prev = 0x0}
+4

Source: https://habr.com/ru/post/1569913/


All Articles