我正在尝试构建一个类似于xv6的系统,我正在下面复制xv6的代码:
if (ph.p_vaddr % PGSIZE) {
cprintf("exec: addr not page aligned.n");
goto bad;
}
这是将ELF加载到内存中的部分。
它检查每个PT_LOAD段的vaddr,并确保它在加载到内存之前对齐。
但是代码令人困惑,因为当我使用readelf
检查我的ELF文件加载:
Elf file type is EXEC (Executable file)
Entry point 0x400260
There are 4 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x0021f0 0x0021f0 R E 0x1000
LOAD 0x002eb8 0x0000000000403eb8 0x0000000000403eb8 0x000268 0x0008e8 RW 0x1000
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x002eb8 0x0000000000403eb8 0x0000000000403eb8 0x000148 0x000148 R 0x1
Section to Segment mapping:
Segment Sections...
00 .init .text .fini .rodata .eh_frame
01 .init_array .fini_array .data.rel.ro .got .got.plt .data .bss
02
03 .init_array .fini_array .data.rel.ro .got .got.plt
vaddr并不总是页面对齐,所以我想问的是,这是我的编译方式或代码本身是错误的吗?
是我的编译方式有问题还是代码本身有问题?
代码错误。.p_vaddr - .p_offset
必须对齐;.p_vaddr
单独不需要。
这是因为该段需要 CC__ed,而mmap
需要对齐页面的偏移量。为了在.p_vaddr
处对第二个段进行mmap
,加载器将.p_vaddr
和.p_offset
舍入,并且mmap
在段的开始处增加了一点额外的值。