How can I compile Rust so that it does not use __cxa_thread_atexit_impl?

I compiled the Rust program for armv7-unknown-linux-gnueabihf and I want it to run on a system with glibc 2.16 installed. Unfortunately, when I start, I get this error:

 ./foo: /lib/libc.so.6: version `GLIBC_2.18' not found (required by ./foo) 

Running objdump -T foo shows that the only character needed for glibc 2.18 is:

 00000000 w DF *UND* 00000000 GLIBC_2.18 __cxa_thread_atexit_impl 

Rust makes __cxa_thread_atexit_impl weak character (as seen from the small w flag from objdump ), however GCC is apparently stupid, and although all characters from GLIBC_2.18 are weak, it still makes GLIBC_2.18 itself a strong requirement. You can see that with 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 

Note that GLIBC_2.18 says Flags: none . He should say Flags: WEAK . Fortunately, I found an amazing page where someone shows how to fix this . Unfortunately, it includes hex editing binary !

Take the offset of this table .gnu.version_r ( 0x001e4c ), add the write offset for GLIBC_2.18 ( 0x00a0 ), then add the offset for the flags field of the structure at this address ( 0x04 ). This gives 0x001EF0 . There must be two null bytes at this address: 0x0000 . Change them to 0x0200 .

Confirm with 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 

Success! Except this still does not work:

 ./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 

How else do you need a weak version ?! I can't wait for glibc to die.

Is there a way to get Rust to create a program without using this symbol?

+7
glibc rust
source share
1 answer

You need a Rust binding that was compiled for glibc 2.16 or earlier. glibc 2.17 probably works because it lacks __cxa_thread_atexit_impl , so it won’t have the binary GLIBC_2.18 character version.

Using a weak character in rust code is not particularly useful because a particular version of ELF character versioning does not have weak character versions. In the end, we can change this, but for now, the best way to handle this is to put together using a fairly old toolchain.

Another option is to back up the character to the glibc you are using. It should be a pretty isolated backport, possibly consisting of these commits:

(I did not try to perform backport for glibc 2.16, but as far as possible it does not look particularly difficult.)

0
source share

All Articles