Переопределение функций из динамических библиотек - PullRequest
0 голосов
/ 14 декабря 2010

Здравствуйте, у меня есть программа с глобальной функцией, которую я хотел бы настроить во время выполнения.Скажем, существует множество версий функции 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 

Однако слабый символ не переопределяется.Есть намеки?

Ответы [ 2 ]

4 голосов
/ 14 декабря 2010

Символы разрешаются во время загрузки изображения, на которое они ссылаются. Поэтому, когда ваш исполняемый файл загружен, ссылка на foo уже разрешена. Более поздний длопен не пойдет и не перепривязает все символы - он может повлиять только на последующие загрузки.

Вместо этого вам придется использовать dlsym или установить LD_PRELOAD:

martin@mira:/tmp$ LD_PRELOAD=/tmp/other.so ./loaded 
FOO!
0 голосов
/ 16 сентября 2014

Вы скомпилировали общую библиотеку с помощью g ++.В результате имя функции искажено:

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

Если вы сделаете его чистым кодом C и скомпилируете с gcc вместо g ++, вы обнаружите, что оно работает так, как вы ожидаете.

В качестве альтернативы, определите его следующим образом:

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