ELF文件格式是一个开放标准,各种UNIX系统的可执行文件都采用ELF格式,它有三种不同的类型:
ELF Header描述了体系结构和操作系统等基本信息,并指出Section Header Table和Program Header Table在文件中的什么位置。
Section Header Table中保存了所有Section的描述信息,通过Section Header Table可以找到每个Section在文件中的位置。
Program Header Table中保存了所有Segment的描述信息,一个Segment由一个或多个Section组成,Segment里面的Section加载到内存时具有相同的访问权限。
Section只对链接器有用,对应Section Header Table。
Segment只对加载器有用,对应Program Header Table。
目标文件需要链接器做进一步处理,所以一定有Section Header Table。
可执行文件需要加载运行,所以一定有Program Header Table。
共享库既要加载运行,又要在加载时做动态链接,所以既有Section Header Table又有Program Header Table。
用到的代码
.section .data data_items: .long 3,67,34,222,45,75,54,34,44,33,22,11,66,0 .section .text .globl _start _start: movl $0, %edi # move 0 into the index register movl data_items(,%edi,4), %eax # load the first byte of data movl %eax, %ebx start_loop: # start loop cmpl $0, %eax # check to see if we've hit the end je loop_exit incl %edi movl data_items(,%edi,4), %eax cmpl %ebx, %eax jle start_loop movl %eax, %ebx jmp start_loop loop_exit: movl $1, %eax #1 is the _exit() syscall int $0x80
汇编、链接、运行:
$ as max.s -o max.o $ ld max.o -o max $ ./max $ echo $?
下面分析一个.o文件的ELF信息
下面分一个可执行文件ELF信息
这个可执行文件很小,总共也不超过一页大小,但是两个Segment必须加载到内存中两个不同的页面,因为MMU的权限保护机制是以页为单位的,一个页面只能设置一种权限。此外还规定每个Segment在文件页面内偏移多少加载到内存页面仍然要偏移多少,比如第二个Segment在文件中的偏移是0xa0,在内存页面0x08049000中的偏移仍然是0xa0,所以从0x080490a0开始,这样规定是为了简化链接器和加载器的实现 。