Linux二进制文件通常动态链接到核心系统库(libc).这使得二进制文件的内存占用空间非常小,但依赖于最新库的二进制文件将无法在较旧的系统上运行.相反,链接到旧库的二进制文件将在最新系统上运行愉快.
因此,为了确保我们的应用程序在分发期间具有良好的覆盖率,我们需要找出我们可以支持的最旧的libc并将我们的二进制文件链接起来.
我们应该如何确定我们可以链接到的最旧版本的libc?
在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并且我的构建系统需要.
所以我正在寻找一种方法来告诉链接器采用旧的版本符号.
对我不起作用的替代方案是:
在考虑链接器所做的所有工作时,实现它似乎并不困难,毕竟它还有一些代码可以找出符号的默认版本.
任何其他与简单链接器命令行具有相同复杂程度的想法(如创建简单的链接描述文件等)也是受欢迎的,只要它们不像编辑生成的二进制文件那样奇怪的黑客...
编辑:
为了保护未来的读者,除了以下的想法,我找到--wrap了链接器的选项,这有时也很有用.
以下问题是相关的,但不回答我的问题:
我之前提出了一个非常类似的问题,但是由于我开始的上一个问题在评论部分有些混乱而没有得到完全回答(但我将其标记为已回答,因为这是一项很好的努力并至少部分回答了它)我会问一个新问题.问题是具体如何将libc链接为静态,同时动态链接其他库(例如libm).有人提出在第一个问题中无法做到,是真的吗?如果是这样,知道为什么不是很有趣.
甚至可以这样做吗?有人发表了意见(这是出于某种原因删除,也许这是不正确的?),这是可能的,但那么一定还存在libc中的动态链接的版本,因为它会通过动态库需要(如动态的libm会需要动态libc(?)).
这对我来说很好,但对我来说如何告诉GCC这样做并不明显,即在libc中链接为静态和动态.我该怎么做(我做了几次尝试,有些会在后面的问题中展示)?或者还有其他方法可以做我想要的吗?
我们首先看到,通过简单地运行gcc test.c -lm,一切都是动态链接的,如下所示:
$ gcc test.c -lm
$ ldd a.out
linux-vdso.so.1 (0x00007fffb37d1000)
libm.so.6 => /lib64/libm.so.6 (0x00007f3b0eeb6000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3b0eb10000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3b0f1b0000)
Run Code Online (Sandbox Code Playgroud)
要仅将libm链接为静态,同时允许libc保持动态,我们可以这样做(正如Z boson在前面提到的一个问题中指出的那样):
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libm.a
$ ldd a.out
linux-vdso.so.1 (0x00007fff747ff000)
libc.so.6 => /lib64/libc.so.6 (0x00007f09aaa0c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f09aadb2000)
Run Code Online (Sandbox Code Playgroud)
但是,尝试使用相同的过程来链接libc static和libm dynamic,似乎不起作用:
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a -lm
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink …Run Code Online (Sandbox Code Playgroud)