一尘不染

在.so文件中链接到较旧的符号版本

linux

在x86_64 linux上使用gcc和ld我需要链接到库的新版本(glibc
2.14),但是可执行文件需要在具有旧版本(2.5)的系统上运行。由于唯一不兼容的符号是memcpy(需要memcpy@GLIBC_2.2.5,但提供memcpy@GLIBC_2.14的库),我想告诉链接器,它应该使用我指定的旧版本,而不是使用memcpy的默认版本。

我发现这样做很尴尬:只需在链接器命令行中指定旧.so文件的副本即可。这可以正常工作,但是我不喜欢将多个.so文件(只能通过指定我链接到的所有旧库才能工作,也有对memcpy的引用)来将其检入svn并由我的构建系统使用的想法。

因此,我正在寻找一种方法来告诉链接器采用旧版本的符号。

对我不起作用的替代方法是:

  • 使用asm .symver(如Trevor Pounds的Web存档上的Web存档所示),因为这将需要我确保symver位于所有使用memcpy的代码之前,这将非常困难(带有第三方代码的复杂代码库)
  • 使用旧库维护构建环境;仅仅因为我想在我的桌面系统上进行开发,而在我们的网络中同步内容将是皮塔饼。

考虑链接器的所有工作时,似乎并不难实现,毕竟它也有一些代码可以找出符号的默认版本。

只要不是像编辑最终二进制文件这样的怪异技巧,任何其他与简单链接程序命令行具有相同复杂性级别的想法(例如创建简单的链接脚本等)也将受到欢迎。

编辑: 为了保护以后的读者,除了以下想法外,我还找到--wrap了链接器选项,该选项有时也很有用。


阅读 517

收藏
2020-06-02

共1个答案

一尘不染

只需静态链接memcpy-将memcpy.o从libc.a中拉出ar x /path/to/libc.a memcpy.o(无论哪个版本-memcpy
几乎都是一个独立的函数),并将其包含在您的最终链接中。请注意,如果您的项目是公开发布而不是开源的,则静态链接可能会使许可问题复杂化。

另外,您可以简单地自己实现memcpy,尽管glibc中的手工调整程序集版本可能更有效

请注意,memcpy @
GLIBC_2.2.5
映射到memmove(以可预测的方向一致地复制memcpy的旧版本,这有时会使它在应使用memmove的情况下被误用),这是造成版本颠簸的唯一原因-
您在这种情况下,只需在代码中将memcpy替换为memmove即可。

或者,您可以进行静态链接,或者可以确保网络上的所有系统都具有与构建计算机相同或更好的版本。

2020-06-02