cexecelfxv6

Why ELF's vaddr is not page aligned?


I'm trying to build a xv6-like system and I'm copying xv6's code below:

    if (ph.p_vaddr % PGSIZE) {
            cprintf("exec: addr not page aligned.\n");
            goto bad;
    }

This is the part where ELF is loaded into memory.

It checks every PT_LOAD segment's vaddr and makes sure it's page aligned before load it into the memory.

But the code is confusing because when I use readelf to check my ELF file to load:

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 

The vaddr is not always page aligned, so I'd like to ask that is it something wrong with my way of compiling or the code itself is wrong?


Solution

  • is it something wrong with my way of compiling or the code itself is wrong?

    The code is wrong. .p_vaddr - .p_offset must be page-aligned; .p_vaddr alone does not have to be.

    This is because the segment needs to be mmaped, and mmap requires page-aligned offset. In order to mmap the second segment at .p_vaddr, the loader rounds down both .p_vaddr and .p_offset, and mmaps a bit of extra at the beginning of the segment.