文章目录
2 编译和链接
2.1 被隐藏的过程
2.2 编译器做了什么
2.3 连接器年龄比编译器长
2.4 模块拼装——静态链接
2.5 小结
1 Elf文件
1.1 文件头
Magic:魔术数字
魔术数字16个字节。最开始的4个字节是所有的ELF文件都必须相同的标识码。分别为:0x7F(ASCII中的DEL控制字符)、0x45(‘E’)、0x4c(‘L’)和0x46(‘F’)。这四个字节又被称为ELF文件的魔数。
第5个字节: 0x01表示32位。 0x02表示64位。
第6个字节: 字节序。标识ELF文件是大端的还是小端。
第7个字节: 主版本号,一般是1. 因为ELF标准自1.2版本以后就再无更新。
最后的9个字节:没有标准定义, 一般填写0。有的平台会将其作为扩展标志。
Class:Elf32 / Elf64
Data:大小端
Type: REL(Relocatable file),可执行文件,动态链接文件。
常量 | 值 | 含义 |
---|---|---|
ET_REL | 1 | 可重定位文件,一般为.o文件 |
ET_EXEC | 2 | 可执行文件 |
ET_DYN | 3 | 共享目标文件,一般为.so文件 |
机器类型:
ELF文件做不到像java字节码文件那样跨平台。 也就是说不同操作系统下的elf文件内容是有区别的。
e_machine就表示平台属性,3就表示在intel x86机器下使用。
常量 | 值 | 含义 |
---|---|---|
EM_M32 | 1 | AT&T WE 32100 |
EM_SPARC | 2 | SPARC |
EM_386 | 3 | Intel X86 |
EM_68K | 4 | Motorola 68000 |
文件机器字节长度
数据存储方式
版本
运行平台
ABI版本
硬件平台,
硬件平台版本
入口地址,
程序头入口和长度
段表的位置和长度
段的数量
ELF文件头的结构和相关常数被定义在“/usr/include/elf.h”里面。ELF文件有32和64位的版本,相应地,文件头结构有两种,分别是:Elf32_Ehdr和Elf64_Ehdr. 32位和64位的文件头的内容是一样的,有些成员大小不一样。
1.2 段表
段表是保存段基本属性的结构。段表是ELF文件中除文件头外最重要的结构。 它描述了各个段的信息,例如段名、段长度、在文件中的偏移读写权限等。编译器、连接器和装载器都是依靠段表来定位和访问各个段的属性的。段表在ELF文件中的位置由文件头中e_shoff成员决定。
段表是以Elf32_Shdr结构体为元素的数组。数组元素的个数就是段的个数,每个结构体对应一个段。Elf32_Shdr又被称为段描述符。
段名称
段类型:
段名字只在链接和编译过程中有意义,并不能真正表示段类型。我们可以将一个数据段命名为“.text”
常量 | 值 | 含义 |
---|---|---|
SHT_NULL | 0 | 无效段 |
SHT_PROGBITS | 1 | 程序段。代码段、数据段都是这种类型的。 |
SHT_SYMTAB | 2 | 表示该段的内容为符号表。 |
… | … | … |
段的标志位:
表示该段在进程虚拟地址空间中的属性,例如是否可写,是否可执行等。
常量 | 值 | 含义 |
---|---|---|
SHF_WRITE | 1 | 表示该段在进程空间中可写 |
SHF_ALLOC | 2 | 表示该段在进程空间中须要分配空间。有些包含指示或控制信息的段不需要在进程空间中被分配空间,它们一般不会有这个标志。像代码段、数据段和.bss段都会有这个标志 |
SHF_EXECINSTR | 4 | 表示该段在进程空间中可被执行,一般指代码段 |
段的链接信息(sh_link,sh_info):
与链接没有关系的段,这两个成员是没有意义的。
1.2.1 重定位表
.rel.text段,其类型(sh_type)为“SHT_REL”,即是一个重定位表。
一个重定位表同时也是ELF的一个段。 它的sh_link表示符号表得下标,sh_info表示其作用于哪个段。
1.2.2 字符串表
ELF文件中有很多字符串,如段名,变量名等。因为字符串长度往往不固定,所以很难用固定的结构来表示。 常见的做法就是把字符串集中起来放到一个表,然后使用字符串在表中的偏移来引用字符串。
一般字符串表在ELF文件中以段的形式保存。常见的段名为.strtab或.shstrtab。这两个字符串表分别为字符串表(String Table)和段表字符串表(Section Header String Table)。顾名思义,字符串表用来保存普通的字符串,比如符号的名字;段表字符串用来保存段表中用到的字符串,最常见的就是段名(sh_name)。
e_shstrndx是文件头结构体的最后一个成员,它是“Section header string table index”。段表字符串表本身也是ELF文件中的一个普通的段,e_shstrndx就表示段表字符串表在段表中的下表。
参考资料
[1] 程序员的自我修养——链接、装载与库
[2] https://www.bilibili.com/video/BV1mK411B7Ux/?spm_id_from=333.337.search-card.all.click&vd_source=f4dcb991bbc4da0932ef216329aefb60