Linux上对共享库的依赖性较弱

mrs*_*ith 5 c linux ld dlopen

我想让我的可执行文件"可选地依赖"其他共享对象.因此,如果DSO不存在,它将能够在没有某些符号的情况下运行.

我可以通过dlopen/dlsym调用实现这一点,但我必须手动加载每个符号并为它们添加包装器,如下所示:

void *my_lib = dlopen("my_lib.so", RTLD_LAZY);  
if (!my_lib)  {
    // ok, I promise not to touch my_lib symbols
} else {
    my_foo_ptr = dlsym(my_lib, "my_foo");
    my_bar_ptr = dlsym(my_lib, "my_bar");
}

... my_foo(...) {
    assert(my_foo_ptr);
    return (*my_foo_ptr)(...);
}

... my_bar(...) {
    assert(my_foo_ptr);
    return (*my_bar_ptr)(...);
}
Run Code Online (Sandbox Code Playgroud)

这是一个愚蠢的代码,它直接依赖于"my_lib.so"ABI,这意味着每次库更新时我都必须更新它.

我正在寻找一些方法来ld.so为我做这件事.所以理想的是:

void *my_lib = dlopen("my_lib.so", /* bring me all my symbols */);  
if (!my_lib)  {
    // ok, I promise not to touch my_lib symbols
} else {
    // ok, I can directly call symbols from my_lib.so
    my_foo();
    my_bar();
}
Run Code Online (Sandbox Code Playgroud)

但是有两个问题:
1.在app链接阶段如何处理这些符号?如果我显式链接到my_lib.so,应用程序将严格依赖于它,因此无法在没有my_lib.so的情况下启动.如果没有,ld将抱怨未定义的符号.
2.如何强制dlopen()使我的应用程序可以使用所有my_lib.so符号?

Upd:我意识到显式链接共享库而不标记它就DT_NEEDED可以了.但我不知道如何ld做到这一点.

Aar*_*lla 0

这是可能的,但可能比您愿意投入的工作量还要多。去做吧:

  1. 您需要创建 GCC 的补丁版本,特别是 binutils,它允许您创建“可选”符号列表(即动态加载程序在丢失时不会抱怨的符号)。

  2. 您必须修补动态加载程序才能理解您的符号。

更简单的方法可能是使用DSL,工具(= 脚本或简单的 C 程序)可以读取并使用它来生成样板 C 代码。

DSL 将定义所有符号(和参数),并且该工具将使用上面的代码模板将其转换为 .h 和 .c 文件。

my_lib.so更改时(或当您需要更多符号时),您只需编辑(小)DSL 并重新运行脚本。