静态链接中的目标文件
1.编译过程
⦁ 预处理
⦁ 编译
⦁ 汇编
⦁ 链接
图:gcc编译过程
链接包括动态链接和静态链接,静态链接过程中有地址和空间分配(Address and Storage Allocation)、符号决议(Symbol Resolution)和重定位(Relocation)等。静态链接过程如图:
2.目标文件
编译器编译源代码之后生成的文件称为目标文件。
2.1 目标文件的格式
从结构上讲,它是按照可执行文件的格式存储的。只是没有经过链接的过程,其中可能有符号和地址没有被调整。
平台 | 目标文件格式 | 目标文件后缀名 |
Windows | PE-COFF | .obj |
Linux | ELF | .o |
目标文件中有指令、数据,还有链接时需要的一些信息,如符号表,调试信息,字符串表等。将这些信息按不同的属性,以“段”的形式存储。
ELF Header |
.text |
.data |
.bss |
...... Other sections |
Section header table |
String Tables Symbol Tables |
图:ELF结构
⦁ ELF文件头:描述文件的基本属性,如ELF文件版本、目标机器型号、程序入口地址等。
⦁ 段表:描述包含的所有段的信息,包括段名、段的长度、在文件中的偏移、读写权限等。
⦁ 辅助结构:字符串表、符号表等。
除了.text .data .bss外,其他常用的段名如下表:
2.2 一个例子
图:程序与目标文件
查看上述文件的目标文件,可以看到包含的段如下:
⦁ 代码段
⦁ 数据段
⦁ bss段 :未初始化的全局变量和局部静态变量。
⦁ rodata只读数据段:只读数据,如字符串常量,全局const变量。
⦁ comment注释信息段:编译器版本信息
⦁ 堆栈提示段
CONTENTS:该段在文件中存在。
VLM和LMA:虚拟内存地址、装载内存地址。
File off : 在文件中的偏移。
图:目标文件结构图
2.3 分段的优点
⦁ 程序加载后,数据和指令分别映射到两个虚拟区域,数据区可读写,指令区只能读,权限不同。
⦁ CPU缓存一般都设计成数据缓存和指令缓存,分开有利于提高程序局部性,提升CPU缓存命中率。
⦁ 运行多个程序副本时,程序指令都一样,每个进程保存自己的数据区域。