Опубликован выпуск проекта Cosmopolitan 2.0, развивающего стандартную Си-библиотеку и универсальный формат исполняемых файлов, который можно использовать для распространения программ для разных операционных систем без использования интерпретаторов и виртуальных машин. Получаемый при помощи компиляции в GCC и Clang результат компонуется в статически связываемый универсальный исполняемый файл, который пригоден для запуска в любом дистрибутиве Linux, macOS, Windows, FreeBSD, OpenBSD, NetBSD и даже вызова из BIOS. Код проекта распространяется под лицензией ISC (упрощённый вариант MIT/BSD).
Контейнер для формирования универсальных исполняемых файлов основан на совмещении специфичных для разных операционных систем сегментов и заголовков (PE, ELF, MACHO, OPENBSD) в одном файле, комбинируя в нем несколько разных форматов, используемых в Unix, Windows и macOS. Для обеспечения запуска одного исполняемого файла в Windows и Unix-системах применяется трюк, связанный с кодированием файлов Windows PE в виде shell-скрипта, пользуясь тем, что Thompson Shell не использует маркер скриптов “#!”. Для создания программ, включающих несколько файлов (компоновки всех ресурсов в один файл), поддерживается формирование исполняемого файла в виде специально оформленного ZIP-архива. Схема предложенного формата (пример приложения 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…
Вначале файле указывается метка “MZqFpD”, которая воспринимается как заголовок формата Windows PE. Данная последовательность также декодируется в инструкции “pop %r10 ; jno 0x4a ; jo 0x4a”, а строка “177ELF” в инструкцию “jg 0x47”, которые применяются для проброса на точку входа. В Unix-системах выполняется shell-код, в котором используется команда exec с передачей исполняемого кода через неименованный канал. Ограничением предложенного метода является возможность запуска в Unix-подобных ОС только с использованием оболочек, поддерживающих режим совместимости с Thompson Shell.
Вызов qemu-x86_64 предусмотрен для реализации дополнительной переносимости и позволяет выполнить скомпилированный для архитектуры x86_64 код на платформах, отличных от x86, например, на платах Raspberry Pi и устройствах Apple, укомплектованных процессорами ARM. Проект также может использоваться для создания самодостаточных приложений, работающих без операционной системы (bare metal). В таких приложениях к исполняемому файлу прикрепляется загрузчик, а программа выступает в роли загружаемой операционной системы.
В развиваемой проектом стандартной Си-библиотеке libc предложено 2024 функции (в первом выпуске было около 1400 функций). По производительности Cosmopolitan работает также быстро как и glibc и заметно опережает Musl и Newlib, при том, что Cosmopolitan по размеру кода на порядок меньше glibc и примерно соответствует Musl и Newlib. Для оптимизации часто вызываемых функций таких как memcpy и strlen, дополнительно используется техника “trickle-down performance”, при которой для вызова функции применяется макрос-обвязка, в котором компилятор информируется о задействованных в процессе выполнения кода регистрах CPU, что позволяет экономить ресурсы при сохранении состояния CPU за счёт сохранения только изменяемых регистров.
Среди изменений в новом выпуске:
- Изменена схема обращения к внутренним ресурсам внутри zip-файла (при открытии файлов теперь используются обычные пути /zip/… вместо обращения по префиксу zip:..). Аналогично для доступа к дискам в Windows предоставлена возможность использования путей вида “/c/…” вместо “C:/…”.
- Предложен новый загрузчик APE (Actually Portable Executable), определяющий формат универсальных исполняемых файлов. Новый загрузчик использует mmap для размещения программы в памяти и больше не изменяет содержимое на лету. При необходимости универсальный исполняемый файл может быть сконвертирован в обычные исполняемые файлы, привязанные к отдельным платформам.
- На платформе Linux реализована возможность использования модуля ядра binfmt_misc для запуска APE-программ. Отмечается что использование binfmt_misc является наиболее быстрым методом запуска.
- Для Linux предложена реализация функциональности системных вызовов pledge() и unveil(), развиваемых проектом OpenBSD. Предоставляется API для использования данных вызовов в программах на языках C, C++, Python и Redbean, а также утилита pledge.com для изоляции произвольных процесов.
- Для сборки задействована утилита Landlock Make – редакция GNU Make с более жёсткой проверкой зависимостей и использованием системного вызова Landlock для изоляции программы от остальной системы и повышения эффективности кэширования. В качестве опции сохранена возможности сборки и обычным GNU Make.
- Реализованы функции для многопоточности – _spawn() и _join(), представляющие собой универсальные обвязки над специфичными для разных операционных систем API. Также ведётся работа над реализацией поддержки POSIX Threads.
- Предоставлена возможность использования ключевого слова _Thread_local для использования отдельных для каждого потока хранилищ (TLS, Thread-Local Storage). По умолчанию C runtime инициализирует TLS для основного потока, что привело к увеличению минимального размера исполняемого файл с 12 до 16 КБ.
- В исполняемые файлы добавлена поддержка параметров “–ftrace” и “–strace” для вывода в stderr информации о всех вызовах функций и системных вызовах.
- Добавлена поддержка системного вызова closefrom(), поддерживаемого в Linux 5.9+, FreeBSD 8+ и OpenBSD.
- На платформе Linux до 10 раз увеличена производительность вызовов clock_gettime и gettimeofday за счёт использования механизма vDSO (virtual dynamic shared object), дающего возможность перенести обработчик системного вызова в пространство пользователя и избежать переключений контекста.
- Из библиотеки Musl перенесены математические функции для работы с комплексными числами. Ускорена работа многих математических функций.
- Предложена функция nointernet(), отключающая сетевые возможности.
- Добавлены новые функции для эффективного прикрепления строк: appendd, appendf, appendr, appends, appendw, appendz, kappendf, kvappendf и vappendf.
- Добавлен защищённый вариант семейства функций kprintf(), предназначенный для работы при повышенных привилегиях.
- Значительно повышена производительность реализаций SSL, SHA, curve25519 и RSA.