在 dlopen 上检测重复的符号

Detect duplicate symbols at dlopen

本文关键字:符号 检测 dlopen      更新时间:2023-10-16

在我的 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.sob.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.sog++ -fPIC b.cpp -share -o b.so。现在,如果我执行./main我会得到

a.cpp
a.cpp

有了RTLD_LOCAL我得到

a.cpp
b.cpp

但正如我所解释的,我不会RTLD_LOCAL.

我想在 dlopen 检测重复的符号并警告它们。

我认为dlopen做不到。

即使可以,在运行时检测到该问题也可能为时已晚。您应该在构建时检测到该问题,并且作为构建后步骤这样做是微不足道的:

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

如果你得到任何输出,你有重复的符号(一些重复的符号实际上可能没问题;你必须过滤掉"已知良好"的重复

(。