覆盖动态库中的函数

时间:2010-12-13 22:06:10

标签: gcc dlopen weak-linking

你好,我有一个程序,它有一个全局函数,我想在运行时自定义。比如,有许多版本的函数foo()分散在共享库中。现在,基于在运行时检测到的系统配置,我想使用来自适当库的函数。

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

文件other.cpp:

#include <iostream>

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

我用

编译程序
g++ -Wall -fPIC -o loaded loader.cpp -ldl
g++ -Wall -fPIC -shared -o other.so  other.cpp 

但弱符号不会被覆盖。任何提示?

2 个答案:

答案 0 :(得分:4)

在引用它们的图像的加载时间内解析符号。因此,当加载可执行文件时,对foo的引用已经解决。稍后的dlopen将不会重新绑定所有符号 - 它只会影响以后的加载。

您必须使用dlsym,或设置LD_PRELOAD:

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

答案 1 :(得分:0)

您使用g ++编译了共享库。 结果,函数的名称被破坏了:

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

如果你使它成为一个纯C代码并使用 gcc而不是g ++,你会发现它按预期工作。

或者,按如下方式定义:

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