Fett binär - Fat binary

Ein Fat Binary (oder Multiarchitecture Binary ) ist ein computerausführbares Programm oder eine Bibliothek, die mit Code erweitert (oder "gefettet") wurde, der für mehrere Befehlssätze nativ ist und die folglich auf mehreren Prozessortypen ausgeführt werden können. Dies führt zu einer Datei, die größer ist als eine normale Binärdatei mit einer Architektur, daher der Name.

Die übliche Implementierungsmethode besteht darin, für jeden Befehlssatz eine Version des Maschinencodes einzufügen , der ein einzelner Einstiegspunkt mit Code vorangeht , der mit allen Betriebssystemen kompatibel ist, der einen Sprung zum entsprechenden Abschnitt ausführt. Alternative Implementierungen speichern verschiedene ausführbare Dateien in verschiedenen Forks , jede mit ihrem eigenen Einstiegspunkt, der direkt vom Betriebssystem verwendet wird.

Die Verwendung von Fat Binaries ist in Betriebssystemsoftware nicht üblich ; gibt es mehrere Alternativen , um das gleiche Problem, wie die Verwendung eines zu lösen Installer - Programm bei der Installation (zB mit einer Architektur-spezifischen binären wählen Android mehrere APKs), eine Architektur-spezifische binäre zur Laufzeit (wie bei der Auswahl - Plan 9's Union-Verzeichnisse und GNUsteps Fat Bundles), das Verteilen von Software in Quellcodeform und deren direkte Kompilierung oder die Verwendung einer virtuellen Maschine (wie bei Java ) und die Just-In-Time-Kompilierung .

Apollo

Die zusammengesetzten ausführbaren Dateien von Apollo

Im Jahr 1988, Apollo Computer ‚s Domain / OS eingeführt SR10.1 einen neuen Dateityp "cmpexe"(Verbindung ausführbar), dass Binärdateien für gebündelte Motorola 680x0 und Apollo PRISM ausführbare Dateien.

Apfel

Apples fette Binärdatei

Ein Fat-Binary-Schema glättete den Übergang des Apple Macintosh , beginnend im Jahr 1994, von 68k- Mikroprozessoren zu PowerPC- Mikroprozessoren. Viele Anwendungen für die alte Plattform liefen auf der neuen Plattform unter einem sich weiterentwickelnden Emulationsschema transparent , aber emulierter Code läuft im Allgemeinen langsamer als nativer Code. Anwendungen, die als "fette Binärdateien" veröffentlicht wurden, benötigten mehr Speicherplatz, liefen jedoch auf beiden Plattformen mit voller Geschwindigkeit. Dies wurde erreicht, indem sowohl eine 68000- kompilierte Version als auch eine PowerPC-kompilierte Version desselben Programms in ihre ausführbaren Dateien gepackt wurden. Der ältere 68K-Code (CFM-68K oder klassischer 68K) wurde weiterhin im Resource Fork gespeichert , während der neuere PowerPC-Code im Data Fork im PEF- Format enthalten war.

Fat Binaries waren größer als Programme, die nur PowerPC oder 68k unterstützten, was zur Entwicklung einer Reihe von Dienstprogrammen führte, die die nicht benötigte Version entfernen würden. In der Ära der kleinen Festplatten , als 80-MB-Festplatten eine übliche Größe waren, waren diese Dienstprogramme manchmal nützlich, da der Programmcode im Allgemeinen einen großen Prozentsatz der gesamten Laufwerksnutzung ausmachte und das Entfernen der nicht benötigten Mitglieder einer fetten Binärdatei frei werden würde viel Speicherplatz auf einer Festplatte.

Die Multi-Architektur-Binärdateien von NeXT/Apple

NeXTSTEP Multi-Architektur-Binärdateien

Fat Binaries waren ein Merkmal von NeXT ‚s Nextstep / OPENSTEP - Betriebssystem, beginnend mit Nextstep 3.1. In NeXTSTEP hießen sie "Multi-Architecture Binaries". Multi-Architektur-Binärdateien waren ursprünglich dazu gedacht, die Kompilierung von Software zu ermöglichen, um sowohl auf NeXTs Motorola 68k-basierter Hardware als auch auf Intel IA-32- basierten PCs mit NeXTSTEP mit einer einzigen Binärdatei für beide Plattformen zu laufen. Es wurde später verwendet, um die Ausführung von OPENSTEP-Anwendungen auf PCs und den verschiedenen von OPENSTEP unterstützten RISC- Plattformen zu ermöglichen. Multi-Architektur-Binärdateien haben ein spezielles Archivformat, in dem eine einzelne Datei eine oder mehrere Mach-O- Unterdateien für jede Architektur speichert, die von der Multi-Architektur-Binärdatei unterstützt wird. Jede Multi-Architecture Binary beginnt mit einer Struktur (struct fat_header), die zwei vorzeichenlose Ganzzahlen enthält. Die erste ganze Zahl ("magic") wird als magische Zahl verwendet , um diese Datei als Fat Binary zu identifizieren. Die zweite Ganzzahl ("nfat_arch") definiert, wie viele Mach-O-Dateien das Archiv enthält (wie viele Instanzen desselben Programms für verschiedene Architekturen). Nach diesem Header gibt es nfat_arch Anzahl der fat_arch Strukturen (struct fat_arch). Diese Struktur definiert den Offset (vom Dateianfang), an dem die Datei zu finden ist, das Alignment, die Größe und den CPU-Typ und -Subtyp, auf den die Mach-O-Binärdatei (innerhalb des Archivs) ausgerichtet ist.

Die Version der GNU Compiler Collection ausgeliefert mit den Developer Tools konnte Quer Kompilierung Quellcode für die verschiedenen Architekturen , auf denen Nextstep der Lage war , zu laufen. Beispielsweise war es möglich, die Zielarchitekturen mit mehreren '-arch'-Optionen (mit der Architektur als Argument) auszuwählen. Dies war eine bequeme Möglichkeit, ein Programm für NeXTStep zu verteilen, das auf verschiedenen Architekturen läuft.

Es war auch möglich, Bibliotheken (zB mit libtool) mit verschiedenen Zielobjektdateien zu erstellen.

Mach-O und Mac OS X

1996 erwarb Apple Computer NeXT und arbeitete weiter mit dem OPENSTEP-Code. Mach-O wurde das native Objektdateiformat in Apples kostenlosem Darwin-Betriebssystem (2000) und Apples Mac OS X (2001), und die Multi-Architektur-Binärdateien von NeXT wurden weiterhin vom Betriebssystem unterstützt. Unter Mac OS X können Multi-Architecture Binaries verwendet werden, um mehrere Varianten einer Architektur zu unterstützen, beispielsweise um verschiedene Versionen von 32-Bit- Code zu haben, die für die Prozessorgenerationen PowerPC G3 , PowerPC G4 und PowerPC 970 optimiert sind . Es kann auch verwendet werden, um mehrere Architekturen wie 32-Bit- und 64-Bit- PowerPC oder PowerPC und x86 oder x86-64 und ARM64 zu unterstützen .

Apples Universal Binary

Apple Universal Binary - Logo

2005 kündigte Apple einen weiteren Übergang von PowerPC-Prozessoren zu Intel x86-Prozessoren an . Apple förderte die Verbreitung neuer Anwendungen, die sowohl PowerPC als auch x86 nativ unterstützen, indem ausführbare Dateien im Multi-Architecture Binary-Format verwendet wurden. Apple nennt solche Programme " Universal Applications " und nennt das Dateiformat " Universal Binary ", um vielleicht diesen neuen Übergang vom vorherigen Übergang oder anderen Verwendungen des Multi-Architecture Binary-Formats zu unterscheiden.

Für die Vorwärtsmigration bereits vorhandener nativer PowerPC-Anwendungen war kein universelles Binärformat erforderlich; von 2006 bis 2011 lieferte Apple Rosetta , einen dynamischen PowerPC (PPC)-to-x86- Binärübersetzer , um diese Rolle zu übernehmen. Rosetta hatte jedoch einen ziemlich hohen Performance-Overhead, daher wurden Entwickler ermutigt, sowohl PPC- als auch Intel-Binärdateien mit Universal-Binärdateien anzubieten. Der offensichtliche Preis von Universal Binary besteht darin, dass jede installierte ausführbare Datei größer ist, aber in den Jahren seit der Veröffentlichung der PPC hat der Festplattenspeicher die ausführbare Größe bei weitem übertroffen; Während eine Universal-Binärdatei doppelt so groß sein kann wie eine Einzelplattformversion derselben Anwendung, verkleinern die Ressourcen des freien Speicherplatzes im Allgemeinen die Codegröße, was zu einem kleinen Problem wird. Tatsächlich ist eine Universal-Binäranwendung oft kleiner als zwei Anwendungen mit einer einzelnen Architektur, da Programmressourcen gemeinsam genutzt und nicht dupliziert werden können. Wenn nicht alle Architekturen erforderlich sind, können die Befehlszeilenanwendungen lipo und ditto verwendet werden, um Versionen aus dem Multi-Architecture Binary-Image zu entfernen, wodurch eine sogenannte Thin Binary erstellt wird .

Darüber hinaus können ausführbare Multi-Architecture-Binärdateien Code für 32-Bit- und 64-Bit-Versionen von PowerPC und x86 enthalten, sodass Anwendungen in einer Form ausgeliefert werden können, die 32-Bit-Prozessoren unterstützt, aber den größeren Adressraum nutzt und breitere Datenpfade bei Ausführung auf 64-Bit-Prozessoren.

In Versionen der Xcode- Entwicklungsumgebung von 2.1 bis 3.2 (die auf Mac OS X 10.4 bis Mac OS X 10.6 ) laufen , hat Apple Dienstprogramme hinzugefügt, die es ermöglichten, Anwendungen sowohl für die Intel- als auch für die PowerPC-Architektur zu verwenden; universelle Binärdateien könnten schließlich bis zu vier Versionen des ausführbaren Codes enthalten (32-Bit-PowerPC, 32-Bit-x86, 64-Bit-PowerPC und 64-Bit-x86 ). Die PowerPC-Unterstützung wurde jedoch aus Xcode 4.0 entfernt und steht daher Entwicklern mit Mac OS X 10.7 oder höher nicht zur Verfügung .

Im Jahr 2020 kündigte Apple einen weiteren Übergang an, diesmal von Intel x86-Prozessoren auf Apple-Silizium . Um den Übergang zu erleichtern, hat Apple Unterstützung für das Binärformat Universal 2 hinzugefügt . Dies ermöglicht die Erstellung von Binärdateien, die nativ sowohl auf 64-Bit-Intel- als auch auf 64-Bit-Apple-Silizium (eine AArch64- Variante) ausgeführt werden. Darüber hinaus führte Apple die dynamische Binärübersetzung von Rosetta 2 für den Befehlssatz von x86 in Arm64 ein, damit Benutzer Anwendungen ausführen können, die keine universellen Binärvarianten haben.

CP/M und DOS

Kombinierte Binärdateien im COM-Stil für CP/M-80 und DOS

CP/M-80 , MP/M-80 , Concurrent CP/M , CP/M Plus und Personal CP/M-80 ausführbare Dateien für die Intel 8080 (und Z80 ) Prozessorfamilien verwenden dieselbe .COM- Dateierweiterung wie DOS- kompatibel Betriebssysteme für Intel 8086- Binärdateien. In beiden Fällen werden Programme mit Offset +100h geladen und durch Sprung auf das erste Byte in der Datei ausgeführt. Da die Opcodes der beiden Prozessorfamilien nicht kompatibel sind, führt der Versuch, ein Programm unter dem falschen Betriebssystem zu starten, zu falschem und unvorhersehbarem Verhalten.

Um dies zu vermeiden, wurden einige Methoden entwickelt, um fette Binärdateien zu erstellen, die sowohl ein CP/M-80- als auch ein DOS-Programm enthalten, denen ein anfänglicher Code vorangeht, der auf beiden Plattformen korrekt interpretiert wird. Die Methoden kombinieren entweder zwei voll funktionsfähige Programme, die jeweils für ihre entsprechende Umgebung erstellt wurden, oder fügen Stubs hinzu, die bewirken, dass das Programm ordnungsgemäß beendet wird, wenn es auf dem falschen Prozessor gestartet wird. Damit dies funktioniert, müssen die ersten Anweisungen in der .COM-Datei gültiger Code für 8086- und 8080-Prozessoren sein, was dazu führen würde, dass die Prozessoren an verschiedene Stellen innerhalb des Codes verzweigen. Zum Beispiel beginnen die Dienstprogramme in Simeon Crans Emulator MyZ80 mit der Opcode-Sequenz EBh, 52h, EBh . Ein 8086 sieht dies als Sprung und liest seinen nächsten Befehl von Offset +154h, während ein 8080 oder kompatibler Prozessor direkt durchgeht und seinen nächsten Befehl von +103h liest. Eine ähnliche Sequenz, die für diesen Zweck verwendet wird , ist EBh, 03h, C3h .

Eine andere Methode, um zu verhindern, dass ein DOS-kompatibles Betriebssystem fälschlicherweise .COM-Programme für CP/M-80- und MSX-DOS- Rechner ausführt, besteht darin , den 8080-Code mit C3h, 03h, 01h zu starten , der als "RET" -Befehl dekodiert wird x86-Prozessoren, wodurch das Programm anmutig beendet wird, während es von 8080-Prozessoren als "JP 103h"-Befehl decodiert wird und einfach zum nächsten Befehl im Programm springen.

Einige CP/M-80 3.0 .COM-Dateien können von GENCOM mit einem oder mehreren RSX- Overlays versehen sein. Wenn dies der Fall ist, beginnen sie mit einem zusätzlichen 256-Byte- Header (eine Seite ). Um dies anzuzeigen, wird das erste Byte im Header auf das magische Byte C9h gesetzt , das sowohl als Signatur zur Identifizierung dieser Art von COM-Datei für den ausführbaren CP/M 3.0- Lader als auch als "RET"-Anweisung für 8080 . dient -kompatible Prozessoren, die zu einem ordnungsgemäßen Beenden führen, wenn die Datei unter älteren Versionen von CP/M-80 ausgeführt wird.

C9h ist niemals als erstes Byte eines Programms für einen x86-Prozessor geeignet (es hat für verschiedene Generationen unterschiedliche Bedeutungen, ist aber nie ein sinnvolles erstes Byte); der ausführbare Lader in einigen DOS-Versionen lehnt COM-Dateien ab, die mit C9h beginnen , und verhindert so eine fehlerhafte Operation.

Kombinierte Binärdateien für CP/M-86 und DOS

CP/M-86 und DOS haben keine gemeinsame Dateierweiterung für ausführbare Dateien. Daher ist es normalerweise nicht möglich, ausführbare Dateien zu verwechseln. Allerdings hatten frühe DOS-Versionen in Bezug auf die Architektur so viel mit CP/M gemeinsam, dass einige frühe DOS-Programme entwickelt wurden, um Binärdateien mit ausführbarem Code gemeinsam zu nutzen. Ein dafür bekanntes Programm war WordStar 3.2x , das identische Overlay-Dateien in ihren Ports für CP/M-86 und MS-DOS verwendet und dynamisch korrigierten Code verwendet, um sich zur Laufzeit an die unterschiedlichen Aufrufkonventionen dieser Betriebssysteme anzupassen .

Digital Research ‚s GSX für CP / M-86 und DOS teilt auch binäre identische 16-Bit - Treiber.

Kombinierte COM- und SYS-Dateien

DOS- Gerätetreiber beginnen mit einem Dateiheader , dessen erste vier Byte laut Konvention FFFFFFFFh sind , obwohl dies nicht erforderlich ist. Dies ist fest auf dynamisch durch das Betriebssystem , wenn der Fahrer Lasten (typischerweise im DOS - BIOS , wenn es ausführt GERÄTE Anweisungen in CONFIG.SYS ). Da DOS Dateien mit einer .COM-Endung, die pro DEVICE zu laden sind, nicht ablehnt und nicht auf FFFFFFFFh testet, ist es möglich, ein COM-Programm und einen Gerätetreiber in derselben Datei zu kombinieren, indem eine Sprunganweisung an den Einstiegspunkt des eingebettetes COM-Programm innerhalb der ersten vier Byte der Datei (drei Byte sind normalerweise ausreichend). Wenn das eingebettete Programm und die Gerätetreiber-Abschnitte einen gemeinsamen Code- oder Datenteil gemeinsam nutzen, muss der Code mit dem Laden bei Offset +0100h als Programm im .COM-Stil und bei +0000h als Gerätetreiber umgehen. Für gemeinsam genutzten Code, der am "falschen" Offset geladen wird, aber nicht als positionsunabhängig konzipiert ist , erfordert dies eine interne Adresskorrektur ähnlich der, die sonst bereits von einem sich verlagernden Loader durchgeführt worden wäre , außer dass in diesem Fall dies durch das geladene Programm selbst zu erledigen; Dies ist ähnlich der Situation bei selbstverlagernden Treibern , wobei das Programm jedoch bereits vom Lader des Betriebssystems am Zielort geladen wurde.

Absturzgeschützte Systemdateien

Unter DOS haben einige Dateien per Konvention Dateierweiterungen, die nicht ihren tatsächlichen Dateityp widerspiegeln. Zum Beispiel COUNTRY.SYS ist keine DOS - Gerätetreiber, sondern eine binäre NLS - Datenbank - Datei für die Verwendung mit der CONFIG.SYS COUNTRY Richtlinie und dem NLSFUNC Fahrer. Die PC-DOS- und DR-DOS-Systemdateien IBMBIO.COM und IBMDOS.COM sind spezielle Binärbilder, keine Programme im COM-Stil. Der Versuch, COUNTRY.SYS mit einer DEVICE-Anweisung zu laden oder IBMBIO.COM oder IBMDOS.COM an der Eingabeaufforderung auszuführen, führt zu unvorhersehbaren Ergebnissen.

Es ist manchmal möglich, dies zu vermeiden, indem Techniken verwendet werden, die den oben beschriebenen ähnlich sind. Beispielsweise enthalten DR-DOS 7.02 und höher eine von Matthias R. Paul entwickelte Sicherheitsfunktion: Wenn diese Dateien unangemessen aufgerufen werden, zeigen winzige eingebettete Stubs nur einige Dateiversionsinformationen an und werden ordnungsgemäß beendet.

Eine ähnliche Schutzfunktion war die 8080-Anweisung C7h ("RST 0") ganz am Anfang von Z-System- Sprachüberlagerungsdateien, die unter CP/M-80 bei unsachgemäßem Laden zu einem Warmstart (statt einem Absturz) führen würde.

In ähnlicher Weise enthalten viele (binäre) Dateiformate laut Konvention ein 1Ah- Byte ( ASCII ^Z ) am Anfang der Datei. Dieses Steuerzeichen wird beim Öffnen einer Datei im nicht-binären Modus als "weicher" End-of-File (EOF)-Marker interpretiert und somit unter vielen Betriebssystemen (einschließlich RT-11 , VMS , CP/M, DOS , und Windows), verhindert es, dass "binärer Müll" angezeigt wird, wenn eine Datei versehentlich an der Konsole eingegeben wird.

Linux

FatELF: Universelle Binärdateien für Linux

FatELF- Logo

FatELF ist eine fette Binärimplementierung für Linux und andere Unix-ähnliche Betriebssysteme. Technisch gesehen ist eine FatELF-Binärdatei eine Verkettung von ELF- Binärdateien mit einigen Metadaten, die angeben, welche Binärdatei auf welcher Architektur verwendet werden soll. Zusätzlich zur Abstraktion der CPU-Architektur ( Bytereihenfolge , Wortgröße , CPU- Befehlssatz usw.) gibt es den Vorteil von Binärdateien mit Unterstützung für mehrere Kernel- ABIs und -versionen.

FatELF hat laut Entwicklern mehrere Anwendungsfälle:

  • Distributionen müssen nicht mehr separate Downloads für verschiedene Plattformen haben.
  • Getrennte /lib- , /lib32- und /lib64- Bäume werden in der OS-Verzeichnisstruktur nicht mehr benötigt .
  • Die richtigen Binärdateien und Bibliotheken werden zentral vom System anstelle von Shell-Skripten ausgewählt .
  • Wenn sich die ELF ABI eines Tages ändert, können ältere Benutzer weiterhin unterstützt werden.
  • Verteilung von Webbrowser-Plug-Ins, die sofort mit mehreren Plattformen funktionieren.
  • Verteilung einer Anwendungsdatei, die über Linux- und BSD- Betriebssystemvarianten hinweg funktioniert , ohne eine Plattform-Kompatibilitätsschicht darauf.
  • Eine Festplattenpartition kann zu Entwicklungs- und Experimentierzwecken auf verschiedenen Maschinen mit unterschiedlichen CPU-Architekturen gebootet werden. Gleiches Root-Dateisystem, unterschiedliche Kernel- und CPU-Architektur.
  • Anwendungen, die von Netzwerkfreigaben oder USB-Sticks bereitgestellt werden, funktionieren auf mehreren Systemen. Dies ist auch hilfreich, um portable Anwendungen und auch Cloud-Computing- Images für heterogene Systeme zu erstellen.

Ein Proof-of-Concept- Image für Ubuntu 9.04 ist verfügbar. Ab dem 25. April 2020 ist FatELF nicht in den Mainline-Linux-Kernel integriert.

Fenster

Fettpackung

Obwohl das von Windows verwendete Portable Executable- Format das Zuweisen von Code zu Plattformen nicht zulässt, ist es dennoch möglich, ein Ladeprogramm zu erstellen, das basierend auf der Architektur verteilt. Dies liegt daran, dass Desktop-Versionen von Windows auf ARM die 32-Bit- x86- Emulation unterstützen, was sie zu einem nützlichen "universellen" Maschinencode-Ziel macht. Fatpack ist ein Loader, der das Konzept demonstriert: Es enthält ein 32-Bit-x86-Programm, das versucht, die in seine Ressourcenabschnitte gepackten ausführbaren Dateien nacheinander auszuführen.

Ähnliche Konzepte

Die folgenden Ansätze ähneln Fat Binaries darin, dass mehrere Versionen von Maschinencode mit demselben Zweck in derselben Datei bereitgestellt werden.

Fette Gegenstände

GCC und LLVM haben kein fettes Binärformat, aber sie haben fette Objektdateien für die Link-Time-Optimierung (LTO). Da bei LTO die Kompilierung auf die Verbindungszeit verzögert wird, müssen die Objektdateien die Zwischendarstellung (IR) speichern , aber andererseits muss möglicherweise auch Maschinencode gespeichert werden (aus Gründen der Geschwindigkeit oder Kompatibilität). Ein LTO-Objekt, das sowohl IR- als auch Maschinencode enthält, wird als Fat Object bezeichnet .

Funktion Multiversionierung

Sogar in einem Programm oder einer Bibliothek, die für dieselbe Befehlssatzarchitektur bestimmt ist , möchte ein Programmierer möglicherweise einige neuere Befehlssatzerweiterungen verwenden, während er die Kompatibilität mit einer älteren CPU behält. Dies kann mit Function Multi-Versioning (FMV) erreicht werden: Versionen derselben Funktion werden in das Programm geschrieben, und ein Codeabschnitt entscheidet, welcher verwendet wird, indem er die Fähigkeiten der CPU erkennt (z. B. durch CPUID ). Intel C++ Compiler , GNU Compiler Collection und LLVM haben alle die Fähigkeit, Funktionen mit mehreren Versionen automatisch zu generieren. Dies ist eine Form des dynamischen Versands ohne semantische Auswirkungen.

Viele mathematische Bibliotheken verfügen über handgeschriebene Assemblierungsroutinen, die automatisch entsprechend der CPU-Fähigkeit ausgewählt werden. Beispiele sind glibc , Intel MKL und OpenBLAS . Darüber hinaus unterstützt der Bibliothekslader in glibc das Laden von alternativen Pfaden für bestimmte CPU-Funktionen.

Ein ähnlicher, aber granularer Ansatz auf Byte-Ebene, der ursprünglich von Matthias R. Paul und Axel C. Frinke entwickelt wurde, besteht darin, einen kleinen selbstverwerfenden, entspannenden und verlagernden Loader in die ausführbare Datei eingebettet zusammen mit einer beliebigen Anzahl alternativer Binärcode-Schnipsel bedingt erstellen zu lassen ein größen- oder geschwindigkeitsoptimiertes Laufzeitabbild eines Programms oder Treibers, das erforderlich ist, um eine bestimmte Funktion in einer bestimmten Zielumgebung zur Ladezeit durch eine Form der dynamischen Totcode- Elimination (DDCE) auszuführen (oder nicht auszuführen ).

Siehe auch

Anmerkungen

Verweise

Weiterlesen