编译器编译源代码后生成的文件叫做目标文件,目标文件从结构上讲,它已经是编译后可执行文件的格式,只是还没有经过链接的过程,其中可能有些符号或有些地址还没有调整。其实它本身就是按照可执行文件格式存储的,只是跟真正的可执行文件结构上有所不同。
目标文件的格式
现在pc平台流行的可执行文件格式,主要是windows平台下的PE和Linux的ELF,它们都是COFF格式的变种。
动态链接库文件都按照可执行文件格式存储。
静态链接库稍有不同,它把很多目标文件捆绑到一起形成一个文件,再加上一个索引,可以简单理解为一个包含有很多目标文件的文件包。
在linux下,可以使用file命令来查看相应的文件格式。
目标文件什么样?
一般目标文件按照相关信息的不同属性,以“节”的形式存储,也叫“段”,一般情况下,它们都表示一个一定长度的区域。唯一的区别是在ELF链接视图和装载视图的时候。
感觉原子性确实是不变的主题,一定要有数据的最小单位,只是处于不同的层次,就像数据库里面的数据块。
程序源代码编译后的机器指令经常被放在代码段(常见的名字有.code或者.text)。
全局变量和局部静态变量放在数据段(数据段名称一般是.data)
如下图:
ELF文件的开头是个文件头,它描述了整个文件的文件属性,包括文件是否可执行,是静态链接还是动态链接的入口地址(如果是可执行文件),目标硬件,目标操作系统等信息。
文件头还包括一个段表:
1.段表其实是描述文件中各个段的数组;
2.段表描述了文件中各个段在文件中的偏移位置及段的属性等。
3.从段表里面可以得到每个段的所有信息。
文件头后面就是各个段的内容;
对照上图:
1.一般C语言编译后执行语句都编译成机器代码,保存在.text段
2.已经初始化的全局变量和局部静态变量都保存在.data段
3.未初始化的全局变量和局部的静态变量默认值都为0,本来它们也可以放在data段中,但是因为它们都是0,因此在data段放置它们没有必要。
程序运行的时候,它们是需要占据空间的,并且可执行文件必须记录所有未初始化全局变量和局部静态变量的大小总和,即为.bss段。bss段只是为未初始化的全局变量和局部静态变量预留位置而已。
它没有内容,因此在文件中也不占据空间。