Unlocking ELF: A Deep Dive into Linux Executable File Structure
This article provides a comprehensive, byte‑level walkthrough of the ELF file format on Linux, explaining headers, sections, program headers, string tables, and how linkers and loaders interpret each part using tools like readelf and od.
Introduction
The ELF (Executable and Linkable Format) file is the standard binary format used by Linux for executables, object files, and shared libraries. Understanding its internal layout is essential for mastering compilation, linking, and program loading.
Overall ELF Layout
ELF files consist of four logical parts: the ELF header, the Program header table, the Section header table, and the actual data sections. The header identifies the file type (executable, object, or shared library) and provides offsets to the other tables.
ELF Header
The ELF header acts as a master index, containing basic metadata such as file class, endianness, entry point, and the locations of the Program and Section header tables. For a 32‑bit ELF, the header occupies the first 52 bytes. od -Ax -t x1 -N 52 main The first 16 bytes ( e_ident) store the magic number and class information, while later fields describe the entry point, program header offset ( e_phoff), section header offset ( e_shoff), and counts of entries.
Program Header Table
The Program header describes how the loader should map segments into memory. Each entry (32 bytes for 32‑bit ELF) includes fields such as p_type, p_offset, p_vaddr, p_filesz, and p_memsz. For the example main binary, there are nine program headers, the first LOAD segment starting at file offset 0 and virtual address 0x08048000.
readelf -l mainSection Header Table
Sections are logical groupings of data (code, read‑only data, symbol tables, string tables, etc.). The Section header table, located at the offset given by e_shoff, contains an entry for each section. Important fields include sh_name (index into the string table), sh_type, sh_offset, and sh_size.
For example, the string‑table section ( .shstrtab) is entry 28, starting at file offset 0x0016ed and spanning 0x10a bytes.
readelf -S mainString Table
The string table stores all section names and other variable‑length strings. Its location and size are obtained from the corresponding section header entry. By extracting the bytes with od, you can view the raw strings. od -Ad -t c -j 5869 -N 266 main Offsets inside the string table (e.g., 0x11 = 17) point to specific names such as .shstrtab or .text.
Code Section (.text)
The executable code resides in a PROGBITS section, typically named .text. Its header entry provides the virtual address (e.g., 0x08048470), file offset (e.g., 0x470), and size (e.g., 434 bytes). od -Ad -t x1 -j 1136 -N 434 main Sample source used to generate the ELF:
// mymath.c
int my_add(int a, int b)
{
return a + b;
} // main.c
#include <stdio.h>
extern int my_add(int a, int b);
int main()
{
int i = 1;
int j = 2;
int k = my_add(i, j);
printf("k = %d
", k);
}Key Takeaways
ELF header gives a high‑level overview of the file and points to the program and section header tables. Each table consists of multiple entries that describe individual segments or sections, and linkers/loaders only read the parts they need.
By mastering these structures, you can confidently navigate compilation, linking, and runtime loading processes on Linux.
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.
