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

* 一直被催更。。。 *

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

PC平台流行的可执行文件格式(Executable)主要为Windows下的PE(Portable
Executable)和Linux下的ELF(Executable Linkable
Format),都是COFF(Common file format)格式的变种。

编译器编译源代码后生成的目标文件,其结构已经是编译后的可执行文件格式,但还没有经过链接,有些符号或地址还未调整,所以一般跟可执行文件采用相同格式存储。在Windows下将它们统称为PE-COFF文件格式,在Linux下将它们统称为ELF文件。

动态链接库(DLL,Dynamic Linking Library)Windows的.dll和Linux的.so)、静态链接库(Static Linking Library)Windows的.lib和Linux的.a)都按照可执行文件格式存储。静态链接库是把很多目标文件捆绑在一起形成一个文件再加上索引,简单理解为一个包含很多目标文件的文件包。

图3.1 ELF格式文件(1)
图3.2 ELF格式文件(2)

1.目标文件文件中至少包含编译后的机器指令代码、数据、链接时所需信息(如符号表、调试信息、 字符串等)。一般目标文件将这些信息按不同属性以“(Section)的形式存储,有时也叫段(Segment)(其实这两个是不同的角度的定义,看到后面时才理解),一般情况下他们都表示一个一定长度的区域。

  • 程序源代码编译后的机器指令保存在代码段(Code Section,常见名字.code或.text)

  • 初始化的全局变量局部静态变量保存在数据段(Data Section,常见名字.data)

  • 未初始化的全局变量局部静态变量保存在.bss section

  • 图3.3 程序与目标文件

  • ELF文件的文件头描述了整个文件的属性,包括文件是否可执行、是静态链接还是动态链接及入口地址、目标硬件、目标操作系统等信息。文件头还包含一个段表(Section Table),段表是一个描述文件各段的数组,具有每个段的信息(各段在文件中的偏移位置和段的属性等)。

  • 未初始化的全局变量和局部静态变量默认值都为0,本可以存放在.data段,但是在.data存放数据0没有必要。程序运行时他们的确占内存空间,并且可执行文件必须记录它们的大小总和,为其预留位置,记为.bss段。但.bss段没有内容,在文件中不占空间(better save space)。

2.程序源代码被编译后主要分为两种段:程序指令程序数据。区分好处如下:

  • 程序被装载后,数据和指令被分别映射到两个虚存空间,将其权限分别设置为可读写只读防止程序的指令被改写。

  • 指令和数据分离有利于提高程序的局部性。现代计算机的CPU缓存一般都被设计成数据缓存和指令缓存分离,所以两者分离存放对CPU缓存命中率提高有好处。

  • 当系统中运行同一个程序的多个副本时,其指令都是一样的,所以内存中只须保存一份该程序的指令部分。共享指令可以大量节省内存,对其他的只读数据同理。

* 先大概了解目标文件里面有什么,下次再逐个深入。。。 *