2016-09-28 1 views
7

Ich habe ein Rust-Programm für armv7-unknown-linux-gnueabihf kompiliert, und ich möchte, dass es auf einem System läuft, auf dem glibc 2.16 installiert ist. Leider bekomme ich, wenn es ausgeführt wird diesen Fehler:Wie kann ich ein Rust-Programm kompilieren, so dass es __cxa_thread_atexit_impl nicht verwendet?

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

Lauf objdump -T foo zeigt, dass das einzige Symbol von glibc 2.18 erforderlich ist:

00000000 w DF *UND* 00000000 GLIBC_2.18 __cxa_thread_atexit_impl 

Rust makes __cxa_thread_atexit_impl a weak symbol (wie die kleine w Flagge von objdump gesehen), aber GCC ist offensichtlich dumm und obwohl alle Symbole von GLIBC_2.18 schwach sind, macht GLIBC_2.18 selbst immer noch eine starke Anforderung. Sie können sehen, dass mit 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 

Beachten Sie, dass GLIBC_2.18 sagt Flags: none. Es sollte Flags: WEAK sagen. Glücklicherweise fand ich an amazing page where someone shows how to fix this. Leider beinhaltet es hex bearbeiten die binäre!

die dieser .gnu.version_r Tabellenversatzes Nimm (0x001e4c), fügen Sie den für GLIBC_2.18 (0x00a0) Offset-Eintrag, dann ein für das Flags-Feld der Struktur an dieser Adresse (0x04) Offsetzumischung. Das gibt 0x001EF0. Bei dieser Adresse sollte es zwei Nullbytes geben: 0x0000. Ändern Sie sie in 0x0200.

Stellen Sie sicher, mit 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 

Erfolg! Außer es immer noch nicht funktioniert:

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

Wie ist die schwach Version noch erforderlich ?! Ich kann nicht darauf warten, dass glibc stirbt.

Gibt es eine Möglichkeit, Rust das Programm zu erstellen, ohne dieses Symbol zu verwenden?

+2

Zu akzeptieren, wenn die Dinge schrecklich sind, ist der einzige Weg (sie werden verbessert) (https://www.musl-libc.org/). Entschuldigung, wenn ich irgendwelche GNU-Entwickler beleidigt habe. – Timmmm

+0

Sie beleidigen absichtlich die * sehr * Leute, die Ihre Frage beantworten können. Ich werde @tumdum als zweites vorschlagen und vorschlagen, dass Sie die kontraproduktiven Teile entfernen. Als Teilantwort gibt es * gute Gründe, warum GLIBC so funktioniert. Und wenn Sie glauben, dass Musl die Antwort ist, was hindert Sie daran, es zu benutzen? –

+0

'armv7-unknown-linux-muscl' ist leider noch nicht als Ziel verfügbar. Auch wenn ich * das * zur Arbeit bringen kann, ist glibc 2.4 alt genug (2006), was es nicht unangemessen macht und es spart Platz im Vergleich zu Muscl. Wenn es keinen Weg gibt, 2.18 (2013) zu fordern, dann ist muscl definitiv eine bessere Option. – Timmmm

Antwort

0

Sie benötigen eine Rust Toolchain, die für glibc 2.16 oder früher kompiliert wurde. glibc 2.17 funktioniert wahrscheinlich auch, weil es __cxa_thread_atexit_impl fehlt, so dass es nicht eine GLIBC_2.18 Symbol Version im binären tragen.

Die Verwendung des schwachen Symbols im Code Rust ist nicht besonders nützlich, da GNU bestimmte Version von ELF Symbol Versionierung nicht schwach Symbol Versionen hat. Wir könnten das irgendwann ändern, aber im Moment ist der beste Weg, damit umzugehen, mit einer ausreichend alten Toolchain zu kompilieren.

Eine weitere Option ist das Symbol in der glibc Sie verwenden zurückzuportieren.Dies sollte eine ziemlich isoliert Rückportierung, wahrscheinlich dieser Commits aus:

(Ich habe nicht die Rückportierung versucht 2,16 bis glibc, aber soweit solche Dinge gehen, sieht es nicht besonders schwierig aus.)

+0

Gibt es irgendwelche Gedanken, die Sie vielleicht für die Verwendung von Glib in der Toolchain geben könnten, um vielleicht die Verwendung von __cxa_thread_atexit_impl zu entspannen? Kann die Funktion nur von einem expliziten Aufruf der Toolchain verwendet werden, oder gibt es einen Pfad, der es indirekt nutzt? – Digikata

Verwandte Themen