本课时主要帮助同学了解可执行文件.elf的文件格式,以及如何对.elf文件格式进行解析,并加载到内存中。
下面的文字主要对elf文件格式和加载过程做简要的分析,详细的信息需要查看【参考资料】中的文档,以及本课时的视频。

ELF文件格式

windows的可执行文件格式通常为.exe结尾的PE 文件格式,而linux/unix用得更多的则为elf文件格式。
我们的工具链编译生成的即为这种文件格式。此种文件格式结构简要图如下。对我们而言,只需要关注下图右半部分(即Execution View,左半部分是给链接器用的)。
\image (15).png

(摘自ELF_Format.pdf,第7页)
该文件中包含了前一节课时中提到的.text/.rodata/.data/.bss各段的信息。通常解析该文件,找到program header table,从该表中,即可从中读取出相应的代码、数据段的相关信息,并可根据该信息将代码或数据加载到对应的内存中,完成整个加载过程。
其中elf header包含了有关该文件的全局性配置数据,以及描述了该文件的具体结构,其位于文件的最开头。
\image (16).png

programe header table具体在文件中的位置,由e_phoff来指定,该位置存储了以下结构体数组。表项数量由e_phnum来决定。
\image (17).png

该结构体描述了需要加载到内存中的相关配置信息,我们可以根据其中的配置,进行解析加载。根据以下分析,具体的加载过程如下:
● 初步检查elf header的合法性(课程中只做了非常简单的检查)
● 通过elf header->e_phoff定位到programe header table,遍历elf header->e_phnum次,加载各个段
○ 从文件位置p_offset处读取filesz大小的数据,写入到内存中paddr的位置处
○ 如果p_filesz < p_memsz,则将部分内存清零(bss区初始化)
● 取elf header->e_entry,跳转到该地址运行。
从上述流程可以看出,在C代码中定义的未初始化的全局变量(分配在BSS区,初始值为0),并没有在ELF中分配相应的空间,需要自己在内存中手动清0.
下图仅为某elf文件的内容存储示例,不同elf文件可能组织不同。课程视频中所展示的为text, rodata, data, bss被组织在一起,而非下图的分开存放。
\image (18).png

(注:以上不考虑虚拟内存开启的情况,所以不关注vaddr,以后会再讲这部分)

参考资料

● ELF文件格式简介及加载过程:https://wiki.osdev.org/ELF
● ELF格式详细说明:ELF_Format.pdf(见课程附带的文档资料中)



登陆发表评论