GNU/Linux >> Znalost Linux >  >> Linux

Linux ELF Object File Format (a struktura záhlaví ELF) Základy

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.


Linux
  1. Jak přesměrovat výstup do souboru a Stdout v Linuxu

  2. Linux – Jak lze zkontrolovat informace o struktuře adresářů souboru Unix/linux?

  3. Linux .htaccess tipy a triky

  1. Základy oprávnění k souborům Linux

  2. Příklady příkazů Linux Objcopy pro kopírování a překlad objektových souborů

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

  1. Jak dekomprimovat formát souboru .xz v Linuxu pomocí nástrojů tar a xz?

  2. Podporované a doporučené souborové systémy v systému Linux

  3. Jak přidat záhlaví a řádek upoutávky do souboru v Linuxu