Question

Hello I have a program with a global function that I'd like to customize at run time. Say, there are many versions of function foo() scattered over shared libraries. Now, based on system configuration detected at run time I'd like to use function from appropriate library.

File loader.cpp:

#include <dlfcn.h>
#include <iostream>

void __attribute__((weak)) foo();

    int main(int argc, char *argv[])
    {
        void* dl = dlopen("./other.so", RTLD_NOW | RTLD_GLOBAL);
        if (!dl)
        {
            std::cerr << dlerror() << std::endl;
            return 1;
        }
        if (foo)
        {
            foo();
        }
        else
        {
            std::cerr << "No foo?" << std::endl;
        }
        dlclose(dl);
        return 0;
    }

File other.cpp:

#include <iostream>

void foo()
{
    std::cout << "FOO!" << std::endl;
}

I compile the program with

g++ -Wall -fPIC -o loaded loader.cpp -ldl
g++ -Wall -fPIC -shared -o other.so  other.cpp 

However the weak symbol is not overriden. Any hints?

Was it helpful?

Solution

Symbols are resolved during load time of the image in which they are referenced. So when your executable is loaded, the reference to foo is already resolved. A later dlopen won't go and rebind all symbols - it only may affect later loads.

You'll have to use dlsym instead, or set LD_PRELOAD:

martin@mira:/tmp$ LD_PRELOAD=/tmp/other.so ./loaded 
FOO!

OTHER TIPS

You compiled the shared lib with g++. As a result, the name of the function is mangled:

$ nm -S other.so |grep foo
0000000000000690 000000000000002e T _Z3foov

If you make it a pure C code and compile with gcc instead of g++, you'll find it working as you expect.

Alternatively, define it as follows:

extern "C" void foo()
{
  std::cout << "FOO!" << std::endl;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top