kyku
kyku

Reputation: 6042

Overriding functions from dynamic libraries

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?

Upvotes: 1

Views: 2895

Answers (2)

stsp
stsp

Reputation: 1

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;
}

Upvotes: 0

Martin v. L&#246;wis
Martin v. L&#246;wis

Reputation: 127457

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!

Upvotes: 5

Related Questions