第二个插件崩溃再次引用代码段

时间:2013-03-25 21:49:02

标签: linux gcc dynamic linker dlopen

我想在我工作的有问题的案例中理解Linux上的动态链接器/加载器行为。

崩溃的代码作为插件加载(dlopen(libwrapper.so,RTLD_GLOBAL))。 libwrapper.so只是一个薄层,可以加载另一个完成实际工作的插件。这些插件可以命名为:P1和P2,每个插件都依赖于名为F的公共库(所有这些都非常简化)。

引入了Wrapper(libwrapper.so)以允许在没有RTLD_GLOBAL的情况下加载Pn,因为该标志集导致加载Pns的明显链接问题(它们具有相同的API)。 RTLD_DEEPBIND不是一个选项,因为目标平台太旧 - 不支持它。

令我们惊讶的是,在P2的加载时间(当P1已经加载(和初始化)而F作为其隐式依赖)时,问题在F库中出现。在显式加载P2时(dlopen(libP2.so,RTLD_LOCAL | RTLD_NOW)),动态链接器报告没有问题,但调用F中的代码来实例化F中定义的某些类型实例(再次)导致各个地方的分段错误(如果一个被跳过/超出评论,它会在另一个地方崩溃 - 因此没有花时间调查可能很麻烦的代码模式,因为怀疑存在更普遍的问题/误解。没有使用内联函数,代码链接-Wl,-E,可见性默认,GCC是3.4.4 .. F代码非常稳定,可以在独立应用程序中使用,也可以作为插件的一部分使用。

我想将F作为静态库链接,以解决动态链接器可能存在的任何问题,但结果是相同的。

我对这个主题的看法:

  • 将F作为动态库链接导致动态链接器“知道”F被引用第二次加载P2并且只增加引用计数器并且不调用静态初始化器(这是可以的),但是重新定位(再次,这似乎是有问题)。
  • 将F链接为静态库导致动态链接器将F代码加载为P2(P2F)的静态链接部分,并在P2F中进行重定位。但是,来自F的“某种方式”常见符号与P1F代码实例相混淆。

关于使代码至少工作的解决方法的假设:

  • 在单个共享库(单个插件)中链接P1 ... Pn,无论F是共享/静态都无关紧要。这样任何重定位都只进行一次。

我很感激任何反馈是我对该主题的看法错误/过于简化/缺失的重要部分?这是过去一些已知的GCC / binutils错误吗?

1 个答案:

答案 0 :(得分:1)

  

我对这个主题的看法:

您对该主题的看法是错误的;但是没有办法向你证明这一点。

编写一个模拟系统功能的最小测试用例,但仍然以类似的方式崩溃。用实际破坏的代码更新您的问题;然后我们可以告诉你完全问题是什么。

还有一个非常好的机会,在将问题简化为最小的例子时,你会发现自己的问题。

无论哪种方式,你都会理解这个问题,并会学到新的东西。