Skip to content

06. Compilation Process and ELF Architecture (Compilation & ELF File Format)

Investigating the low-level toolchain pipeline converting source text into machine code, and the Dual View architecture (Linking View vs Execution View) governing the Executable and Linkable Format (ELF).


1. Learning Objectives & Overview

  • Understand how C code progresses through lexical analysis, syntax parsing, intermediate representation (IR), and assembly into an ELF binary.
  • Examine why the ELF specification provides both a Linking View (Section Header oriented) for static linkers and an Execution View (Program Header oriented) for operating system loaders.
  • Analyze the 64-byte Elf64_Ehdr structure and the kernel's validation of magic bytes (\x7fELF).
  • Parse key program segments (PT_LOAD, PT_INTERP, PT_GNU_STACK) referenced by the Linux kernel when materializing virtual memory areas (VMAs).

2. Interactive ELF Architecture & Dual View Diagram

Explore the dual view mapping and W^X memory permissions through the interactive diagram below:


3. Toolchain Code Transformation Pipeline

High-level C syntax is downgraded to CPU opcodes across several compiler phases:

flowchart LR
    A["C Source Code"] --> B["Lexical Analysis (Lexer)"]
    B --> C["Syntax Analysis (Parser: AST)"]
    C --> D["Intermediate Representation (LLVM IR)"]
    D --> E["Optimization Passes"]
    E --> F["Code Generation (ASM: .s)"]
    F --> G["Assembler (as ➔ .o)"]
    G --> H["Linker (ld ➔ ELF64)"]

    style A fill:#1e293b,stroke:#38bdf8,stroke-width:2px,color:#fff
    style D fill:#1e293b,stroke:#a855f7,stroke-width:2px,color:#fff
    style H fill:#1e293b,stroke:#10b981,stroke-width:2px,color:#fff
  1. Lexical and Syntax Parsing:
  2. Tokenizes raw characters into syntax tokens, building an Abstract Syntax Tree (AST).
  3. Intermediate Representation & Optimization:
  4. Generates architecture-neutral IR (LLVM IR) for optimization passes (dead code elimination, loop unrolling).
  5. Code Generation & Assembly:
  6. Emits target assembly instructions, mapped 1:1 into relocatable object files (.o).

4. Dual View Architecture: Linking vs Execution

The ELF specification serves two separate consumers across the binary lifecycle:

[ Linking View: Section Focused ]               [ Execution View: Segment Focused ]
  (Used by ld and GDB)                            (Used by kernel load_elf_binary)
┌─────────────────────────┐                   ┌─────────────────────────┐
│       ELF Header        │                   │       ELF Header        │
├─────────────────────────┤                   ├─────────────────────────┤
│  Program Header Table   │ (Optional)        │  Program Header Table   │ (Required!)
├─────────────────────────┤                   ├─────────────────────────┤
│  .text / .init / .plt   │ ──(Bundling)────> │  PT_LOAD 1 (RX)         │ (Code Segment)
├─────────────────────────┤                   ├─────────────────────────┤
│  .rodata / .eh_frame    │ ──(Bundling)────> │  PT_LOAD 2 (R--)        │ (Read-Only Segment)
├─────────────────────────┤                   ├─────────────────────────┤
│  .data / .bss / .got    │ ──(Bundling)────> │  PT_LOAD 3 (RW-)        │ (Data Segment)
├─────────────────────────┤                   ├─────────────────────────┤
│  Section Header Table   │ (Required!)       │  Section Header Table   │ (Optional / Strippable)
└─────────────────────────┘                   └─────────────────────────┘

4.1 Key ELF Header Fields (Elf64_Ehdr)

Field Name Type Purpose & Security Implications
e_ident[EI_MAG0..3] unsigned char[4] ELF Magic bytes (\x7fELF). Validated first by the kernel
e_type Elf64_Half ET_EXEC (Fixed address executable) or ET_DYN (PIE / Shared object)
e_machine Elf64_Half Target architecture (EM_X86_64 = 62, EM_AARCH64 = 183)
e_entry Elf64_Addr Virtual memory address of initial execution entry point (_start)
e_phoff / e_phnum Elf64_Off / Half Offset and count of Program Header Table entries
e_shoff / e_shnum Elf64_Off / Half Offset and count of Section Header Table entries

5. Lab Source Code & Direct ELF Parsing

5.1 Building and Running the Parser

cd labs/principles/06-elf-structure
make inspect-self
============================================================
 64-bit ELF Header Inspection: elf_inspector
============================================================
[1] Magic Bytes      : 7f 45 4c 46 (ASCII: \x7fELF)
[2] Architecture     : ELF64 (64-bit)
[3] Data Encoding    : 2's complement, Little Endian
[4] Entry Point      : 0x401130
[5] Program Headers  : Offset 0x40 (13 entries, size 56 bytes)
[6] Section Headers  : Offset 0x3890 (30 entries, size 64 bytes)
============================================================

=== [Execution View] Program Headers (Segments) ===
Type               Offset     VirtAddr           MemSize    Flags 
-----------------------------------------------------------------
PT_PHDR            0x40       0x400040           0x2d8      R--
PT_INTERP          0x318      0x400318           0x1c       R--
PT_LOAD            0x0        0x400000           0x780      R--
PT_LOAD            0x1000     0x401000           0x691      R-E
PT_LOAD            0x2000     0x402000           0x6cc      R--
PT_LOAD            0x2de8     0x403de8           0x2a8      RW-
PT_GNU_STACK       0x0        0x0                0x0        RW-
PT_GNU_RELRO       0x2de8     0x403de8           0x218      R--
  • Confirm separation of permissions across segments: PT_LOAD R-E for text, PT_LOAD RW- for data, and PT_GNU_STACK RW- indicating NX/DEP enforcement.

6. Summary & Next Chapter