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

问题描述:

我一直在阅读并试图理解符号如何在Linux中的共享库中得到解决。所以这里是我所面对的内容的描述。使用相同的静态链接函数加载两个共享库时,使用哪个函数

我正在使用可以加载用户创建的共享库来添加功能的应用程序(APP)。我有两个这样的库,LIB_A.soLIB_B.so执行单独的事情,不依赖于另一个工作。它们是独立编译的,并且基于编译器参数(-fPIC),似乎它会使符号(从我对该主题的研究中)处置一段时间。所以大多数符号默认会被导出。

现在,有两个LIB_ALIB_B使用被编译并与每个库静态链接的这个共同的代码。通用代码不使用任何名称空间或静态函数,因此我假定它们也将被导出。 LIB_A和LIB_B都按照APP中的预期加载和工作。

但是如果在通用代码中发现了一个bug,但是只有LIB_A可以重新编译,因为它需要固定的代码。我的问题是,当LIB_A重新编译拿起在公共代码这一变化,并在APP得到加载,会有的公共代码独立副本都LIB_A(有bug修复)和LIB_B(它没有错误修复),并且每个都将使用它们各自的副本,或者将两者都链接和共享其中一个通用代码版本?有没有办法让我用调试器发现符号的来源?

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

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

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

我一直在阅读文章和搜索,但这一件事情我不知道我100%被钉死。

编辑有关更多信息,请在运行时按需加载这些库。这是否会改变任何使用dlopenRTLD_LOCALRTLD_GLOBAL?从描述中,RTLD_LOCAL似乎阻止全局加载符号,因此不会冲突或链接到库外的其他符号?

+0

如果您正在动态链接,那么意味着每个库都有一个单独的句柄,您正在使用'dlopen'创建。它们分享的代码并不特别重要。 –

+0

感谢您的回复,请在我的帖子中查看我的编辑。这是你指的是什么? – scottiedoo

会不会有(具有错误修复)的两个LIB_A通用代码单独副本 和LIB_B(即不具有错误修复)

在不存在-fvisibility=hidden(或其它您提到的类似标志) 运行时链接程序将确保将所有重复的符号解析为相同的实现(在LIB_A或LIB_B中)。 所以库将有效地共享代码。

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

通常,符号将从第一个加载的库中提取它们(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,但我的印象是编译器的优化标记为 ,通常不能保证符号的本地分辨率。

我看着使用纳米-D命令,我看到一些符号是W,这是否意味着如果使用一个静态与库建立了一个之前已经存在,它会使用现有符号 ?

不,运行时链接程序没有考虑到符号的弱点(至少没有我不推荐使用的LD_DYNAMIC_WEAK environment variable)。

+0

感谢您的回复。我在编辑中添加了一些额外的信息。如果它在运行时使用带有RTLD_LOCAL标志的dlopen加载,会发生变化吗? APP不依赖于这些库,并且可以在APP的生命周期的任何时候加载和卸载 – scottiedoo