Comment faire en sorte que gcc ne génère que du code machine pouvant être chargé directement dans la mémoire et exécuté?

Je souhaite créer un fichier que je peux charger en mémoire (par exemple, avec mmap ), puis passer au début de cette mémoire pour exécuter le code.

Idéalement, j’aimerais pouvoir soit rendre le code déplaçable (ce qui pourrait être inefficace), soit spécifier une adresse explicite à laquelle le code s’attend à être chargé (ce qui est pénible), mais l’un ou l’autre fonctionnerait probablement tout seul. .

Vous pouvez le faire, mais vous devrez passer par le format de fichier object. En particulier, la commande objcopy peut transformer un fichier exécutable en un fichier binary “plat” (selon votre plate-forme cible). Peut-être quelque chose comme ça:

 gcc -o test test.c objcopy -O binary test test.bin 

Voir man objcopy sur votre plate-forme pour plus de détails.

Vous voulez en savoir plus sur l’utilitaire objcopy , généralement disponible avec GCC. C’est un composant du paquet d’outils binutils , dont le membre le plus visible est l’éditeur de liens, ld .

Le processus consiste à comstackr votre ou vos fichiers source et à les lier généralement comme d’habitude. Cela vous donne un exécutable fini au format elf (ou un autre fichier binary dépendant de la plate-forme). Vous utilisez ensuite objcopy pour transformer l’exécutable en une image binary à plat.

Ceci est très utile pour préparer le code à exécuter à partir de la ROM, où vous voulez vous assurer que vous utilisez une bibliothèque d’exécution C appropriée pour votre plate-forme cible et que vous devez probablement personnaliser le fichier de script de l’éditeur de liens et fournir votre propre runtime C. code de démarrage.

Si votre objective est d’obtenir quelque chose qui ressemble à un fichier .so, afin de le charger dans un processus existant, sachez qu’une partie du travail du chargeur de bibliothèques partagées consiste à terminer la liaison de manière à ce que les symboles du fichier .so Les fichiers faisant référence aux adresses de l’exécutable principal (ou d’autres fichiers .so) sont résolus au moment du chargement. Objcopy ne fera pas cela, et il pourrait donc être difficile pour les fonctions chargées de cette manière d’utiliser correctement votre bibliothèque d’exécution C existante et les objects qu’elle conserve, tels que les fichiers ouverts.

Quels que soient vos objectives, vous allez avoir besoin de prendre le contrôle de l’éditeur de liens afin de localiser votre binary à une adresse connue. Pour ce faire, vous devrez créer un script de l’éditeur de liens. La documentation pour le langage de script se trouve dans le manuel binutils . Vous vous intéresserez principalement aux sections “.text *”, et éventuellement aux sections “.rodata *” si vous prévoyez d’avoir des variables globales initialisées. En fait, organiser cette initialisation rest un exercice pour le lecteur.

Dans l’ensemble, il ne s’agit que de la pointe d’un très grand iceberg. Je suggérerais de passer un peu de temps avec un compilateur croisé pour voir comment ces choses sont utilisées dans la pratique. Les communautés AVR et MSP430 utilisent GCC, ont une participation active et un matériel peu coûteux (et souvent même open source) pour démarrer.