2010-12-13 89 views
0

你好,我有一個程序帶有一個全局函數,我想在運行時自定義它。假設有很多版本的函數foo()分佈在共享庫上。現在,根據運行時檢測到的系統配置,我想使用適當庫中的函數。覆蓋來自動態庫的函數

文件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 

程序但是弱符號未覆蓋。任何提示?

回答

4

符號在引用它們的圖像的加載時間期間被解析。所以當你的可執行文件被加載時,對foo的引用已經解決了。後來的dlopen不會去並重新綁定所有的符號 - 它只會影響以後的加載。

你將不得不改爲使用的dlsym,或設置LD_PRELOAD:

[email protected]:/tmp$ LD_PRELOAD=/tmp/other.so ./loaded 
FOO! 
0

您編譯克共享庫++。 其結果是,該功能的名稱是錯位:

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

如果你讓一個純粹的C代碼,並與 GCC代替G ++編譯,你會發現它的工作如預期。

可替換地,如下進行定義:

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