archiveAug 16, 2020
ELF program headers
How ELF program headers describe loadable segments — PT_LOAD, PT_DYNAMIC, PT_NOTE, PT_INTERP, PT_PHDR — and what readelf -l shows for text versus data.
ELF program headers
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
ElfN_Addr e_entry;
ElfN_Off e_phoff;
ElfN_Off e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} ElfN_Ehdr;ELF program headers define the binary segments needed to load a program. A segment describes how an on-disk executable maps into memory when the kernel loads it. Reach the program header table through the ELF header's e_phoff field.
The five program header types you meet most often define segments for executables and shared libraries and say what kind of data or code each segment holds. Below is a walk through Elf32_Phdr for a 32-bit ELF.
PT_LOAD
An executable needs at least one PT_LOAD segment. That header marks a loadable segment that the loader maps into memory.
동적 링킹이 가능한 ELF 실행 파일에 두 가지 로드 가능한 세그먼트가(PT_LAOD)가 포함된다.
1. 프로그램 코드가 위치한 텍스트 세그먼트
2. 전역 변수와 동적 링킹 정보가 위치한 데이터 세그먼트Dynamically linked ELF binaries typically carry two loadable segments: a text segment for code, and a data segment for globals and dynamic linking metadata. Both are aligned with p_align before mapping. The Linux ELF(5) man page is the right place to see how Phdr fields behave on disk versus in memory. Program headers describe the in-memory layout of a running program.
Code segment
- Permissions:
PF_X | PF_R(read + execute)
Data segment
- Permissions:
PF_W | PF_R(read + write)
PT_DYNAMIC
Program header used by the dynamic segment. Present in dynamically linked binaries; it holds what the dynamic linker needs.
Values commonly found via PT_DYNAMIC
- Shared libraries linked at runtime
- Address / location of the GOT
- Relocation entry information
Common PT_DYNAMIC tags
The dynamic segment stores linking metadata. The d_tag member controls how you read d_un.
typedef struct
{
Elf32_Sword d_tag;
union {
Elf32_Word d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;
extern Elf32_Dyn _DYNAMIC[];PT_NOTE
Holds vendor- or system-specific extras. Builders can use SHT_NOTE sections and PT_NOTE headers to record compatibility information. Entries are sequences of 4-byte words and strings with no fixed size limit. Labels are optional.
PT_NOTE is for the OS; a process does not need it while it runs.
PT_INTERP
A small segment that points at a NUL-terminated path to the program interpreter (the dynamic linker), usually /lib/linux-ld.so.2.

PT_PHDR
Gives the address and size of the program header table itself — where that table sits in the file and in the memory image.
readelf -l <binary>
You see the entry point and the segment types discussed above. Looking at offsets and alignment on the two PT_LOAD segments: text is typically read+execute and data is read+write. Alignment offsets such as 0x600e10 / 0x600e28 match page size on 32-bit builds and are used while the program is loaded.