GNU/Linux >> LINUX-Kenntnisse >  >> Linux

ELF-Datei-Header

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;

Linux
  1. Linux – Alles ist eine Datei?

  2. Zeilen in einer Datei zählen?

  3. Grundlagen des Linux-ELF-Objektdateiformats (und der ELF-Header-Struktur).

  4. Abschnitt zur ELF-Datei hinzufügen

  5. C fopen gegen offen

VIM-Editor

glibc:Elf-Datei OS ABI ungültig

Was ist der Unterschied zwischen Abschnitt und Segment im ELF-Dateiformat

kann ein programm seinen eigenen elfabschnitt lesen?

Wie man einen Abschnitt einer Datei in der Bash-Shell grep

cp-L vs. cp-H