Segments are the execution view of an ELF file: the program header table at
e_phoff tells the system how to build a process image. Executables and
shared objects need it; relocatable files do not. This page follows the gABI chapter 5,
with GNU/Linux additions from glibc’s elf.h and elf(5).
Program header
The 64-bit layout moves p_flags to second place.
| Offset 32 | Offset 64 | Type 32 / 64 | Field | Meaning |
|---|---|---|---|---|
0x00 | 0x00 | Word | p_type | Segment type. |
0x18 | 0x04 | Word | p_flags | Permissions. |
0x04 | 0x08 | Off | p_offset | File offset of the segment’s first byte. |
0x08 | 0x10 | Addr | p_vaddr | Virtual address of the first byte in memory. |
0x0C | 0x18 | Addr | p_paddr | Physical address, where that matters. |
0x10 | 0x20 | Word / Xword | p_filesz | Bytes in the file (may be 0). |
0x14 | 0x28 | Word / Xword | p_memsz | Bytes in memory (may be 0). |
0x1C | 0x30 | Word / Xword | p_align | Alignment: 0 or 1 for none, otherwise a power of two with p_vaddr ≡ p_offset (mod p_align). |
Each header is 32 bytes in 32-bit files and 56 bytes in 64-bit files.
p_type
| Value | Name | Segment |
|---|---|---|
0 | PT_NULL | Unused entry |
1 | PT_LOAD | Loadable: p_filesz bytes from the file, then zeros up to p_memsz |
2 | PT_DYNAMIC | Dynamic linking information |
3 | PT_INTERP | Path name of the program interpreter (dynamic linker) |
4 | PT_NOTE | Notes |
5 | PT_SHLIB | Reserved, semantics unspecified; a program with one does not conform to the ABI |
6 | PT_PHDR | The program header table itself |
7 | PT_TLS | Thread-local storage template |
0x60000000–0x6FFFFFFF | PT_LOOS–PT_HIOS | Operating-system-specific, including: |
0x6474E550 | PT_GNU_EH_FRAME | GNU EH frame |
0x6474E551 | PT_GNU_STACK | GNU: its p_flags set the state of the stack (Linux kernel) |
0x6474E552 | PT_GNU_RELRO | GNU RELRO |
0x6474E553 | PT_GNU_PROPERTY | GNU program properties |
0x6474E554 | PT_GNU_SFRAME | GNU SFrame |
0x6FFFFFFA | PT_SUNWBSS | Sun |
0x6FFFFFFB | PT_SUNWSTACK | Sun |
0x70000000–0x7FFFFFFF | PT_LOPROC–PT_HIPROC | Processor-specific, for example 0x70000002 PT_AARCH64_MEMTAG_MTE (AArch64 memory tags) |
Values after PT_TLS are from glibc’s elf.h. The sources
read describe only PT_GNU_STACK (in elf(5)); the others are
given by name.
p_flags
| Value | Name | Meaning |
|---|---|---|
0x1 | PF_X | Execute |
0x2 | PF_W | Write |
0x4 | PF_R | Read |
0x0FF00000 | PF_MASKOS | Reserved for the OS |
0xF0000000 | PF_MASKPROC | Reserved for the processor |
A system may give exactly the permissions asked for, or the “allowable” ones, which add read (and, for write, execute); write is never given unless asked for:
| Flags | Exact | Allowable |
|---|---|---|
| none (0) | no access | no access |
PF_X (1) | execute only | read, execute |
PF_W (2) | write only | read, write, execute |
PF_W + PF_X (3) | write, execute | read, write, execute |
PF_R (4) | read only | read, execute |
PF_R + PF_X (5) | read, execute | read, execute |
PF_R + PF_W (6) | read, write | read, write, execute |
PF_R + PF_W + PF_X (7) | read, write, execute | read, write, execute |
Rules
PT_LOADentries are sorted byp_vaddr;p_fileszmay not exceedp_memsz, and the extra memory is zero-filled. For loadable segmentsp_vaddrandp_offsetare also congruent modulo the page size.PT_INTERPandPT_PHDRoccur at most once each and come before every loadable entry;PT_PHDRonly if the table is part of the memory image.- Other entries may come in any order, and every type is optional.
- The base address of a loaded object is the difference between its memory address
and the lowest
PT_LOADp_vaddr, both truncated to a multiple of the maximum page size.
PT_TLS
| Field | Meaning |
|---|---|
p_offset, p_vaddr | Where the TLS initialisation image is in the file and memory |
p_paddr | Reserved |
p_filesz | Size of the initialisation image |
p_memsz | Total size of the TLS template |
p_flags | PF_R |
p_align | Alignment of the template |
The template is all SHF_TLS sections together: the initialised part
from PROGBITS sections, the rest from NOBITS ones. Support is
optional.
Notes
PT_NOTE segments and SHT_NOTE sections hold a series of
entries:
| Field | Size | Meaning |
|---|---|---|
n_namesz | 4 | Length of the name including its zero byte, not counting padding (4 for GNU); 0 for none |
n_descsz | 4 | Length of the descriptor, not counting padding |
n_type | 4 | Type, defined by the owner; a reader matches name and type together |
| name | n_namesz, padded | Owner, zero-terminated, padded to the alignment |
| desc | n_descsz, padded | Descriptor, padded to the alignment |
The gABI pads to 4 bytes in 32-bit files and 8 bytes in 64-bit files; Linux’s
elf(5) pads to 4 bytes. An empty name is reserved. Notes must not change
how a program runs.
Core file notes
Core files use what elf(5) calls the default namespace. Values from glibc:
| Value | Name | Value | Name |
|---|---|---|---|
1 | NT_PRSTATUS | 14 | NT_PRCRED |
2 | NT_PRFPREG / NT_FPREGSET | 15 | NT_UTSNAME |
3 | NT_PRPSINFO | 16 | NT_LWPSTATUS |
4 | NT_PRXREG / NT_TASKSTRUCT | 17 | NT_LWPSINFO |
5 | NT_PLATFORM | 20 | NT_PRFPXREG |
6 | NT_AUXV | 0x53494749 | NT_SIGINFO (“SIGI”) |
7 | NT_GWINDOWS | 0x46494C45 | NT_FILE (“FILE”) |
8 | NT_ASRS | 0x46E62B7F | NT_PRXFPREG |
10 | NT_PSTATUS | 0x700 | NT_VMCOREDD |
13 | NT_PSINFO |
Processor register sets in core files:
| Range | Architecture | Names, in order of value |
|---|---|---|
0x100–0x112 | PowerPC | NT_PPC_ VMX, SPE, VSX, TAR, PPR, DSCR, EBB, PMU, TM_CGPR, TM_CFPR, TM_CVMX, TM_CVSX, TM_SPR, TM_CTAR, TM_CPPR, TM_CDSCR, PKEY, DEXCR, HASHKEYR |
0x200, 0x201, 0x202, 0x204, 0x205 | x86 | NT_386_TLS, NT_386_IOPERM, NT_X86_XSTATE, NT_X86_SHSTK, NT_X86_XSAVE_LAYOUT |
0x300–0x30E | s390 | NT_S390_HIGH_GPRS to NT_S390_PV_CPU_DATA (elf(5) lists TIMER, TODCMP, TODPREG, CTRS, PREFIX, LAST_BREAK, SYSTEM_CALL, TDB among them) |
0x400–0x410 | ARM, AArch64 | NT_ARM_ VFP, TLS, HW_BREAK, HW_WATCH, SYSTEM_CALL, SVE, PAC_MASK, PACA_KEYS, PACG_KEYS, TAGGED_ADDR_CTRL, PAC_ENABLED_KEYS, SSVE, ZA, ZT, FPMR, POE, GCS |
0x800–0x802 | MIPS | NT_MIPS_DSP, NT_MIPS_FP_MODE, NT_MIPS_MSA |
0x900–0x902 | RISC-V | NT_RISCV_CSR, NT_RISCV_VECTOR, NT_RISCV_TAGGED_ADDR_CTRL |
0xA00–0xA06 | LoongArch | NT_LOONGARCH_ CPUCFG, CSR, LSX, LASX, LBT, HW_BREAK, HW_WATCH |
The PowerPC and ARM ranges hold exactly as many values as names, given here in glibc’s order; the individual s390 values were not read.
GNU notes (owner GNU)
| Value | Name | Descriptor |
|---|---|---|
1 | NT_GNU_ABI_TAG | Four words: the OS (ELF_NOTE_OS_ 0 LINUX, 1 GNU, 2 SOLARIS2, 3 FREEBSD), then the major, minor and subminor ABI version. Section .note.ABI-tag. |
2 | NT_GNU_HWCAP | Synthetic hwcap entries: a count and a bit mask, then named entries. |
3 | NT_GNU_BUILD_ID | Unique build ID, as made by ld --build-id. Section .note.gnu.build-id. |
4 | NT_GNU_GOLD_VERSION | Version of the gold linker. |
5 | NT_GNU_PROPERTY_TYPE_0 | Program properties, below. |
In object files with other owners, NT_VERSION (1) holds a version
string and NT_ARCH architecture information (elf(5)). glibc also defines
the owners FDO, with NT_FDO_PACKAGING_METADATA
(0xCAFE1A7E) and NT_FDO_DLOPEN_METADATA
(0x407C0C0A), and SUNW Solaris.
GNU program properties
| Value | Name |
|---|---|
1 | GNU_PROPERTY_STACK_SIZE |
2 | GNU_PROPERTY_NO_COPY_ON_PROTECTED |
0xB0000000–0xB0007FFF | GNU_PROPERTY_UINT32_AND range |
0xB0008000–0xB000FFFF | GNU_PROPERTY_UINT32_OR range; its first value is GNU_PROPERTY_1_NEEDED (bit 0: indirect extern access) |
0xC0000000–0xDFFFFFFF | processor-specific |
0xC0000000 | GNU_PROPERTY_AARCH64_FEATURE_1_AND: bit 0 BTI, bit 1 PAC, bit 2 GCS |
0xC0000002 | GNU_PROPERTY_X86_FEATURE_1_AND: bit 0 IBT, bit 1 SHSTK |
0xC0008002 | GNU_PROPERTY_X86_ISA_1_NEEDED: bit 0 baseline, bit 1 v2, bit 2 v3, bit 3 v4 |
0xC0010002 | GNU_PROPERTY_X86_ISA_1_USED: the same bits |
0xE0000000–0xFFFFFFFF | user-defined |
The layout of the property entries inside the note is not described in the sources read.
Sources
- gABI chapter 5: Program Header – program header, types 0–7, flags, permissions, rules, base address, notes, TLS
- glibc elf.h – GNU, Sun and AArch64 segment types; every note value; ABI tag OS values; program property values
- elf(5) –
PT_GNU_STACK, note owners and descriptors, Linux note alignment