目标文件里有什么?
编译器编译源代码后生成的文件叫做目标文件,目标文件从结构上来讲,它是已经编译后的可执行文件格式,只是还没有经历过链接的过程,其中可能有些符号和地址还没有被调整。其实它本身就是按照可执行文件格式存储的,只是跟真正的可执行文件在结构上稍有不同。现在PC平台流行的可执行文件格式(Executable)主要是PE(portable executable)和linux下的elf(executable linkable format),它们都是COFF(common file format)格式的变种
目标文件即编译后未链接的中间文件(windows下的.obj和linux下的.o),其他不太常见的可执行文件格式还有intel/microsoft的OMF(objectmodule format),unix下的a.out格式和ms-dos下的.com格式
动态链接库(dll)(windows的dll和Linux的so)及静态链接库(static linking library)(windows下的lib和linux下的.a)都按照可执行文件格式存储。静态链接库稍有不同,他是把很多目标文件捆绑在一起形成一个文件,在加上一些索引,你可以简单地把它理解为一个包含很多文件的文件包
Elf文件标准把ELF格式的文件归为4类:
可重定位文件(relocatable file) 包含代码和数据,可被链接成可执行文件或共享目标文件。静态链接库归入这类 linux的.o和windows的.obj
可执行文件(executable file) 包含可直接执行程序,一般无扩展名 /bin/bash文件和windows的.exe
共享目标文件(shared object file) 包含代码和数据,以下2种情况使用:一种是将此文件与其他可重定位文件和共享目标文件链接,产生新的目标文件。第二种是将几个此种文件与可执行文件结合,作为进程映像的一部分来运行 linux下的/lib/glibc-2.5.so和windows下的dll
核心转储文件(core dump file ) 当进程意外中止时,系统可以将该进程的地址空间的内容终止时的一些其他信息转储到核心文件中 linux下的core dump
程序源代码编译的机器指令放在代码段(code section)里,代码段常见的名字有.code和.text;全局变量的局部静态变量数据经常放在数据段(data section)一般名字叫.data,ELF文件的开头是一个“文件头”,描述了整个文件的文件属性,包括文件是否可执行,是静态链接还是动态链接及入口地址(如果是可执行文件)、目标硬件、目标操作系统等信息。文件头还包括一个段表(section table),段表其实是一个描述了文件中各个段的数组。段表描述了文件中各个段在文件中的偏移位置及段的属性等。从段表里面可以得到,每个段的所有信息。
未初始化的全局变量和局部静态变量一般放在”.bss”段里。它们默认值为0,可执行文件必须记录所有未初始化的全局变量和局部静态变量的大小总和,记为.bss段,所以,.bss段只是为未初始化的全局变量和局部静态变量预留位置而已,它并无内容,所以它在文件中也不占据空间
程序被装载后,数据和指令分别被映射到两个虚拟区域,由于数据区域对进程可读写,指令区域对进程来说只是只读。
指令区和数据区的分离有利于提高程序的局部性。现代CPU的缓存一般都被设置成数据缓存和指令缓存分离,使得CPU的缓存命中率提高
共享指令
ELF的文件夹中定义了ELF魔、文字机器字节长度、数据存储方式、版本、运行平台、API版本、ELF重定位类型、硬件平台、硬件平台版本、入口地址、程序头入口和长度、段表的位置和长度及段的数量
在链接中,我们将函数和变量统称为符号(symbol),函数名或变量名就是符号名(symbol name)