GNU/Linux >> Znalost Linux >  >> Linux

Záhlaví souborů ELF

Nevím o příkazech linker script, které by to uměly, ale můžete to udělat post-link pomocí objcopy příkaz. --add-section možnost lze použít k přidání sekce obsahující libovolná data do souboru ELF. Pokud záhlaví ELF neobsahuje požadovaná pole, vytvořte novou sekci a přidejte je tam.


Tento odkaz (binární teensy elf) byl něčí odpovědí na jinou otázku, ale jde do detailů do složitosti hlavičky ELF.


Můžete vytvořit soubor objektu s informativními poli, jako je číslo verze, a propojit tento soubor tak, aby byly zahrnuty do výsledného binárního souboru ELF.

Identita

Například jako součást procesu sestavování můžete vygenerovat - řekněme - info.c který obsahuje jeden nebo více #ident směrnice:

#ident "Build: 1.2.3 (Halloween)"
#ident "Environment: example.org"

Zkompilujte to:

$ gcc -c info.c

Zkontrolujte, zda jsou informace zahrnuty:

$ 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)

Případně můžete použít objdump -s --section .comment info.o . Všimněte si, že GCC také ve výchozím nastavení píše svůj vlastní komentář.

Po propojení spustitelného souboru ELF zkontrolujte informace:

$ 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

Sekce komentářů

Pomocí #ident v překladové jednotce C je v podstatě ekvivalentní vytvoření .comment sekce v souboru assembleru. Příklad:

$ 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

Funguje také použití neobvyklého názvu sekce (např. .section .blahblah ). Ale .comment je používán a chápán jinými nástroji. GNU as také rozumí .ident a to je to, co GCC překládá #ident do.

Se symboly

Pro data, ke kterým chcete přistupovat také ze samotného spustitelného souboru ELF, musíte vytvořit symboly.

Objcopy

Řekněme, že chcete zahrnout nějaké magické bajty uložené v datovém souboru:

$ cat magic.bin 
2342

Převeďte na objektový soubor pomocí GNU objcopy:

$ objcopy -I binary -O elf64-x86-64 -B i386 \
    --rename-section .data=.rodata,alloc,load,readonly,data,contents \
    magic.bin magic.o

Zkontrolujte symboly:

$ nm  magic.o  
0000000000000005 R _binary_magic_bin_end
0000000000000005 A _binary_magic_bin_size
0000000000000000 R _binary_magic_bin_start

Příklad použití:

#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;
}

Propojit vše dohromady:

$ gcc -g -o main_magic main_magic.c magic.o

GNU ld

GNU ld je také schopen převést datové soubory na objektové soubory pomocí schématu pojmenování kompatibilního s objcopy:

$ ld -r -b binary magic.bin -o magic-ld.o

Na rozdíl od objcopy umístí symboly do .data místo .rodata sekce však (srov. objdump -h magic.o ).

Inbin

V případě, že GNU objcopy není k dispozici, lze použít GNU jako .incbin direktiva k vytvoření objektového souboru (sestavení s 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

Přenosnější alternativa, která nevyžaduje GNU objcopy ani GNU, jako je vytvoření přechodného souboru C a jeho kompilace a propojení. Například s 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. Pořadí přesměrování?

  2. Třídit část souboru?

  3. Počítat řádky v souboru?

  1. Spuštění plochého binárního souboru pod Linuxem

  2. a.out nahrazeno formátem souboru ELF?

  3. Čtení ze souboru v sestavě

  1. Linux – všechno je soubor?

  2. Jak extrahovat pouze surový obsah sekce ELF?

  3. Jak grepovat část souboru v bash shellu