À partir de http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967:
J'ai récemment eu le besoin d'incorporer un fichier dans un fichier exécutable. Depuis que je suis en train de travailler sur la ligne de commande avec gcc, et al et non pas avec une fantaisie RAD outil qu'il fait, tout se fait comme par magie, il n'était pas immédiatement évident pour moi comment faire ça. Un peu de recherche sur le net trouvé un hack pour essentiellement de chat sur la fin de l'exécutable, puis déchiffrer où il était basé sur un tas d'information, je ne veux pas le savoir. Semble comme il devrait y avoir une meilleure façon...
Et bien, ce n'est objcopy à la rescousse. objcopy convertit les fichiers objets ou des fichiers exécutables à partir d'un format à un autre. L'un des formats qu'il comprenne, c'est "binaire", qui est essentiellement un fichier qui n'est pas dans l'un des autres formats qu'il comprend. Donc, vous avez probablement imaginé l'idée: convertir le fichier que nous voulons intégrer dans un fichier objet, alors il peut être tout simplement liée avec le reste de notre code.
Disons que nous avons un nom de fichier data.txt que nous souhaitons intégrer dans notre exécutable:
# cat data.txt
Hello world
Afin de le convertir en un fichier objet que nous pouvons faire un lien avec notre programme, nous utilisons tout simplement objcopy à produire un ".o" fichier:
# objcopy --input binary \
--output elf32-i386 \
--binary-architecture i386 data.txt data.o
Cela dit objcopy que notre fichier d'entrée est dans le "binaire", format, que notre fichier de sortie doit être dans le "elf32-i386" (format de fichiers objets sur les architectures x86). L' --binary-architecture option indique objcopy que le fichier de sortie est destinée à "exécuter" sur un système x86. Ceci est nécessaire afin que ld va accepter le fichier pour faire le lien avec d'autres fichiers pour le x86. On pourrait penser que le fait de spécifier le format de sortie comme "elf32-i386" impliquerait cela, mais il ne le fait pas.
Maintenant que nous avons un fichier de l'objet, nous avons seulement besoin de l'inclure lors de l'éditeur de liens:
# gcc main.c data.o
Quand nous courons le résultat nous obtenons le pria de sortie:
# ./a.out
Hello world
Bien sûr, je n'ai pas raconté toute l'histoire, ni de vous montrer principal.c. Lorsque objcopy n'est au-dessus de la conversion, il ajoute quelques "linker" les symboles de la conversion d'un fichier de l'objet:
_binary_data_txt_start
_binary_data_txt_end
Après la liaison, ces symboles pour indiquer le début et la fin du fichier incorporé. Le symbole noms sont formés en ajoutant le binaire et en ajoutant _start ou _end pour le nom de fichier. Si le nom de fichier contient des caractères qui ne sont pas valables dans un nom de symbole, ils sont convertis à des traits de soulignement (par exemple data.txt devient data_txt). Si vous obtenez les noms non résolus lors de la liaison à l'aide de ces symboles, faire un hexdump-C sur le fichier de l'objet et de regarder à la fin de la décharge pour les noms que objcopy choisi.
Le code à utiliser effectivement le fichier incorporé doit être maintenant assez évident:
#include <stdio.h>
extern char _binary_data_txt_start;
extern char _binary_data_txt_end;
main()
{
char* p = &_binary_data_txt_start;
while ( p != &_binary_data_txt_end ) putchar(*p++);
}
Un important et subtil chose à noter est que les symboles ajoutés au fichier de l'objet ne sont pas des "variables". Ils ne contiennent pas toutes les données, plutôt, leur adresse est leur valeur. Je leur déclare que le type char parce que c'est pratique pour cet exemple: les données incorporées, c'est le caractère de données. Cependant, vous pouvez les déclarer comme n'importe quoi, comme int si les données est un tableau d'entiers, ou comme struct foo_bar_t si les données étaient tout tableau de foo bars. Si les données incorporées n'est pas uniforme, le char est probablement le plus pratique: prendre son adresse et lancer le pointeur vers le type que vous traversez les données.