Se ha publicado la versión del proyecto Cosmopolitan 2.0, que desarrolla la biblioteca estándar de C y un formato universal de archivos ejecutables que se puede utilizar para distribuir programas para diferentes sistemas operativos sin el uso de intérpretes y máquinas virtuales. El resultado obtenido mediante compilación en GCC y Clang se enlaza en un archivo ejecutable universal vinculable de forma estática, adecuado para su ejecución en cualquier distribución de Linux, macOS, Windows, FreeBSD, OpenBSD, NetBSD e incluso para ser llamado desde la BIOS. El código del proyecto se distribuye bajo la licencia ISC (una versión simplificada de MIT/BSD).
El contenedor para la formación de archivos ejecutables universales se basa en la combinación de segmentos y encabezados específicos de diferentes sistemas operativos (PE, ELF, MACHO, OPENBSD) en un solo archivo, combinando varios formatos diferentes utilizados en Unix, Windows y macOS. Para asegurar la ejecución de un mismo archivo ejecutable en sistemas Windows y Unix, se aplica un truco relacionado con la codificación de archivos Windows PE en forma de un script de shell, aprovechando que Thompson Shell no utiliza el marcador de scripts «#!». Para crear programas que incluyan varios archivos (agrupando todos los recursos en un solo archivo), se admite la formación de un archivo ejecutable en forma de un archivo ZIP estructurado especialmente. El esquema del formato propuesto (ejemplo de aplicación 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…
Al principio del archivo se indica la etiqueta «MZqFpD», que se interpreta como el encabezado del formato Windows PE. Esta secuencia también se decodifica en la instrucción «pop %r10 ; jno 0x4a ; jo 0x4a», y la cadena «\177ELF» en la instrucción «jg 0x47», que se utilizan para redirigir al punto de entrada. En sistemas Unix, se ejecuta el código de shell, en el cual se utiliza el comando exec para pasar el código ejecutable a través de un canal anónimo. La limitación del método propuesto es que solo se puede ejecutar en sistemas operativos tipo Unix mediante el uso de shells que soportan el modo de compatibilidad con Thompson Shell.
La llamada a qemu-x86_64 está diseñada para lograr una portabilidad adicional y permite ejecutar código compilado para la arquitectura x86_64 en plataformas distintas a x86, como en placas Raspberry Pi y dispositivos Apple equipados con procesadores ARM. El proyecto también puede ser utilizado para crear aplicaciones autónomas que funcionen sin un sistema operativo (bare metal). En tales aplicaciones, se adjunta un cargador al archivo ejecutable y el programa actúa como un sistema operativo cargable.
La biblioteca estándar de C libc, desarrollada por el proyecto, ofrece 2024 funciones (en el primer lanzamiento había alrededor de 1400 funciones). En términos de rendimiento, Cosmopolitan es tan rápido como glibc y supera notablemente a Musl y Newlib, a pesar de que Cosmopolitan tiene un tamaño de código significativamente menor que glibc y es aproximadamente del mismo tamaño que Musl y Newlib. Para optimizar funciones que se llaman con frecuencia, como memcpy y strlen, se utiliza una técnica llamada 'trickle-down performance', donde se aplica un macro envolvente a la llamada de función que informa al compilador sobre los registros de CPU utilizados durante la ejecución, lo que permite ahorrar recursos al conservar el estado de la CPU conservando solo los registros que cambian.
Entre los cambios en la nueva versión:
- Se ha modificado el esquema de acceso a los recursos internos dentro del archivo zip (al abrir archivos ahora se utilizan rutas normales /zip/... en lugar de acceder a través del prefijo zip:..). De manera similar, para acceder a discos en Windows se ha habilitado el uso de rutas del tipo '/c/...' en lugar de 'C:/...'.
- Se ha propuesto un nuevo cargador APE (Actually Portable Executable), que define el formato de archivos ejecutables universales. El nuevo cargador utiliza mmap para ubicar el programa en la memoria y ya no modifica el contenido sobre la marcha. Si es necesario, un archivo ejecutable universal puede ser convertido a archivos ejecutables comunes vinculados a plataformas específicas.
- En la plataforma Linux se ha implementado la posibilidad de usar el módulo del núcleo binfmt_misc para ejecutar programas APE. Se señala que el uso de binfmt_misc es el método más rápido para iniciar.
- Para Linux, se ha implementado la funcionalidad de las llamadas al sistema pledge() y unveil(), desarrolladas por el proyecto OpenBSD. Se ofrece una API para usar estas llamadas en programas escritos en C, C++, Python y Redbean, así como una herramienta pledge.com para aislar procesos arbitrarios.
- Para la compilación se utiliza la herramienta Landlock Make, una edición de GNU Make con una verificación de dependencias más estricta y el uso de la llamada al sistema Landlock para aislar el programa del resto del sistema y mejorar la eficiencia de la caché. También se ha mantenido la posibilidad de compilación con el GNU Make tradicional.
- Se han implementado funciones para la programación en múltiples hilos: _spawn() y _join(), que son envolturas universales sobre APIs específicas para diferentes sistemas operativos. También se está trabajando en la implementación del soporte para POSIX Threads.
- Se ha proporcionado la posibilidad de usar la palabra clave _Thread_local para tener almacenes separados para cada hilo (TLS, Thread-Local Storage). Por defecto, el entorno de ejecución de C inicializa TLS para el hilo principal, lo que ha incrementado el tamaño mínimo del archivo ejecutable de 12 a 16 KB.
- Se ha añadido soporte para las opciones «—ftrace» y «—strace» en los archivos ejecutables, lo que permite la salida en stderr de información sobre todas las llamadas a funciones y llamadas al sistema.
- Se ha añadido soporte para la llamada al sistema closefrom(), compatible con Linux 5.9+, FreeBSD 8+ y OpenBSD.
- En la plataforma Linux, se ha incrementado hasta 10 veces el rendimiento de las llamadas clock_gettime y gettimeofday gracias al uso del mecanismo vDSO (virtual dynamic shared object), que permite trasladar el manejador de la llamada al sistema al espacio de usuario y evitar cambios de contexto.
- Se han trasladado funciones matemáticas de la biblioteca Musl para trabajar con números complejos. Se ha acelerado el rendimiento de muchas funciones matemáticas.
- Se ha propuesto la función nointernet(), que desactiva las capacidades de red.
- Se han añadido nuevas funciones para la concatenación eficiente de cadenas: appendd, appendf, appendr, appends, appendw, appendz, kappendf, kvappendf y vappendf.
- Se ha añadido una variante segura de la familia de funciones kprintf(), destinada a trabajar con privilegios elevados.
- Se ha incrementado significativamente el rendimiento de las implementaciones SSL, SHA, curve25519 y RSA.
Fuente: opennet.ru
