Läuft die ausführbare Datei eines kleinen, extrem einfachen Programms, wie dem unten gezeigten, das auf einer Linux-Variante kompiliert wurde, auf einer anderen Variante? Oder müsste es neu kompiliert werden?
Spielt die Maschinenarchitektur in einem solchen Fall eine Rolle?
int main()
{
return (99);
}
Akzeptierte Antwort:
Es hängt davon ab, ob. Etwas, das für IA-32 (Intel 32-Bit) kompiliert wurde, kann auf AMD64 ausgeführt werden, da Linux auf Intel die Abwärtskompatibilität mit 32-Bit-Anwendungen behält (mit geeigneter installierter Software). Hier ist Ihr code
kompiliert auf einem RedHat 7.3 32-Bit-System (ca. 2002, gcc Version 2.96) und dann die Binärdatei auf ein Centos 7.4 64-Bit-System kopiert und darauf ausgeführt (ca. 2017):
-bash-4.2$ file code
code: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped
-bash-4.2$ ./code
-bash: ./code: /lib/ld-linux.so.2: bad ELF interpreter: No such file or directory
-bash-4.2$ sudo yum -y install glibc.i686
...
-bash-4.2$ ./code ; echo $?
99
Ancient RedHat 7.3 bis Centos 7.4 (im Wesentlichen RedHat Enterprise Linux 7.4) bleibt in der gleichen „Distributionsfamilie“, wird also wahrscheinlich eine bessere Portabilität aufweisen, als von einer zufälligen „Linux from scratch“-Installation aus dem Jahr 2002 zu einer anderen zufälligen Linux-Distribution im Jahr 2018 zu wechseln .
Etwas, das für AMD64 kompiliert wurde, würde nicht auf reinen 32-Bit-Versionen von Linux laufen (alte Hardware weiß nichts über neue Hardware). Dies gilt auch für neue Software, die auf modernen Systemen kompiliert wurde und dazu bestimmt ist, auf alten alten Geräten ausgeführt zu werden, da Bibliotheken und sogar Systemaufrufe möglicherweise nicht rückwärts portierbar sind und daher möglicherweise Kompilierungstricks erfordern oder einen alten Compiler usw. oder möglicherweise stattdessen benötigen Kompilieren auf dem alten System. (Dies ist ein guter Grund, virtuelle Maschinen von uralten alten Dingen zu behalten.)
Architektur spielt eine Rolle; AMD64 (oder IA-32) unterscheidet sich stark von ARM oder MIPS, sodass nicht erwartet wird, dass die Binärdatei von einem von ihnen auf einem anderen ausgeführt wird. Auf der Assembly-Ebene die Datei main
Abschnitt Ihres Codes auf IA-32 wird über gcc -S code.c
kompiliert zu
main:
pushl %ebp
movl %esp,%ebp
movl $99,%eax
popl %ebp
ret
mit denen ein amd64-System umgehen kann (auf einem Linux-System – OpenBSD hingegen auf amd64 nicht unterstützt 32-Bit-Binärdateien; Abwärtskompatibilität mit alten Archs gibt Angreifern Spielraum, z. CVE-2014-8866 und Freunde). Inzwischen auf einem Big-Endian-MIPS-System main
stattdessen kompiliert zu:
main:
.frame $fp,8,$31
.mask 0x40000000,-4
.fmask 0x00000000,0
.set noreorder
.set nomacro
addiu $sp,$sp,-8
sw $fp,4($sp)
move $fp,$sp
li $2,99
move $sp,$fp
lw $fp,4($sp)
addiu $sp,$sp,8
j $31
nop
mit denen ein Intel-Prozessor nichts anzufangen weiß, und ebenso für die Intel-Baugruppe auf MIPS.
Sie könnten möglicherweise QEMU oder einen anderen Emulator verwenden, um fremden Code auszuführen (vielleicht sehr, sehr langsam).
Jedoch! Ihr Code ist sehr einfacher Code und wird daher weniger Portabilitätsprobleme haben als alles andere; Programme verwenden typischerweise Bibliotheken, die sich im Laufe der Zeit geändert haben (glibc, openssl, …); für diese müssen möglicherweise auch ältere Versionen verschiedener Bibliotheken installiert werden (RedHat zum Beispiel fügt normalerweise „compat“ irgendwo in den Paketnamen für solche ein)
compat-glibc.x86_64 1:2.12-4.el7.centos
oder machen Sie sich möglicherweise Gedanken über ABI-Änderungen (Application Binary Interface) für alte Dinge, die glibc verwenden, oder neuere Änderungen aufgrund von C++11 oder anderen C++-Versionen. Man könnte auch statisch kompilieren (die Binärgröße auf der Festplatte stark erhöhen), um zu versuchen, Bibliotheksprobleme zu vermeiden, aber ob eine alte Binärdatei dies getan hat, hängt davon ab, ob die alte Linux-Distribution fast alles dynamisch kompiliert hat (RedHat:ja) oder nicht. Andererseits Dinge wie patchelf
kann dynamisch rejiggern (ELF, aber wahrscheinlich nicht a.out
Format) Binärdateien, um andere Bibliotheken zu verwenden.
Jedoch! Ein Programm ausführen zu können, ist eine Sache, und tatsächlich etwas Nützliches damit zu tun, eine andere. Alte 32-Bit-Intel-Binärdateien können Sicherheitsprobleme haben, wenn sie von einer Version von OpenSSL abhängen, die ein schreckliches und nicht zurückportiertes Sicherheitsproblem enthält, oder das Programm kann überhaupt nicht mit modernen Webservern (wie die modernen Server lehnen die alten Protokolle und Chiffren des alten Programms ab), oder das SSH-Protokoll Version 1 wird nicht mehr unterstützt, oder …