如何编译Rust程序,使其不使用__cxa_thread_atexit_impl?

栏目: 编程语言 · Rust · 发布时间: 7年前

内容简介:翻译自:https://stackoverflow.com/questions/39744926/how-can-i-compile-a-rust-program-so-it-doesnt-use-cxa-thread-atexit-impl
我为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 (从objdump的小w旗看到),然而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)处为结构的flags字段添加偏移量.这给出了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在不使用此符号的情况下构建程序?

你需要一个为glibc 2.16或更早版本编译的Rust工具链. glibc 2.17可能也有效,因为它缺少__cxa_thread_atexit_impl,因此它不会在二进制文件中携带GLIBC_2.18符号版本.

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

另一种选择是将符号反向移植到您使用的glibc中.这应该是一个相当孤立的backport,可能包含这些提交:

> Avoid unconditional __call_tls_dtors calls in static linking.

> Also use l_tls_dtor_count to decide on object unload (BZ #18657)

> Harden tls_dtor_list with pointer mangling [BZ #19018]

(我没有尝试过后退到glibc 2.16,但就这些事情而言,看起来并不是特别困难.)

翻译自:https://stackoverflow.com/questions/39744926/how-can-i-compile-a-rust-program-so-it-doesnt-use-cxa-thread-atexit-impl


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

尽在双11:阿里巴巴技术演进与超越

尽在双11:阿里巴巴技术演进与超越

阿里巴巴集团双11技术团队 / 电子工业出版社 / 2017-4 / 79

“双 11”,诞生于杭州,成长于阿里,风行于互联网,成就于新经济,贡献于全世界。 从 2009 年淘宝商城起,双 11 已历经八年。每年的双 11 既是当年的结束,又是走向未来的起点。技术的突破创新,商业模式的更替交互,推动着双 11 迈步向前。 《尽在双11——阿里巴巴技术演进与超越》是迄今唯一由阿里巴巴集团官方出品、全面阐述双 11 八年以来在技术和商业上演进和创新历程的书籍。内容......一起来看看 《尽在双11:阿里巴巴技术演进与超越》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

随机密码生成器
随机密码生成器

多种字符组合密码

html转js在线工具
html转js在线工具

html转js在线工具