Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ELF program header offset

Tags:

assembly

elf

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.

like image 617
Fotinopoulos Giorgos Avatar asked Oct 12 '22 15:10

Fotinopoulos Giorgos


1 Answers

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.

like image 151
Simon Richter Avatar answered Oct 18 '22 01:10

Simon Richter