Linux 加载具有不同版本的多个共享库

Linux 加载具有不同版本的多个共享库,linux,gcc,versioning,shared-libraries,dynamic-linking,Linux,Gcc,Versioning,Shared Libraries,Dynamic Linking,我在Linux上有一个可执行文件,它加载libfoo.so.1(这是一个SONAME)作为它的一个依赖项(通过另一个共享库)。它还链接到另一个系统库,而另一个系统库又链接到一个系统版本,libfoo.so.2。因此,libfoo.so.1和libfoo.so.2都在执行过程中加载,本来应该从版本1的库中调用函数的代码最终从版本2的较新系统库中调用(二进制不兼容)函数,因为某些符号保持不变。结果通常是堆栈崩溃和随后的segfault 现在,链接旧版本的库是一个封闭源代码的第三方库,我无法控制它编译

我在Linux上有一个可执行文件,它加载
libfoo.so.1
(这是一个
SONAME
)作为它的一个依赖项(通过另一个共享库)。它还链接到另一个系统库,而另一个系统库又链接到一个系统版本,
libfoo.so.2
。因此,libfoo.so.1和
libfoo.so.2
都在执行过程中加载,本来应该从版本1的库中调用函数的代码最终从版本2的较新系统库中调用(二进制不兼容)函数,因为某些符号保持不变。结果通常是堆栈崩溃和随后的segfault

现在,链接旧版本的库是一个封闭源代码的第三方库,我无法控制它编译的
libfoo
的版本。假设这样,剩下的唯一其他选项是重建一组当前链接到
libfoo.so.2
的系统库,以链接到
libfoo.so.1


有没有办法避免用链接到旧版
libfoo
的本地副本替换系统库?我可以加载这两个库并让代码调用正确版本的符号吗?所以我需要一些特殊的符号级版本控制?

我只能想出一个解决办法。这将是静态链接您正在使用的“系统库”版本。对于静态构建,您可以将其链接到与第三方库相同的旧版本。考虑到它不依赖于较新的版本


也许也可以通过不以普通方式链接到第三方库来避免这些问题。相反,您的程序可以在执行时加载它。也许到那时,它就可以被其他的影子遮住了。但是我对这个不太了解。

您可能会做一些版本脚本技巧:

这可能需要您在lib周围编写一个包装器,以拉入libfoo.so.1,显式导出一些符号,并将所有其他符号屏蔽为本地符号。例如:

MYSYMS{ 全球的: foo1; foo2; 本地: *; };

当您链接包装器时,请使用此选项,如:

gcc-shared-Wl,--version脚本,mysyms.map-o mylib wrapper.o-lfoo-L/path/to/foo.so.1


这将使libfoo.so.1的符号在包装器中是本地的,而在主exe中不可用。

Alex:您是如何解决这个问题的?你能和我们分享一下吗?@Nawaz我记不清了,已经9年了!我想我放弃了,只加载了一个版本的库。Alex,谈到了这个问题,并提出了解决方案。我还没试过。但是了解/探索是很有趣的。