ELF二进制文件LOAD段未遵循p_align对齐要求的疑问
问题:ELF LOAD段为何未遵守程序头指定的对齐值?
我发现ELF二进制文件的LOAD段常常不遵守程序头中指定的Alignment(对齐)值。程序头中定义了对齐要求,man页对p_align的描述如下:
p_align This member holds the value to which the segments are aligned in memory and in the file. Loadable process segments must have congruent values for p_vaddr and p_offset, modulo the page size. Values of zero and one mean no alignment is required. Otherwise, p_align should be a positive, integral power of two, and p_vaddr should equal p_offset, modulo p_align.
显然文件中的段应按此值对齐,但为何示例hello world二进制的第二个LOAD段未做到?其应对齐至0x10000,但实际起始偏移为0x000db8,程序头信息如下:
Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align PHDR 0x000040 0x0000000000000040 0x0000000000000040 0x0001f8 0x0001f8 R 0x8 INTERP 0x000238 0x0000000000000238 0x0000000000000238 0x00001b 0x00001b R 0x1 LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000b6c 0x000b6c R E 0x10000 LOAD 0x000db8 0x0000000000010db8 0x0000000000010db8 0x000280 0x000288 RW 0x10000 DYNAMIC 0x000dc8 0x0000000000010dc8 0x0000000000010dc8 0x0001e0 0x0001e0 RW 0x8 NOTE 0x000254 0x0000000000000254 0x0000000000000254 0x000044 0x000044 R 0x4 GNU_EH_FRAME 0x00098c 0x000000000000098c 0x000000000000098c 0x00006c 0x00006c R 0x4 GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10 GNU_RELRO 0x000db8 0x0000000000010db8 0x0000000000010db8 0x000248 0x000248 R 0x1
解答
- 核心规则理解偏差:man页对
p_align的要求不是文件偏移必须对齐到p_align,而是**p_vaddr和p_offset模p_align的结果必须相等**。 - 验证第二个LOAD段的合规性:
p_offset = 0x000db8,p_vaddr = 0x00010db8,p_align = 0x10000- 计算模值:
0x000db8 % 0x10000 = 0xdb8,0x00010db8 % 0x10000 = 0xdb8 - 两者结果完全一致,完全符合
p_align的规定。
- 设计逻辑:这种规则既保证了内存中虚拟地址的对齐(
p_vaddr所在页起始为0x00010000,对齐到0x10000页大小),又允许文件中的数据紧凑存放,避免不必要的空间浪费。加载器映射时,会把文件中0x000db8开始的数据放到内存页0x00010000的0xdb8偏移处,页内剩余空间会被初始化为零(对应MemSiz比FileSiz多的0x8字节)。
内容的提问来源于stack exchange,提问作者Fee
相关产品推荐
相关产品推荐

