What exactly is the purpose of the p_align
field? Every source online has only said something vague about it saying the "required alignment" of segment or only that its a value so that p_vaddr = p_offset mod p_allign
. Using readelf
, I can see that LOAD segments have p_align
of 4KB. The modulo statement with p_align
being 4KB mathematically guarantees its possible to mmap
file pages to memory pages to correctly load the segment. This is the only utility I see for p_align
. But it is anyways required for p_align
of LOAD segments to be page-sized, so is there no purpose?
What exactly is the purpose of the
p_align
field?
To make it possible to use mmap
to bring LOAD
segments into memory.
I can see that
LOAD
segments havep_align
of 4KB. The modulo statement withp_align
being 4KB mathematically guarantees its possible tommap
file pages to memory pages to correctly load the segment.
Some architectures have a different page size. For example powerpc64
page size is 64KB, and binaries linked for it will have p_align == 0x10000
.
Further, x86_64
supports multiple page sizes, and if you want to be able to use e.g. 2MB pages for your binary, then you need to set alignment appropriately:
echo "int main() { return 0; }" | gcc -xc - -Wl,-z,max-page-size=0x200000
readelf -Wl ./a.out
Elf file type is EXEC (Executable file)
Entry point 0x600020
There are 13 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000400040 0x0000000000400040 0x0002d8 0x0002d8 R 0x8
INTERP 0x000318 0x0000000000400318 0x0000000000400318 0x00001c 0x00001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x0004b8 0x0004b8 R 0x200000
LOAD 0x200000 0x0000000000600000 0x0000000000600000 0x000121 0x000121 R E 0x200000
LOAD 0x400000 0x0000000000800000 0x0000000000800000 0x00009c 0x00009c R 0x200000
LOAD 0x5ffe38 0x0000000000bffe38 0x0000000000bffe38 0x0001cc 0x0001d0 RW 0x200000
DYNAMIC 0x5ffe48 0x0000000000bffe48 0x0000000000bffe48 0x000190 0x000190 RW 0x8
...
Indeed, 2MB pages used to be the default on x86_64
, precisely because someone might decide to use 2MB (aka huge) pages, until the default was changed to 4KB in this commit.