GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Linux – Wird eine ausführbare Linux-Datei, die auf einer „Variante“ von Linux kompiliert wurde, auf einer anderen laufen?

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.

Verwandte:Linux – Fehler beim Installieren von Perf auf Slackware 13.1?

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 …


Linux
  1. Befehl, der Linux dazu zwingt, den Cache einer Datei auf einer NFS-Freigabe zu leeren?

  2. Wie führe ich ein Programm mit einem anderen Arbeitsverzeichnis als dem aktuellen aus, von der Linux-Shell?

  3. Verwenden Sie für einen Befehl eine andere ausführbare CLI-Version der PHP-Version

  4. Wie kann ich eine nicht vertrauenswürdige ausführbare Datei sicher unter Linux ausführen?

  5. Läuft eine ausführbare Linux-Datei, die auf einer Linux-Variante kompiliert wurde, auf einer anderen?

Stellen Sie ein altes MacBook mit Linux wieder her

Wie man eine Datei unter Linux ausführbar macht

Binärdateien unter Linux ausführen

So führen Sie Windows 95 unter Linux aus

So führen Sie mehrere Linux-Befehle in einem einzigen Befehl aus

Einbetten eines Symbols in eine ausführbare Linux-Datei