A Complete Technical Reference for Systems Programmers
Introduction
- The Promise of This Book
- How This Book Is Organized
- How to Use This Book
- Prerequisites
- Conventions
Chapter 1: Origins and Design
- The Need for a Unified Format
- Design Objectives: Portability, Extensibility and Separation of Concerns
- The SVR4 Project and ELF Standardization
- ELF in the Modern Ecosystem
- Terminology and Conventions Used in This Book
Chapter 2: ELF at a Glance
- The Dual View: Linking Representation and Execution Representation
- High-Level File Layout
- ELF File Types
- Identification: Magic, Class, Data Encoding, Version, OS ABI
- Word Size, Endianness and Alignment Rules
Chapter 3: The ELF Header
- e_ident: The Identification Array in Detail
- 32-bit ELF Header Structure: elf32_hdr Field by Field
- 64-bit ELF Header Structure: elf64_hdr Field by Field
- Machine Types: EM_X86_64, EM_AARCH64 and the Complete List
- Entry Points, Program Header Table and Section Header Table Offsets
- Flags, Header Sizes and Alignment Constraints
Chapter 4: Sections and the Section Header Table
- The Section Header Table Structure and Layout
- sh_name, sh_type and All Defined Section Types
- Section Flags: SHF_WRITE, SHF_ALLOC, SHF_EXECINSTR and Beyond
- Address, Offset, Size, Link, Info and Alignment Fields
- Section Name String Table and the Null Section
- Special Sections: .text, .data, .bss, .rodata, .symtab, .strtab
Chapter 5: Segments and the Program Header Table
- The Program Header Table Structure and Layout
- Segment Types: PT_LOAD, PT_DYNAMIC, PT_INTERP, PT_GNU_STACK and All Others
- The Segment Type System: Standard and GNU Extensions
- Memory Mapping Semantics: Offsets, Virtual Addresses, Sizes
- Segment Permissions: PF_R, PF_W, PF_X and NX Interaction
- Overlapping Segments and File-to-Memory Mapping
Chapter 6: Symbol Tables
- Symbol Table Structure: elf64_sym Fields and Semantics
- Symbol Names and the String Table Relationship
- Symbol Types: STT_NOTYPE, STT_FUNC, STT_OBJECT and Complete List
- Symbol Binding: Local, Global, Weak and Their Linking Implications
- Symbol Visibility: STV_DEFAULT, STV_HIDDEN, STV_PROTECTED, STV_INTERNAL
- Symbol Table Organization and Index Conventions
Chapter 7: Relocations
- Why Relocation is Necessary: Positions, Dependencies and Resolving Addresses
- Relocation Entry Formats: elf64_Rel vs elf64_Rela
- The r_offset, r_info and r_addend Fields Decoded
- Relocation Type Encoding and Architecture-Specific Types
- Relative, Absolute and Copy Relocations: How Each Works
- The Relocation Application Algorithm
Chapter 8: String Tables and Names
- String Table Structure: Null-Terminated Concatenation
- String Indexing: Offset as Identifier
- Section Header String Table (.shstrtab)
- Symbol String Tables and Name Resolution
- Dynamic String Tables and Runtime Name Lookups
Chapter 9: The Dynamic Section and Dynamic Linking
- Dynamic Section Structure: elf64_Dyn and DT_* Entries
- DT_NEEDED: Dependency Declaration and Resolution
- DT_STRTAB, DT_SYMTAB, DT_HASH: The Dynamic Name System
- DT_RELA, DT_REL: Dynamic Relocation Descriptors
- DT_RPATH, DT_RUNPATH, DT_ORIGIN: Library Search Paths
- DT_SONAME, DT_FLAGS, DT_FLAGS_1: Identity and Capabilities
Chapter 10: Hash Tables and Symbol Lookup
- The System V Hash Table: Structure and Algorithm
- Hash Function: ELF_GNU_HFST and ELF_HFST
- The GNU Hash Table (g_HASH): Design and Lookup Algorithm
- Comparison: System V Hash vs GNU Hash Performance
- Symbol Lookup Rules: Preemption, Interposition and Binding Priority
Chapter 11: PLT, GOT and Lazy Binding
- The Global Offset Table: Indirect Addressing for Data and Code
- The Procedure Linkage Table: Trampolines for Indirect Calls
- Lazy Binding: How dlopen and Symbol Resolution Work at Runtime
- Eager Binding: DT_BIND_NOW and DF_1_NOW
- PLT/GOT Layout: x86-64 Convention and AArch64 Equivalents
- Symbol Interposition and the PLT
Chapter 12: Position-Independent Code and PIE
- Position-Independent Code: Concepts and Requirements
- PIC vs PIE: Shared Objects and Position-Independent Executables
- Relative Addressing and GOT/PCREL Relocations
- PIE and ASLR: Security Benefits and Implementation
- Building PIE: Compiler Flags, Linker Options and Resulting ELF
Chapter 13: Thread-Local Storage
- TLS Concepts: Thread-Local Data and Storage Models
- TLS Sections: .tdata, .tbss and the SHF_TLS Flag
- TLS Relocation Types: R_X86_64_TPOFF32, R_X86_64_GOTTPOFF and Others
- The Four TLS Access Models: Local-Exec, Initial-Exec, Local-Dynamic, General-Dynamic
- TLS Descriptor Mechanism
- Thread Pointer and TLS Base
Chapter 14: Constructors, Destructors and Initialization
- Preinit Arrays: .preinit_array and DT_PREINIT_ARRAY
- Init Arrays: .init_array, .fini_array and Their Roles
- Init and Fini Functions: .init and .fini Sections
- Initialization Order: Dependencies, Library Initialization Sequence
- attribute((constructor)) and attribute((destructor))
Chapter 15: Linker Scripts and Custom Sections
- Linker Script Language: INPUT, SECTIONS, OUTPUT FORMAT
- Section Assignment and Memory Region Control
- Custom Sections: Creating and Populating .my_section
- Linker Script Variables and Symbols
- Advanced Layouts: Discontiguous Sections, Padding, Alignment
- Example: Building a Custom Layout with GCC and LD Scripts
Chapter 16: From Source to Binary: The Complete Lifecycle
- Compilation: From C to Assembly to Object File
- The Object File: Sections, Symbols and Relocations Generated
- Static Linking: Merging Objects, Resolving Symbols, Applying Relocations
- Dynamic Linking: Shared Object References and Unresolved Symbols
- Build Case Study: From hello.c Through All Stages to a Running Process
Chapter 17: The Dynamic Linker and Loader
- PT_INTERP and the Dynamic Linker Entry
- Loading Sequence: Map, Parse, Resolve, Initialize
- Library Search Path Resolution: LD_LIBRARY_PATH, RPATH, RUNPATH, System Paths
- Dependency Graph Resolution and Load Order
- Relocation Application at Load Time
- Lazy Resolution and PLT Trampolines in Action
Chapter 18: Executing an ELF Binary
- execve and the Kernel: Parsing ELF in sys_execve
- Kernel ELF Loading: Mapping Segments into Address Space
- PT_GNU_STACK and Stack Permissions
- Auxiliary Vector: AT_ENTRY, AT_PHDR, AT_RANDOM and Others
- Stack Setup, Environment and argc/argv
- Transfer of Control to Entry Point and _start
Chapter 19: Notes and Metadata
- Note Section Structure: n_name, n_descsz, n_desc
- PT_NOTE Segments and Core Dump Notes
- GNU Build Attributes: .note.gnu.build-id
- Build ID: Computing and Using ELF Identity
- Core Dump Notes: NT_PRSTATUS, NT_PRPSINFO, NT_FILE, NT_SIGINFO
- Notes in Shared Objects and Executables
Chapter 20: GNU and Linux Extensions
- GNU Hash Table: DT_GNU_HASH Details
- RELRO: PT_GNU_RELRO and Partial RELRO vs Full RELRO
- IFUNC: Indirect Functions
- Verneed and Verdef: Symbol Versioning
- Stack Protector and Canary Implementation
- GNU Property Notes: .note.gnu.property
Chapter 21: Architecture-Specific Details: x86-64
- x86-64 ELF Conventions: ABI and Calling Convention Impact
- x86-64 Relocation Types: Complete Reference
- x86-64 PLT/GOT Layout and Calling Sequences
- x86-64 TLS: FS Register and Access Models
- x86-64 e_flags and Machine-Specific Behavior
Chapter 22: Architecture-Specific Details: AArch64
- AArch64 ELF Conventions: AAPCS64 and Calling Convention Impact
- AArch64 Relocation Types: Key Types and Semantics
- AArch64 PLT/GOT Layout and Calling Sequences
- AArch64 TLS: TPIDR_EL0 and Access Models
- AArch64 e_flags and Machine-Specific Behavior
Chapter 23: Tools and Practical Analysis
- readelf: Complete Option Reference and Interpretation
- objdump: Disassembly, Relocation Listing and Headers
- nm: Symbol Table Inspection and Symbol Types
- ldd: Dynamic Dependency Analysis
- file, hexdump and Strace for Binary Analysis
- GDB for Runtime ELF Inspection: Breakpoints, Memory Maps and Symbols
Chapter 24: An ELF Parser and Inspector
- Project Setup and Header Definitions
- Parsing the ELF Header and Validating the File
- Parsing Section Headers and Enumerating Sections
- Parsing Program Headers and Mapping Segments
- Symbol Table Parsing and Display
- Relocation Parsing and Decode
- Dynamic Section Analysis
- Complete Utility Usage and Example Output
Chapter 25: ELF Security
- Buffer Overflows and Stack Smashing: ELF Perspective
- Format String Vulnerabilities and GOT Overwrite
- Return-Oriented Programming: PLT, Gadgets and RELRO
- GOT Hijacking and Symbol Interposition Attacks
- ASLR and PIE: Mitigating Address Revelation
- NX and W^X: Enforcing Through PT_GNU_STACK and Segment Permissions
- LD_PRELOAD Attacks and Defense
- Malformed ELF Exploitation and Parser Robustness
Chapter 26: Advanced Topics
- Binary Instrumentation: ptrace, LD_PRELOAD and ELF Modification
- Runtime Patching: Modifying Running ELF Processes
- Custom ELF Generation: Building ELF in User Space
- Packing and Unpacking: Obfuscated ELF Binaries
- Reverse Engineering ELF: Static Analysis Techniques
- Forensic Analysis: Core Dumps and Memory Images
- ELF Parsing Edge Cases: Robustness and Security
