2010-12-13 5 views
0

Здравствуйте, у меня есть программа с глобальной функцией, которую я бы хотел настроить во время выполнения. Скажем, существует множество версий функции foo(), разбросанных по разделяемым библиотекам. Теперь, основываясь на конфигурации системы, обнаруженной во время выполнения, я хотел бы использовать функцию из соответствующей библиотеки.Переопределение функций из динамических библиотек

Файл loader.cpp: other.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; 
    } 

Файл:

#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

Вы скомпилирован совместно LIB с г ++. В результате, имя функции подогнаны:

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

Если вы сделаете это чистый код C и скомпилировать с GCC вместо г ++, вы увидите, что работает, как вы ожидаете.

С другой стороны, определить его следующим образом:

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