Обнаружить дубликаты символов на dlopen
В моем приложении 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 ответ
Я хотел бы обнаружить дубликаты символов на dlopen и предупредить о них.
Я не думаю dlopen
могу сделать это.
Даже если это возможно, обнаружить эту проблему во время выполнения, вероятно, слишком поздно. Вы должны обнаружить эту проблему во время сборки, и это тривиально сделать в качестве шага после сборки:
nm -D your_plugin_dir/*.so | egrep ' [TD] ' | cut -d ' ' -f3 |
sort | uniq -c | grep -v ' 1 '
Если вы получаете какой-либо вывод, у вас есть дубликаты символов (некоторые дубликаты символов могут быть действительно нормальными; вам придется отфильтровывать "заведомо исправные" дубликаты).