5

Here's the setup:

  1. There's an application A that loads liba.so (linked at compile time)
  2. liba.so exports a symbol expA
  3. I don't control either A or liba.so
  4. Application A can load a library I specify, libmine.so, into the same process via dlopen (think plugin architecture)
  5. I need to use expA from libmine.so but don't know how to find it without explicitly linking against liba.so, which is what I've been doing so far. I assume this won't work in the real world since that symbol is not guaranteed to be at the same address as the one in my local copy of liba.so (or is it?). libmine.so will be closed-source and can't be recompiled with A.

I've never done anything like this, so am a bit unclear on the details of library loading. For example, if I try to dlopen("liba.so") from within libmine.so, will I get a handle to the already loaded library or a new copy?

In terms of how libmine.so is loaded, all I know is that it will be loaded with RTLD_LAZY (and nothing else).

Any help and pointers would be greatly appreciated!

Delyan
  • 8,881
  • 4
  • 37
  • 42

1 Answers1

5

If all the liba.so library is dlopened using RTLD_GLOBAL, then you can use dlsym(RTLD_DEFAULT, "expA") to find the symbol without needing to reopen the library.

If the liba.so library is dlopened using RTLD_LOCAL then you will need to obtain a handle to the library using dlopen again within your own libmine.so. Note the following:

If the same library is loaded again with dlopen(), the same file handle is returned. The dl library maintains reference counts for library handles, so a dynamic library is not deallocated until dlclose() has been called on it as many times as dlopen() has succeeded on it. The _init() routine, if present, is only called once. But a subsequent call with RTLD_NOW may force symbol resolution for a library earlier loaded with RTLD_LAZY.

i.e. it's the same copy of the library.

the mechanism is (pseudo), assuming expA is a function: int expA(int value):

int (*fpointer)(int) = NULL;

void *handle = dlopen("liba.so", RTLD_LAZY | RTLD_LOCAL);
if (handle != NULL) {
    void *symbol = dlsym(handle, "expA");
    if (symbol != NULL) {
        fpointer = (int (*)(int ))symbol;
    }
}

That's pseudo code, with little to no error handling.

Anya Shenanigans
  • 91,618
  • 3
  • 107
  • 122
  • Right. Thanks for that. The thing is, `liba.so` is linked at compile-time (`LD_FLAGS = -la`), so I'm not entirely sure what that ends up looking like at runtime (which is my main confusion, tbh). Will `dlopen` still give me a handle to the existing library even though it was never explicitly `dlopen`ed from `A` (but rather from the linker)? – Delyan Sep 15 '13 at 11:24
  • I've never had issues using `dlsym(RTLD_DEFAULT, symbol)` against symbols that are exposed by libraries that are linked as `.so` at compile time at run-time; i.e. you should be just able to `dlsym` without needing to re-do a `dlopen` – Anya Shenanigans Sep 15 '13 at 11:27
  • Got it. I've just never dealt with dynamic libraries at this level and am still piecing together the puzzle. Thanks for your time :) – Delyan Sep 15 '13 at 11:44