ELF程序头偏移

发布于 2024-10-19 10:03:17 字数 1828 浏览 5 评论 0原文

我像这样手动编写可执行的 ELF 标头+程序标头:

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

我在 p_align 字段之后设置了 e_entry 字段点,我将代码放入正在创建的文件中。但这不起作用!我对 p_offset 字段有点困惑。我在那里放置了从文件开头 (0x00) 到段代码的第一个字节的偏移量。由于段的代码在 p_align 字段之后开始,我是否正确输入值 elf_head_len ?当我尝试运行新创建的可执行文件时,bash 响应: 分段错误!

好吧,我发现我的程序有一个错误,导致了分段错误。 (对此感到抱歉)。但问题仍然是关于 p_off 字段,我还发现,如果我设置 p_off dd 0 和 p_vaddr dd 0x08048000 和 p_paddr dd 0x08048000 可执行文件有效。如果我输入 p_off dd elf_head_len 和 p_vaddr dd 0x08048000+elf_head_len 和 p_paddr dd 0x08048000+elf_head_len,它也有效。这让我想起了我在 ELF 格式规范中读到的关于 p_off 和 p_vaddr 值必须一致的内容(也就是说,我认为当对每个值取页面大小的模时,它们必须给出相同的结果)。这就是程序使用这些值的原因。那么现在的问题是:如果上述逻辑有错误请考虑更正。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

追星践月 2024-10-26 10:03:17

ELF 规范要求,对于按需分页可执行文件,段的文件偏移量和虚拟地址必须在低位中确实匹​​配。

这些限制与 mmap() 系统调用对映射施加的限制相同——它只接受文件中偏移量为页面大小倍数的映射。映射 ELF 文件时,段将扩展到最近的页边界,因此除了段大小计算之外,低位位实际上被忽略。

这样做的一个可能的理由是底层设备可能已经是内存映射的(例如帧缓冲区或闪存),在这种情况下,创建具有未页面对齐的偏移量的映射会产生大量开销。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文