深入剖析 Win32 可移植可执行文件格式
第二部分
作者:Matt Pietrek
上个月在本文的第一部分中,我首先对可移植可执行文件进行了全面的介绍。我讲了 PE 文
件的历史和组成 PE 文件头的数据结构,还讲了节表。PE 文件头和节表告诉你在可执行文件中都
包含什么类型的代码和数据,以及在哪里能找到它们。
本月我要讲一下常见的节。最后讲一下我的最新的经过彻底改进的PEDUMP程序,它可以在
2002 年 2 月的专栏中
下载。如果你不熟悉PE文件的基本概念,应该首先读一下本文的第一部分。
上个月我讲了节是怎样的一个逻辑上属于一起的代码或数据块。例如可执行文件的所有导入
信息都在一个节中。现在让我们来看一下在可执行文件和 OBJ 文件中经常遇到的一些节。除非特
别说明,否则下表中的节名都来自 Microsoft 的工具。
名称 描述
.text 默认的代码节。
.data 默认的可读/可写数据节。全局变量通常在这个节中。
.rdata 默认的只读数据节。字符串常量和 C++/COM 虚表就放在这个节中。
.idata 导入表。实际上,链接器经常把.idata 节合并到其它节中(或者是明确指定的,或者是通
过链接器的默认行为)。默认情况下,链接器仅在创建发行版的程序时才把.idata 节合并
到其它节中。
.edata 导出表。当创建要导出函数或数据的可执行文件时,链接器会创建一个.EXP 文件。这个.EXP
文件包含一个.edata 节,这个节被添加到最后的可执行文件中。与.idata 节一样,.edata
节也经常被合并到.text 节或.rdata 节中。
.rsrc 资源节。这个节是只读的。它不应该被命名为其它名称,也不应该被合并到其它节中。
.bss 未初始化的数据节。在最新的链接器创建的可执行文件中很少见到。链接器扩展可执行文件
的.data 节的 VirtualSize 域以便容纳未初始化的数据。
.crt 添加到可执行文件中的数据,用来支持C++运行时库(CRT)。一个比较好的例子就是用于调
用静态C++对象的构造函数和析构函数的指针。要获取更详细的信息,可以参考
2001 年 1 月
的Under The Hood专栏。
.tls 这个节中的数据用来支持使用__declspec(thread)语法创建的线程局部存储变量。它包括数
据的初始值,以及运行时需要的附加变量。
.reloc 可执行文件中的基址重定位节。通常 DLL 需要基址重定位信息而 EXE 并不需要。在创建发行
版的程序时,链接器并不为 EXE 文件生成基址重定位信息。可以使用/FIXED 链接器选项移
除基址重定位信息。
.sdata 通过全局指针(Global Pointer)相对寻址的“短(Short)”可读/可写数据。用于 IA-64
和其它使用全局指针寄存器的平台上。IA-64 平台上正常大小的全局变量在这个节中。
.srdata 通过全局指针相对寻址的“短(Short)”只读数据。用于 IA-64 和其它使用全局指针寄存
器的平台上。
.pdata 异常表。它包含一个 IMAGE_RUNTIME_FUNCTION_ENTRY 结构数组,这个结构与平台体系结构
相关。数据目录中索引为 IMAGE_DIRECTORY_ENTRY_EXCEPTION 的项指向它。用于使用基于表
的异常处理的平台,例如 IA-64。惟一不使用基于表的异常处理的平台是 x86(它使用的是