Ce qui se passe
Farid Zakaria publie SELF (Structured Executable & Linkable Format), un prototype où le binaire que vous lancez est une base SQLite. Pas une base qui décrit un binaire : le fichier lui-même.
$ file hello
hello: SQLite 3.x database, application id 0x53454c46, user version 1
$ ./hello
Hello, world!
$ sqlite3 hello 'SELECT soname FROM ldd'
libc.so.6L'idée vient de sa thèse, où elle avait reçu un accueil tiède, et qu'il ressort
aujourd'hui — un précédent outil du même auteur, sqlelf, permettait déjà
d'explorer un fichier ELF en SQL au lieu de combiner readelf et grep.
L'argument central
Le constat qui porte tout le travail : ELF est déjà une base de données qui refuse de l'admettre, et qui réimplémente ses primitives à la main.
| Mécanisme ELF | Primitive de base réinventée |
|---|---|
.strtab / .dynstr |
internement de chaînes |
.hash / .gnu.hash |
un index, avec filtre de Bloom maison |
| table des en-têtes de sections | un catalogue de tables |
st_name → position dans .strtab |
une clé étrangère écrite à la main |
objcopy --strip-debug |
un DELETE suivi d'un VACUUM |
cache ldconfig, debuginfod |
des index hors bande |
À cela s'ajoutent les défauts d'un format pensé quand l'octet coûtait cher : chaque outil réécrit le même analyseur, chaque producteur réécrit le même sérialiseur, le format est trop compact pour être modifié sans réécrire des sections entières, et il n'a aucun schéma auto-descriptif.
Ce que ça donne concrètement
Deux tables suffisent à faire tourner un programme : l'en-tête ELF stocké en paires clé-valeur, et une table de segments — une ligne par en-tête de programme, les octets rangés dans un champ binaire.
La table des symboles est plus parlante encore. Une seule table, un seul index
(name, version), et plusieurs mécanismes disparaissent : la table de chaînes
n'a plus lieu d'être puisque SQLite interne déjà les chaînes, le versionnement
de symboles devient une colonne au lieu des sections dédiées, et l'index est
un vrai arbre B maintenu par le moteur plutôt qu'un filtre de Bloom écrit à la
main.
Les tables restantes — sections, notes, entrées dynamiques — n'existent que pour l'outillage. Supprimez-les : le programme fonctionne toujours. Autrement dit, dépouiller un binaire devient une transaction, avec ce que cela implique d'atomicité et de possibilité d'annulation.
Bénéfice collatéral : les commandes d'inspection deviennent des requêtes.
ldd, nm -D --undefined, readelf -l s'expriment en SELECT.
Les limites
L'auteur ne vend pas un remplaçant. C'est un prototype, l'idée n'a pas convaincu lors de sa thèse, et l'inertie d'un format installé depuis trente ans ne se renverse pas avec un dépôt public. Restent ouvertes les questions de démarrage par le noyau, de performance de chargement à grande échelle et de compatibilité avec toute la chaîne de compilation existante.
À retenir
Même sans jamais exécuter une base SQLite, l'exercice change la lecture : les
formats binaires que nous manipulons implémentent des index, des catalogues et
des clés étrangères — mal, et sans le dire. La prochaine fois que vous lirez une
sortie de readelf, vous saurez que vous interrogez une base de données à la
main.
Source : Farid Zakaria