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

时间:2008-10-23 00:59:01

标签: linux gcc versioning shared-libraries dynamic-linking

我在Linux上有一个可执行文件,它加载libfoo.so.1(这是一个SONAME)作为其依赖项之一(通过另一个共享库)。它还链接到另一个系统库,该系统库又链接到系统版本libfoo.so.2。结果, libfoo.so.1libfoo.so.2在执行期间被加载,并且应该从具有版本1的库调用函数的代码最终调用(二进制不兼容)函数来自版本2的较新系统库,因为某些符号保持不变。结果通常是堆栈粉碎和随后的段错误。

现在,链接旧版本的库是一个封闭源的第三方库,我无法控制它编译的libfoo版本。假设,剩下的唯一选择是重建当前与libfoo.so.2链接以与libfoo.so.1链接的一系列系统库。

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

2 个答案:

答案 0 :(得分:7)

你可以做一些版本脚本技巧:

http://sunsite.ualberta.ca/Documentation/Gnu/binutils-2.9.1/html_node/ld_26.html

这可能要求您在lib周围编写一个包装器,它会引入libfoo.so.1,它会明确地导出一些符号并将所有其他符号屏蔽为本地符号。例如:

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

并在链接包装器时使用它:

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

这应该使libfoo.so.1的符号位于包装器的本地,而不能用于主exe。

答案 1 :(得分:0)

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

也许通过普通方式不链接​​到第三方库也可以避免这些问题。相反,您的程序可以在执行时加载它。也许那时它可能会被其他人遮挡。但我对此并不了解。