Ich kenne keine Linker-Skriptbefehle, die dies tun können, aber Sie können dies mit objcopy nach dem Link tun Befehl. Der --add-Abschnitt kann verwendet werden, um der ELF-Datei einen Abschnitt hinzuzufügen, der beliebige Daten enthält. Wenn der ELF-Header nicht die gewünschten Felder enthält, erstellen Sie einfach einen neuen Abschnitt und fügen Sie sie dort hinzu.
Dieser Link (Teensy Elf Binary) war jemandes Antwort auf eine andere Frage, aber er geht etwas detaillierter auf die Feinheiten eines ELF-Headers ein.
Sie können eine Objektdatei mit informativen Feldern wie einer Versionsnummer erstellen und diese Datei so verknüpfen, dass sie in der resultierenden ELF-Binärdatei enthalten sind.
Ident
Beispielsweise können Sie als Teil Ihres Build-Prozesses beispielsweise info.c
generieren die einen oder mehrere #ident
enthält Anweisungen:
#ident "Build: 1.2.3 (Halloween)"
#ident "Environment: example.org"
Kompilieren Sie es:
$ gcc -c info.c
Überprüfen Sie, ob die Informationen enthalten sind:
$ 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)
Alternativ können Sie objdump -s --section .comment info.o
verwenden . Beachten Sie, dass GCC standardmäßig auch einen eigenen Kommentar schreibt.
Überprüfen Sie die Informationen nach dem Verknüpfen einer ausführbaren ELF-Datei:
$ 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
Kommentarbereich
Mit #ident
in einer C-Übersetzungseinheit entspricht im Grunde der Erstellung eines .comment
Abschnitt in einer Assembler-Datei. Beispiel:
$ 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
Die Verwendung eines ungewöhnlichen Abschnittsnamens funktioniert ebenfalls (z. B. .section .blahblah
). Aber .comment
von anderen Tools verwendet und verstanden wird. GNU as versteht auch den .ident
Direktive, und das ist, was GCC #ident
übersetzt zu.
Mit Symbolen
Für Daten, auf die Sie auch von der ausführbaren ELF-Datei selbst zugreifen möchten, müssen Sie Symbole erstellen.
Objektkopie
Angenommen, Sie möchten einige magische Bytes einschließen, die in einer Datendatei gespeichert sind:
$ cat magic.bin
2342
Mit GNU objcopy in eine Objektdatei konvertieren:
$ objcopy -I binary -O elf64-x86-64 -B i386 \
--rename-section .data=.rodata,alloc,load,readonly,data,contents \
magic.bin magic.o
Suchen Sie nach den Symbolen:
$ nm magic.o
0000000000000005 R _binary_magic_bin_end
0000000000000005 A _binary_magic_bin_size
0000000000000000 R _binary_magic_bin_start
Beispielverwendung:
#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;
}
Alles miteinander verknüpfen:
$ gcc -g -o main_magic main_magic.c magic.o
GNU-ld
GNU ld ist auch in der Lage, Datendateien in Objektdateien umzuwandeln, indem es ein objcopy-kompatibles Namensschema verwendet:
$ ld -r -b binary magic.bin -o magic-ld.o
Im Gegensatz zu objcopy platziert es die Symbole in .data
statt .rodata
Abschnitt jedoch (vgl. objdump -h magic.o
).
incbin
Falls GNU objcopy nicht verfügbar ist, kann man GNU als .incbin
verwenden Direktive zum Erstellen der Objektdatei (assemblieren mit 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
Eine portablere Alternative, die weder GNU objcopy noch GNU benötigt, da eine C-Zwischendatei erstellt und kompiliert und gelinkt wird. Zum Beispiel mit 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;