Je ne connais pas les commandes de script de l'éditeur de liens qui peuvent le faire, mais vous pouvez le faire après le lien en utilisant le objcopy commande. La section --add-section L'option peut être utilisée pour ajouter une section contenant des données arbitraires au fichier ELF. Si l'en-tête ELF ne contient pas les champs souhaités, créez simplement une nouvelle section et ajoutez-les ici.
Ce lien (binaire teensy elf) était la réponse de quelqu'un à une autre question, mais il aborde en détail les subtilités d'un en-tête ELF.
Vous pouvez créer un fichier objet avec des champs informatifs comme un numéro de version et lier ce fichier de sorte qu'ils soient inclus dans le binaire ELF résultant.
Identifier
Par exemple, dans le cadre de votre processus de construction, vous pouvez générer - disons - info.c
qui contient un ou plusieurs #ident
instructions :
#ident "Build: 1.2.3 (Halloween)"
#ident "Environment: example.org"
Compilez-le :
$ gcc -c info.c
Vérifiez si les informations sont incluses :
$ readelf -p .comment info.o
String dump of section '.comment':
[ 1] Build: 1.2.3 (Halloween)
[ 1a] Environment: example.org
[ 33] GCC: (GNU) 7.2.1 20170915 (Red Hat 7.2.1-2)
Alternativement, vous pouvez utiliser objdump -s --section .comment info.o
. Notez que GCC écrit également son propre commentaire, par défaut.
Vérifiez les informations après avoir lié un exécutable ELF :
$ gcc -o main main.o info.o
$ readelf -p .comment main
String dump of section '.comment':
[ 0] GCC: (GNU) 7.2.1 20170915 (Red Hat 7.2.1-2)
[ 2c] Build: 1.2.3 (Halloween)
[ 45] Environment: example.org
Section des commentaires
Utilisation de #ident
dans une unité de traduction C est fondamentalement équivalent à créer un .comment
section dans un fichier assembleur. Exemple :
$ cat info.s
.section .comment
.string "Build: 1.2.3 (Halloween)"
.string "Environment: example.org"
$ gcc -c info.s
$ readelf -p .comment info.o
String dump of section '.comment':
[ 0] Build: 1.2.3 (Halloween)
[ 19] Environment: example.org
L'utilisation d'un nom de section inhabituel fonctionne également (par exemple, .section .blahblah
). Mais .comment
est utilisé et compris par d'autres outils. GNU comprend également le .ident
directive, et c'est ce que GCC traduit #ident
à.
Avec symboles
Pour les données auxquelles vous souhaitez également accéder à partir de l'exécutable ELF lui-même, vous devez créer des symboles.
Objcopy
Supposons que vous souhaitiez inclure des octets magiques stockés dans un fichier de données :
$ cat magic.bin
2342
Convertir en fichier objet avec GNU objcopy :
$ objcopy -I binary -O elf64-x86-64 -B i386 \
--rename-section .data=.rodata,alloc,load,readonly,data,contents \
magic.bin magic.o
Vérifiez les symboles :
$ nm magic.o
0000000000000005 R _binary_magic_bin_end
0000000000000005 A _binary_magic_bin_size
0000000000000000 R _binary_magic_bin_start
Exemple d'utilisation :
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
extern const char _binary_magic_bin_start[];
extern const char _binary_magic_bin_end[];
extern const unsigned char _binary_magic_bin_size;
static const size_t magic_bin_size = (uintptr_t) &_binary_magic_bin_size;
int main()
{
char s[23];
memcpy(s, _binary_magic_bin_start,
_binary_magic_bin_end - _binary_magic_bin_start);
s[magic_bin_size] = 0;
puts(s);
return 0;
}
Reliez le tout :
$ gcc -g -o main_magic main_magic.c magic.o
Ld GNU
GNU ld est également capable de transformer des fichiers de données en fichiers objets en utilisant un schéma de nommage compatible avec objcopy :
$ ld -r -b binary magic.bin -o magic-ld.o
Contrairement à objcopy, il place les symboles dans le .data
au lieu du .rodata
cependant (cf. objdump -h magic.o
).
incbin
Dans le cas où GNU objcopy n'est pas disponible, on peut utiliser le GNU comme .incbin
directive pour créer le fichier objet (assembler avec gcc -c incbin.s
):
.section .rodata
.global _binary_magic_bin_start
.type _binary_magic_bin_start, @object
_binary_magic_bin_start:
.incbin "magic.bin"
.size _binary_magic_bin_start, . - _binary_magic_bin_start
.global _binary_magic_bin_size
.type _binary_magic_bin_size, @object
.set _binary_magic_bin_size, . - _binary_magic_bin_start
.global _binary_magic_bin_end
.type _binary_magic_bin_end, @object
.set _binary_magic_bin_end, _binary_magic_bin_start + _binary_magic_bin_size
; an alternate way to include the size
.global _binary_magic_bin_len
.type _binary_magic_bin_len, @object
.size _binary_magic_bin_len, 8
_binary_magic_bin_len:
.quad _binary_magic_bin_size
xxj
Une alternative plus portable qui ne nécessite pas GNU objcopy ni GNU comme c'est le cas pour créer un fichier C intermédiaire et le compiler et le lier. Par exemple avec xxd :
$ xxd -i magic.bin | sed 's/\(unsigned\)/const \1/' > magic.c
$ gcc -c magic.c
$ nm magic.o
0000000000000000 R magic_bin
0000000000000008 R magic_bin_len
$ cat magic.c
const unsigned char magic_bin[] = {
0x32, 0x33, 0x34, 0x32, 0x0a
};
const unsigned int magic_bin_len = 5;