elf - Waaal/BobaOS GitHub Wiki
Elf is a executable file with a structure. ELF Files are object files that contain symbols that point to data or functions. Elf files can be dynamically linked at runtime. A modern kernel should be able to load and execute ELF files. A ELF file has a header tha contains various information like the entry point.
A ELF file contains a list of symbols with positioning information of where that symbol is located in the binary.
Note
A symbol in a assembly files are lables A symbol in a c file are functions and global variables
A ELF file also contains info about all the sections (text, data etc) so that we as the kernel can load and treat them differently. With ELF files DLLs (shared libraries) are also possbile because ELF files can contain references to symbol that are not known yet. So the kernel/loader can find these unknown symbols when loading a ELF file and resolve them.
A ELF file is structured like this
| ELF header |
| Program header table |
| .text |
| .rodata |
| .data |
| ... |
| Section header table |
ELF header: Contains the elf header, there is only one efl header at the beginning of a file
Program header table: Contains a array of different program headers. The Program header table is optional.
Section header table: Contains a array of different section headers
.text: contains code
.data: contains data
.rodata: contains read only data
A normal executable file contains sections (data, text) and a ELF file consits out of segments. One segment can hold one or multiple sections.
The ELF header contains all of the important info and positions of this file and a magic number at the start to identify that this is a ELF file.
| Index (32 bit) | Index (64 bit) | Size (32 bit) | Size (64 bit) | Description |
|---|---|---|---|---|
| 0 | 0 | 16 | 16 | e_ident |
| 16 | 16 | 2 | 2 | e_type |
| 18 | 18 | 2 | 2 | e_machine |
| 20 | 20 | 4 | 4 | e_version |
| 24 | 24 | 4 | 8 | e_entry |
| 28 | 32 | 4 | 8 | e_phoff |
| 32 | 40 | 4 | 8 | e_shoff |
| 36 | 48 | 4 | 4 | e_flags |
| 40 | 52 | 2 | 2 | e_ehsize |
| 42 | 54 | 2 | 2 | e_phentsize |
| 44 | 56 | 2 | 2 | e_phnum |
| 46 | 58 | 2 | 2 | e_shentsize |
| 48 | 60 | 2 | 2 | e_shnum |
| 50 | 62 | 2 | 2 | e_shstrndx |
e_ident:
| Index | Size | Description |
|---|---|---|
| 0 | 4 | Magic number (0x7F, 'E', 'L', 'F') |
| 4 | 1 | Class (1 = 32 bit, 2 = 64 bit) |
| 5 | 1 | Data (1 = little endian, 2 = big endian) |
| 6 | 1 | ELF header version |
| 7 | 1 | OS ABI |
| 8 | 8 | Unused/Padding |
e_type: Identifies the type of current ELF file
- 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 (A snapshot of the process right before it crashed or dumped)
- ET_LOPROC = 0xff00: Processor-specific
- ET_HIPROC = 0xffff: Processor-specific
e_machine: Required architecture for current file
- EM_NONE = 0: No machine
- EM_M32 = 1: AT&T WE 32100
- EM_SPARC = 2: SPARC
- EM_386 = 3: Intel
- 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
e_version: Version of the object file. 1 = original file. Extension will create new versions with higher numbers. Value EV_CURRENT is given as 1 or above.
- EV_NONE = 0: Invalid version
- EV_NONE = 1: Current version
e_entry: Virtual address of entry point of program.
e_phoff: Offset of program header table into ELF file in bytes. If there is no Program header table than 0.
e_shoff: Offset of section table into ELF file in bytes.
e_flags: Processor specific flags associated with the file.
e_ehsize: Size of the ELF header in bytes.
e_phentsize: Size of a entry in the program header table in bytes.
e_phnum: Number of entries in program header table.
e_shentsize: Size of a entry in the section table in bytes.
e_shnum: Number of entries in section table.
e_shstrndx: ????? Has something to do with the string table
A program header is a struct that normally describes one segment or other information the system needs to load the ELF file. Program headers a needed for executable (ET_EXEC) and shared object (ET_DYN) files.
| Index (32 bit) | Index (64 bit) | Size (32 bit) | Size (64 bit) | Description |
|---|---|---|---|---|
| 0 | 0 | 4 | 4 | p_type |
| - | 4 | - | 4 | p_flags |
| 4 | 8 | 4 | 8 | p_offset |
| 8 | 16 | 4 | 8 | p_vaddr |
| 12 | 24 | 4 | 8 | p_paddr |
| 16 | 32 | 4 | 8 | p_filesz |
| 20 | 40 | 4 | 8 | p_memsz |
| 24 | - | 4 | - | p_flags |
| 28 | 48 | 4 | 8 | p_align |
p_type: What kind of segment this program header describes.
- PT_NULL = 0: This segment is unused.
- PT_LOAD = 1: Loadable segment. Described by p_filesz and p_memsz.
- PT_DYNAMIC = 2: This segment is dynamic linking information.
- PT_INTERP = 3: This is the location and size of a null-terminated path name to invoke as interpreter.
- PT_NOTE = 4: This specifies the location and size of a auxiliary information.
- PT_SHLIB = 5: Reserved but has unspecified semantics.
- PT_PHDR = 6: Specifies the location nad size of the program header table itself.
p_offset: Offset from the begining of the ELF file to this segment.
p_vaddr: Virtual address of the segment.
p_paddr: On systems if the physical address is relevant. Physical address of the segment.
p_filesz: Size in bytes of this segment in the file.
p_memsz: Size in bytes of the segment in memory.
p_flags: Flags we should set on our paging.
- PF_X = 1: Segment is only executable.
- PF_W = 2: Segment is only writable.
- PF_W + PF_X = 3: Segment is executable and writable.
- PF_R = 4: Segment is only readable.
- PF_R + PF_X = 5: Segment is executable and readable.
- PF_R + PF_W = 6: Segment is readable and writable.
- PF_R + PF_W + PF_X = 7: Segment is readable, writable and executable
p_align: Loadable process: The required alignment for this section. (Because in paging everything has to be paging aligned). Values of 0 and 1 means no alignment is required.
Note
ELF file specification pdf: https://refspecs.linuxfoundation.org/elf/elf.pdf