我为armv7-unknown-linux-gnueabihf
编译了一个Rust程序,我想让它在安装了glibc 2.16的系统上运行。不幸的是,在运行它时我收到了这个错误:
./foo: /lib/libc.so.6: version `GLIBC_2.18' not found (required by ./foo)
运行objdump -T foo
显示glibc 2.18所需的唯一符号是:
00000000 w DF *UND* 00000000 GLIBC_2.18 __cxa_thread_atexit_impl
Rust makes __cxa_thread_atexit_impl
a weak symbol(从w
的小objdump
标志看到),但GCC显然是愚蠢的,即使GLIBC_2.18中的所有符号虽然很弱,但它仍然是GLIBC_2.18本身的强烈要求。你可以看到readelf
:
$ readelf -V foo
...
Version needs section '.gnu.version_r' contains 5 entries:
Addr: 0x0000000000001e4c Offset: 0x001e4c Link: 6 (.dynstr)
000000: Version: 1 File: ld-linux-armhf.so.3 Cnt: 1
0x0010: Name: GLIBC_2.4 Flags: none Version: 9
0x0020: Version: 1 File: librt.so.1 Cnt: 1
0x0030: Name: GLIBC_2.4 Flags: none Version: 5
0x0040: Version: 1 File: libgcc_s.so.1 Cnt: 4
0x0050: Name: GCC_4.3.0 Flags: none Version: 10
0x0060: Name: GCC_3.0 Flags: none Version: 7
0x0070: Name: GCC_3.5 Flags: none Version: 6
0x0080: Name: GCC_3.3.1 Flags: none Version: 4
0x0090: Version: 1 File: libc.so.6 Cnt: 2
0x00a0: Name: GLIBC_2.18 Flags: none Version: 8
0x00b0: Name: GLIBC_2.4 Flags: none Version: 3
0x00c0: Version: 1 File: libpthread.so.0 Cnt: 1
0x00d0: Name: GLIBC_2.4 Flags: none Version: 2
请注意GLIBC_2.18
说Flags: none
。应该说Flags: WEAK
。幸运的是我找到了an amazing page where someone shows how to fix this。不幸的是,它涉及 十六进制编辑二进制文件 !
获取.gnu.version_r
表(0x001e4c
)的偏移量,添加GLIBC_2.18
(0x00a0
)的条目偏移量,然后为标志字段添加偏移量该地址的结构(0x04
)。这给了0x001EF0
。在该地址处应该有两个零字节:0x0000
。将它们更改为0x0200
。
使用readelf
验证
Version needs section '.gnu.version_r' contains 5 entries:
Addr: 0x0000000000001e4c Offset: 0x001e4c Link: 6 (.dynstr)
000000: Version: 1 File: ld-linux-armhf.so.3 Cnt: 1
0x0010: Name: GLIBC_2.4 Flags: none Version: 9
0x0020: Version: 1 File: librt.so.1 Cnt: 1
0x0030: Name: GLIBC_2.4 Flags: none Version: 5
0x0040: Version: 1 File: libgcc_s.so.1 Cnt: 4
0x0050: Name: GCC_4.3.0 Flags: none Version: 10
0x0060: Name: GCC_3.0 Flags: none Version: 7
0x0070: Name: GCC_3.5 Flags: none Version: 6
0x0080: Name: GCC_3.3.1 Flags: none Version: 4
0x0090: Version: 1 File: libc.so.6 Cnt: 2
0x00a0: Name: GLIBC_2.18 Flags: WEAK Version: 8
0x00b0: Name: GLIBC_2.4 Flags: none Version: 3
0x00c0: Version: 1 File: libpthread.so.0 Cnt: 1
0x00d0: Name: GLIBC_2.4 Flags: none Version: 2
成功!除了它仍然没有工作:
./foo: /lib/libc.so.6: weak version `GLIBC_2.18' not found (required by ./foo)
./foo: relocation error: ./foo: symbol __cxa_thread_atexit_impl, version GLIBC_2.18 not defined in file libc.so.6 with link time reference
如何仍然需要弱版本?!我等不及glibc死了。
有没有办法让Rust在不使用此符号的情况下构建程序?
答案 0 :(得分:1)
你需要一个为glibc 2.16或更早版本编译的Rust工具链。 glibc 2.17可能也有效,因为它缺少__cxa_thread_atexit_impl
,因此它不会在二进制文件中携带GLIBC_2.18
符号版本。
在Rust代码中使用弱符号并不是特别有用,因为GNU的特定版本的ELF符号版本控制没有弱符号版本。我们最终可能会改变这种情况,但是现在,解决这个问题的最佳方法是使用足够旧的工具链进行编译。
另一种选择是将符号反向移植到您使用的glibc中。这应该是一个相当孤立的backport,可能包含这些提交:
(我没有尝试过backport到glibc 2.16,但就这些事情而言,看起来并不是特别困难。)