我想了解在我工作的有问题的情况下,Linux上的动态链接器/加载器行为。代码段再次引用第二个插件崩溃
我们的代码崩溃被加载为插件(dlopen(libwrapper.so,RTLD_GLOBAL))。 libwrapper.so只是一个很薄的层,可以加载其他插件来完成真正的工作。这些插件可以被命名为:P1和P2,这些插件都依赖于称为F的通用库(所有这些都非常简化)。
引入了包装器(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 ...光合速率在一个单一的共享库(单插件),F是否共享/静态没关系。这样任何重新安置只能完成一次。
我很感激任何反馈意见是我对该主题的看法错误/过于简化/缺少重要的部分?这是一些从过去已知的GCC/binutils错误吗?
上面的文字中是否有任何特定部分可以声称“它是错误的”?这会帮助我更有效地集中注意力。 – user2208924 2013-03-26 08:49:44
@ user2208924是的:这部分:“链接F作为动态库导致动态链接器”知道“F被第二次加载P2引用,并且只增加引用计数器并且不调用静态初始化器” - 正确到该点,但下一个断言:“但重定位”是错误的。 – 2013-03-26 13:58:49