问题描述
我有一个问题,关于文件中的 elf 程序段过大。例如,一个程序 readelf -f xx -W
像这样:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000400040 0x0000000000400040 0x0001f8 0x0001f8 R E 0x8
INTERP 0x000238 0x0000000000400238 0x0000000000400238 0x00001c 0x00001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x4ca8e6 0x4ca8e6 R E 0x200000
LOAD 0x4cb000 0x0000000000acb000 0x0000000000acb000 0x035db8 0x04ed80 RW 0x200000
DYNAMIC 0x4ed4c8 0x0000000000aed4c8 0x0000000000aed4c8 0x000230 0x000230 RW 0x8
NOTE 0x000254 0x0000000000400254 0x0000000000400254 0x000044 0x000044 R 0x4
TLS 0x4cb000 0x0000000000acb000 0x0000000000acb000 0x000010 0x000018 R 0x10
GNU_EH_FRAME 0x3dcf04 0x00000000007dcf04 0x00000000007dcf04 0x024c64 0x024c64 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame .gcc_except_table
03 .tdata .init_array .fini_array .jcr .data.rel.ro .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .tdata .tbss
07 .eh_frame_hdr
08
第一次加载从偏移量 0x000000
开始,大小为 0x4ca8e6
。为什么第二个偏移量不是 (0x000000 + 0x4ca8e6
),我看到 (0x4cb000 - 0x4ca8e6
) 内容,全部为 0。我无法理解。文件中偏移量的规则是什么?
解决方法
第一次加载从偏移 0x000000 开始,大小为 0x4ca8e6。为什么第二个偏移量不是 (0x000000 + 0x4ca8e6)
因为加载器 mmap
的 LOAD
段直接进入内存,对于每个 LOAD
段,以下必须为真:(p_vaddr - p_offset) % page_size == 0
。
在 x86_64
上,最大页面大小为 2MiB (0x200000
)。这对第二个(及后续)LOAD
段位置施加了严格限制。