目标文件格式

在Linux 0.12 系统中, GNU gcc 或gas 编译输出的目标模块文件和链接程序生成的可执行文件都使用了UNIX传统的a.out格式。这是一种被称为汇编与链接输出(assembly & linker editor output) 的目标文件格式。对于具有内存分页机制的系统来说,这是一种简单有效的目标文件格式。a.out 格式文件由一个文件头和随后的代码区(text section, 也称为正文段)已初始化数据区(data section, 也称为数据段),重定位信息区。符号表以及符号名字符串构成,

a.out 格式7个区的基本定义和用途是:

  执行头部分(exec header). 执行文件头部分。该部分中含有一些参数(exec 结构), 是有关目标文件的整体结构信息。例如代码和数据区的长度,未初始化数据区的长度。对应源程序文件名以及目标文件创建时间等。内核使用这些参数把执行文件加载到内存中并执行,而链接程序使用这些参数将一些模块文件组合成一个可执行文件。这是目标文件唯一必要的组成部分。

  代码区(text segment). 由编译器或汇编器生成的二进制指令代码和数据信息,这部分含有已经初始化过的数据,总是被加载到可读完蛋的内存中。

代码重定位部分(text relocation). 这部分含有供链接程序使用的记录数据。在组合目标文件时用于定位代码段中的指针或地址。当链接程序需要改变目标代码的地址时,就需要修正和维护这些地方。

数据重定位部分(symbol table). 这部分同样含有供链接程序使用的记录数据。这些记录数据保存着模块文件中定义的全局符号以及霜从其他模块文件中输入的符号,或者由链接器定义的符号,用于在模块文件之间对命名的变量和函数时行交叉引用。

字符串表部分(string table).该部分含有与符号名相对应的字符串, 供调试程序调试目标代码,与链接过程无关。这些信息可包含源程序代码和行号,局部符号以及数据描述信息等。

     对于一个指定的目标文件并非一定会包含所有以上信息。下面对其中几个重要的区域或部分进行说明。

   1 执行头部分

   目标文件的文件头含有一个长度为32B 的exec 数据结构,通常称为文件头结构或执行头结构。其定义如下所示。有关a.out结构的详细信息请参见include/a.out.h 文件后的介绍。

struct exec {
  unsigned long a_magic 
  unsigned a_text
  unsigned a_data
  unsigned a_bss
  unsigned a_syms
  unsigned a_entry
  unsigned a_trsize
  unsigned a_drsize
}

    根据a.out 文件中头部结构magic 数字段的值,可以把a.out格式的文件分成几种类型。对于执行文件,使用了zmagic 类型的a.out 格式,它指明文件为需求分页处理(demand-paging), 即需求加载load on demand) 的可执行文件。其魔数是0x10b.  主要区别在于它们对各个部分存储分配方式上。虽然该结构的总长度只有32B, 但是对于一个zmagic 类型的执行文件来说,其文件开始部分却需要专门留出1kb的空间给头结构使用。除被头结构占用的32B以外,其余部分均为0. 从1024字节之后才开始放置程序的正文段和数据段等信息。而对于一个OMAGIC类型的.o 模块文件来说,文件开始部分的32字节头结构后面紧接着就执行区和数据区。

     执行头结构中的a_text和a_data字段分别指明后面只读的代码段和可读数据段的字节长度。a_bss 字段指明内核在加载目标文件时数据段后面未初化数据区域(bss段)的长度。由于linux 在分配内存时会自动对内存对齐清零,因此bss段不需要被包括在模块文件或执行文件中。

    a_entry字段指定了程序从代码开始执行的地址,而a_syms, a_trsize 和a_drsize 字段则分别说明数据段后符号表,代码和数据段重定位信息的大小。对于可执行文件来说并不需要符号表和定位信息。因此除非链接程序为了调试目的而包括了符号信息,执行文件中的这几个字段通常为0.

猜你喜欢

转载自blog.csdn.net/robinsongsog/article/details/106108896