MODULE 5

Segments and Loading

While sections organize a binary for the linker, program headers (segments) tell the kernel how to load the binary into memory. The kernel ignores section names entirely — it only reads the program header table.

Memory Map

Load a binary to view its memory map

PT_LOAD — The Workhorse

PT_LOAD segments are the only ones that actually get mapped into memory. A typical executable has two or three PT_LOAD segments:

R X

Code Segment

Contains .text, .rodata, and other read/execute sections. Mapped as readable and executable but not writable.

R W

Data Segment

Contains .data, .bss, .got, and other writable sections. Mapped as readable and writable.

R

Read-Only Segment

Contains the ELF header, program headers, and other metadata. Mapped as read-only.

PT_INTERP — Dynamic Linker Path

This segment contains a single null-terminated string: the path to the dynamic linker (usually /lib64/ld-linux-x86-64.so.2). When the kernel loads a dynamically-linked executable, it reads this path and hands control to the dynamic linker before your program's main() runs.

PT_DYNAMIC — Dynamic Section Pointer

Points to the .dynamic section, which contains the roadmap for dynamic linking: which shared libraries to load, where to find the symbol table, relocation entries, and more. The dynamic linker reads this to set up the process.

p_memsz > p_filesz — The BSS Gap

When a segment's memory size exceeds its file size, the extra bytes are zero-filled by the kernel. This is how .bss data gets included in a PT_LOAD segment without wasting disk space. The segment covers both initialized data (from the file) and uninitialized data (zero-filled by the kernel).

File:
p_filesz bytes from disk
Mem:
file data
zeros (BSS)
p_memsz = p_filesz + BSS size
💡Kernel vs Linker
The kernel doesn't care about section names. It only reads program headers. Sections like .text, .data, and .rodata are meaningful to the linker and debugger, but the kernel maps memory based purely on PT_LOAD segments and their permission flags.

Program Header Table

Loading binary...
Challenge

Why might p_memsz be larger than p_filesz?