Die Veröffentlichung des Projekts Cosmopolitan 2.0 wurde herausgegeben, das eine standardisierte C-Bibliothek und ein universelles Format für ausführbare Dateien entwickelt, das zur Verbreitung von Software für verschiedene Betriebssysteme ohne Interpreter und virtuelle Maschinen verwendet werden kann. Das mit GCC und Clang kompilierte Ergebnis wird in eine statisch bindbare, universelle ausführbare Datei integriert, die auf jedem Linux-Distribution, macOS, Windows, FreeBSD, OpenBSD, NetBSD und sogar über das BIOS aufgerufen werden kann. Der Quellcode des Projekts steht unter der ISC-Lizenz (eine vereinfachte Version von MIT/BSD).
Der Container zur Erstellung universeller ausführbarer Dateien basiert auf der Kombination von betriebssystemspezifischen Segmenten und Headern (PE, ELF, MACHO, OPENBSD) in einer einzigen Datei und kombiniert mehrere verschiedene Formate, die in Unix, Windows und macOS verwendet werden. Um die Ausführung einer ausführbaren Datei sowohl unter Windows als auch unter Unix-Systemen zu ermöglichen, wird ein Trick verwendet, der das Codieren von Windows PE-Dateien in ein Shell-Skript beinhaltet, wobei zu beachten ist, dass die Thompson Shell das Skriptmarker «#!» nicht verwendet. Für die Erstellung von Programmen, die mehrere Dateien enthalten (Kombination aller Ressourcen in einer Datei), wird die Erstellung einer ausführbaren Datei in Form eines speziell gestalteten ZIP-Archivs unterstützt. Das Schema des vorgeschlagenen Formats (Beispielanwendung hello.com):
MZqFpD=’ BIOS BOOT SECTOR’ exec 7 $(command -v $0) printf ‘\177ELF…LINKER-ENCODED-FREEBSD-HEADER’ >&7 exec "$0" "$@" exec qemu-x86_64 "$0" "$@" exit 1 REAL MODE… ELF SEGMENTS… OPENBSD NOTE… MACHO HEADERS… CODE AND DATA… ZIP DIRECTORY…
Zunächst wird im Dateiheader das Label „MZqFpD“ angegeben, das als Kopfzeile für das Windows PE-Format interpretiert wird. Diese Sequenz wird ebenfalls in den Anweisungen „pop %r10 ; jno 0x4a ; jo 0x4a“ decodiert, während die Zeile „\177ELF“ in der Anweisung „jg 0x47“ verwendet wird, um auf den Einstiegspunkt zuzugreifen. In Unix-Systemen wird Shell-Code ausgeführt, der den exec-Befehl nutzt, um den ausführbaren Code über eine unbenannte Pipe zu übergeben. Eine Einschränkung der vorgeschlagenen Methode besteht darin, dass sie in Unix-ähnlichen Betriebssystemen nur mit Shells ausgeführt werden kann, die den Kompatibilitätsmodus mit der Thompson-Shell unterstützen.
Der Aufruf von qemu-x86_64 ist vorgesehen, um zusätzliche Portabilität zu gewährleisten und ermöglicht die Ausführung von für die Architektur x86_64 kompiliertem Code auf Plattformen, die sich von x86 unterscheiden, wie z. B. Raspberry Pi-Boards und Apple-Geräte mit ARM-Prozessoren. Das Projekt kann auch zur Erstellung selbsttragender Anwendungen verwendet werden, die ohne Betriebssystem (bare metal) laufen. In solchen Anwendungen wird dem ausführbaren Datei ein Bootloader angehängt, während das Programm als bootfähiges Betriebssystem fungiert.
In der entwickelten Standard-C-Bibliothek libc bietet das Projekt 2024 Funktionen an (bei der ersten Version waren es etwa 1400 Funktionen). In Bezug auf die Leistung arbeitet Cosmopolitan genauso schnell wie glibc und übertrifft Musl und Newlib deutlich, während der Codeumfang von Cosmopolitan um den Faktor 10 kleiner ist als der von glibc und etwa dem von Musl und Newlib entspricht. Um häufig aufgerufene Funktionen wie memcpy und strlen zu optimieren, wird zusätzlich die Technik der „trickle-down performance“ eingesetzt, bei der ein Makro-Wrapper für den Funktionsaufruf verwendet wird. Der Compiler wird dabei über die verwendeten CPU-Register informiert, was Ressourcen spart, indem nur die veränderten Register zum Speichern des CPU-Zustands gesichert werden.
Zu den Änderungen in der neuen Version gehören:
- Das Schema für den Zugriff auf interne Ressourcen innerhalb von ZIP-Dateien wurde geändert (beim Öffnen von Dateien werden nun normale Pfade /zip/… anstelle des Zugriffs über das Präfix zip:.. verwendet). Ähnlich wurde für den Zugriff auf Laufwerke in Windows die Möglichkeit geschaffen, Pfade wie „/c/…“ anstelle von „C:/…“ zu verwenden.
- Ein neuer APE-Loader (Actually Portable Executable) wurde vorgestellt, der das Format universeller ausführbarer Dateien definiert. Der neue Loader verwendet mmap, um das Programm im Speicher zu platzieren, und ändert den Inhalt nicht mehr zur Laufzeit. Bei Bedarf kann die universelle ausführbare Datei in herkömmliche ausführbare Dateien umgewandelt werden, die an bestimmte Plattformen gebunden sind.
- Auf der Linux-Plattform wurde die Nutzung des Kernel-Moduls binfmt_misc zur Ausführung von APE-Programmen implementiert. Es wird festgestellt, dass die Verwendung von binfmt_misc die schnellste Methode zur Ausführung ist.
- Für Linux wurde die Funktionalität der Systemaufrufe pledge() und unveil(), die im OpenBSD-Projekt entwickelt werden, angeboten. Eine API zur Nutzung dieser Aufrufe in Programmen in den Programmiersprachen C, C++, Python und Redbean sowie ein Tool pledge.com zur Isolation beliebiger Prozesse wird bereitgestellt.
- Für den Build-Prozess wird das Landlock Make-Tool verwendet – eine Version von GNU Make mit strengerer Abhängigkeitserkennung und dem Systemaufruf Landlock zur Isolation des Programms vom Rest des Systems und zur Verbesserung der Cache-Effizienz. Die Möglichkeit, mit herkömmlichem GNU Make zu bauen, bleibt als Option erhalten.
- Die Funktionen für Multithreading wurden implementiert — _spawn() und _join(), die universelle Wrapper über die plattformabhängigen APIs darstellen. Zudem arbeiten wir an der Implementierung der Unterstützung für POSIX-Threads.
- Es besteht die Möglichkeit, das Schlüsselwort _Thread_local zu verwenden, um thread-spezifische Speicher (TLS, Thread-Local Storage) zu nutzen. Standardmäßig initialisiert die C-Laufzeitumgebung TLS für den Hauptthread, was die minimale Größe der ausführbaren Datei von 12 auf 16 KB erhöht hat.
- Es wurde Unterstützung für die Parameter „—ftrace“ und „—strace“ in die ausführbaren Dateien integriert, um im stderr Informationen über alle Funktionsaufrufe und Systemaufrufe auszugeben.
- Die Unterstützung für den Systemaufruf closefrom() wurde hinzugefügt, der in Linux 5.9+, FreeBSD 8+ und OpenBSD verfügbar ist.
- Auf der Linux-Plattform wurde die Leistung von clock_gettime- und gettimeofday-Aufrufen um bis zu das Zehnfache verbessert, indem der Mechanismus vDSO (virtual dynamic shared object) verwendet wird, der es ermöglicht, den Systemaufruf-Handler in den Benutzerspeicher zu verlagern und Kontextwechsel zu vermeiden.
- Mathematische Funktionen für die Arbeit mit komplexen Zahlen wurden aus der Musl-Bibliothek übertragen. Viele mathematische Funktionen wurden beschleunigt.
- Die Funktion nointernet() wurde eingeführt, um die Netzwerkfähigkeiten zu deaktivieren.
- Neue Funktionen für das effiziente Anfügen von Strings wurden hinzugefügt: appendd, appendf, appendr, appends, appendw, appendz, kappendf, kvappendf und vappendf.
- Eine sichere Variante der kprintf()-Funktionsfamilie wurde hinzugefügt, die für die Ausführung mit erhöhten Rechten konzipiert ist.
- Die Leistung der Implementierungen wurde erheblich gesteigert SSL, SHA, curve25519 und RSA.
Quelle: opennet.ru
