Läuft die ausführbare Datei eines kleinen, extrem einfachen Programms, wie das unten gezeigte, das auf einer Linux-Version kompiliert ist, auf einer anderen Version? Oder müsste es neu kompiliert werden?
Ist in einem solchen Fall die Maschinenarchitektur von Bedeutung?
int main()
{
return (99);
}
glibc
wurde, oder umgekehrt. Zugegeben, das ist nicht ganz unmöglich .gcc -m32 -static
) statisch verknüpfen . Auf diese Weise kann jedes i386- oder amd64-Linux die ausführbare Datei ausführen.Antworten:
Es hängt davon ab, ob. Ein für IA-32 kompiliertes Produkt (Intel 32-Bit) kann unter amd64 ausgeführt werden, da Linux unter Intel die Abwärtskompatibilität mit 32-Bit-Anwendungen (mit geeigneter installierter Software) beibehält. Hier ist Ihr
code
auf RedHat 7.3 32-Bit-System (ca. 2002, gcc-Version 2.96) kompiliertes und dann das Binärprogramm, das auf ein Centos 7.4 64-Bit-System (ca. 2017) kopiert und ausgeführt wird:Die alten Versionen von RedHat 7.3 bis Centos 7.4 (im Wesentlichen RedHat Enterprise Linux 7.4) gehören weiterhin zur selben "Distributions" -Familie, weshalb sie wahrscheinlich besser portiert werden können, als wenn sie ab 2002 von einer zufälligen "Linux from scratch" -Installation auf eine andere zufällige Linux-Distribution im Jahr 2018 umsteigen .
Etwas, das für amd64 kompiliert wurde, läuft nicht auf 32-Bit-Versionen von Linux (alte Hardware kennt keine neue Hardware). Dies gilt auch für neue Software, die auf modernen Systemen kompiliert wurde, die auf alten Dingen ausgeführt werden sollen, da Bibliotheken und sogar Systemaufrufe möglicherweise nicht rückwärts portierbar sind und daher Kompilierungstricks oder den Erwerb eines alten Compilers usw. erfordern Kompilieren auf dem alten System. (Dies ist ein guter Grund, virtuelle Maschinen mit alten Dingen in der Nähe zu halten.)
Architektur ist wichtig; amd64 (oder IA-32) unterscheidet sich stark von ARM oder MIPS, so dass nicht erwartet wird, dass die Binärdatei auf einer anderen ausgeführt wird. Auf der Assembly-Ebene wird der
main
Abschnitt Ihres Codes auf IA-32 übergcc -S code.c
to kompiliertmit denen ein amd64-System umgehen kann (auf einem Linux-System - OpenBSD unterstützt im Gegensatz zu amd64 keine 32-Bit-Binärdateien; Abwärtskompatibilität mit alten Archs lässt Angreifern Spielraum, z. B. CVE-2014-8866 und Freunden). In der Zwischenzeit wird auf einem Big-Endian-MIPS-System
main
Folgendes kompiliert:Womit ein Intel-Prozessor keine Ahnung haben wird, was zu tun ist, und ebenfalls für die Intel-Baugruppe auf MIPS.
Sie könnten möglicherweise QEMU oder einen anderen Emulator verwenden, um Fremdcode auszuführen (möglicherweise sehr, sehr langsam).
Jedoch! Ihr Code ist sehr einfach und hat daher weniger Portabilitätsprobleme als alles andere. Programme verwenden normalerweise Bibliotheken, die sich im Laufe der Zeit geändert haben (glibc, openssl, ...). Für diese muss möglicherweise auch eine ältere Version verschiedener Bibliotheken installiert werden (RedHat setzt zum Beispiel typischerweise "compat" irgendwo in den Paketnamen für solche).
oder möglicherweise über ABI-Änderungen (Application Binary Interface) besorgt sein, die sich auf ältere Dinge beziehen, die glibc verwenden, oder auf Änderungen, die in jüngster Zeit aufgrund von C ++ 11 oder anderen C ++ - Versionen vorgenommen wurden. Man könnte auch statisch kompilieren (was die Binärgröße auf der Festplatte stark erhöht), um Bibliotheksprobleme zu vermeiden. Ob dies jedoch durch eine alte Binärdatei geschehen ist, hängt davon ab, ob die alte Linux-Distribution fast alles Dynamische kompiliert hat (RedHat: yes) oder nicht. Auf der anderen Seite können Dinge wie
patchelf
dynamische (ELF, aber wahrscheinlich nichta.out
formatierte) Binärdateien rejiggern , um andere Bibliotheken zu verwenden.Jedoch! In der Lage zu sein, ein Programm auszuführen, ist eine Sache und damit etwas Nützliches zu tun eine andere. Alte 32-Bit-Binärdateien von Intel können Sicherheitsprobleme aufweisen, wenn sie von einer OpenSSL-Version abhängen, die ein schreckliches und nicht rückportiertes Sicherheitsproblem aufweist, oder wenn das Programm überhaupt nicht mit modernen Webservern (wie den modernen) verhandeln kann Server lehnen die alten Protokolle und Chiffren des alten Programms ab, oder SSH-Protokoll Version 1 wird nicht mehr unterstützt, oder ...
quelle
for GNU/Linux 2.6.32
(oder solche) in der Ausgabe vonfile /usr/bin/ls
.Kurz gesagt: Wenn Sie eine kompilierte Binärdatei mit derselben (oder einer kompatiblen) Architektur von einem Host auf einen anderen übertragen , ist es möglicherweise in Ordnung, sie auf eine andere Distribution zu übertragen . Mit zunehmender Komplexität des Codes steigt jedoch die Wahrscheinlichkeit, mit einer nicht installierten Bibliothek verknüpft zu werden. an einem anderen Ort installiert; oder in einer anderen Version installiert, erhöht. Nehmen wir zum Beispiel Ihren Code, für
ldd
den beim Kompilierengcc -o exit-test exit-test.c
auf einem (von Debian abgeleiteten) Ubuntu-Linux-Host die folgenden Abhängigkeiten gemeldet werden :Offensichtlich wird diese Binärdatei nicht ausgeführt, wenn ich sie beispielsweise einem Mac (
./exit-test: cannot execute binary file: Exec format error
) übergebe. Lassen Sie uns versuchen, es in eine RHEL-Box zu verschieben:Ach je. Warum könnte das so sein?
Selbst für diesen Anwendungsfall schlug das Gabelstaplern aufgrund fehlender gemeinsamer Bibliotheken fehl.
Wenn ich es jedoch mit kompiliere
gcc -static exit-test-static exit-test.c
, funktioniert das Portieren auf das System ohne die Bibliotheken einwandfrei. Natürlich auf Kosten des Speicherplatzes:Eine andere praktikable Lösung wäre die Installation der erforderlichen Bibliotheken auf dem neuen Host.
Wie bei vielen Dingen im U & L-Universum ist dies eine Katze mit vielen Häuten, von denen zwei oben aufgeführt sind.
quelle
amd64
Binärdatei zu erstellen und auf einer anderenamd64
Distribution auszuführen, oder einei386
Binärdatei zu erstellen und auf einer anderen Distributioni386
auszuführen.Ergänzend zu den hervorragenden Antworten von @thrig und @DopeGhoti: Unix oder Unix-ähnliche Betriebssysteme, einschließlich Linux, wurden traditionell eher für die Portierbarkeit von Quellcode als für Binärdateien entwickelt und ausgerichtet.
Wenn Sie keine bestimmte Hardware haben oder eine einfache Quelle wie in Ihrem Beispiel sind, können Sie diese problemlos zwischen nahezu jeder Linux- oder Architekturversion als Quellcode verschieben, sofern auf den Zielservern die C-Entwicklungspakete installiert sind. die erforderlichen Bibliotheken und die entsprechenden installierten Entwicklungsbibliotheken.
Wenn Sie fortgeschritteneren Code aus älteren Linux-Versionen oder spezifischere Programme wie Kernelmodule für verschiedene Kernelversionen portieren möchten, müssen Sie möglicherweise den Quellcode anpassen und ändern, um veraltete Bibliotheken / APIs / ABIs zu berücksichtigen.
quelle
Mit dem Standard werden Sie mit ziemlicher Sicherheit Probleme mit externen Bibliotheken laufen. Einige der anderen Antworten gehen näher auf diese Probleme ein, sodass ich ihre Arbeit nicht duplizieren werde.
Sie können jedoch viele - auch nicht triviale - Programme kompilieren, um sie zwischen Linux-Systemen zu portieren. Der Schlüssel ist das als Linux Standard Base bezeichnete Toolkit . Das LSB ist für die Erstellung genau dieser Arten von tragbaren Anwendungen ausgelegt. Kompilieren Sie eine Anwendung für LSB v5.0, und sie kann in jeder anderen Linux-Umgebung (mit derselben Architektur) ausgeführt werden, in der LSB v5.0 implementiert ist. Einige Linux-Distributionen sind LSB-kompatibel, andere enthalten LSB-Toolkits / -Bibliotheken als installierbares Paket. Wenn Sie Ihre Anwendung mit den LSB-Tools (wie dem
lsbcc
Wrapper fürgcc
) erstellen und eine Verknüpfung zur LSB-Version der Bibliotheken herstellen, erstellen Sie eine portable Anwendung.quelle
qemu
Sie sogar Programme ausführen, die für verschiedene Architekturen kompiliert wurden (keine hohe Leistung, aber Sie können sie ausführen)apt-get install
ein paar Pakete.Vielleicht.
Dinge, die dazu neigen, es zu brechen, gehören.
Wenn Sie es vermeiden, sich schnell ändernde Bibliotheken zu verwenden, vermeiden Sie Änderungen der Architektur und bauen Sie auf der ältesten Distribution auf, auf die Sie abzielen möchten. Sie haben gute Chancen, dass eine Binärdatei auf vielen Distributionen funktioniert.
quelle
Zusätzlich zu einigen der zuvor erwähnten Dinge gab es einige Änderungen im ausführbaren Dateiformat. In den meisten Fällen verwendet Linux ELF, in älteren Versionen jedoch a.out oder COFF.
Der Beginn eines Wikilochs:
https://en.wikipedia.org/wiki/Comparison_of_executable_file_formats
Es könnte eine Möglichkeit geben, ältere Versionen dazu zu bringen, neuere Formate auszuführen, aber ich persönlich habe mich noch nie damit befasst.
quelle