Skip to content

0x03 - The Program Header

Picsart_25-08-21_18-46-34-427

This is the final part of the ELF: Diving Deep Inside series.
In this article, we’ll explore the Program Header Table, its fields and view of an PHT of a real ELF binary.

Program Header table provides the segment view of the binary as opposed to section header table which provide the section view of the binary.

Segements are used by the operating system and dynamic linkers to load the data and code in virtual memory and make the process run.

Each Segment can consist of one or more section.

The segment (defined in the Program Header Table) is what decides:

  • Which sections go together

  • What virtual address they get mapped to

  • What memory permissions (R, W, X) they will have

Typedef of Program Header Table in /usr/include/elf.h

Screenshot From 2025-08-23 09-56-53

Now let’s dicuss about each of the field one by one.

  • As the name implies this field denotes the type of the segment.
  • Size : 4 Bytes
  • Values : PT_LOAD (Sections covered in this type of segment should be loaded in memory), PT_DYNAMIC (This include the .dynamic section which tells how to parse and prepare for execution), PT_PHDR (Includes the program header table) and PT_INTERP (include .interp section which denotes the interpreter to be used for loading)
  • Flags are used to define the access permission of segment in memory.
  • Size : 4 Bytes
  • Values : PF_X, PF_W, PF_R - for execute, write, read respectively.

p_offset, p_vaddr, p_paddr, p_filesz, and p_memsz

Section titled “p_offset, p_vaddr, p_paddr, p_filesz, and p_memsz”
  • p_offset
    • This denotes the posiiton of the segement in the binary
    • Size : 8 Bytes
    • Value : Not the address but the offset (value that need to be added to the start address of segment)
  • p_vaddr
    • This denotes the virtual address where the segment will be loaded.
    • Size : 8 Bytes
  • p_filesz
    • Size of the segment when stored in disk.
    • Size (of field in struct) : 8 Bytes
  • p_memsz
    • Size of the segment in memory.
    • Size (of field in struct) : 8 Bytes

p_filesz and p_memsz can be different for a single segment because when storing file on disk data block with null bytes are not actually stored with all null bytes but when loaded in memory all null bytes are stored

  • p_paddr
    • Physical address where the segement will be loaded. (NOTE: This is no more used in modern OS)
    • Size : 8 Bytes
  • This defines the alignment requirement for the segment.
  • Size : 8 Bytes
  • Value : Should be power of 2 , Value 0 and 1 means no alignment required.

To view the program header table for a ELF binary use -

readelf --segments --wide <binary>
Screenshot From 2025-08-23 11-19-04

The Section to Segment mapping clearly defines which segment consists exactly which sections.

The Program Header Table defines how an ELF binary is loaded into memory, grouping sections into segments with proper addresses and permissions. With this, we wrap up the ELF deep dive series—you now have the essentials to understand and explore ELF internals further.