我如何编译一个Rust程序,使它不会';不使用线程退出?

我如何编译一个Rust程序,使它不会';不使用线程退出?,rust,glibc,Rust,Glibc,我已经为armv7 unknown linux gnueabihf编译了一个Rust程序,我希望它能在安装了glibc 2.16的系统上运行。不幸的是,在运行它时,我遇到了以下错误: /foo:/lib/libc.so.6:找不到版本'GLIBC_2.18'(为./foo所需) 运行objdump-tfoo可以发现,glibc2.18所需的唯一符号是: 00000000 w DF*UND*00000000 GLIBC_2.18____cxa_thread_atexit_impl (从objd

我已经为
armv7 unknown linux gnueabihf
编译了一个Rust程序,我希望它能在安装了glibc 2.16的系统上运行。不幸的是,在运行它时,我遇到了以下错误:

/foo:/lib/libc.so.6:找不到版本'GLIBC_2.18'(为./foo所需)
运行
objdump-tfoo
可以发现,glibc2.18所需的唯一符号是:

00000000 w DF*UND*00000000 GLIBC_2.18____cxa_thread_atexit_impl
(从
objdump
中的小
w
标志可以看出),然而GCC显然很愚蠢,尽管GLIBC_2.18中的所有符号都很弱,但它仍然使GLIBC_2.18本身成为一个强大的需求。通过
readelf
,您可以看到:

$readelf-V foo
...
版本需要部分“.gnu.Version\r”包含5个条目:
地址:0x0000000000001e4c偏移量:0x001e4c链接:6(.dynstr)
000000:Version:1文件:ld linux armhf.so.3 Cnt:1
0x0010:名称:GLIBC_2.4标志:无版本:9
0x0020:版本:1文件:librt.so.1 Cnt:1
0x0030:名称:GLIBC_2.4标志:无版本:5
0x0040:版本:1文件:libgcc_.so.1 Cnt:4
0x0050:名称:GCC_4.3.0标志:无版本:10
0x0060:名称:GCC_3.0标志:无版本:7
0x0070:名称:GCC_3.5标志:无版本:6
0x0080:名称:GCC_3.3.1标志:无版本:4
0x0090:版本:1文件:libc.so.6 Cnt:2
0x00a0:名称:GLIBC_2.18标志:无版本:8
0x00b0:名称:GLIBC_2.4标志:无版本:3
0x00c0:Version:1文件:libpthread.so.0 Cnt:1
0x00d0:名称:GLIBC_2.4标志:无版本:2
请注意,
GLIBC_2.18
表示
标志:无
。它应该说
标志:弱
。幸运的是我找到了。不幸的是,它涉及到对二进制文件进行十六进制编辑

获取
.gnu.version\r
表(
0x001e4c
)的偏移量,为
GLIBC\u 2.18
0x00a0
)添加条目偏移量,然后为该地址处的结构的flags字段添加偏移量(
0x04
)。这将给出
0x001EF0
。在该地址处应该有两个零字节:
0x0000
。将其更改为
0x0200

使用
readelf
验证:

版本需要部分“.gnu.Version\r”包含5个条目:
地址:0x0000000000001e4c偏移量:0x001e4c链接:6(.dynstr)
000000:Version:1文件:ld linux armhf.so.3 Cnt:1
0x0010:名称:GLIBC_2.4标志:无版本:9
0x0020:版本:1文件:librt.so.1 Cnt:1
0x0030:名称:GLIBC_2.4标志:无版本:5
0x0040:版本:1文件:libgcc_.so.1 Cnt:4
0x0050:名称:GCC_4.3.0标志:无版本:10
0x0060:名称:GCC_3.0标志:无版本:7
0x0070:名称:GCC_3.5标志:无版本:6
0x0080:名称:GCC_3.3.1标志:无版本:4
0x0090:版本:1文件:libc.so.6 Cnt:2
0x00a0:名称:GLIBC_2.18标志:弱版本:8
0x00b0:名称:GLIBC_2.4标志:无版本:3
0x00c0:Version:1文件:libpthread.so.0 Cnt:1
0x00d0:名称:GLIBC_2.4标志:无版本:2
成功!但它仍然不起作用:

/foo:/lib/libc.so.6:未找到弱版本'GLIBC_2.18'(为./foo所需)
./foo:relocation error:./foo:symbol\u cxa\u thread\u atexit\u impl,版本GLIBC\u 2.18未在文件libc.so.6中定义,带有链接时间参考
怎么还需要弱版本?!我等不及glibc死了


有没有办法让Rust在不使用此符号的情况下构建程序?

您需要一个为glibc 2.16或更早版本编译的Rust工具链。glibc 2.17可能也能正常工作,因为它缺少
\uucxa\u thread\u atexit\u impl
,因此它不会在二进制中携带
glibc\u 2.18
符号版本

在Rust代码中使用弱符号不是特别有用,因为GNU的ELF符号版本控制的特定版本没有弱符号版本。我们最终可能会改变这一点,但现在,处理这一问题的最佳方法是使用足够旧的工具链进行编译

另一个选项是将符号向后移植到您使用的glibc中。这应该是一个相当独立的后端口,可能由以下提交组成:


(我还没有尝试过将glibc 2.16作为后端口,但就这类事情而言,它看起来并不特别困难。)

在事情糟糕时接受是唯一的方法。对不起,如果我冒犯了任何GNU开发者,你是故意冒犯了那些能够回答你问题的人。我会支持@tumdum,并建议您删除适得其反的部分。作为部分答案,GLIBC有充分的理由这样做。如果您相信Musl就是答案,那么到底是什么阻止了您使用它呢?
armv7未知linux muscl
还不能作为目标。另外,如果我能让它工作的话,Glibc2.4已经足够老了(2006年),要求它不是不合理的,它比muscl节省了空间。如果没有办法满足2.18(2013)的要求,那么muscl肯定是一个更好的选择。发言太早了-今天发布了Rust 1.12,支持
armv7未知linux musclabihf
!事实上,目前还没有针对muscl目标的二进制版本,但希望它们很快就会发布。对于工具链使用glib来放松uu cxa_thread_atexit_impl的使用,您有什么想法吗?该函数只能由来自工具链的显式调用使用,还是有一条路径可以间接使用它?