我在Linux上有一个可执行文件,它加载libfoo.so.1
(这是一个SONAME
)作为其依赖项之一(通过另一个共享库)。它还链接到另一个系统库,该系统库又链接到系统版本libfoo.so.2
。结果, libfoo.so.1
和libfoo.so.2
在执行期间被加载,并且应该从具有版本1的库调用函数的代码最终调用(二进制不兼容)函数来自版本2的较新系统库,因为某些符号保持不变。结果通常是堆栈粉碎和随后的段错误。
现在,链接旧版本的库是一个封闭源的第三方库,我无法控制它编译的libfoo
版本。假设,剩下的唯一选择是重建当前与libfoo.so.2
链接以与libfoo.so.1
链接的一系列系统库。
有没有办法避免使用链接到较早libfoo
的本地副本替换系统库?我可以加载两个库并让代码调用正确的符号版本吗?所以我需要一些特殊的符号级版本?
答案 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)
我只能想出一个解决方法。这将静态链接您正在使用的“系统库”的版本。对于静态构建,您可以将其链接到与第三方库相同的旧版本。鉴于它不依赖于较新版本......
也许通过普通方式不链接到第三方库也可以避免这些问题。相反,您的程序可以在执行时加载它。也许那时它可能会被其他人遮挡。但我对此并不了解。