I write an executable ELF header+program header manually like this:
elf_head:
e_ident db 7Fh, 'ELF', 1, 1, 1
times 9 db 0
e_type dw 2 ; ET_EXEC
e_mach dw 3 ; EM_386
e_ver dd 1 ; EV_CURRENT
e_entry dd 0x08048000+elf_head_len ; entry point
e_phoff dd 34h ; program header table offset
e_shoff dd 00h ; section header table offset
e_flags dd 0 ; flags
e_elfhs dw 34h ; ELF header size
e_phes dw 20h ; program header entry size
e_phec dw 01h ; program header entries count
e_shes dw 00h
e_shec dw 00h
e_shsn dw 00h
elf_ph:
p_type dd 01h ; PT_LOAD
p_off dd elf_head_len
p_vaddr dd 0x08048000+elf_head_len
p_paddr dd 0x08048000+elf_head_len
p_filsz dd elf_head_len+file_len
p_memsz dd elf_head_len+file_len
p_flags dd 7 ; segment flags (RWX)
p_align dd 0x1000 ; page_size==4096bytes
elf_head_len equ $ - elf_head
I set up the e_entry field point right after the p_align field where i put my code in the file being created. But it doesn't work! I am a little confused with the p_offset field. I put there an offset from the start of the file (0x00) until the first byte of segment's code. Since the segment's code start right after p_align field, do i enter correctly the value elf_head_len ? When i try to run the new created executable, bash responds: Segmentation fault!
Ok i figure out that i had an error on the program that gave the segmentation fault. (sorry about that). But the question remains about the p_off field and i figure out also that if i set p_off dd 0 and p_vaddr dd 0x08048000 and p_paddr dd 0x08048000 executable works. It also works if i enter p_off dd elf_head_len and p_vaddr dd 0x08048000+elf_head_len and p_paddr dd 0x08048000+elf_head_len. That reminds me something i read on ELF Format specifivation about p_off and p_vaddr values that must be congruent (that is i think they must give same result when modulo each one with page size). So this is why the program works with these values. So the question now is: If there is an error on the above logic please consider to correct.
The ELF specification requires that for demand paged executables, the file offset and virtual address for a segment must indeed match in the lower-order bits.
These restrictions are the same that the mmap()
system call places on mappings -- it only accepts mappings at an offset in the file that is a multiple of the page size. When mapping an ELF file, the segments are extended to the nearest page boundary, so the lower-order bits are effectively ignored except for the segment size calculation.
One possible rationale for this is that the underlying device may already be memory-mapped -- such as a frame buffer, or flash memory -- in which case it would impose a substantial overhead to create a mapping with an offset that is not page aligned.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With