ELF znamená spustitelný a propojitelný souborový formát.
ELF se používá jako standardní souborový formát pro objektové soubory v Linuxu. Předtím se jako standard používal souborový formát a.out, ale v poslední době převzal standard ELF.
ELF podporuje :
- Různé procesory
- Odlišné kódování dat
- Různé třídy strojů
Tento článek vysvětluje různé typy souborů objektů ELF a záhlaví ELF.
ELF Object Files
Soubor, který obsahuje zkompilovaný kód, se nazývá objektový soubor. Soubor objektu může být kteréhokoli z následujících typů:
1. Přemístitelný soubor
Tento typ objektového souboru obsahuje data a kód, které lze propojit s jinými přemístitelnými soubory a vytvořit spustitelný binární nebo sdílený objektový soubor. Laicky řečeno, přemístitelný soubor je stejný jako soubor .o vytvořený při kompilaci kódu následujícím způsobem:
gcc -Wall -c test.c -o test.o
Takže test.o vytvořený po operaci výše by byl přemístitelný soubor.
2. Soubor sdíleného objektu
Tento typ objektového souboru používá dynamický linker ke spojení se spustitelným souborem a/nebo jinými sdílenými objektovými soubory k vytvoření kompletního obrazu procesu. Laicky řečeno, soubor sdíleného objektu je stejný jako soubor .so vytvořený při kompilaci kódu s parametrem -fPIC následujícím způsobem:
gcc -c -Wall -Werror -fPIC shared.c gcc -shared -o libshared.so shared.o
Po provedení dvou výše uvedených příkazů se jako výstup vytvoří sdílený objektový soubor libshared.o.
POZNÁMKA:Další informace o sdílených knihovnách Linuxu naleznete v našem článku Sdílené knihovny pro Linux
3. Spustitelný soubor
Tento typ objektového souboru je soubor, který je schopen při spuštění spustit program. Laicky řečeno, je to výstup příkazů jako je tento:
gcc -Wall test.c -o test
Takže výstupní „test“ by byl spustitelný soubor, který by při spuštění provedl logiku zapsanou v souboru test.c.
Jak lze tedy usoudit z výše uvedených typů objektových souborů, objektový soubor se účastní od vytvoření programu až po jeho spuštění nebo můžeme říci od propojení do fáze provádění (více o fázích kompilace Linux/GCC se dozvíte v našem článku Journey of program C).
Záhlaví ELF
Všechny výše popsané objektové soubory jsou v Linuxu typu ELF.
To lze snadno dokázat pohledem do každého z těchto souborů. Například jsem se podíval do každého ze tří souborů v mém systému:
Přemístitelný soubor:
$ vim func.o ^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^A^@>^@^A^@^@^@^@^@^@^@^@^@^@^@ ^@UHå¿^@^@^@^@è^@^@^@^@¸^@^@^@^@è^@^@^@^@ÉÃ^@^@ Inside func()^@^@GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3^@^T^@^@^@^@ ^@^@^@^AzR^@^Ax^P^A^[^L^G^H^A^@^@^\^@^.symtab^@.strtab^@.shstrtab^ @.rela.text^@.data^@.bss^@.rodata^@.comment^@.note.GNU-stack^@.rela.eh_frame ^@^@^@^@^@^@^@^@^@^@^@^@^@
Soubor sdíleného objektu:
$ vim libshared.so ^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^C^@>^@^A^@^@^@ ^@^@^@^@^@^A^@^@^@^F^@^ ^@^@^@^@^@è^A^@^@^@^@^@^@è^A^@^@^@^@^@^@^A^@^@^@^@^@^@^@^D^@^@^@^T^@^@^ @^C^@^@^@GNU^@·YG®z^L^ZÊ7uÈí,?^N^@^@^@^@^C^@^@^@^L^@^@^@
Spustitelný soubor:
$ vim test ^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^B^@>^@^A^@^@^@P@^@^@^@^@^@@^@^@^@^@^@< ^@^@^@D^@^@^^B^@^@^@^@^@^@^A^@^@^@^@^@^@^@/lib64/ld-linux-x86-64.so.2^@^D^ @^@^@^D^@^@^@^T^@^@^@^C^@^@^@GNU^@òÁ}CKbE;ära`6"^O^N\^C^@^@^@
Vidíme tedy, že jelikož se jedná o binární soubory, není nic moc srozumitelného kromě řetězce ELF na začátku každého souboru. To ukazuje, že tyto soubory jsou pouze ve formátu ELF.
Každý soubor začíná hlavičkou ELF, která v podstatě vypovídá o kompletní organizaci souboru. Například soubory přemístitelných a sdílených objektů obsahují sekce, ale na druhém konci se spustitelný soubor skládá ze segmentů. V závislosti na typu objektového souboru tedy hlavička ELF poskytuje podrobné informace o souboru.
Většinou v případě spustitelných souborů následuje po hlavičce ELF tabulka hlaviček programu. Tabulka záhlaví programu pomáhá při vytváření obrazu procesu. Protože pomáhá při vytváření obrazu procesu (který se vytváří po spuštění spustitelného souboru), tabulka záhlaví programu se stává povinnou pro spustitelné soubory, ale je volitelná pro soubory s přemístitelnými a sdílenými objekty.
Následuje organizace hlavičky ELF:
#define EI_NIDENT 16 typedef struct { e_ident[EI_NIDENT]; unsigned char e_type; Elf32_Half e_machine; Elf32_Half e_version; Elf32_Word e_entry; Elf32_Addr e_phoff; Elf32_Off e_shoff; Elf32_Off e_flags; Elf32_Word e_ehsize; Elf32_Half e_phentsize; Elf32_Half e_phnum; Elf32_Half e_shentsize; Elf32_Half e_shnum; Elf32_Half e_shstrndx; } Elf32_Ehdr;
Vidíme tedy, že výše uvedená organizace má formu struktury. Podrobné vysvětlení každého člena zde by věci zkomplikovalo, takže si pojďme projít základní význam a informace, které má každý člen této struktury, abychom získali představu o tomto konkrétním oboru.
1. e_ident
Jak již víme, formát ELF podporuje různé třídy strojů, procesorů atd. Abychom toto vše podpořili, počáteční informace v souboru ELF obsahují informace o tom, jak interpretovat soubor nezávisle na procesoru, na kterém spustitelný soubor běží. Pole „e_ident“ poskytuje přesně stejné informace:
Name Value Purpose EI_MAG 0 File identification EI_MAG1 1 File identification EI_MAG2 2 File identification EI_MAG3 3 File identification EI_CLASS 4 File class EI_DATA 5 Data encoding EI_VERSION 6 File version EI_PAD 7 Start of padding bytes EI_NIDENT 16 Size of e_ident[]
- EI_MAG První čtyři bajty výše obsahují magické číslo „0x7fELF“.
- EI_CLASS ELF může mít dvě třídy, 32bitovou nebo 64bitovou. Díky tomu je formát souboru přenosný.
- EI_DATA Tento člen poskytuje informace o kódování dat. Jednoduše řečeno, tato informace říká, zda jsou data ve formátu big endian nebo little endian.
- EI_VERSION Tento člen poskytuje informace o verzi objektového souboru.
- EI_PAD Tento člen označuje začátek nepoužitých bajtů v poli informací e_indent.
- EI_NIDENT Tento člen poskytuje velikost pole e_indent. To pomáhá při analýze souboru ELF.
2. e_type
Tento člen identifikuje typ souboru objektu. Objektový soubor může být například následujících typů:
Name Value Meaning ET_NONE 0 No file type ET_REL 1 Relocatable file ET_EXEC 2 Executable file ET_DYN 3 Shared object file ET_CORE 4 Core file
POZNÁMKA:Výše uvedený seznam není vyčerpávající, ale stále poskytuje informace o hlavních typech souborů objektů, na které může ELF odkazovat.
3. e_machine
Tento člen poskytuje informace o architektuře, kterou soubor ELF vyžaduje.
Name Value Meaning ET_NONE 0 No machine EM_M32 1 AT&T WE 32100 EM_SPARC 2 SPARC EM_386 3 Intel Architecture EM_68K 4 Motorola 68000 EM_88K 5 Motorola 88000 EM_860 7 Intel 80860 EM_MIPS 8 MIPS RS3000 Big-Endian EM_MIPS_RS4_BE 10 MIPS RS4000 Big-Endian RESERVED 11-16 Reserved for future use
4. Další členové
Kromě výše uvedených tří členů má ještě tyto členy:
- e_version:Tento člen poskytuje informace o verzi souboru objektu ELF.
- e_entry:Tento člen poskytuje informace o virtuální adrese vstupního bodu, na který musí systém přenést řízení, aby mohl být proces zahájen.
- e_phoff:Tento člen drží offset tabulky záhlaví programu. Tyto informace jsou uloženy v bytech. Při absenci tabulky záhlaví programu jsou informace obsažené tímto členem nulové.
- e_shoff:Tento člen uchovává posun tabulky záhlaví sekce. Stejně jako u e_phoff jsou i tyto informace uloženy ve formě bajtů a při absenci tabulky záhlaví sekcí jsou informace obsažené v tomto poli nulové.
- e_flags:Tento člen uchovává informace související se specifickými příznaky procesu.
- e_ehsize:Tento člen uchovává informace související s velikostí záhlaví ELF v byes.
- e_phentsize:Tento člen obsahuje informace související s velikostí jedné položky v tabulce záhlaví programu objektového souboru. Všimněte si, že všechny položky mají stejnou velikost.
- e_phnum:Tento člen obsahuje informace související s počtem položek v tabulce záhlaví programu.
- e_shentsize:Tento člen obsahuje informace týkající se velikosti jednoho záznamu v tabulce záhlaví sekce. Velikost je reprezentována ve formě počtu bajtů.
- e_shnum:Tento člen poskytuje informace související s počtem záznamů v tabulce záhlaví sekce.
Všimněte si, že součin ephnum a ephentsize udává celkovou velikost tabulky záhlaví programu v bajtech a stejným způsobem součin eshnum a eshentsize udává celkovou velikost tabulky záhlaví sekcí v bajtech.