GNU/Linux >> Linux Esercitazione >  >> Linux

Nozioni di base sul formato file oggetto ELF Linux (e struttura intestazione ELF).

ELF sta per formato file eseguibile e collegabile.

ELF viene utilizzato come formato di file standard per i file oggetto su Linux. Prima di questo, il formato di file a.out veniva utilizzato come standard, ma recentemente ELF ha assunto l'incarico come standard.

ELF supporta :

  • Diversi processori
  • Diversa codifica dei dati
  • Diverse classi di macchine

Questo articolo spiega i diversi tipi di file oggetto ELF e di intestazione ELF.

File oggetto ELF

Un file che contiene codice compilato è noto come file oggetto. Un file oggetto può essere di uno qualsiasi dei seguenti tipi:

1. File trasferibile

Questo tipo di file oggetto contiene dati e codice che possono essere collegati insieme ad altri file riposizionabili per produrre un file binario eseguibile o un file oggetto condiviso. In parole povere, un file rilocabile è lo stesso del file .o prodotto quando compiliamo un codice nel modo seguente:

 gcc -Wall -c test.c -o test.o

Quindi il test.o prodotto dopo l'operazione di cui sopra sarebbe un file rilocabile.

2. File oggetto condiviso

Questo tipo di file oggetto viene utilizzato dal linker dinamico per combinarlo con l'eseguibile e/o altri file oggetto condivisi per creare un'immagine di processo completa. In parole povere, un file oggetto condiviso è uguale al file .so prodotto quando il codice viene compilato con il flag -fPIC nel modo seguente:

gcc -c -Wall -Werror -fPIC shared.c
gcc -shared -o libshared.so shared.o

Dopo aver eseguito i due comandi precedenti, viene prodotto come output un file oggetto condiviso libshared.o.

NOTA:per saperne di più sulle librerie condivise Linux, fare riferimento al nostro articolo Librerie condivise Linux

3. File eseguibile

Questo tipo di file oggetto è un file in grado di eseguire un programma durante l'esecuzione. In parole povere, è l'output di comandi come questo:

 gcc -Wall test.c -o test

Quindi, l'output "test" sarebbe un eseguibile che, una volta eseguito, eseguirà la logica scritta nel file test.c.

Quindi, come si può concludere dai suddetti tipi di file oggetto, un file oggetto partecipa dalla creazione del programma alla sua esecuzione o possiamo dire dal collegamento alla fase di esecuzione (per saperne di più sulle fasi di compilazione Linux/GCC, fare riferimento al nostro articolo Viaggio di un programma C).

Intestazione ELF

Tutti i file oggetto descritti sopra sono di tipo ELF su Linux.

Questo può essere facilmente dimostrato esaminando ciascuno di questi file. Ad esempio, ho esaminato ciascuno dei tre file nel mio sistema:

File trasferibile:

 $ 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
^@^@^@^@^@^@^@^@^@^@^@^@^@

File oggetto condiviso:

$ 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^@^@^@

File eseguibile:

$ 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^@^@^@

Quindi vediamo che poiché si tratta di file binari, nulla è comprensibile tranne la stringa ELF all'inizio di ogni file. Questo mostra che questi file sono solo in formato ELF.

Ogni file inizia con un'intestazione ELF che indica praticamente l'organizzazione completa del file. Ad esempio, i file oggetto rilocabili e condivisi contengono sezioni ma all'altra estremità il file eseguibile è composto da segmenti. Quindi, a seconda del tipo di file oggetto, l'intestazione ELF fornisce informazioni dettagliate sul file.

Per lo più in caso di file eseguibili, un'intestazione ELF è seguita da una tabella di intestazione del programma. Una tabella di intestazione del programma aiuta nella creazione dell'immagine di processo. Poiché aiuta nella creazione di un'immagine di processo (che viene creata dopo l'esecuzione dell'eseguibile), la tabella di intestazione del programma diventa obbligatoria per i file eseguibili ma è facoltativa per i file oggetto riposizionabili e condivisi.

Quella che segue è l'organizzazione dell'intestazione 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;

Quindi vediamo che l'organizzazione mostrata sopra ha la forma di una struttura. Spiegare ogni membro in dettaglio qui renderebbe le cose complesse, quindi esaminiamo il significato di base e le informazioni detenute da ciascun membro di questa struttura per avere un'idea di quel particolare campo.

1. e_ident

Come già sappiamo, il formato ELF supporta varie classi di macchine, processori ecc. Quindi, per supportare tutto ciò, le informazioni iniziali nel file ELF contengono informazioni su come interpretare il file indipendentemente dal processore su cui è in esecuzione l'eseguibile. L'array 'e_ident' fornisce esattamente le stesse informazioni :

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 I primi quattro byte sopra contengono il numero magico "0x7fELF".
  • EI_CLASS Un ELF può avere due classi, 32 bit o 64 bit. Questo rende il formato file portatile.
  • EI_DATA Questo membro fornisce le informazioni sulla codifica dei dati. In poche parole, queste informazioni indicano se i dati sono in formato big endian o little endian.
  • EI_VERSION Questo membro fornisce informazioni sulla versione del file oggetto.
  • EI_PAD Questo membro segna l'inizio dei byte non utilizzati nell'array di informazioni e_indent.
  • EI_NIDENT Questo membro fornisce la dimensione dell'array e_indent. Questo aiuta nell'analisi del file ELF.

2. e_type

Questo membro identifica il tipo di file oggetto. Ad esempio, un file oggetto può essere dei seguenti tipi:

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

NOTA:L'elenco sopra non è esaustivo ma fornisce comunque informazioni sui principali tipi di file oggetto a cui ELF può fare riferimento.

3. e_macchina

Questo membro fornisce informazioni sull'architettura richiesta da un file ELF.

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. Membri aggiuntivi

Oltre ai tre membri di cui sopra, ha anche i seguenti membri:

  • e_version:questo membro fornisce le informazioni sulla versione del file oggetto ELF.
  • e_entry:questo membro fornisce le informazioni sull'indirizzo virtuale del punto di ingresso a cui il sistema deve trasferire il controllo in modo che il processo possa essere avviato.
  • e_phoff:questo membro mantiene l'offset nella tabella di intestazione del programma. Queste informazioni sono memorizzate in termini di byte. In assenza di una tabella di intestazione del programma, le informazioni contenute da questo membro sono zero.
  • e_shoff:questo membro mantiene l'offset alla tabella di intestazione della sezione. Come per e_phoff, anche queste informazioni sono memorizzate sotto forma di byte e in assenza di una tabella di intestazione di sezione, le informazioni contenute in questo campo sono zero.
  • e_flags:questo membro contiene informazioni relative al processo di flag specifici.
  • e_ehsize:questo membro contiene informazioni relative alla dimensione dell'intestazione ELF in bye.
  • e_phentsize:questo membro contiene informazioni relative alla dimensione di una voce nella tabella dell'intestazione del programma del file oggetto. Nota che tutte le voci hanno le stesse dimensioni.
  • e_phnum:questo membro contiene le informazioni relative al numero di voci nella tabella dell'intestazione del programma.
  • e_shentsize:questo membro contiene le informazioni relative alla dimensione di una voce nella tabella dell'intestazione della sezione. La dimensione è rappresentata sotto forma di numero di byte.
  • e_shnum:questo membro fornisce le informazioni relative al numero di voci nella tabella dell'intestazione della sezione.

Nota che il prodotto di ephnum ed ephentsize fornisce la dimensione totale della tabella di intestazione del programma in byte e allo stesso modo il prodotto di eshnum ed eshentsize fornisce la dimensione totale della tabella di intestazione della sezione in byte.


Linux
  1. Come reindirizzare l'output su un file e Stdout in Linux

  2. Come decomprimere il formato di file .xz in Linux usando le utility tar e xz?

  3. Esempi di comandi Linux Objcopy per copiare e tradurre file oggetto

  4. File system supportati e consigliati su Linux

  5. Come aggiungere riga di intestazione e trailer a un file in Linux

Come montare e smontare i file system in Linux

Comando Ls in Linux (Elenca file e directory)

Nozioni di base su Linux:come nascondere, bloccare, crittografare e proteggere i tuoi file su Linux

File host Linux:come modificarlo e utilizzarlo?

Un'introduzione all'hashing e ai checksum in Linux

Nozioni di base sul legame Ethernet in Linux