Search code examples
clinuxshared-librarieselfdlopen

`dlopen`ing a DSO from inside that same DSO


I have a DSO (mylibrary.so.0 library) with a func1 function marked as extern "C" and which I'm sure it's exported since

nm -D mylibrary.so.0 | grep func1
000000000009f9bb T func1 <- symbol is visible and exported

This DSO is being loaded in a chain of dependencies I have no control over, e.g.

executable1 -dlopen-> 3rdpartydispatcher.so -dlopen-> my_library.so.0

Now, my library has a method which gets called (I can see it's getting called by stepping into it via gdb) and receives a C string with the function name it should call, e.g.

void call_function_from_name(const char *function_name) {

    void *mylibrary_so_0 = dlopen(NULL, RTLD_NOW); // (*)
    void *func1 = dlsym(mylibrary_so_0, function_name);
    if (!func1) {
        log_error(dlerror());
    }
    ...
}

The problem is: even if call_function_from_name is being called with argument func1, i.e. a perfectly valid and exported symbol, dlsym is failing and the error is executable1 has no func1 symbol.

I come from a Windows environment and I assumed that dlopen(NULL, ..) returns me a handle on the main executable but that any subsequent dlopen'd library from that executable gets also mapped in its virtual address space and therefore I can use that handle to search for the symbols those libraries exported.

Is my assumption incorrect? If it is, how can I refer to func1 from within a same-dso function call?


Solution

  • `void *mylibrary_so_0 = dlopen(NULL, RTLD_NOW); // (*)`
    

    For some reason you believe that this should dlopen my_library.so.0, but it doesn't -- it opens the main executable.

    The error message clearly tells you that: executable1 has no func1.

    A possible fix is use dlopen("my_library.so.0", RTLD_NOW), but a much better fix it to provide a static map of functions you want to be able to call this way, and use that:

    struct mapping { const char *f_name; void (*f_ptr)(); } = {
      { "func1", &func1 },
      { "func2", &func2 },
      { NULL, NULL },
    };
    

    Now just search your mapping, and call the target function; no dlsym required.