《程序员的自我修养——链接、装载与库》Windwos PE/COFF(五)

PE/COFF 可执行格式

先来看一下 COFF

COFF

 COFF 几乎和 ELF 一样,也是由文件头以及后面的若干个段组成,再加上符号表和调试信息构成 COFF 的基本结构。COFF 文件头包含了两个部分,一个是描述文件总体结构的映像头,另一个是描述该文件各段属性的段表。后面跟着代码段、数据段等,最后还有符号表。几乎都与 ELF 对于。

冷知识:PE 文件装载时直接映射到进程的虚拟空间中运行,作为进程虚拟空间的映像,所以 PE 很多时候又称为映像文件。

COFF 映像头

 它是一个 "IMAGE_FILE_HEADER" 的结构与 ELF 中的 "Elf32_Ehdr" 结构的作用相同。
包含内容:

  • 目标机器类型
  • PE 包含的段的数量
  • PE 文件创建时间
  • PE 中符号表的位置
  • Optional Header 的大小,这个只存在于 PE 不存在于COFF

COFF 段表

 COFF 的段表是一个 "IMAGE_SECTION_HEADER" 结构的数组,数组里每一个元素代表一个段,元素个数就是映像头中包含的段数。

每个段的属性包括:

  • 段名
  • 物理地址
  • 虚拟地址
  • 原始数据大小
  • 段在文件中的位置
  • 段的重定位表在文件中的位置
  • 段的行号表在文件中的位置
  • 标志位

链接指示信息

 COFF 中存在两个 ELF 中不存在的段 ".drectve",".debug$S" 段

.drectve

 ".drectve"段的内容是编译器传递给链接器的指令,编译器通过这个段标志位的组合告诉链接器如何链接这个目标文件。

.debug

 COFF 中所有以 ".debug" 开始的段都是包含的调试信息。

  • .debug$S 符号相关调试信息
  • .debug$P 预编译头文件相关调试信息
  • .debug$T 类型相关调试信息

".debug" 段的格式被定义在 PE 格式文件标准中。

PE

 PE 是 Win32 平台的标准可执行文件格式,但是在 Windwos 平台,Visual C++ 编译器生产的目标文件仍然是 COFF 。PE 与 ELF 同根同源,均由 COFF 文件格式发展而来。

 所以 PE 与 ELF 基本相同,都采用了基于段的格式。在 PE/COFF 文件中,至少包含一个代码段,通常称为 ".code" ,数据段称为 ".data",而不同的编译器产生的目标文件段名也不同,但都大同小异,而且段名只有提示作用,除了利用链接脚本控制链接时有一定作用以为,并没有太大的实际意义。

PE 与 COFF 的区别

 PE 是基于 COFF 的扩展,在 COFF 的基础上多了几个结构,最主要的变化有两个:

  • 一、文件开始部分不是 COFF 的映射头,而是 DOS MZ 可执行文件格式的文件头和代码桩。
  • 二、原 COFF 中的 "IMAGE_FILE_HEADER" 部分扩展成了 PE 文件头结构 "IMAGE_NT_HEADERS",这个结构包括了原来的映射头,另外增加了 PE 扩展头部结构 "IMAGE_OPTION_HEADER"

PE 数据目录

 Windows 系统装载 PE 可执行文件时,经常需要很快找到导入表、导出表、重定位表等所需的数据结构。而这类数据的位置属性等都保存在一个被称为数据目录的结构里。就是前面的 "IMAGE_OPTIONAL_HEADER" 结构中的 "IMAGE_DATA_DIRECTORY" 数组。这个数组每一个元素都对应一个包含一定含义的表,例如导入表、资源表、异常表、重定位表、调试信息表等。这些表多数都与装载和 DLL 动态链接相关,跟静态链接没什么关系。

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据