加载具有相同静态链接函数的两个共享库时使用哪个函数

时间:2017-04-25 23:15:06

标签: c++ linux gcc shared-libraries symbols

我一直在阅读并尝试了解如何在Linux中的共享库中解析符号。所以这里是对我所面对的描述。

我正在使用可以加载用户创建的共享库来添加功能的应用程序( APP )。我有两个这样的库, LIB_A.so LIB_B.so ,它们执行单独的操作并且不依赖于另一个工作。它们是独立编译的,并且基于编译器参数(-fPIC),似乎它会使符号成为可插入的(来自我对该主题的研究)。因此,默认情况下将导出大多数符号。

现在,有一个通用代码, LIB_A LIB_B 使用的代码与每个库进行编译和静态链接。公共代码不使用任何名称空间或静态函数,所以我假设它们也将被导出。 LIB_A和LIB_B都按照APP中的预期加载和工作。

但是如果在公共代码中发现了一个错误,但只有 LIB_A 可以重新编译,因为它需要固定的代码。我的问题是,当重新编​​译 LIB_A 以在公共代码中获取此更改并加载到 APP 中时,是否会有单独的副本 LIB_A (有错误修复)和 LIB_B (没有错误修复)的公共代码,每个都会使用各自的副本或两者都链接并在两者中共享公共代码的一个版本?有没有办法让我使用调试器来发现符号的来源?

为了提前回答问题,我不知道库的加载顺序是什么,我不能重新编译LIB_B以获取更改,只有LIB_A。我没有APP的源代码知道它是如何动态加载库的。

我知道编译器标志有很多,但假设它只是-fPIC,没有设置-fvisibility-hidden-Wl,-Bsymbolic-fno-semantic-interposition标志。如果发生冲突,这些会解决这个问题吗?

我查看了使用nm -D命令,我看到一些符号是W,这是否意味着如果现有符号在使用静态构建的库之前已经存在,它将使用现有符号? / p>

我一直在阅读文章和搜索,但这一件事我不确定我是100%确定的。

编辑有关详细信息,我将根据需要在运行时加载这些库。通过dlopenRTLD_LOCAL使用RTLD_GLOBAL,这会改变什么吗?从描述中,RTLD_LOCAL似乎阻止符号被全局加载,因此不会冲突或链接到库外的其他符号?

2 个答案:

答案 0 :(得分:1)

  

是否会为LIB_A(具有错误修复)的公共代码单独复制   和LIB_B(没有错误修复)

缺少-fvisibility=hidden(或您提及的其他类似标志) 运行时链接程序将确保将所有重复的符号解析为相同的实现(在LIB_A或LIB_B中)。 因此,libs将有效地共享代码。

  

我是否有办法使用调试器发现符号的来源?

通常,符号将从提供它们的第一个加载库中获取(LIB_A或LIB_B)。 库将按照可执行文件的.dynamic部分中列出的顺序加载(运行readelf -d app,以确保或只是在LD_DEBUG变量设置为symbols的情况下运行您的应用程序。 如果要强制首先加载LIB_A,可以相应地设置LD_PRELOAD

  

我知道编译器标志有很多,但假设它只是   -fPIC,未设置-fvisibility-hidden-Wl,-Bsymbolic-fno-semantic-interposition个标记。   如果发生冲突,这些会解决这个问题吗?

我假设您希望每个库都使用它自己的常用符号版本? 实现这一目标的最标准方法是-fvisibility=hidden。这将阻止导出常见符号 然后他们将被静态地解析为本地副本。 当然,您需要查找并注释需要导出的其他函数。

-Bsymbolic也可以提供帮助,但这会强制解析所有本地可解析的参考文献 即您希望能够将其限制为您感兴趣的符号子集。 它的使用也不太广泛。

关于-fno-semantic-interposition,我手头没有最近的GCC,但我的印象是它是一个优化标志 对于编译器而言通常不保证符号的局部解析。

  

我查看了使用nm -D命令,我看到一些符号是W,这是否意味着它将使用现有的符号   如果在使用静态构建库的那个之前它已经存在了吗?

不,运行时链接器不会考虑符号的弱点(至少没有LD_DYNAMIC_WEAK environment variable我不建议使用)。

答案 1 :(得分:0)

要回答部分问题:

  

有没有办法让我发现符号的来源

如果您定义环境变量LD_DEBUG=bindings并运行您的程序,您将得到满足。其他选项可用,使用LD_DEBUG=help获取列表。