Обнаружить дубликаты символов на dlopen - PullRequest
4 голосов
/ 24 января 2012

В моем приложении Linux я использую архитектуру плагинов через dlopen. Общие объекты открываются с

dlopen (путь, RTLD_GLOBAL | RTLD_LAZY) `

Опция RTLD_GLOBAL необходима, поскольку плагинам необходим доступ к общей информации RTTI. Иногда бывает, что некоторые плагины экспортируют одни и те же символы. Обычно это не должно происходить, но когда это происходит, это приводит к случайным ошибкам, и это трудно отладить. Поэтому я хотел бы обнаружить дубликаты символов в dlopen и предупредить их.

Есть ли способ сделать это?

Вот простой пример, иллюстрирующий это. Код основного исполняемого файла

#include <string>
#include <dlfcn.h>
#include <iostream>
#include <cassert>

typedef void (*Function)();

void open(const std::string& soname)
{
    void* so = dlopen(soname.c_str(), RTLD_LAZY | RTLD_GLOBAL);
    if (!so) {
        std::cout << dlerror() << std::endl;
    } else {
        Function function = reinterpret_cast<Function>(dlsym(so, "f"));
        assert(function);
        function();
    }
}

int main()
{
    open("./a.so");
    open("./b.so");
    return 0;
}

И он строится командой g++ main.cpp -o main -ldl

a.so и b.so строятся из

#include <iostream>

void g()
{
     std::cout << "a.cpp" << std::endl;
}

extern "C" {
    void f()
    {
        g();
    }
}

и

#include <iostream>

void g()
{
     std::cout << "b.cpp" << std::endl;
}

extern "C" {
    void f()
    {
        g();
    }
}

по командам g++ -fPIC a.cpp -share -o a.so и g++ -fPIC b.cpp -share -o b.so соответственно. Теперь, если я выполню ./main, я получу

a.cpp
a.cpp

С RTLD_LOCAL Я получаю

a.cpp
b.cpp

но, как я уже объяснил, я не буду RTLD_LOCAL.

1 Ответ

1 голос
/ 28 января 2012

Я бы хотел обнаружить дубликаты символов в dlopen и предупредить их.

Не думаю, что dlopen может это сделать.

Даже если бы это моглообнаружение этой проблемы во время выполнения, вероятно, слишком поздно .Вы должны обнаружить эту проблему во время build , и это легко сделать в качестве шага после сборки:

nm -D your_plugin_dir/*.so | egrep ' [TD] ' | cut -d ' ' -f3 |
  sort | uniq -c | grep -v ' 1 '

Если вы получили какой-либо вывод, у вас есть повторяющиеся символы (некоторые дубликаты символов могут быть в порядке, вам придется отфильтровывать дубликаты "заведомо исправных").

...