What Makes an ELF File Tick? A Deep Dive into ELF and ARM ELF Formats
This article explains the ELF (Executable and Linking Format) specification, its variants for Windows PE and Linux, the classification of ELF object files, data representation, ARM‑specific extensions, and the structure of headers, sections, symbols, and related file types such as .axf, .bin and .hex.
ELF (Executable and Linking Format) is a binary file specification used to describe object files, executable files and shared libraries on Unix‑like systems and many embedded architectures, including ARM.
ELF File Types
Three main ELF object‑file categories are defined:
Relocatable file – contains code and data that can be linked into an executable or shared object (e.g., Linux .o, Windows .obj).
Executable file – a ready‑to‑run image without an extension on Linux (e.g., /bin/bash) or with .exe on Windows.
Shared object file – contains code and data that can be linked at runtime (Linux .so, Windows .dll).
A core‑dump file is also defined for storing a process’s memory image after a crash.
Data Representation
ELF stores control data in a machine‑independent format while actual program data follows the target processor’s encoding. No bit‑fields are used for portability. Common data types include Elf32_Addr (4‑byte address), Elf32_Half (2‑byte half‑word), Elf32_Off (file offset), Elf32_Word (4‑byte unsigned integer) and unsigned char (1‑byte).
ARM ELF Specifics
ARM uses the standard ELF format for all binaries. An ELF image consists of input sections, output sections, regions and segments, each visible at different linker stages. Input sections are grouped by the armlink tool into larger output sections and regions.
Input section – a distinct part of an object file (code, initialized data, or zero‑initialised memory).
Output section – a collection of input sections with the same attributes (RO, RW, XO, ZI).
Region – up to four output sections, ordered by attribute (XO → RO → RW → ZI) and typically mapped to physical storage (ROM, RAM, peripherals).
Program segment – a region that contains the executable image.
When an ELF image contains execute‑only (XO) sections, the linker creates separate XO segments unless the --xo-base option is used.
ELF Header
The ELF header appears at the very start of the file and defines architecture, OS ABI, file type, entry point, and offsets to the program‑header table and section‑header table. Key fields include: e_ident – magic number (0x7F, 'E', 'L', 'F'), class (32‑ or 64‑bit), data encoding, version. e_type – file type (ET_REL, ET_EXEC, ET_DYN, ET_CORE). e_machine – target architecture (e.g., EM_ARM = 40). e_entry – virtual address of the program’s entry point. e_phoff and e_shoff – file offsets of program and section header tables.
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT]; // Magic
Elf32_Half e_type; // Type
Elf32_Half e_machine; // Machine
Elf32_Word e_version; // Version
Elf32_Addr e_entry; // Entry point address
Elf32_Off e_phoff; // Start of program headers
Elf32_Off e_shoff; // Start of section headers
Elf32_Word e_flags; // Processor‑specific flags
Elf32_Half e_ehsize; // ELF header size
Elf32_Half e_phentsize; // Program header entry size
Elf32_Half e_phnum; // Number of program header entries
Elf32_Half e_shentsize; // Section header entry size
Elf32_Half e_shnum; // Number of section header entries
Elf32_Half e_shstrndx; // Section header string table index
} Elf32_Ehdr;Section Header Table
Each section in an ELF file has a corresponding header describing its name, type, flags, address, offset, size, link information and alignment. Important fields: sh_name – index into the string‑table for the section name (e.g., .text, .data, .bss). sh_type – classification such as SHT_PROGBITS, SHT_SYMTAB, SHT_STRTAB, SHT_RELA, SHT_NOBITS. sh_flags – attributes like SHF_ALLOC, SHF_WRITE, SHF_EXECINSTR, and ARM‑specific SHF_ARM_NOREAD. sh_addr – virtual address when loaded. sh_offset and sh_size – file location and length.
typedef struct {
Elf32_Word sh_name; // Section name index
Elf32_Word sh_type; // Section type
Elf32_Word sh_flags; // Section flags
Elf32_Addr sh_addr; // Virtual address
Elf32_Off sh_offset;// File offset
Elf32_Word sh_size; // Section size
Elf32_Word sh_link; // Link to another section
Elf32_Word sh_info; // Extra info
Elf32_Word sh_addralign; // Alignment
Elf32_Word sh_entsize; // Entry size if section holds a table
} Elf32_Shdr;Program Header Table
Only present in executable and shared‑object files, each entry describes a loadable segment. Key fields: p_type – segment type (PT_LOAD, PT_DYNAMIC, PT_INTERP, etc.). p_offset – file offset of the segment. p_vaddr – virtual address where the segment will reside. p_filesz and p_memsz – size in file and memory. p_flags – PF_X, PF_W, PF_R indicating executable, writable, readable. p_align – alignment requirement (must be a power of two).
typedef struct {
Elf32_Word p_type; // Segment type
Elf32_Off p_offset; // File offset
Elf32_Addr p_vaddr; // Virtual address
Elf32_Addr p_paddr; // Physical address (unused on most systems)
Elf32_Word p_filesz; // Size in file
Elf32_Word p_memsz; // Size in memory
Elf32_Word p_flags; // Segment flags
Elf32_Word p_align; // Alignment
} Elf32_Phdr;Symbol Table
The symbol table maps names to addresses, sizes and other attributes needed for linking and relocation. Each entry contains: st_name – index into the string table. st_value – address or offset depending on file type. st_size – size of the symbol. st_info – binding (local, global, weak) and type (function, object, section). st_shndx – section index (e.g., SHN_UNDEF, SHN_ABS, SHN_COMMON).
typedef struct {
Elf32_Word st_name; // Symbol name index
Elf32_Addr st_value; // Symbol value
Elf32_Word st_size; // Symbol size
unsigned char st_info; // Type and binding
unsigned char st_other; // Reserved
Elf32_Half st_shndx; // Section index
} Elf32_Sym;String Table
String‑table sections store null‑terminated strings used for section names and symbol names. The tables themselves have no special flags.
File Variants Used in ARM Development
.axf – an ELF‑based debug file that contains the full binary plus extensive debugging sections (DWARF, .debug, .line, etc.). Only the executable code is loaded onto the target.
.bin – a raw binary image containing just the machine code and data; it lacks any address or metadata, so the programmer must specify the load address when flashing.
.hex – Intel‑HEX format; ASCII records encode address, data bytes and a checksum. Each line follows the pattern :CCAAAARR[DD...]ZZ where CC is byte count, AAAA is the start address, RR is record type, DD is data and ZZ is the checksum.
References
Tool Interface Standard (TIS) ELF Specification v1.2
ARM® Compiler v5.06 User Guides (armlink, armcc)
ARM ELF File Format (ARM DUI 00101‑A)
ELF for the ARM® Architecture
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
