【问题标题】:dlopen with two shared libraries, exporting symbolsdlopen 与两个共享库,导出符号
【发布时间】:2011-03-22 11:53:28
【问题描述】:

我有一个 linux 共享库 foo.so,它是使用 dlopen("foo.so", RTLD_NOW | RTLD_LOCAL) 从可执行文件加载的。从 foo.so 我想 dlopen 另一个库 bar.so,它引用了 foo.so 中定义的符号,但链接器找不到它们。我无法将 RTLD_LOCAL 更改为 RTLD_GLOBAL,因为我没有执行加载的可执行文件的源代码。我认为-Wl,--export-dynamic 在链接 foo.so 时可能会有所帮助,但它不会将本地标志覆盖为 dlopen。 GCC 的新属性可见性功能似乎也无法提供答案。

有没有一种方法可以指示链接器将对 bar.so 中未定义符号的引用解析为 foo.so 中的那些定义,而无需使用 -lfoo 链接 bar 或相似性将符号移动到第三个库并链接 foo 和反对吧?我唯一想到的是从 foo.so 本身使用 RTLD_GLOBAL dlopen foo.so,然后 dlopen bar.so,但这让我觉得有点混乱。谢谢。

【问题讨论】:

    标签: linux shared-libraries dlopen


    【解决方案1】:

    链接foo.sobar.so

    当可执行dlopen()s foo.sobar.so也会被加载。

    或者,对可执行文件进行二进制修补以将RTLD_GLOBAL 添加到dlopen() 调用的标志中。代码看起来像

        movl    $2, 4(%esp)       # $2 == RTLD_NOW; RTLD_LOCAL is 0
        movl    $0xNNNNN, (%esp)  # $0xNNNNN == &"foo.so"
        call    dlopen
    

    将其修补到movl $0x102, 4(%esp) (RTLD_GLOBAL == 0x100),然后瞧。

    编辑:
    如果您知道bar.so 的名称,那么您可以将foo.so 链接到“存根”bar.so。你没有“真实的”bar.so没关系;重要的是foo.so 依赖于它。在运行时,无论何时加载 foo.so,该依赖项都会导致加载 bar.so

    【讨论】:

    • 感谢您的回复。我无法将 foo.so 与 bar.so 链接,因为 bar.so 将是用户提供的插件。我也无法修补可执行文件,因为它通常在客户的系统上是 root 拥有的,而且我不确定修补它是否会很好地解决它们,它确实使安装过程变得相当复杂。它还会破坏 exec 正在打开的其他库,其中一些依赖于 RTLD_LOCAL。我想我必须使用 dlopen foo.so 本身的 hack,这似乎可行。干杯
    • 来自this question,如果bar.so在加载foo.so时不存在,但在宿主程序运行时会存在,由dlopen加载怎么办?有什么方法可以实现这一点并避免undefined symbol 问题?
    【解决方案2】:

    这是另一种方式显示如下:

    excutable --dlopen local--> fakefoo.so(rename to foo) --dlopen global--> foo.so(rename to other)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-06
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-27
      相关资源
      最近更新 更多