
Arquitectura de máquina minimalista con backend de compilador LLVM, puerto Linux y máquina virtual para crear cápsulas de software autocontenidas que permanezcan ejecutables indefinidamente sin dependencias complejas.
Este es el repositorio raíz de la Eternal Software Initiative.
La ESI define una arquitectura de máquina mínima (basada en una modificación de Subleq OISC) tan simple que su especificación completa puede escribirse en una servilleta. Luego proporcionamos un backend del compilador LLVM para esta arquitectura, un port de Linux, ports de las bibliotecas de tiempo de ejecución C/C++ y otras herramientas (incluyendo una implementación de máquina virtual de referencia en ~50 líneas de C) necesarias para construir y ejecutar una 'cápsula' autocontenida a partir de software existente.
¿Cuál es el propósito de todo esto? Ejecutar el software actual requiere una pila compleja de dependencias (compiladores, bibliotecas, frameworks, SO) sobre hardware propietario e incompletamente documentado, lo que hace muy difícil asegurar que el software actual continúe funcionando en el futuro. Este problema de 'bit rot' es bien conocido por cualquiera que mantenga software heredado durante años o décadas, pero ahora imagine a un historiador dentro de 1,000 años tratando de entender la vida del siglo XXI, gran parte de la cual se experimenta a través del software. Incluso si los binarios del software actual se preservan, es poco probable imaginar que esos binarios aún sean ejecutables. Emuladores como QEMU trasladan este problema pero no lo resuelven: también tienen una pila igualmente compleja de dependencias de software y hardware, por lo que tampoco serán ejecutables en un futuro lejano.
La ESI resuelve este problema (1) definiendo una arquitectura lo suficientemente simple como para escribirla en una servilleta pero lo suficientemente potente para representar eficientemente cualquier software, sin requerir conocimiento de hardware propietario, software, frameworks, etc., y (2) implementando una cadena de herramientas para compilar cualquier software existente en una 'cápsula' autocontenida para esta arquitectura. Esto asegura que, siempre que el binario de la cápsula y las instrucciones de la servilleta se conserven, el software pueda ser revivido y experimentado en un futuro lejano sin asumir ningún conocimiento de los sistemas informáticos actuales.
Este repositorio incluye todo lo necesario para construir y ejecutar su propia máquina ESI, y construir 'cápsulas' ESI a partir de software existente.
Para más información sobre la misión de la ESI, consulte: https://www.eternal-software.org
Este repositorio incluye, como submódulos, forks ESI de la cadena de herramientas LLVM, el kernel de Linux, uClibc-ng y Busybox. Todos deben clonarse juntos.
git clone --recurse-submodules https://github.com/adriancable/eternal
Necesitará SDL3 para construir la máquina virtual ESI. Instálelo con, por ejemplo, apt install libsdl3-dev. No hay otras dependencias. SDL3 puede reemplazarse fácilmente con cualquier otro medio para escribir píxeles y capturar eventos de teclado, ahora o en el futuro.
cd eternal/vm
make
xz -d ../capsules/vmlinux.bootimage.xz
./vm ../capsules/vmlinux.bootimage
Cuando Linux haya arrancado, pruebe por ejemplo:
cd doom
./doom
La cadena de herramientas ESI debería compilarse en cualquier sistema Linux con mínimo esfuerzo. También hemos compilado con éxito en macOS, con algunas modificaciones. Asegúrese de tener gcc, python3, CMake, ninja, flex, bison instalados y operativos.
Comience en la carpeta eternal clonada.
rm -rf llvm-project/build && mkdir -p llvm-project/build
cmake -G Ninja -S llvm-project/llvm -B llvm-project/build -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_BUILD_TOOLS=ON -DLLVM_ENABLE_ASSERTIONS=OFF -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="" -DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD="Subleq" -DLLVM_DEFAULT_TARGET_TRIPLE="subleq-unknown-linux" -DLLVM_FORCE_VC_REPOSITORY="ESI" -DLLVM_FORCE_VC_REVISION=""
cd llvm-project/build
ninja llc clang llvm-mc lld llvm-objcopy llvm-ar llvm-ranlib llvm-nm llvm-readelf llvm-strip llvm-objdump
cd ../../linux
make ARCH=subleq \
CC=../llvm-project/build/bin/clang \
LD=../llvm-project/build/bin/ld.lld \
AR=../llvm-project/build/bin/llvm-ar \
NM=../llvm-project/build/bin/llvm-nm \
OBJCOPY=../llvm-project/build/bin/llvm-objcopy \
INSTALL_HDR_PATH=../runtime/sysroot/kernel-headers \
headers_install
cd ../uclibc-ng
make ARCH=subleq defconfig
make ARCH=subleq \
CC=../llvm-project/build/bin/clang \
LD=../llvm-project/build/bin/ld.lld \
AR=../llvm-project/build/bin/llvm-ar \
NM=../llvm-project/build/bin/llvm-nm \
PREFIX=../runtime/sysroot \
STRIPTOOL=../llvm-project/build/bin/llvm-strip \
DEVEL_PREFIX=/ \
install_dev
cd ../runtime
./build_and_install_runtime.sh
./build_libcxx.sh
ninja -C ./libcxx install
cd ../busybox
make subleq_defconfig
make CC=../llvm-project/build/bin/clang \
AR=../llvm-project/build/bin/llvm-ar \
STRIP=../llvm-project/build/bin/llvm-strip
mkdir ../initramfs_root/bin
cp busybox ../initramfs_root/bin/busybox
cd ../linux
export KBUILD_BUILD_USER="root"
export KBUILD_BUILD_HOST="eternal"
make ARCH=subleq \
CC=../llvm-project/build/bin/clang \
LD=../llvm-project/build/bin/ld.lld \
AR=../llvm-project/build/bin/llvm-ar \
NM=../llvm-project/build/bin/llvm-nm \
OBJCOPY=../llvm-project/build/bin/llvm-objcopy \
defconfig
make ARCH=subleq \
CC=../llvm-project/build/bin/clang \
LD=../llvm-project/build/bin/ld.lld \
AR=../llvm-project/build/bin/llvm-ar \
NM=../llvm-project/build/bin/llvm-nm \
OBJCOPY=../llvm-project/build/bin/llvm-objcopy
cd ..
python3 tools/make_boot_image.py --stack-size 536870912 linux/vmlinux
./vm/vm linux/vmlinux.bootimage
Escriba exit cuando termine para finalizar la VM.
Flujo de trabajo estándar de compilación cruzada. Para comenzar rápidamente, proporcionamos un script de conveniencia (clang_userspace.sh) que configura el entorno y llama a clang.
cat << 'EOF' > hello.c
#include <stdio.h>
int main() {
printf("Hello, ESI world!\n");
return 0;
}
EOF
tools/clang_userspace.sh hello.c
cp hello.elf initramfs_root/root
Luego reconstruya el initramfs y la cápsula:
cd linux
make ARCH=subleq \
CC=../llvm-project/build/bin/clang \
LD=../llvm-project/build/bin/ld.lld \
AR=../llvm-project/build/bin/llvm-ar \
NM=../llvm-project/build/bin/llvm-nm \
OBJCOPY=../llvm-project/build/bin/llvm-objcopy
cd ..
python3 tools/make_boot_image.py --stack-size 536870912 linux/vmlinux
Arranque la VM:
./vm/vm linux/vmlinux.bootimage
Una vez que Linux haya arrancado:
./hello.elf
Proporcionada para que los desarrolladores de hoy comprendan la arquitectura y la cadena de herramientas. Nada de esto (excepto la servilleta) es necesario para que alguien dentro de 1,000 años reviva una cápsula y ejecute el software contenido.
Si has portado la máquina virtual ESI a una nueva plataforma, por favor háznoslo saber abriendo un Issue y lo agregaremos a esta lista.
Una versión minimizada de la máquina virtual ESI (en 366 bytes de C) fue ganadora de la 29ª competición IOCCC.