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

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

问题描述:

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

I been reading and trying to understand how symbols get resolved within a shared library in Linux. So here is a description of what I am faced with.

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

I am using an application (APP) that can load user created shared libraries to add features. I have two such libraries, LIB_A.so and LIB_B.so that perform separate things and do not depend on another to work. They are independently compiled and based on the compiler arguments (-fPIC), will seem it will make the symbols interposable (from my research on the topic). So most symbols will be exported by default.

现在,存在 LIB_A LIB_B 都使用的通用代码,它们已编译并与每个库静态链接.通用代码不使用任何名称空间或静态函数,因此我假设它们也将被导出. LIB_A和LIB_B均按APP预期的方式加载和工作.

Now, there is this common code that both LIB_A and LIB_B uses that is compiled and statically linked with each library. The common code does not use any namespaces or static functions, so I am assuming they will be exported as well. Both LIB_A and LIB_B load and work as intended in the APP.

但是,如果在通用代码中发现一个错误,但是只有 LIB_A 可以重新编译,该怎么办,因为它需要固定代码.我的问题是,当重新编​​译 LIB_A 以便在通用代码中获得此更改并加载到 APP 中时,是否会有单独个副本 LIB_A (已修复错误)和 LIB_B (未修复错误)的通用代码,并且每个都将使用各自的副本或都链接并在两者*享通用代码的一个版本?也许我有办法使用调试器发现符号的来源吗?

But what if there was a bug found inside the common code but only LIB_A can be recompiled because it needs the fixed code. My question is, when LIB_A is recompiled to pick up this change in the common code and get loaded in the APP, would there be separate copies of the common code for both LIB_A (that has the bug fix) and LIB_B (that does not have the bug fix) and each would use their respective copies or would both link and share one of the versions of the common code in both? Is there a way for me to discover the source of the symbol using a debugger perhaps?

要想提前得到答案,我不知道将按哪个顺序加载库,我无法重新编译LIB_B来获取更改,只能重新编译LIB_A.我没有APP的源代码,无法知道它是如何动态加载库的.

To just to get answer questions ahead of time, I do not know which order the libraries will be loaded, I can not recompiled LIB_B to pick up the changes, only LIB_A. I do not have the source code of the APP to know how it's dynamically loading the libraries.

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

I know there is a great deal with the compiler flags but assume it's just -fPIC, no -fvisibility-hidden, -Wl,-Bsymbolic, -fno-semantic-interposition flags are set. Would these solve this issue if there was a conflict?

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

I looked at using the nm -D command and I see some of the symbols are W, does that mean it will use an existing symbol if it already exists before using the one that was statically built with the library?

我一直在阅读文章并进行搜索,但是我不确定这件事是我100%被钉牢了.

I been reading articles and search, but this one things I am not sure I 100% nailed down.

编辑有关更多信息,我将在运行时按需加载这些库.通过将dlopenRTLD_LOCALRTLD_GLOBAL一起使用,这会发生任何变化吗?从描述中看,RTLD_LOCAL似乎可以防止全局加载符号,因此不会冲突或链接到库外的其他符号吗?

EDIT For further information, I am loading these libraries at runtime on demand. Would this change anything by using dlopen with RTLD_LOCAL vs RTLD_GLOBAL? From the description, RTLD_LOCAL seems to prevent symbols from being loaded globally and therefore will not conflict or link to other symbols outside of the library?

两个LIB_A(具有错误修复)的通用代码是否应有单独的副本 和LIB_B(没有错误修复)

Would there be separate copies of the common code for both LIB_A (that has the bug fix) and LIB_B (that does not have the bug fix)

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

In absence of -fvisibility=hidden (or other similar flags you mention) runtime linker will ensure that all duplicate symbols are resolved to the same implementation (either in LIB_A or LIB_B). So libs will effectively share code.

也许我可以使用调试器发现符号的来源吗?

Is there a way for me to discover the source of the symbol using a debugger perhaps?

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

In general, symbols would be taken from the first loaded library that provides them (LIB_A or LIB_B). Libraries will be loaded in the order they are listed in .dynamic section of executable (run readelf -d app to be sure or simply run your app with LD_DEBUG variable set to symbols). If you want to force LIB_A to be loaded first, you can set LD_PRELOAD accordingly.

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

I know there is a great deal with the compiler flags but assume it's just -fPIC, no -fvisibility-hidden, -Wl,-Bsymbolic, -fno-semantic-interposition flags are set. Would these solve this issue if there was a conflict?

我假设您希望每个库都使用它自己的通用符号版本? 实现此目标的最标准方法是-fvisibility=hidden.这将防止导出通用符号,并且 那么它们将被静态解析为本地副本. 当然,那么您将需要查找并注释其他需要导出的功能.

I assume you want each library to use it's own version of common symbols? The most standard way to achieve this is -fvisibility=hidden. This will prevent common symbols from being exported and then they'll be statically resolved to local copies. Of course then you'll need to find and annotate other functions that need to be exported.

-Bsymbolic可能也有帮助,但这将强制解决所有本地可解析的引用 也就是说,您将无法将其限制为您感兴趣的符号的子集. 另外,它的使用范围也较小.

-Bsymbolic may also help but this would forcefully resolve all locally resolvable references i.e. you won't be able to limit it to a subset of symbols you're interested in. Also it's less widely used.

关于-fno-semantic-interposition,我手头没有最近的GCC,但我的印象是这是一个优化标记 对于编译器,通常不能保证符号的局部分辨率.

As for -fno-semantic-interposition, I do not have recent GCC at hand but my impression was that it's an optimization flag for compiler and generally would not guarantee local resolution of symbols.

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

I looked at using the nm -D command and I see some of the symbols are W, does that mean it will use an existing symbol if it already exists before using the one that was statically built with the library?

否,运行时链接程序不会考虑符号的弱点(至少没有

No, runtime linker does not take weakness of symbol into account (at least without LD_DYNAMIC_WEAK environment variable which I do not recommend to use).