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?