SELF: Wenn die ausführbare Datei eine SQLite-Datenbank ist
Farid Zakaria stempelt SQLite-Dateien mit der Kennung SELF an Byte 68 — der Linux-Kernel startet sie dann wie ein ELF-Binary.
Symbolbild: übereinandergestapelte Glasplatten mit feinen Gitterlinien, von warmem Licht durchleuchtet.
Farid Zakaria hat mit SELF ein Format gebaut, bei dem die ausführbare Datei selbst eine SQLite-Datenbank ist, die Linux über binfmt_misc und den Interpreter self-exec startet.
Auf einen Blick
- Die Anwendungs-ID an Byte 68 der SQLite-Datei trägt den Wert SELF, in Hex 5345 4c46.
- Interpreter ist self-exec, ein C-Programm gegen libsqlite3 — es muss selbst eine ELF-Datei bleiben.
- coreutils ohne Debug-Symbole: 1.794.048 B als SELF gegenüber 1.768.632 B als ELF, Unterschied unter 1 %.
- 723 Programme und 400 Bibliotheken: 611,9 MiB Datenbank gegenüber 644,4 MiB ELF-Dateien.
- Startaufschlag rund 5 ms fix; der SQL-Lader ist laut Autor ein Machbarkeitsnachweis, nicht produktionsreif.
Ausführbare Dateien unter Linux sind seit Jahrzehnten ELF-Dateien. Farid Zakaria zeigt in einem Beitrag vom 23.08.2026, dass es auch anders geht. Sein Format heißt SELF und ist eine gewöhnliche SQLite-Datenbank, die man mit chmod +x versehen und starten kann. Der Kernel stolpert nicht darüber, weil ihm vorher eine passende Regel beigebracht wurde.
Vier Bytes an Position 68
SQLite hält im Dateikopf ein Feld namens application_id bereit: vier Bytes, 68 Bytes vom Dateianfang entfernt. Dort steht bei Zakaria die Zeichenfolge SELF, ausgeschrieben Structured Executable and Linkable Format. Ein Blick mit xxd auf diese Stelle zeigt die Hex-Folge 5345 4c46.
Über den Kernel-Mechanismus binfmt_misc wird eine Regel registriert, die auf die SQLite-Signatur am Dateianfang und zusätzlich auf SELF an Byte 68 anspringt. Als Interpreter trägt Zakaria ein kleines C-Programm namens self-exec ein, das gegen libsqlite3 gelinkt ist. Dieses Programm muss selbst eine ELF-Datei bleiben, sonst würde der Mechanismus sich endlos selbst aufrufen.
ELF-Strukturen als Tabellen
Statt Sektionen und Offsets liegen die Bestandteile des Programms in Tabellen. Zwei davon genügen zum Start: segments enthält pro Programm-Header eine Zeile mit den Bytes als BLOB, symbols ersetzt die Symboltabellen durch Spalten wie name, version, value und bind, indexiert über name und version.
Weitere Tabellen wie sections, notes und dynamic_entries sind laut Zakaria optional — löscht man sie, läuft das Programm weiter. Sein Argument: ELF baue viele Grundfunktionen einer Datenbank von Hand nach. Die String-Tabellen ersetzt SQLite durch eigenes String-Interning, die ELF-Hash-Tabellen durch B-Baum-Indizes, manuelle Offset-Rechnerei durch Fremdschlüssel. Aus strip wird ein DELETE mit anschließendem VACUUM, aus patchelf ein UPDATE.
Größe und Startzeit
Eine einzelne hello-Datei wächst auf etwa das Doppelte der ELF-Fassung. Im größeren Maßstab dreht sich das Bild, wie Zakarias Messungen zeigen.
| Messung | SELF | ELF |
|---|---|---|
| coreutils, ohne Debug-Symbole | 1.794.048 B | 1.768.632 B |
| Userland: 723 Programme, 400 Bibliotheken | 611,9 MiB | 644,4 MiB |
Bei coreutils liegt der Abstand unter 1 %. Die komplette Userland-Sammlung passt sogar in eine Datenbank, die kleiner ist als der entsprechende Bestand an ELF-Dateien — weil gemeinsame Bibliotheken nur einmal gespeichert werden.
Beim Start fallen rund 5 ms fixe Kosten für die SQLite-Initialisierung an, dazu ein Anteil, der mit der Größe des Speicherabbilds wächst. Grund dafür ist, dass die Bytes aus B-Baum-Seiten kopiert und nicht wie bei ELF per mmap eingeblendet werden.
Abhängigkeiten in einer einzigen Datei
Der Befehl self closure packt ein Programm samt aller mittelbaren Abhängigkeiten in eine Datenbank. Aufgelöste Bibliothekspfade stehen als Fremdschlüssel in einer Tabelle needs, womit die Mehrdeutigkeit von SONAMEs entfällt. Für das dynamische Linken hat Zakaria zwei Wege gebaut: einen, der ld.so behält und die Bibliothekssuche über die rtld-audit-Schnittstelle von glibc in SQL-Abfragen umlenkt, und self-ld als vollständigen Ersatz, der Relokationen und Symbolauflösung selbst per Abfrage erledigt.
Was noch offen ist
Zakaria bezeichnet den SQL-Lader ausdrücklich als Machbarkeitsnachweis, nicht als produktionsreif. Eine bekannte Einschränkung: Zwei Prozesse, die dieselbe SELF-Datei starten, können sich die Textseiten nicht teilen. Die Umwandlung zwischen ELF und SELF soll über das Werkzeug elf2self verlustfrei in beide Richtungen laufen, der Prototyp liegt im Repository fzakaria/selfdb. Simon Willison griff den Beitrag am 24.08.2026 auf.
Häufige Fragen
Was ist SELF bei SQLite?
SELF steht für Structured Executable and Linkable Format. Es ist eine SQLite-Datenbank, die an Byte 68 die Anwendungs-ID SELF trägt und die Bestandteile eines Programms in Tabellen statt in ELF-Sektionen ablegt.
Wie bringt man Linux dazu, eine SQLite-Datei auszuführen?
Über binfmt_misc: Man registriert eine Regel, die auf die SQLite-Signatur und auf SELF an Byte 68 anspringt, und gibt self-exec als Interpreter an. Der Interpreter liest Programm-Header und Symbole aus der Datenbank.
Ist SELF schon produktiv einsetzbar?
Nein. Der Autor nennt den SQL-Lader einen Machbarkeitsnachweis. Der Start kostet rund 5 ms zusätzlich, und zwei Prozesse mit derselben SELF-Datei können sich die Textseiten nicht teilen.