在我的Linux应用程序中,我通过dlopen
使用插件架构。正在使用
dlopen(path,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
。
答案 0 :(得分:1)
我想在dlopen中检测重复的符号并警告它们。
我认为dlopen
无法做到这一点。
即使可以,在运行时检测到该问题可能太晚。您应该在 build 时检测到该问题,并且在构建后的步骤中这样做是微不足道的:
nm -D your_plugin_dir/*.so | egrep ' [TD] ' | cut -d ' ' -f3 |
sort | uniq -c | grep -v ' 1 '
如果你得到任何输出,你有重复的符号(一些重复的符号实际上可能没问题;你必须过滤掉“已知良好”的重复符号。)