本文最后更新于:2020年6月27日 晚上

* 总结的速度,追不上看书的速度了。。。 *

第三章 目标文件里面有什么

ELF文件的基本结构是什么样子?

图3.6 ELF文件结构

ELF目标文件的最前部是ELF 文件头(ELF Header),其包含描述整个文件的基本属性,如ELF文件版本、目标机器型号、程序入口地址等。接着是各段。之后为段表(Section Header Table),该表描述了ELF文件包含的所有段的信息,如短的段名、段的长度、在文件中的偏移、读写权限及段的其他属性。

  1. ELF文件头中定义了ELF魔数文件机器字节长度数据存储方式、版本、运行平台、ABI版本、ELF重定位类型、硬件平台、硬件平台版本、入口地址程序头入口和长度段表的位置和长度及段的数量。ELF文件头结构及相关常数被定义在“/usr/include/elf.h”。

    //32位文件结构头
    typedef struct
    {
    	 unsigned char e_ident[16];//魔数
    	 ELF32_Half e_type;//文件类型
    	 ELF32_Half e_machine;//平台属性
    	 ELF32_Word e_version;//版本号
    	 ELF32_Addr e_entry;//入口虚拟地址
    	 ELF32_Off e_phoff;
    	 ELF32_Off e_shoff;//段表在文件中的偏移
    	 ELF32_Word e_flags;
    	 ELF32_Half e_ehsize;
    	 ELF32_Half e_phentsize;
    	 ELF32_Half e_phnum;
    	 ELF32_Half e_shentsize;//段表描述符大小,一般为sizeof(Elf32_Shdr)
    	 ELF32_Half e_shnum;//段描述符数量,等于文件中拥有段的数量
    	 //Seciton header sting table index
    	 ELF32_Half e_shstrndx;//段表字符串表所在的段在段表中的下标
    }ELF32_Ehdr;
  • ELF文件头最前面的“Magic”的16个字节对应“ELF32_Ehdr“的e_ident成员,用来标识ELF文件的平台属性。
    ELF魔数
  • 前四个字节为ELF文件统一标识码,为0x7F、0x45、0x4c、0x46.分别对应ASCII字符中的DEL控制符、E、L、F。第五个字节用来标识ELF文件类。第六个字节规定ELF文件大小端。第七个字节规定ELF文件主版本号。后九个未定义,填0。
  1. 段表(Section Header Table)保存着段的基本属性的结构,它描述了各段的信息,如段的段名、段的长度、在文件中的偏、读写权限及段的其他属性。段结构由段表决定,编译器、连接器依靠段表定位和访问各段的属性。段表的位置由文件头的”e_shoff“决定。

    //段描述符结构
    typedef struct
    {	
    	//段名是一个字符串,位于.shstrtab字符串表。sh_name是段名字符串在.shstrtab中的偏移
    	Elf32_Word sh_name;
    	Elf32_Word sh_type;//段的类型
    	Elf32_Word sh_flags;//段的标志位
    	//段虚拟地址,若该段可以被加载则sh_addr为该段被加载后在进程地址空间中的虚拟的地址;否则为0
    	Elf32_Addr sh_addr;
    	//段偏移,如果该段存在于文件中,则表示该段在文件中的偏移,否则无意义如.bss段
    	Elf32_Off sh_offset;
    	Elf32_Word sh_size;//段的长度
    	Elf32_Word sh_link;//段链接信息
    	Elf32_Word sh_info;//段链接信息
    	//段地址对齐,地址对齐的数量都是2的指数倍,sh_addralign表示地址对齐数量中的指数
    	Elf32_Word sh_addralign;
    	//项的长度,有些段包含固定大小的项,如符号表所包含的每个符号大小一样;若不包含固定大小的项,则为0
    	Elf32_Word sh_entsize;
    }Elf32_Shdr;
    • 段表是一个以”Elf32_Shdr“ ——段描述符(Section Description)结构体为元素的数组数组元素的个数等于段的个数,每个”Elf32_Shdr“结构体对应一个段。ELF段表的数组的第一个元素是无效的段描述符,其类型为NULL。Elf32_Shdr被定义在”/usr/include/elf.h“中

    更复杂的ELF文件结构:

    更复杂的ELF文件结构

  2. 重定位表(Relocation Table),类型(sh_type)为”SHT_REL“。链接器在处理目标文件时,须要对目标文件中的某些部位进行重定位,即代码段和数据段中对绝对地址引用的位置。重定位信息都记录在重定位表中,每个须要重定位的段都会有一个相应的重定位表。一个重定位表同时也是ELF的一个段。

  3. 因为字符串的长度是不固定的,所以常见的表示方法是把字符串集中起来存放到一个表,然后使用字符串在表中的偏移来引用字符串。在ELF文件中引用字符串只须给出一个数字下标即可,不用考虑字符串长度的问题
    一般字符串表在ELF文件中以段的形式保存,常见段字符串表(String Table)”.strtab“段表字符串表(Section Header String Table)”.shstrtab“。字符串表保存普通的字符串,如符号的名字;段表字符串表保存段表中用到的字符串,如段名(sh_name)

分析ELF文件头,得到段表和段表字符串表的位置,继而解析整个ELF文件

* 下次就是静态链接了。。。Link! *