Projekt Cosmopolitan 2.0, który rozwija standardową bibliotekę C i uniwersalny format pliku wykonywalnego, umożliwiający dystrybucję programów w różnych systemach operacyjnych bez konieczności używania interpreterów ani maszyn wirtualnych, został uruchomiony. Kompilacja za pomocą GCC i Clanga skutkuje statycznie linkowanym, uniwersalnym plikiem wykonywalnym, który można uruchomić w dowolnej dystrybucji. Linux, macOS, Windows, FreeBSD, OpenBSD, NetBSD, a nawet dostęp do BIOS-u. Kod projektu jest rozpowszechniany na licencji ISC (uproszczonej wersji licencji MIT/BSD).
Kontener do tworzenia uniwersalnych plików wykonywalnych opiera się na łączeniu segmentów i nagłówków (PE, ELF, MACHO, OPENBSD) specyficznych dla różnych systemów operacyjnych w jednym pliku, łącząc kilka różnych formatów używanych w systemie Unix, Windows и macOSAby zapewnić możliwość uruchomienia jednego pliku wykonywalnego Windows a systemy Unix wykorzystują sztuczkę związaną z kodowaniem plików Windows PE jako skrypt powłoki, wykorzystujący brak znacznika skryptu „#!” w Thompson Shell. Aby tworzyć programy zawierające wiele plików (łącząc wszystkie zasoby w jeden plik), plik wykonywalny można utworzyć jako specjalnie sformatowane archiwum ZIP. Proponowany format (przykład: aplikacja hello.com):
MZqFpD=' SEKTOR ROZRUCHOWY BIOS-u' exec 7 $(command -v $0) printf '\177ELF...LINKER-ENCODED-FREEBSD-HEADER' >&7 exec "$0" "$@" exec qemu-x86_64 "$0" "$@" exit 1 TRYB RZECZYWISTY... SEGMENTY ELF... UWAGA DO OPENBSD... NAGŁÓWKI MACHO... KOD I DANE... KATALOG ZIP...
Na początku pliku znajduje się etykieta „MZqFpD”, która jest postrzegana jako nagłówek formatu Windows PE. Ta sekwencja jest również dekodowana do instrukcji „pop %r10 ; jno 0x4a ; jo 0x4a” oraz ciągu „\177ELF” do instrukcji „jg 0x47”, które służą do przekierowania do punktu wejścia. W systemach Unix kod powłoki jest wykonywany za pomocą polecenia exec, przekazując kod wykonywalny przez nienazwany potok. Ograniczeniem proponowanej metody jest to, że można ją uruchomić tylko w systemach operacyjnych typu Unix, korzystających z powłok obsługujących tryb zgodności z powłoką Thompson.
Wywołanie qemu-x86_64 ma na celu zapewnienie dodatkowej przenośności i pozwala na uruchamianie skompilowanego kodu x86_64 na platformach innych niż x86, takich jak płyty Raspberry Pi i urządzenia Apple z procesorami ARM. Projekt można również wykorzystać do tworzenia samodzielnych aplikacji, które działają bez systemu operacyjnego (tzw. bare metal). W takich aplikacjach do pliku wykonywalnego dołączany jest program ładujący, a program pełni funkcję rozruchowego systemu operacyjnego.
Standardowa biblioteka języka C libc opracowana w ramach projektu oferuje 2024 funkcje (pierwsza wersja zawierała około 1400 funkcji). Jeśli chodzi o wydajność, Cosmopolitan działa równie szybko co glibc i wyraźnie wyprzedza Musl i Newlib, mimo że Cosmopolitan ma o rząd wielkości mniejszy rozmiar kodu niż glibc i jest w przybliżeniu równy Musl i Newlib. Aby zoptymalizować często wywoływane funkcje, takie jak memcpy i strlen, dodatkowo stosowana jest technika „efektywnego przekazywania”, w której do wywołania funkcji stosuje się powiązanie makra, w którym kompilator jest informowany o rejestrach procesora zaangażowanych w proces wykonywania kodu, co pozwala oszczędzać zasoby, a jednocześnie zachowywać stan procesora dzięki zapisywaniu wyłącznie rejestrów zmiennych.
Wśród zmian w nowej wersji:
- Zmieniono sposób dostępu do zasobów wewnętrznych w pliku zip (podczas otwierania plików używane są teraz zwykłe ścieżki /zip/… zamiast dostępu do nich za pomocą prefiksu zip:..). Podobnie, dostęp do dysków w Windows Wprowadzono możliwość używania ścieżek takich jak „/c/...” zamiast „C:/...”.
- Zaproponowano nowy program ładujący APE (Actually Portable Executable), definiujący format uniwersalnych plików wykonywalnych. Nowy bootloader używa mmap do umieszczania programu w pamięci i nie modyfikuje już jego zawartości „w locie”. W razie potrzeby uniwersalny plik wykonywalny można przekonwertować na zwykłe pliki wykonywalne powiązane z poszczególnymi platformami.
- Platforma Linux Zaimplementowano możliwość użycia modułu jądra binfmt_misc do uruchamiania programów APE. Należy zauważyć, że użycie binfmt_misc jest najszybszą metodą uruchamiania.
- dla Linux Zaproponowano implementację wywołań systemowych pledge() i reveal() opracowanych w ramach projektu OpenBSD. Udostępniono API do korzystania z tych wywołań w programach w językach C, C++, Python i Redbean, a także narzędzie pledge.com do izolowania dowolnych procesów.
- Narzędzie Landlock Make jest używane do asemblacji — wersji GNU Make z bardziej rygorystycznym sprawdzaniem zależności i wykorzystaniem wywołania systemowego Landlock do odizolowania programu od reszty systemu i zwiększenia wydajności buforowania. Możliwość kompilacji za pomocą zwykłego GNU Make jest zachowana jako opcja.
- Zaimplementowano funkcje wielowątkowości — _spawn() i _join(). Są to uniwersalne powiązania z interfejsami API specyficznymi dla różnych systemów operacyjnych. Trwają również prace nad wdrożeniem obsługi wątków POSIX.
- Wprowadzono możliwość użycia słowa kluczowego _Thread_local w celu wykorzystania protokołu TLS (Thread-Local Storage) dla każdego wątku. Domyślnie środowisko wykonawcze C inicjuje protokół TLS dla wątku głównego, co spowodowało zwiększenie minimalnego rozmiaru pliku wykonywalnego z 12 do 16 KB.
- Dodano obsługę parametrów „--ftrace” i „--strace” do plików wykonywalnych w celu drukowania informacji o wszystkich wywołaniach funkcji i wywołaniach systemowych do stderr.
- Dodano obsługę wywołania systemowego closefrom(), obsługiwanego w Linux 5.9+, FreeBSD 8+ i OpenBSD.
- Platforma Linux Wydajność wywołań clock_gettime i gettimeofday została zwiększona nawet dziesięciokrotnie dzięki zastosowaniu mechanizmu vDSO (wirtualny dynamiczny obiekt współdzielony), który umożliwia przeniesienie obsługi wywołań systemowych do przestrzeni użytkownika i uniknięcie przełączania kontekstu.
- Funkcje matematyczne służące do pracy z liczbami zespolonymi zostały przeniesione z biblioteki Musl. Przyspieszono działanie wielu funkcji matematycznych.
- Zaproponowano funkcję nointernet() umożliwiającą wyłączenie funkcji sieciowych.
- Dodano nowe funkcje umożliwiające wydajne dołączanie ciągów znaków: appendd, appendf, appendr, appends, appendw, appendz, kappendf, kvappendf i vappendf.
- Dodano chronioną wersję rodziny funkcji kprintf(), przeznaczoną do pracy z podwyższonymi uprawnieniami.
- Znacznie poprawiona wydajność wdrożeń SSL, SHA, curve25519 i RSA.
Źródło: opennet.ru
