Os arquivos ELF são como mapas para o kernel e as ferramentas de sistema: eles dizem exatamente onde cada pedaço do binário deve ser colocado na memória, quem pode fazer o quê (como executar, escrever ou só ler), e onde tudo começa a rodar. Além disso, eles carregam instruções extras para os carregadores dinâmicos, indicando quais bibliotecas precisam ser conectadas em tempo de execução. Para as ferramentas de análise, como depuradores e linkers, o ELF entrega uma tabela bem organizada com símbolos, endereços, nomes de funções e muito mais.
O ELF Header funciona como o cartão de visitas do binário, contendo informações essenciais que identificam o arquivo como ELF, definem a arquitetura para a qual ele foi compilado, Informa o endereço do entry point, o ponto de partida para a execução do código, e indicam o endianness (ordem dos bytes). Além disso, ele especifica os offsets que apontam para outras estruturas importantes do arquivo, como a Section Header Table (SHT) e a Program Header Table (PHT), além do tamanho do próprio ELF Header, entre outros dados. Esses detalhes serão explorados com mais profundidade nas próximas seções.
A definição formal dos campos do ELF Header é declarada no arquivo de cabeçalho elf.h
. Nesse arquivo, as informações são organizadas em uma struct
C, cuja implementação varia conforme a arquitetura. Para sistemas de 64 bits (x86_64), utiliza-se a estrutura Elf64_Ehdr
, que possui um tamanho fixo de 64 bytes e Para sistemas de 32 bits (x86), a estrutura correspondente é a Elf32_Ehdr
, com um tamanho de 52 bytes.
------elf.h------
#define EI_NIDENT (16)
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf64_Half e_type; /* Object file type */
Elf64_Half e_machine; /* Architecture */
Elf64_Word e_version; /* Object file version */
Elf64_Addr e_entry; /* Entry point virtual address */
Elf64_Off e_phoff; /* Program header table file offset */
Elf64_Off e_shoff; /* Section header table file offset */
Elf64_Word e_flags; /* Processor-specific flags */
Elf64_Half e_ehsize; /* ELF header size in bytes */
Elf64_Half e_phentsize; /* Program header table entry size */
Elf64_Half e_phnum; /* Program header table entry count */
Elf64_Half e_shentsize; /* Section header table entry size */
Elf64_Half e_shnum; /* Section header table entry count */
Elf64_Half e_shstrndx; /* Section header string table index */
} Elf64_Ehdr;
Como definido na estrutura Elf64_Ehdr
, o campo e_ident
é um array de 16 bytes (unsigned char e_ident[16]
). Ele armazena informações fundamentais sobre o formato do binário ELF, sendo cada posição do array responsável por indicar uma característica específica do arquivo.
Offset | Membro | Descrição |
---|---|---|
0x00–0x03 | EI_MAG0…EI_MAG3 | Número Mágico (Magic Number): Contém a sequência 0x7F 'E' 'L' 'F' que identifica o arquivo como um binário no formato ELF. |
0x04 | EI_CLASS | Classe do Arquivo: Define a arquitetura do processo. 1 (ELFCLASS32) para 32 bits ou 2 (ELFCLASS64) para 64 bits. |
0x05 | EI_DATA | Endianness: Define a ordem dos bytes dos dados no arquivo. 1 (ELFDATA2LSB) para Little Endian ou 2 (ELFDATA2MSB) para Big Endian. |
0x06 | EI_VERSION | Versão do ELF: Indica a versão do formato ELF. Atualmente, o valor padrão e único válido é 1. |
0x07 | EI_OSABI | OS/ABI: Identifica a Application Binary Interface (ABI) específica do sistema operacional. Por exemplo, 0 para System V, 3 para GNU/Linux. |
0x08 | EI_ABIVERSION | Versão da ABI: Indica a versão da ABI definida em EI_OSABI. O valor geralmente é 0. |
0x09–0x0F | EI_PAD | Padding: Bytes de preenchimento não utilizados, reservados para futuras extensões da especificação. São sempre preenchidos com zero. |
ELF HEADER
Definição de Elf64/32_Half dentro de elf.h
Como vimos anteriormente, o campo e_type
no cabeçalho ELF é do tipo Elf64_Half
. Ao verificarmos no arquivo elf.h
, constatamos que Elf64_Half
é um alias para uint16_t
, ou seja, um valor inteiro sem sinal de 16 bits. Isso significa que o campo e_type
ocupa exatamente 2 bytes. Portanto, os dois bytes que vêm após o array e_ident
(que tem 16 bytes) correspondem ao valor de e_type
.
ELF HEADER
O campo e_type
no cabeçalho ELF (Executable and Linkable Format) indica o tipo do arquivo ELF, ou seja, qual é o propósito do binário. Ele informa ao sistema operacional como interpretar e lidar com aquele arquivo.
Valor Hex | Nome constante | Significado |
---|---|---|
0x0000 |
ET_NONE |
Tipo indefinido (sem propósito específico) |
0x0001 |
ET_REL |
Object File (.o ) |
0x0002 |
ET_EXEC |
Arquivo executável |
0x0003 |
ET_DYN |
Shared Object (ex: .so ) |
0x0004 |
ET_CORE |
Arquivo de core dump |
0xFE00–FFFF |
ET_LOPROC até ET_HIPROC |
Reservado para uso de processadores específicos |
É importante notar que o tipo ET_DYN (valor 0x03) no cabeçalho ELF não se limita a bibliotecas compartilhadas (.so). Atualmente, ele também é o padrão para executáveis compilados como PIE (Position-Independent Executable).