How to dlopen the dependencies of a library that is to be dlopen-ed?

328 Views Asked by At

I've got two shared object:

  1. libbar.so, in which a function int bar(char const*) is provided;
  2. libfoo.so, in which a function int foo(char const*) is provided, and this foo function would call bar inside; consequently, libfoo.so depends on libbar.so.

Both of them are stored in nonstandard paths, say /whatever/path/to/libfoo.so and /yet/another/path/to/libbar.so. I'd like to dlopen these libraries and invoke foo in my program.

I attempted with this demo:

#include <stdio.h>
#include <dlfcn.h>

int main() {
    char const* libbar_path;
    void* libbar_so;
    int (*bar)(char const*);
    char const* libfoo_path;
    void* libfoo_so;
    int (*foo)(char const*);
    char const* err;

    libbar_path = get_libbar_path();
    libfoo_path = get_libfoo_path();

    libbar_so = dlopen(LIBBAR_SO, RTLD_GLOBAL | RTLD_NOW);
    if ((err = dlerror())) {
        fprintf(stderr, "failed to open libbar: %s\n", err);
        return 1;
    }

    bar = (int (*)(char const*)) dlsym(libbar_so, "bar");
    if ((err = dlerror())) {
        fprintf(stderr, "failed to lookup for bar: %s\n", err);
        return 1;
    }
    printf("main bar: %d\n", bar("hello dlopen!"));

    libfoo_so = dlopen(LIBFOO_SO, RTLD_GLOBAL | RTLD_NOW);
    if ((err = dlerror())) {
        fprintf(stderr, "failed to open libfoo: %s\n", err);
        return 1;
    }

    foo = (int (*)(char const*)) dlsym(libfoo_so, "foo");
    if ((err = dlerror())) {
        fprintf(stderr, "failed to lookup for foo: %s\n", err);
        return 1;
    }
    printf("main foo: %d\n", foo("hello dlopen!"));
}

However, when I compiled and ran this program with gcc -ldl demo.c -o demo && ./demo, it successfully loaded libbar.so and invoked bar, yet then complained about not finding libbar.so when it tried to dlopen libfoo.so:

$ gcc -ldl demo.c -o demo && ./demo
bar: hello dlopen!
main bar: 19
failed to open libfoo: libbar.so: cannot open shared object file: No such file or directory

My Question is: Is dlopen able to load the dependencies of libraries to be dlopen-ed later? If so, how? I must have missed something.

FYI, versions of related tools on my system:

$ gcc --version
gcc (Debian 8.3.0-6) 8.3.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ ld --version
GNU ld (GNU Binutils for Debian) 2.31.1
Copyright (C) 2018 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
1

There are 1 best solutions below

0
Employed Russian On

Is dlopen able to load the dependencies of libraries to be dlopen-ed later?

Yes.

If so, how?

By using absolute paths to the libraries, e.g.

void *h1 = dlopen("/yet/another/path/to/libbar.so", RTLD_GLOBAL|RTLD_NOW);
void *h2 = dlopen("/whatever/path/to/libfoo.so", RTLD_GLOBAL|RTLD_NOW);

Note: since libfoo.so requires a symbol from libbar.so, the latter should be loaded first.