Non conosco i comandi di script del linker che possono farlo, ma puoi farlo post-link usando objcopy comando. La --add-section L'opzione può essere utilizzata per aggiungere una sezione contenente dati arbitrari al file ELF. Se l'intestazione ELF non contiene i campi desiderati, basta creare una nuova sezione e aggiungerli lì.
Questo link (teensy elf binary) era la risposta di qualcuno a un'altra domanda, ma entra nel dettaglio delle intricate intestazioni ELF.
Puoi creare un file oggetto con campi informativi come un numero di versione e collegare quel file in modo che siano inclusi nel binario ELF risultante.
Identificazione
Ad esempio, come parte del processo di compilazione, puoi generare, ad esempio, info.c
che contiene uno o più #ident
direttive:
#ident "Build: 1.2.3 (Halloween)"
#ident "Environment: example.org"
Compilalo:
$ gcc -c info.c
Controlla se le informazioni sono incluse:
$ 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)
In alternativa, puoi usare objdump -s --section .comment info.o
. Nota che GCC scrive anche il proprio commento, per impostazione predefinita.
Controlla le informazioni dopo aver collegato un eseguibile 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
Sezione commenti
Usando #ident
in un'unità di traduzione C equivale sostanzialmente a creare un .comment
sezione in un file assembler. Esempio:
$ 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
Anche l'utilizzo di un nome di sezione non comune funziona (ad es. .section .blahblah
). Ma .comment
viene utilizzato e compreso da altri strumenti. GNU comprende anche il .ident
direttiva, e questo è ciò che GCC traduce #ident
a.
Con simboli
Per i dati a cui vuoi accedere anche dall'eseguibile ELF stesso, devi creare dei simboli.
Oggettocopia
Supponi di voler includere alcuni magic byte memorizzati in un file di dati:
$ cat magic.bin
2342
Converti in un file oggetto con GNU objcopy:
$ objcopy -I binary -O elf64-x86-64 -B i386 \
--rename-section .data=.rodata,alloc,load,readonly,data,contents \
magic.bin magic.o
Controlla i simboli:
$ nm magic.o
0000000000000005 R _binary_magic_bin_end
0000000000000005 A _binary_magic_bin_size
0000000000000000 R _binary_magic_bin_start
Esempio di utilizzo:
#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;
}
Collega tutto insieme:
$ gcc -g -o main_magic main_magic.c magic.o
GNU ld
GNU ld è anche in grado di trasformare i file di dati in file oggetto utilizzando uno schema di denominazione compatibile con objcopy:
$ ld -r -b binary magic.bin -o magic-ld.o
A differenza di objcopy, inserisce i simboli nel .data
invece del .rodata
sezione, tuttavia (cfr. objdump -h magic.o
).
incbin
Nel caso in cui GNU objcopy non sia disponibile, si può usare GNU come .incbin
direttiva per creare il file oggetto (assemble con 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
xxd
Un'alternativa più portabile che non richiede GNU objcopy né GNU come è creare un file C intermedio e compilarlo e collegarlo. Ad esempio con 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;