Mam skompilowany program Rust dla armv7-unknown-linux-gnueabihf
, i chcę go uruchomić w systemie, który ma zainstalowany glibc 2.16. Niestety po uruchomieniu go otrzymuję ten błąd:Jak mogę skompilować program Rust, aby nie używać __cxa_thread_atexit_impl?
./foo: /lib/libc.so.6: version `GLIBC_2.18' not found (required by ./foo)
Running objdump -T foo
ujawnia, że tylko symbol potrzebny od glibc 2.18 brzmi:
00000000 w DF *UND* 00000000 GLIBC_2.18 __cxa_thread_atexit_impl
Rust makes __cxa_thread_atexit_impl
a weak symbol (z punktu widzenia małego w
flagą z objdump
), jednak GCC jest najwyraźniej głupi i pomimo tego, że wszystkie znaki z GLIBC_2.18 są słabe, wciąż powoduje, że GLIBC_2.18 jest silnym wymaganiem. Widać, że z 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
Uwaga, GLIBC_2.18
mówi Flags: none
. Należy powiedzieć: Flags: WEAK
. Na szczęście znalazłem an amazing page where someone shows how to fix this. Niestety wymaga on edycji kodu binarnego !
Take przesunięcie tego .gnu.version_r
tabeli (0x001e4c
), dodać wpis offsetu dla GLIBC_2.18
(0x00a0
), następnie dodać offset dla pola flagami struct pod tym adresem (0x04
). To daje 0x001EF0
. Pod tym adresem powinny znajdować się dwa zero bajtów: 0x0000
. Zmień je na 0x0200
.
Sprawdź u 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
Sukces! Oprócz tego, że nadal nie działa:
./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
Jak jest nadal wymagana wersja słaby ?! Nie mogę się doczekać, aż glibc umrze.
Czy istnieje sposób, aby zmusić Rusta do zbudowania programu bez użycia tego symbolu?
Akceptowanie, gdy rzeczy są straszne, to jedyny sposób [ulegają poprawie] (https://www.musl-libc.org/). Przepraszam, jeśli obraziłem twórców GNU. – Timmmm
Celowo obraziłeś * bardzo * ludzi, którzy mogą odpowiedzieć na twoje pytanie. Wezmę na siebie @tumdum i zasugeruję, że usuniesz przeciwne do zamierzonych części. Jako częściową odpowiedź, istnieją * dobre powody, dla których GLIBC działa tak, jak robi. A jeśli uważasz, że Musl jest odpowiedzią, co dokładnie uniemożliwia ci korzystanie z niej? –
'armv7-unknown-linux-muscl' niestety nie jest jeszcze dostępny jako cel. Również, jeśli * mogę * uzyskać to do pracy glibc 2.4 jest wystarczająco stary (2006), że wymaganie to nie jest nieuzasadnione i oszczędza miejsce w porównaniu do muscl. Jeśli nie ma sposobu, aby wymagać 2.18 (2013), to muscl jest zdecydowanie lepszym rozwiązaniem. – Timmmm