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

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

内容简介:翻译自: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


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

查看所有标签

猜你喜欢:

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

程序员2005精华本

程序员2005精华本

《程序员》杂志社 / 电子工业 / 2006-1 / 45.00元

本书为集结了《程序员》杂志与《msdn开发精选》杂志精华。分上、下两册,内容包括人物&报道、管理与实践、程序员手册、年鉴、《程序员》技术专题、《msdn开发精选》文章精选等。一起来看看 《程序员2005精华本》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

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

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换