admin 管理员组

文章数量: 1086019


2024年12月28日发(作者:linux下载工具哪个好)

Microsoft可移植可执行文件和通

用目标文件格式文件规范

修订版8.1 - 2008年2月15日

摘要

本规范描述了Microsoft® Windows®操作系统家族下的可执行文件(映像)和目

标文件的结构。这些文件分别被称为可移植可执行(PE)文件和通用目标文件格式

(COFF)文件。

注意:提供本文档是为了辅助开发用于Microsoft Windows操作系统上的工具和

应用程序,但并不保证它在各个方面都是完整的规范。Microsoft保留更改本文档而

不通知的权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范的此次修订版取代了

本规范的6.0修订版。

本规范中的信息适用于以下操作系统:

Windows Server® 2008

Windows Vista®

Windows Server 2003

Windows XP

Windows 2000

本规范最后列出了参考信息和相关资源。

本规范的最新版在万维网的以下地址被维护:

/whdc/system/platform/firmware/

SmartTech译

电子信箱:zhzhtst@

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 2

法律声明

Microsoft可移植可执行文件和通用目标文件格式文件规范

Microsoft Corporation

修订版 8.1

注意:提供本规范是为了辅助开发某些用于Microsoft Windows操作系统平台上的开发工具。但是

Microsoft并不保证它在各个方面都是完整的规范,也无法保证这里的所有信息在发布之后一直都是准确

的。Microsoft保留更改本规范而不通知的权利。

在合理的和非歧视性条款和条件下,Microsoft将针对任何Microsoft认为仅在面向Microsoft

Windows的被称为编译器、链接器以及汇编程序的软件开发工具中实现和遵守本规范中所需部分这种有限

用途下所需要的Microsoft权利要求书(如果存在)授予您免版税许可。

遵守所有适用的版权法是用户的责任。在不限制版权许可权利的前提下,未经Microsoft明确书面许

可,不得出于任何目的或以任何形式或任何手段(电子、机械、影印、记录或其他方法)复制本规范的任

何部分,或者将其存储或引入检索系统,或者修改或用于其衍生作品,或者将其进行传播。

对于本规范中的主题,Microsoft可能拥有知识产权。除非在书面许可中明确规定,否则提供本规范

并不意味着Microsoft通过暗示、默许或其它方式针对这些知识产权和其它权利授予您任何许可。

© 2005-2008 Microsoft Corporation。保留所有权利。

本规范依“原样”提供。Microsoft不针对下列情形作任何明示的、暗示的或者法定的表示或担保:(1)

本规范中的信息,包括对适销性、针对特定目的的适用性、不侵权或所有权的担保;(2)本规范中的内容

适用于任何用途;(3)对这些内容的实现不会侵犯任何第三方的专利、版权、商标或其它权利。

Microsoft不就由本规范及其相关的使用或分发所带来的任何直接的、间接的、特别的、偶然的或者后果

性的损害负任何责任。

Microsoft、MS-DOS、MSDN、Visual Studio、Visual C++、Win32、 Windows、Windows NT、Windows

Server和Windows Vista是Microsoft Corporation在美国和/或其它国家的注册商标或商标。这里提到

的其它产品和公司名称可能是其各自所有者的商标。

对于上述名称和商标,在没有事先得到其各自所有者明确书面许可的情况下,不得以任何方式使用,

包括广告或宣传本规范及其内容。

文档更新历史:

日期

2/15/2008

5/18/2006

更改

更新了5.7节,并将附录A移到了“Windows Authenticode可移植可执行签名

格式”中

创建

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 3

目录

1 基本概念......................................................................5

2 概览..........................................................................6

3 文件头........................................................................7

3.1 MS-DOS占位程序(仅适用于映像文件).......................................7

3.2 签名(仅适用于映像文件).................................................7

3.3 COFF文件头(适用于目标文件和映像文件)...................................7

3.3.1 机器类型............................................................8

3.3.2 特征................................................................9

3.4 可选文件头(仅适用于映像文件)...........................................9

3.4.1 可选文件头中的标准域(仅适用于映像文件)...........................10

3.4.2 可选文件头中的Windows特定域(仅适用于映像文件)....................11

3.4.3 可选文件头中的数据目录(仅适用于映像文件).........................13

4 节表(节头).................................................................14

4.1 节标志..................................................................15

4.2 成组的节(仅适用于目标文件)............................................17

5 文件中的其它内容.............................................................17

5.1 节中的数据..............................................................17

5.2 COFF重定位信息(仅适用于目标文件)......................................18

5.2.1 类型指示符.........................................................18

5.3 COFF行号信息(不赞成使用)..............................................25

5.4 COFF符号表..............................................................26

5.4.1 符号名称表示.......................................................27

5.4.2 SectionNumber域的值................................................27

5.4.3 类型表示...........................................................27

5.4.4 存储类别...........................................................28

5.5 辅助符号表记录..........................................................29

5.5.1 辅助符号表记录格式之一:函数定义...................................30

5.5.2 辅助符号表记录格式之二:.bf和.ef符号...............................30

5.5.3 辅助符号表记录格式之三:弱外部符号.................................30

5.5.4 辅助符号表记录格式之四:文件.......................................31

5.5.5 辅助符号表记录格式之五:节定义.....................................31

5.5.6 COMDAT节(仅适用于目标文件).......................................32

5.5.7 CLR记号定义(仅适用于目标文件)....................................32

5.6 COFF字符串表............................................................33

5.7 属性证书表(仅适用于映像文件)..........................................33

5.7.1 证书数据...........................................................34

5.8 延迟加载导入表(仅适用于映像文件)......................................35

5.8.1 延迟加载目录表.....................................................35

5.8.2 属性...............................................................35

5.8.3 名称...............................................................35

5.8.4 模块句柄...........................................................36

5.8.5 延迟导入地址表.....................................................36

5.8.6 延迟导入名称表.....................................................36

5.8.7 延迟绑定导入地址表和时间戳.........................................36

5.8.8 延迟卸载导入地址表.................................................36

6 特殊的节.....................................................................36

6.1 .debug节................................................................38

6.1.1 调试目录(仅适用于映像文件).......................................38

6.1.2 调试类型...........................................................39

6.1.3 .debug$F节(仅适用于目标文件).....................................40

6.1.4 .debug$S节(仅适用于目标文件).....................................40

6.1.5 .debug$P节(仅适用于目标文件).....................................40

6.1.6 .debug$T节(仅适用于目标文件).....................................40

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 4

6.1.7 链接器对Microsoft调试信息的支持....................................

6.2 .drectve节(仅适用于目标文件)..........................................

6.3 .edata节(仅适用于映像文件)............................................

6.3.1 导出目录表.........................................................

6.3.2 导出地址表.........................................................

6.3.3 导出名称指针表.....................................................

6.3.4 导出序数表.........................................................

6.3.5 导出名称表.........................................................

6.4 .idata节................................................................

6.4.1 导入目录表.........................................................

6.4.2 导入查找表.........................................................

6.4.3 提示/名称表........................................................

6.4.4 导入地址表.........................................................

6.5 .pdata节................................................................

6.6 .reloc节(仅适用于映像文件)............................................

6.6.1 基址重定位块.......................................................

6.6.2 基址重定位类型.....................................................

6.7 .tls节..................................................................

6.7.1 TLS目录............................................................

6.7.2 TLS回调函数........................................................

6.8 加载配置结构(仅适用于映像文件)........................................

6.8.1 加载配置目录.......................................................

6.8.2 加载配置结构布局...................................................

6.9 .rsrc节.................................................................

6.9.1 资源目录表.........................................................

6.9.2 资源目录项.........................................................

6.9.3 资源目录字符串.....................................................

6.9.4 资源数据项.........................................................

6.10 .cormeta节(仅适用于目标文件).........................................

6.11 .sxdata节..............................................................

7 档案(库)文件格式...........................................................

7.1 档案文件签名............................................................

7.2 档案文件成员头部........................................................

7.3 第一个链接器成员........................................................

7.4 第二个链接器成员........................................................

7.5 长名称成员..............................................................

8 导入库格式...................................................................

8.1 导入头..................................................................

8.2 导入类型................................................................

8.3 导入名称类型............................................................

参考信息.......................................................................

40

40

41

41

42

42

42

43

43

44

44

44

45

45

45

46

46

46

48

48

49

49

49

50

51

51

51

52

52

52

52

53

53

54

55

55

55

56

56

57

57

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 5

1 基本概念

本文档详细说明了Microsoft® Windows®操作系统家族下的可执行文件(映像)

和目标文件的结构。这些文件分别被称为可移植可执行(PE)文件和通用目标文件格

式(COFF)文件。“可移植可执行”这个名称道出了这种格式与平台体系结构无关的

事实。

下表描述了贯穿于本规范中的一些概念:

名称

属性证书

描述

用来将可校验的声明与映像关联起来的证书。有许多不同的可校验声

明可以与文件关联,最常用的一种就是软件制造商用来指明映像的消

息摘要是什么的声明。消息摘要与校验和类似,但想要伪造它却极其

困难。因此对一个文件进行修改并保持它的消息摘要与原始文件一致

是非常困难的。正如制造商所做的那样,可以使用公钥或私钥加密机

制来校验声明。本文档除了描述允许将它们插入到映像文件中外还描

述了有关属性证书的详细信息。

由于不同目的而用于PE或COFF文件中好几个地方的戳。戳的格式与

C运行时库时间函数所使用的戳的格式相同。

某项内容在文件被链接器处理前(如果是目标文件文件)或者被加载

器处理前(如果是映像文件)在文件自身中的位置。换句话说,这是

一个位于存储在磁盘上的文件中的位置。

指的是随Microsoft Visual Studio®提供的链接器。

可执行文件:或者是.EXE文件,或者是DLL。映像文件可以被认为是

“内存映像”。术语“映像文件”经常用来代替“可执行文件”,因

为后者有时仅用来指代.EXE文件。

作为链接器的输入的文件。链接器生成一个映像文件,而这个映像文

件又作为加载器的输入。

对一个域的这种描述表明,对于生成这个域的程序来说必须将这个域

设置为0,对于使用这个域的程序来说必须忽略它的值。

相对虚拟地址。对于映像文件来说,它是某项内容被加载进内存后的

地址减去映像文件的基地址。某项内容的RVA几乎总是与它在磁盘上

的文件中的位置(文件指针)不同。

对于目标文件来说,RVA并没有什么意义,因为内存位置尚未分配。

在这种情况下,RVA是一个节(后面将要描述)中的地址,这个地址

在以后链接时要被重定位。为了简单起见,编译器应该将每个节的首

个RVA设置为0。

节是PE或COFF文件中代码或数据的基本单元。例如一个目标文件中

所有代码可以被组合成单个节,或者(依赖于编译器的行为)每个函

数独占一个节。增加节的数目会增加文件开销,但是链接器在链接代

码时有更大的选择余地。节与Intel 8086体系结构中的段非常相似。

一个节中的所有原始数据必须被加载到连续的内存中。另外,映像文

件可能包含一些具有特殊用途的节,例如.tls节或.reloc节。

虚拟地址。除了不减去映像文件的基地址外,与RVA相同。这个地址

之所以被叫做“虚拟地址”是因为Windows为每个进程创建一个私有

的虚拟地址空间,它独立于物理内存。无论出于何种目的,VA都只应

该被认为是一个地址。VA并不能像RVA那样能够预先得到,因为加载

器可能不把映像加载到它的首选位置上。

日期/时间戳

文件指针

链接器

映像文件

目标文件

保留,必须为0

RVA

VA

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 6

2 概览

图1 解释了Microsoft PE可执行文件格式:

MS-DOS 2.0 兼容

EXE 文件头

未使用

OEM 标识

OEM 信息

PE文件头偏移

MS-DOS 2.0占位程序

重定位表

未使用

PE 文件头

(按8字节边界对齐)

节头

映像页:

导入信息

导出信息

基址重定位信息

资源信息

映像头基地址

MS-DOS 2.0节

(仅用于MS-DOS兼容)

图 1.典型的可移植EXE文件布局

图2 解释了Microsoft COFF目标模块格式:

Microsoft COFF文件头

节头

原始数据:

代码

数据

调试信息

重定位信息

图 2. 典型的COFF目标模块布局

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 7

3 文件头

PE文件头由Microsoft MS-DOS®占位程序、PE文件签名、COFF文件头以及可选

文件头组成,COFF目标文件头由COFF文件头和可选文件头组成。在这两种情况下,

文件头后面紧跟着的都是节头。

3.1 MS-DOS占位程序(仅适用于映像文件)

MS-DOS占位程序是一个运行于MS-DOS下的合法应用程序,它被放在EXE映像的

最前面。链接器在这里放一个默认的占位程序,当映像运行于MS-DOS下时,这个占

位程序显示“This program cannot be run in DOS mode(此程序不能在DOS模式下

运行)”这条消息。用户可以使用/STUB链接器选项来指定一个不同的占位程序。

在位置0x3C处,这个占位程序包含PE文件签名的偏移地址。此信息的存在使得

即使映像文件中有一个MS-DOS占位程序,Windows仍然能够正常执行它。这个文件

偏移是在链接时被放在0x3C处的。

3.2 签名(仅适用于映像文件)

在MS-DOS占位程序后面、在偏移0x3C指定的文件偏移处,是一个4字节的签

名,它用来标识文件为一个PE格式的映像文件。这个签名是“PE00”(字母“P”

和“E”后跟着两个空字节)。

3.3 COFF文件头(适用于目标文件和映像文件)

在目标文件的开头,或者紧跟着映像文件签名之后,是一个如下格式的标准

COFF文件头。注意Windows加载器限制节的最大数目为96。

偏移

0

2

4

大小

2

2

4

Machine

NumberOfSections

TimeDateStamp

描述

标识目标机器类型的数字。要获取更多信息,请参

考3.3.1节“机器类型”。

节的数目。它给出了节表的大小,而节表紧跟着文

件头。

从UTC时间1970年1月1日00:00起的总秒数

(一个C运行时time_t类型的值)的低32位,它

指出文件何时被创建。

COFF符号表的文件偏移。如果不存在COFF符号

表,此值为0。对于映像文件来说,此值应该为

0,因为已经不赞成使用COFF调试信息了。

符号表中的元素数目。由于字符串表紧跟符号表,

所以可以利用这个值来定位字符串表。对于映像文

件来说,此值应该为0,因为已经不赞成使用COFF

调试信息了。

可选文件头的大小。可执行文件需要可选文件头而

目标文件并不需要。对于目标文件来说,此值应该

为0。要获取可选文件头格式的详细描述,请参考

3.4节“可选文件头(仅适用于映像文件)”。

指示文件属性的标志。对于特定的标志,请参考

3.3.2节“特征”。

8 4 PointerToSymbolTable

12 4 NumberOfSymbols

16 2 SizeOfOptionalHeader

18 2 Characteristics

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 8

3.3.1 机器类型

Machine域可以取以下各值中的一个来指定CPU类型。 映像文件仅能运行于指

定处理器或者能够模拟指定处理器的系统上。

常量

IMAGE_FILE_MACHINE_UNKNOWN

IMAGE_FILE_MACHINE_AM33

IMAGE_FILE_MACHINE_AMD64

IMAGE_FILE_MACHINE_ARM

IMAGE_FILE_MACHINE_EBC

IMAGE_FILE_MACHINE_I386

IMAGE_FILE_MACHINE_IA64

IMAGE_FILE_MACHINE_M32R

IMAGE_FILE_MACHINE_MIPS16

IMAGE_FILE_MACHINE_MIPSFPU

IMAGE_FILE_MACHINE_MIPSFPU16

IMAGE_FILE_MACHINE_POWERPC

IMAGE_FILE_MACHINE_POWERPCFP

IMAGE_FILE_MACHINE_R4000

IMAGE_FILE_MACHINE_SH3

IMAGE_FILE_MACHINE_SH3DSP

IMAGE_FILE_MACHINE_SH4

IMAGE_FILE_MACHINE_SH5

IMAGE_FILE_MACHINE_THUMB

IMAGE_FILE_MACHINE_WCEMIPSV2

0x0

0x1d3

0x8664

0x1c0

0xebc

0x14c

0x200

0x9041

0x266

0x366

0x466

0x1f0

0x1f1

0x166

0x1a2

0x1a3

0x1a6

0x1a8

0x1c2

0x169

描述

适用于任何类型处理器

Matsushita AM33处理器

x64处理器

ARM小尾处理器

EFI字节码处理器

Intel 386或后继处理器及其兼容处理器

Intel Itanium处理器家族

Mitsubishi M32R小尾处理器

MIPS16处理器

带FPU的MIPS处理器

带FPU的MIPS16处理器

PowerPC小尾处理器

带符点运算支持的PowerPC处理器

MIPS 小尾处理器

Hitachi SH3处理器

Hitachi SH3 DSP处理器

Hitachi SH4处理器

Hitachi SH5处理器

Thumb处理器

MIPS小尾WCE v2处理器

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 9

3.3.2 特征

Characteristics域包含指示目标文件或映像文件属性的标志。当前定义了以下值:

标志

IMAGE_FILE_RELOCS_STRIPPED

0x0001

描述

仅适用于映像文件,适用于 Windows CE、

Microsoft Windows NT® 及其后继操作系

统。它表明此文件不包含基址重定位信

息,因此必须被加载到其首选基地址上。

如果基地址不可用,加载器会报错。链接

器默认会移除可执行(EXE)文件中的重定

位信息。

仅适用于映像文件。它表明此映像文件是

合法的,可以被运行。如果未设置此标

志,表明出现了链接器错误。

COFF行号信息已经被移除。不赞成使用此

标志,它应该为0。

COFF符号表中有关局部符号的项已经被移

除。不赞成使用此标志,它应该为0。

此标志已经被舍弃。它用于调整工作集。

Windows 2000及其后继操作系统不赞成使

用此标志,它应该为0。

应用程序可以处理大于2GB的地址。

此标志保留供将来使用。

小尾:在内存中,最不重要位(LSB)在最

重要位(MSB)前面。不赞成使用此标志,

它应该为0。

机器类型基于32位字体系结构。

调试信息已经从此映像文件中移除。

如果此映像文件在可移动介质上,完全加

载它并把它复制到交换文件中。

如果此映像文件在网络介质上,完全加载

它并把它复制到交换文件中。

此映像文件是系统文件,而不是用户程

序。

此映像文件是动态链接库(DLL)。这样的

文件总被认为是可执行文件,尽管它们并

不能直接被运行。

此文件只能运行于单处理器机器上。

大尾:在内存中,MSB在LSB前面。不赞

成使用此标志,它应该为0。

IMAGE_FILE_EXECUTABLE_IMAGE 0x0002

IMAGE_FILE_LINE_NUMS_STRIPPED

IMAGE_FILE_LOCAL_SYMS_STRIPPED

IMAGE_FILE_AGGRESSIVE_WS_TRIM

0x0004

0x0008

0x0010

IMAGE_FILE_LARGE_ADDRESS_AWARE

IMAGE_FILE_BYTES_REVERSED_LO

0x0020

0x0040

0x0080

IMAGE_FILE_32BIT_MACHINE

IMAGE_FILE_DEBUG_STRIPPED

IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP

IMAGE_FILE_NET_RUN_FROM_SWAP

IMAGE_FILE_SYSTEM

IMAGE_FILE_DLL

0x0100

0x0200

0x0400

0x0800

0x1000

0x2000

IMAGE_FILE_UP_SYSTEM_ONLY

IMAGE_FILE_BYTES_REVERSED_HI

0x4000

0x8000

3.4 可选文件头(仅适用于映像文件)

每个映像文件都有一个可选文件头,用于为加载器提供信息。这个文件头之所以

说是可选的是从一些文件(明确地说是目标文件)并不包含它这层意义上来说的。对

于映像文件来说,这个文件头是必须的。目标文件可以包含一个可选文件头,但是通

常它除了增加文件的大小外并无其它作用。

注意可选文件头的大小并不固定。COFF文件头中的SizeOfOptionalHeader域用

来验证某个特别的数据目录不超过SizeOfOptionalHeader。要获取更多信息,请参

考3.3节“COFF文件头(适用于目标文件和映像文件)”

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 10

可选文件头中的NumberOfRvaAndSizes域也应该被用来确保某个特别的数据目录

不超出可选文件头。另外出于格式兼容目的而去校验可选文件头中的幻数也很重要。

可选文件头中的幻数决定一个映像是PE32还是PE32+格式的可执行文件:

幻数

0x10b

0x20b

PE 格式

PE32

PE32+

PE32+映像在限制映像大小最大为2G时可以访问64位地址空间。PE32+的其它更

改在它们各自的节中描述。

可选文件头自身由三个主要部分组成:

偏移

(PE32/PE32+)

0

28/24

96/112

大小

(PE32/PE32+)

28/24

68/88

Variable

文件头部分

标准域

Windows特定域

数据目录

描述

这些域被所有COFF实现所定义,其中

包括UNIX。

支持Windows特性(例如子系统)的

附加域。

映像文件中的特殊表(例如导入表和

导出表)的地址/大小组合,它们供操

作系统使用。

3.4.1 可选文件头中的标准域(仅适用于映像文件)

可选文件头的前8个域为标准域,它们被所有COFF实现所定义。这些域包含对

加载和运行可执行文件有用的常规信息。它们在PE32+中并未改变。

偏移

0

大小

2

Magic

描述

这个无符号整数指出了映像文件的状态。最常

用的数字是0x10B,它表明这是一个正常的可

执行文件。0x107表明这是一个ROM映像,

0x20B表明这是一个PE32+可执行文件。

链接器的主版本号。

链接器的次版本号。

代码节(.text)的大小。如果有多个代码节的

话,它是所有代码节的和。

已初始化数据节的大小。如果有多个这样的数

据节的话,它是所有这些数据节的和。

未初始化数据节(.bss)的大小。如果有多

个.bss节的话,它是所有这些节的和。

当可执行文件被加载进内存时其入口点相对于

映像基址的偏移地址。对于一般程序映像来

说,它就是启动地址。对于设备驱动程序来

说,它是初始化函数的地址。入口点对于DLL

来说是可选的。如果不存在入口点的话,这个

域必须为0。

当映像被加载进内存时代码节的开头相对于映

像基址的偏移地址。

2

3

4

8

12

16

1

1

4

4

4

4

MajorLinkerVersion

MinorLinkerVersion

SizeOfCode

SizeOfInitializedData

SizeOfUninitializedData

AddressOfEntryPoint

20

4 BaseOfCode

PE32中在BaseOfCode域后面是下面这个附加域,它并不存在于PE32+中:

偏移

24

大小

4

BaseOfData

描述

当映像被加载进内存时数据节的开头相对于

映像基址的偏移地址。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 11

3.4.2 可选文件头中的Windows特定域(仅适用于映像文件)

接下来的21个域是COFF可选文件头格式的扩展。它们包含Windows中的链接器

和加载器所必需的附加信息。

偏移 大小 域

(PE32/ (PE32/

PE32+) PE32+)

28/24 4/8 ImageBase

描述

当加载进内存时映像的第一个字节的

首选地址。它必须是64K的倍数。DLL

默认是0x10000000。Windows CE EXE

默认是0x00010000。Windows NT、

Windows 2000、Windows XP、

Windows 95、Windows 98和

Windows Me 默认是0x00400000。

当加载进内存时节的对齐值(以字节

计)。它必须大于或等于

FileAlignment。默认是相应系统的页

面大小。

用来对齐映像文件的节中的原始数据

的对齐因子(以字节计)。它应该是

界于512和64K之间的2的幂(包括

这两个边界值)。默认是512。如果

SectionAlignment小于相应系统的页

面大小,那么FileAlignment必须与

SectionAlignment匹配。

所需操作系统的主版本号。

所需操作系统的次版本号。

映像的主版本号。

映像的次版本号。

子系统的主版本号。

子系统的次版本号。

保留,必须为0。

当映像被加载进内存时的大小(以字

节计),包括所有的文件头。它必须

是SectionAlignment的倍数。

MS-DOS占位程序、PE文件头和节头的

总大小,向上舍入为FileAlignment

的倍数。

映像文件的校验和。计算校验和的算

法被合并到了 中。以

下程序在加载时被校验以确定其是否

合法:所有的驱动程序、任何在引导

时被加载的DLL以及加载进关键

Windows进程中的DLL。

运行此映像所需的子系统。要获取更

多信息,请参考后面的“Windows子

系统”部分。

要获取更多信息,请参考后面的“DLL

特征”部分。

32/32 4 SectionAlignment

36/36 4 FileAlignment

40/40

42/42

44/44

46/46

48/48

50/50

52/52

56/56

2

2

2

2

2

2

4

4

MajorOperatingSystemVersion

MinorOperatingSystemVersion

MajorImageVersion

MinorImageVersion

MajorSubsystemVersion

MinorSubsystemVersion

Win32VersionValue

SizeOfImage

60/60 4 SizeOfHeaders

64/64 4 CheckSum

68/68 2 Subsystem

70/70 2 DllCharacteristics

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 12

偏移 大小 域

(PE32/ (PE32/

PE32+) PE32+)

72/72 4/8 SizeOfStackReserve

描述

保留的堆栈大小。只有

SizeOfStackCommit指定的部分被提

交;其余的每次可用一页,直到到达

保留的大小为止。

提交的堆栈大小。

保留的局部堆空间大小。只有

SizeOfHeapCommit指定的部分被提

交;其余的每次可用一页,直到到达

保留的大小为止。

提交的局部堆空间大小。

保留,必须为0。

可选文件头其余部分中数据目录项的

个数。每个数据目录描述了一个表的

位置和大小。

76/80

80/88

4/8

4/8

SizeOfStackCommit

SizeOfHeapReserve

84/96

88/104

92/108

4/8

4

4

SizeOfHeapCommit

LoaderFlags

NumberOfRvaAndSizes

Windows子系统

为可选文件头的Subsystem域定义了以下值以确定运行映像所需的Windows子系

统(如果存在):

常量

IMAGE_SUBSYSTEM_UNKNOWN

IMAGE_SUBSYSTEM_NATIVE

IMAGE_SUBSYSTEM_WINDOWS_GUI

IMAGE_SUBSYSTEM_WINDOWS_CUI

IMAGE_SUBSYSTEM_POSIX_CUI

IMAGE_SUBSYSTEM_WINDOWS_CE_GUI

IMAGE_SUBSYSTEM_EFI_APPLICATION

IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER

IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER

IMAGE_SUBSYSTEM_EFI_ROM

IMAGE_SUBSYSTEM_XBOX

0

1

2

3

7

9

10

11

12

13

14

描述

未知子系统

设备驱动程序和Native Windows进程

Windows图形用户界面(GUI)子系统

Windows字符模式(CUI)子系统

Posix字符模式子系统

Windows CE

可扩展固件接口(EFI)应用程序

带引导服务的EFI驱动程序

带运行时服务的EFI驱动程序

EFI ROM映像

XBOX

DLL特征

为可选文件头的DllCharacteristics域定义了以下值:

常量

IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE

IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY

IMAGE_DLLCHARACTERISTICS_NX_COMPAT

IMAGE_DLLCHARACTERISTICS_NO_ISOLATION

IMAGE_DLLCHARACTERISTICS_NO_SEH

0x0001

0x0002

0x0004

0x0008

0x0040

0x0080

0x0100

0x0200

0x0400

描述

保留,必须为0。

保留,必须为0。

保留,必须为0。

保留,必须为0。

DLL可以在加载时被重定位。

强制进行代码完整性校验。

映像兼容于NX。

可以隔离,但并不隔离此映像。

不使用结构化异常(SE)处理。

在此映像中不能调用SE处理程

序。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 13

常量

IMAGE_DLLCHARACTERISTICS_NO_BIND

IMAGE_DLLCHARACTERISTICS_WDM_DRIVER

IMAGE_DLLCHARACTERISTICS_

TERMINAL_SERVER_AWARE

0x0800

0x1000

0x2000

0x8000

描述

不绑定映像。

保留,必须为0。

WDM驱动程序。

可以用于终端服务器。

3.4.3 可选文件头中的数据目录(仅适用于映像文件)

每个数据目录给出了Windows使用的表或字符串的地址和大小。这些数据目录项

全部被被加载进内存以备系统运行时使用。数据目录是按照如下格式定义的一个8字

节结构:

typedef struct _IMAGE_DATA_DIRECTORY {

DWORD VirtualAddress;

DWORD Size;

} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

第一个域——VirtualAddress,实际上是表的RVA。这个RVA是当表被加载进内

存时相对于映像基地址的偏移地址。第二个域给出了表的大小(以字节计)。 数据

目录组成了可选文件头的最后一部分,它被列于下表中。

注意目录的数目是不固定的。在查看一个特定的目录之前,先检查可选文件头中

的NumberOfRvaAndSizes域。

同样,不要想当然地认为在这个表中的RVA指向节的开头,或者认为包含特定表

的节有特定的名字。

偏移 大小 域

(PE/PE32+)

96/112

104/120

112/128

120/136

128/144

8

8

8

8

8

Export Table

Import Table

Resource Table

Exception Table

Certificate

Table

Base Relocation

Table

Debug

Architecture

Global Ptr

TLS Table

描述

导出表的地址和大小。要获取更多信息,请参考

6.3节“.edata节(仅适用于映像文件)”。

导入表的地址和大小。要获取更多信息,请参考

6.4节“.idata节”。

资源表的地址和大小。要获取更多信息,请参考

6.9节“.rsrc节”。

异常表的地址和大小。要获取更多信息,请参考

6.5节“.pdata节”。

属性证书表的地址和大小。要获取更多信息,请

参考5.7节“属性证书表(仅适用于映像文

件)”

基址重定位表的地址和大小。要获取更多信息,

请参考6.6节“.reloc节(仅适用于映像文

件)”。

调试数据起始地址和大小。要获取更多信息,请

参考6.1节“.debug节”。

保留,必须为0。

将被存储在全局指针寄存器中的一个值的RVA。

这个结构的Size域必须为0。

线程局部存储(TLS)表的地址和大小。要获取

更多信息,请参考6.7节“.tls节”。

136/152 8

144/160

152/168

160/176

168/184

8

8

8

8

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 14

偏移 大小 域

(PE/PE32+)

176/192 8 Load Config

Table

Bound Import

IAT

Delay Import

Descriptor

CLR Runtime

Header

保留,必须为0。

描述

加载配置表的地址和大小。要获取更多信息,请

参考6.8节“加载配置结构(仅适用于映像文

件)”。

绑定导入表的地址和大小。

导入地址表的地址和大小。要获取更多信息,请

参考6.4.4节“导入地址表”。

延迟导入描述符的地址和大小。要获取更多信

息,请参考5.8节“延迟加载导入表(仅适用于

映像文件)”。

CLR运行时头部的地址和大小。要获取更多信

息,请参考6.10节“.cormeta节(仅适用于目

标文件)”

184/200

192/208

200/216

8

8

8

208/224 8

216/232

8

Certificate Table域指向属性证书表。这些证书并不作为映像的一部分被加载

进内存。此时它的第一个域是一个文件指针,而不是通常的RVA。

4 节表(节头)

节表的每一行等效于一个节头。这个表紧跟可选文件头(如果存在的话)。之所

以必须在这个位置是因为文件头中并没有一个直接指向节表的指针,节表的位置是通

过计算文件头后的第一个字节的位置来得到的。一定要确保使用文件头中指定的可选

文件头的大小(来进行计算)。

节表中的元素数目由文件头中的NumberOfSections域给出。而元素的编号是从

1开始的。表示代码节和数据节的元素的顺序由链接器决定。

在映像文件中,每个节的VA值必须由链接器决定。这样能够保证这些节位置相

邻且按升序排列,并且这些VA值必须是可选文件头中SectionAlignment域的倍数。

每个节头(节表项)格式如下,共40个字节:

偏移

0

大小

8

Name

描述

这是一个8字节的UTF-8编码的字符串,不足8字

节时用NULL填充。如果它正好是8字节,那就没

有最后的NULL字符。如果名称更长的话,这个域

中是一个斜杠(/)后跟一个用ASCII码表示的十

进制数,这个十进制数表示字符串表中的偏移。可

执行映像不使用字符串表也不支持长度超过8字节

的节名。如果目标文件中有长节名的节最后要出现

在可执行文件中,那么相应的长节名会被截断。

当加载进内存时这个节的总大小。如果此值比

SizeOfRawData大,那么多出的部分用0填充。这

个域仅对可执行映像是合法的,对于目标文件来

说,它应该为0。

对于可执行映像来说,这个域的值是这个节被加载

进内存之后它的第一个字节相对于映像基址的偏移

地址。对于目标文件来说,这个域的值是没有重定

位之前其第一个字节的地址;为了简单起见,编译

器应该把此值设置为0。否则这个值是个任意值,

但是在重定位时应该从偏移地址中减去这个值。

8 4 VirtualSize

12 4 VirtualAddress

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 15

偏移

16

大小

4

SizeOfRawData

描述

(对于目标文件来说)节的大小或者(对于映像文

件来说)磁盘文件中已初始化数据的大小。对于可

执行映像来说,它必须是可选文件头中

FileAlignment域的倍数。如果它小于

VirtualSize域的值,余下的部分用0填充。由于

SizeOfRawData域要向上舍入,但是VirtualSize

域并不舍入,因此可能出现SizeOfRawData域大于

VirtualSize域的情况。当节中仅包含未初始化的

数据时,这个域应该为0。

指向COFF文件中节的第一个页面的文件指针。对

于可执行映像来说,它必须是可选文件头中

FileAlignment域的倍数。对于目标文件来说,要

获得最好的性能,此值应该按4字节边界对齐。当

节中仅包含未初始化的数据时,这个域应该为0。

指向节中重定位项开头的文件指针。对于可执行文

件或者没有重定位项的文件来说,此值应该为0。

指向节中行号项开头的文件指针。如果没有COFF

行号信息的话,此值应该为0。对于映像来说,此

值应该为0,因为已经不赞成使用COFF调试信息

了。

节中重定位项的个数。对于可执行映像来说,此值

应该为0。

节中行号项的个数。对于映像来说,此值应该为

0,因为已经不赞成使用COFF调试信息了。

描述节特征的标志。要获取更多信息,请参考4.1

节“节标志”。

20 4 PointerToRawData

24

28

4

4

PointerToRelocations

PointerToLinenumbers

32

34

36

2

2

4

NumberOfRelocations

NumberOfLinenumbers

Characteristics

4.1 节标志

节头中的Characteristics域中的节标志指出了节的属性。

标志

IMAGE_SCN_TYPE_NO_PAD

0x00000000

0x00000001

0x00000002

0x00000004

0x00000008

描述

保留供将来使用。

保留供将来使用。

保留供将来使用。

保留供将来使用。

从这个节结尾到下一个边界之间不

能填充。此标志被舍弃,它已经被

IMAGE_SCN_ALIGN_1BYTES标志取

代。此标志仅对目标文件合法。

保留供将来使用。

此节包含可执行代码。

此节包含已初始化的数据。

此节包含未初始化的数据。

保留供将来使用。

此节包含注释或者其它信息。

.drectve节具有这种属性。此标志

仅对目标文件合法。

保留供将来使用。

IMAGE_SCN_CNT_CODE

IMAGE_SCN_CNT_INITIALIZED_DATA

IMAGE_SCN_CNT_UNINITIALIZED_DATA

IMAGE_SCN_LNK_OTHER

IMAGE_SCN_LNK_INFO

0x00000010

0x00000020

0x00000040

0x00000080

0x00000100

0x00000200

0x00000400

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 16

标志

IMAGE_SCN_LNK_REMOVE

0x00000800

描述

此节不会成为最终形成的映像文件

的一部分。此标志仅对目标文件合

法。

此节包含COMDAT数据。要获取更多

信息,请参考5.5.6节“COMDAT节

(仅适用于目标文件)”。此标志

仅对目标文件合法。

此节包含通过全局指针(GP)来引

用的数据。

保留供将来使用。

保留供将来使用。

保留供将来使用。

保留供将来使用。

按1字节边界对齐数据。此标志仅

对目标文件合法。

按2字节边界对齐数据。此标志仅

对目标文件合法。

按4字节边界对齐数据。此标志仅

对目标文件合法。

按8字节边界对齐数据。此标志仅

对目标文件合法。

按16字节边界对齐数据。此标志仅

对目标文件合法。

按32字节边界对齐数据。此标志仅

对目标文件合法。

按64字节边界对齐数据。此标志仅

对目标文件合法。

按128字节边界对齐数据。此标志

仅对目标文件合法。

按256字节边界对齐数据。此标志

仅对目标文件合法。

按512字节边界对齐数据。此标志

仅对目标文件合法。

按1024字节边界对齐数据。此标志

仅对目标文件合法。

按2048字节边界对齐数据。此标志

仅对目标文件合法。

按4096字节边界对齐数据。此标志

仅对目标文件合法。

按8192字节边界对齐数据。此标志

仅对目标文件合法。

此节包含扩展的重定位信息。

此节可以在需要时被丢弃。

此节不能被缓存。

此节不能被交换到页面文件中。

此节可以在内存中共享。

此节可以作为代码执行。

此节可读。

IMAGE_SCN_LNK_COMDAT 0x00001000

IMAGE_SCN_GPREL

IMAGE_SCN_MEM_PURGEABLE

IMAGE_SCN_MEM_16BIT

IMAGE_SCN_MEM_LOCKED

IMAGE_SCN_MEM_PRELOAD

IMAGE_SCN_ALIGN_1BYTES

IMAGE_SCN_ALIGN_2BYTES

IMAGE_SCN_ALIGN_4BYTES

IMAGE_SCN_ALIGN_8BYTES

IMAGE_SCN_ALIGN_16BYTES

IMAGE_SCN_ALIGN_32BYTES

IMAGE_SCN_ALIGN_64BYTES

IMAGE_SCN_ALIGN_128BYTES

IMAGE_SCN_ALIGN_256BYTES

IMAGE_SCN_ALIGN_512BYTES

IMAGE_SCN_ALIGN_1024BYTES

IMAGE_SCN_ALIGN_2048BYTES

IMAGE_SCN_ALIGN_4096BYTES

IMAGE_SCN_ALIGN_8192BYTES

IMAGE_SCN_LNK_NRELOC_OVFL

IMAGE_SCN_MEM_DISCARDABLE

IMAGE_SCN_MEM_NOT_CACHED

IMAGE_SCN_MEM_NOT_PAGED

IMAGE_SCN_MEM_SHARED

IMAGE_SCN_MEM_EXECUTE

IMAGE_SCN_MEM_READ

0x00008000

0x00020000

0x00020000

0x00040000

0x00080000

0x00100000

0x00200000

0x00300000

0x00400000

0x00500000

0x00600000

0x00700000

0x00800000

0x00900000

0x00A00000

0x00B00000

0x00C00000

0x00D00000

0x00E00000

0x01000000

0x02000000

0x04000000

0x08000000

0x10000000

0x20000000

0x40000000

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 17

标志

IMAGE_SCN_MEM_WRITE

0x80000000

描述

此节可写。

IMAGE_SCN_LNK_NRELOC_OVFL标志表明节中重定位项的个数超出了节头中为每个

节保留的16位所能表示的范围。如果设置了此标志并且节头中的

NumberOfRelocations域的值是0xffff,那么实际的重定位项个数被保存在第一个重

定位项的VirtualAddress域(32位)中。如果设置了IMAGE_SCN_LNK_NRELOC_OVFL

标志但节中的重定位项的个数少于0xffff,则表示出现了错误。

4.2 成组的节(仅适用于目标文件)

目标文件节名中的“$”字符(美元符号)有特殊含义。

当由目标文件节中的内容生成映像文件的节时,链接器丢弃节名中“$”以及它

后面的所有字符。因此目标文件中一个名为.text$X的节实际上成了映像文件

中.text节的一部分。

但是“$”后面的字符决定了这些节在映像文件中的顺序。目标文件中节名(指

的是节名中“$”字符以前的部分)相同的节被放在映像文件中连续的位置上,并且

它们按节名的字母顺序排列。因此目标文件中节名为.text$X的节中的内容被放在一

起,并且它们在名为.text$W节的内容之后,而在名为.text$Y节的内容之前。

映像文件节名中永远不会包含“$”字符。

5 文件中的其它内容

到目前为止我们所描述的结构,直到可选文件头(含),都位于从文件开头算起

的固定偏移处(如果是包含MS-DOS占位程序的映像文件的话则是从PE文件头开始算

起)。

COFF目标文件或映像文件中其余部分包含了那些并不需要处于某一特定文件偏

移处的数据块。它们的位置由可选文件头或节头中相应的指针给出。

对于SectionAlignment值小于平台页面大小(Intel x86和MIPS是4K,

Itanium是8K)的映像文件来说有一个例外。要获取关于SectionAlignment的详细

描述,请参考3.4节“可选文件头(仅适用于映像文件)”。此时节中数据的文件偏

移有一些限制。详细信息请参考5.1节“节中的数据”。另外一个例外情况是,属性

证书和调试信息必须被放在映像文件的最后,并且属性证书表在调试信息节之前,这

是因为加载器并不将这些信息映射进内存。但是对于属性证书和调试信息的这些限制

并不适用于目标文件。

5.1 节中的数据

节中已初始化的数据就是简单的字节块。但是对于那些仅包含0的节来说,节中

的数据就没有必要包含到文件中。

每个节中的数据都位于节头的PointerToRawData域指定的文件偏移处。数据的

大小由SizeOfRawData域给出。如果SizeOfRawData小于VirtualSize,那么余下的

部分用0填充。

在映像文件中,节中的数据必须按可选文件头的FileAlignment域指定的边界对

齐。节中的数据必须按相应节的RVA值的大小顺序出现在文件中(节表中单个的节头

也是如此)。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 18

如果可选文件头的SectionAlignment域的值小于相应平台的页面大小,那么映

像文件有一些附加的限制。对于这种文件,当映像被加载到内存中时,节中数据在文

件中的位置必须与它在内存中的位置匹配,因此节中数据的物理偏移与RVA相同。

5.2 COFF重定位信息(仅适用于目标文件)

目标文件中包含COFF重定位信息,它用来指出当节中的数据被放进映像文件以

及将来被加载进内存时应如何修改这些数据。

映像文件中并不包含COFF重定位信息,这是因为所有被引用的符号都已经被赋

予了一个在平坦内存空间中的地址。映像文件中包含的重定位信息是位于.reloc节

中的基址重定位信息(除非映像具有IMAGE_FILE_RELOCS_STRIPPED属性)。要获取

更多信息,请参考6.6节“.reloc节(仅适用于映像文件)”。

对于目标文件中的每个节,都有一个由长度固定的记录组成的数组来保存此节的

COFF重定位信息。此数组的位置和长度在节头中指定。数组的每个元素格式如下:

偏移

0

大小

4

VirtualAddress

描述

需要进行重定位的代码或数据的地址。这是从节开头

算起的偏移,加上节的RVA/Offset域的值。请参考4

节“节表(节头)”。例如如果节的第一个字节的地

址是0x10,那么第三个字节的地址就是0x12。

符号表的索引(从0开始)。这个符号给出了用于重

定位的地址。如果这个指定符号的存储类别为节,那

么它的地址就是第一个与它同名的节的地址。

重定位类型。合法的重定位类型依赖于机器类型。请

参考5.2.1节“类型指示符”

4 4 SymbolTableIndex

8

2 Type

如果SymbolTableIndex域指定的符号存储类别为IMAGE_SYM_CLASS_SECTION,

那么这个符号的地址就是节的地址。这个节通常就在同一个文件中,除非这个目标文

件是档案(库)文件的一部分。如果是这种情况的话,那么这个节可能位于档案文件

中与当前目标文件的档案文件成员名称相同的任何其它目标文件中。(与档案文件成

员名称的联系用于链接生成导入表,即.idata节。)

5.2.1 类型指示符

重定位记录的Type域指出了重定位类型。对于每种类型的机器都定义了不同的

重定位类型。

x64处理器

为x64及其兼容处理器定义了以下重定位类型指示符:

常量

IMAGE_REL_AMD64_ABSOLUTE

IMAGE_REL_AMD64_ADDR64

IMAGE_REL_AMD64_ADDR32

IMAGE_REL_AMD64_ADDR32NB

IMAGE_REL_AMD64_REL32

IMAGE_REL_AMD64_REL32_1

IMAGE_REL_AMD64_REL32_2

IMAGE_REL_AMD64_REL32_3

IMAGE_REL_AMD64_REL32_4

IMAGE_REL_AMD64_REL32_5

0x0000

0x0001

0x0002

0x0003

0x0004

0x0005

0x0006

0x0007

0x0008

0x0009

描述

重定位被忽略。

重定位目标的64位VA。

重定位目标的32位VA。

不包含映像基址的32位地址(RVA)。

相对于重定位目标的32位地址。

相对于距重定位目标1字节处的32位地址。

相对于距重定位目标2字节处的32位地址。

相对于距重定位目标3字节处的32位地址。

相对于距重定位目标4字节处的32位地址。

相对于距重定位目标5字节处的32位地址。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 19

常量

IMAGE_REL_AMD64_SECTION

IMAGE_REL_AMD64_SECREL

IMAGE_REL_AMD64_SECREL7

IMAGE_REL_AMD64_TOKEN

IMAGE_REL_AMD64_SREL32

IMAGE_REL_AMD64_PAIR

IMAGE_REL_AMD64_SSPAN32

0x000A

0x000B

0x000C

0x000D

0x000E

0x000F

0x0010

描述

包含重定位目标的节的16位索引。用于支持调试

信息。

重定位目标相对于它所在节开头的32位偏移。用

于支持调试信息和静态线程局部存储。

相对于重定位目标所在节基地址的7位偏移(无

符号数)。

CLR记号。

放入目标文件中的32位跨度依赖值(符号数)。

与跨度依赖值成对出现,它必须紧跟每一个跨度

依赖值。

链接时应用的32位跨度依赖值(符号数)。

ARM处理器

为ARM处理器定义了以下重定位类型指示符:

常量

IMAGE_REL_ARM_ABSOLUTE

IMAGE_REL_ARM_ADDR32

IMAGE_REL_ARM_ADDR32NB

IMAGE_REL_ARM_BRANCH24

IMAGE_REL_ARM_BRANCH11

IMAGE_REL_ARM_SECTION

IMAGE_REL_ARM_SECREL

0x0000

0x0001

0x0002

0x0003

0x0004

0x000E

0x000F

描述

重定位被忽略。

重定位目标的32位VA。

重定位目标的32位RVA。

重定位目标的24位相对偏移。

对子程序调用的引用。这个引用由两个16位指令

与11位偏移组成。

包含重定位目标的节的16位索引。用于支持调试

信息。

重定位目标相对于它所在节开头的32位偏移。用

于支持调试信息和静态线程局部存储。

Hitachi SuperH处理器

为SH3和SH4处理器定义了以下重定位类型指示符。专用于SH5处理器的重定位

类型都标有“SHM”字样,SHM代表SHMedia。

常量

IMAGE_REL_SH3_ABSOLUTE

IMAGE_REL_SH3_DIRECT16

IMAGE_REL_SH3_DIRECT32

IMAGE_REL_SH3_DIRECT8

IMAGE_REL_SH3_DIRECT8_WORD

IMAGE_REL_SH3_DIRECT8_LONG

IMAGE_REL_SH3_DIRECT4

IMAGE_REL_SH3_DIRECT4_WORD

IMAGE_REL_SH3_DIRECT4_LONG

IMAGE_REL_SH3_PCREL8_WORD

0x0000

0x0001

0x0002

0x0003

0x0004

0x0005

0x0006

0x0007

0x0008

0x0009

描述

重定位被忽略。

对包含重定位目标符号VA的16位单元的引用。

重定位目标符号的32位VA。

对包含重定位目标符号VA的8位单元的引用。

对包含重定位目标符号16位有效VA的8位指令

的引用。

对包含重定位目标符号32位有效VA的8位指令

的引用。

对其低4位包含重定位目标符号VA的8位单元

的引用。

对其低4位包含重定位目标符号16位有效VA的

8位指令的引用。

对其低4位包含重定位目标符号32位有效VA的

8位指令的引用。

对包含重定位目标符号16位有效相对偏移的8

位指令的引用。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 20

常量

IMAGE_REL_SH3_PCREL8_LONG

IMAGE_REL_SH3_PCREL12_WORD

IMAGE_REL_SH3_STARTOF_SECTION

IMAGE_REL_SH3_SIZEOF_SECTION

IMAGE_REL_SH3_SECTION

IMAGE_REL_SH3_SECREL

IMAGE_REL_SH3_DIRECT32_NB

IMAGE_REL_SH3_GPREL4_LONG

IMAGE_REL_SH3_TOKEN

IMAGE_REL_SHM_PCRELPT

0x000A

0x000B

0x000C

0x000D

0x000E

0x000F

0x0010

0x0011

0x0012

0x0013

描述

对包含重定位目标符号32位有效相对偏移的8

位指令的引用。

对其低12位包含重定位目标符号16位有效相对

偏移的16位指令的引用。

对包含重定位目标符号所在节VA的32位单元的

引用。

对包含重定位目标符号所在节大小的32位单元

的引用。

包含重定位目标的节的16位索引。用于支持调

试信息。

重定位目标相对于它所在节开头的32位偏移。

用于支持调试信息和静态线程局部存储。

重定位目标符号的32位RVA。

与GP相关。

CLR记号。

距当前指令的偏移(长字)。如果没有设置

IMAGE_REL_SHM_NOMODE标志,那么将低位取反插

入到第32位以选择PTA指令或PTB指令。

32位地址的低16位。

32位地址的高16位。

相对地址的低16位。

相对地址的高16位。

只有紧跟IMAGE_REL_SHM_REFHALF、

IMAGE_REL_SHM_RELLO或

IMAGE_REL_SHM_RELHALF类型的重定位项时这种

重定位类型才是合法的。此重定位项的

SymbolTableIndex域包含的是偏移而不是符号表

的索引。

重定位忽略节模式。

IMAGE_REL_SHM_REFLO

IMAGE_REL_SHM_REFHALF

IMAGE_REL_SHM_RELLO

IMAGE_REL_SHM_RELHALF

IMAGE_REL_SHM_PAIR

0x0014

0x0015

0x0016

0x0017

0x0018

IMAGE_REL_SHM_NOMODE 0x8000

IBM PowerPC处理器

为PowerPC处理器定义了以下重定位类型指示符:

常量

IMAGE_REL_PPC_ABSOLUTE

IMAGE_REL_PPC_ADDR64

IMAGE_REL_PPC_ADDR32

IMAGE_REL_PPC_ADDR24

0x0000

0x0001

0x0002

0x0003

描述

重定位被忽略。

重定位目标的64位VA。

重定位目标的32位VA。

重定位目标VA的低24位。只有当重定位目标符

号是绝对符号且可以按符号扩展到它的原始值时

才是合法的。

重定位目标VA的低16位。

重定位目标VA的低14位。只有当重定位目标符

号是绝对符号且可以按符号扩展到它的原始值时

才是合法的。

符号位置相对于PC的24位偏移。

符号位置相对于PC的14位偏移。

重定位目标的32位RVA。

重定位目标相对于它所在节开头的32位偏移。用

于支持调试信息和静态线程局部存储。

IMAGE_REL_PPC_ADDR16

IMAGE_REL_PPC_ADDR14

0x0004

0x0005

IMAGE_REL_PPC_REL24

IMAGE_REL_PPC_REL14

IMAGE_REL_PPC_ADDR32NB

IMAGE_REL_PPC_SECREL

0x0006

0x0007

0x000A

0x000B

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 21

常量

IMAGE_REL_PPC_SECTION

IMAGE_REL_PPC_SECREL16

IMAGE_REL_PPC_REFHI

0x000C

0x000F

0x0010

描述

包含重定位目标的节的16位索引。用于支持调试

信息。

重定位目标相对于它所在节开头的16位偏移。用

于支持调试信息和静态线程局部存储。

重定位目标32位VA的高16位。它用于加载一个

完整地址所需的两指令序列中的第一条指令。这

种重定位类型后面必须紧跟IMAGE_REL_PPC_PAIR

类型的重定位项,而后者的SymbolTableIndex域

包含的是一个16位偏移(符号数),这个偏移要

被加到重定位目标位置的高16位。

重定位目标VA的低16位。

只有紧跟IMAGE_REL_PPC_REFHI或

IMAGE_REL_PPC_SECRELHI类型的重定位时这种重

定位类型才是合法的。此重定位项的

SymbolTableIndex域包含的是偏移而不是符号表

的索引。

重定位目标相对于它所在节开头的32位偏移的低

16位。

重定位目标相对于它所在节开头的32位偏移的高

16位。

重定位目标相对于GP寄存器的16位偏移(带符

号数)。

CLR记号。

IMAGE_REL_PPC_REFLO

IMAGE_REL_PPC_PAIR

0x0011

0x0012

IMAGE_REL_PPC_SECRELLO

IMAGE_REL_PPC_SECRELHI

IMAGE_REL_PPC_GPREL

IMAGE_REL_PPC_TOKEN

0x0013

0x0014

0x0015

0x0016

Intel 386处理器

为Intel 386及其兼容处理器定义了以下重定位类型指示符:

常量

IMAGE_REL_I386_ABSOLUTE

IMAGE_REL_I386_DIR16

IMAGE_REL_I386_REL16

IMAGE_REL_I386_DIR32

IMAGE_REL_I386_DIR32NB

IMAGE_REL_I386_SEG12

IMAGE_REL_I386_SECTION

IMAGE_REL_I386_SECREL

IMAGE_REL_I386_TOKEN

IMAGE_REL_I386_SECREL7

IMAGE_REL_I386_REL32

0x0000

0x0001

0x0002

0x0006

0x0007

0x0009

0x000A

0x000B

0x000C

0x000D

0x0014

描述

重定位被忽略。

不支持。

不支持。

重定位目标的32位VA。

重定位目标的32位RVA。

不支持。

包含重定位目标的节的16位索引。用于支持调试

信息。

重定位目标相对于它所在节开头的32位偏移。用

于支持调试信息和静态线程局部存储。

CLR记号。

相对于重定位目标所在节基地址的7位偏移。

重定位目标的32位相对偏移。用于支持x86的相

对分支和CALL指令。

Intel Itanium处理器家族(IPF)

为Intel Itanium处理器家族及其兼容处理器定义了以下重定位类型指示符。注

意指令重定位使用它所在的指令包的偏移以及相应的指令槽编号作为它的偏移:

常量

IMAGE_REL_IA64_ABSOLUTE

0x0000

描述

重定位被忽略。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 22

常量

IMAGE_REL_IA64_IMM14

0x0001

描述

这种指令重定位后面可以跟着

IMAGE_REL_IA64_ADDEND类型的重定位项,而后者

的值在被插入到IMM14指令包的指定的指令槽中

之前被加到目标地址上。这种重定位目标必须是

绝对符号,否则这个映像必须被修正。

这种指令重定位后面可以跟着

IMAGE_REL_IA64_ADDEND类型的重定位项,而后者

的值在被插入到IMM22指令包的指定的指令槽中

之前被加到目标地址上。这种重定位目标必须是

绝对符号,否则这个映像必须被修正。

这种重定位项的指令槽编号必须为1。这种重定位

后面可以跟着IMAGE_REL_IA64_ADDEND类型的重

定位项,而后者的值在被存储到IMM64指令包的

三个指令槽中之前被加到目标地址上。

重定位目标的32位VA。仅支持使用

/LARGEADDRESSAWARE:NO链接器选项生成的映像。

重定位目标的64位VA。

使用按16位边界对齐的重定位目标的25位相对

偏移来修正指令。这个偏移的低4位全为0,因此

并没有被存储。

使用按16位边界对齐的重定位目标的25位相对

偏移来修正指令。这个偏移的低4位全为0,因此

并没有被存储。

这种重定位目标偏移的LSB部分包含的是指令槽

编号,其余部分包含的是指令包的地址。使用按

16位边界对齐的重定位目标的25位相对偏移来修

正指令。这个偏移的低4位全为0,因此并没有被

存储。

这种指令重定位后面可以跟着

IMAGE_REL_IA64_ADDEND类型的重定位项,后者的

值被加到目标地址上,而后计算GPREL22指令包

相对于GP的偏移并应用。

使用重定位目标符号的常量表项相对于GP的22

位偏移来修正指令。链接器根据这个重定位项以

及可能跟着它的IMAGE_REL_IA64_ADDEND类型的

重定位项来创建这个常量表项。

包含重定位目标的节的16位索引。用于支持调试

信息。

使用重定位目标相对于它所在节开头的22位偏移

来修正指令。这种类型的重定位项后面可以紧跟

着IMAGE_REL_IA64_ADDEND类型的重定位项,后

者的Value域包含重定位目标相对于它所在节开

头的32位偏移(无符号数)。

这种重定位项的指令槽编号必须为1。使用重定位

目标相对于它所在节开头的64位偏移来修正指

令。这种类型的重定位项后面可以紧跟着

IMAGE_REL_IA64_ADDEND类型的重定位项,后者的

Value域包含重定位目标相对于它所在节开头的

32位偏移(无符号数)。

使用重定位目标相对于它所在节开头的32位偏移

来修正的数据的地址。

IMAGE_REL_IA64_IMM22 0x0002

IMAGE_REL_IA64_IMM64 0x0003

IMAGE_REL_IA64_DIR32

IMAGE_REL_IA64_DIR64

IMAGE_REL_IA64_PCREL21B

0x0004

0x0005

0x0006

IMAGE_REL_IA64_PCREL21M 0x0007

IMAGE_REL_IA64_PCREL21F 0x0008

IMAGE_REL_IA64_GPREL22 0x0009

IMAGE_REL_IA64_LTOFF22 0x000A

IMAGE_REL_IA64_SECTION

IMAGE_REL_IA64_SECREL22

0x000B

0x000C

IMAGE_REL_IA64_SECREL64I 0x000D

IMAGE_REL_IA64_SECREL32 0x000E

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 23

常量

IMAGE_REL_IA64_LTOFF64

IMAGE_REL_IA64_DIR32NB

IMAGE_REL_IA64_SREL14

0x000F

0x0010

0x0011

描述

目标的32位RVA。

用于包含两个重定位目标之差的14位立即数(符

号数)。对于链接器来说这是一个说明域,表明

编译器已经生成了这个值。

用于包含两个重定位目标之差的22位立即数(符

号数)。对于链接器来说这是一个说明域,表明

编译器已经生成了这个值。

用于包含两个重定位目标之差的32位立即数(符

号数)。对于链接器来说这是一个说明域,表明

编译器已经生成了这个值。

用于包含两个重定位目标之差的32位立即数(无

符号数)。对于链接器来说这是一个说明域,表

明编译器已经生成了这个值。

相对于PC的60位修正,用于MLX指令包的BRL

指令。

相对于PC的60位修正。如果重定位目标偏移不

超过一个25位域所能表示的范围(符号数),那

么就在1号指令槽中使用NOP.B指令、2号指令槽

中使用25位(最低4位全为0,舍弃)的BR指令

将整个指令包转换成MBB指令包。

相对于PC的60位修正。如果重定位目标偏移不

超过一个25位域所能表示的范围(符号数),那

么就在1号指令槽中使用NOP.F指令、2号指令槽

中使用25位(最低4位全为0,舍弃)的BR指令

将整个指令包转换成MFB指令包。

相对于PC的60位修正。如果重定位目标偏移不

超过一个25位域所能表示的范围(符号数),那

么就在1号指令槽中使用NOP.I指令、2号指令槽

中使用25位(最低4位全为0,舍弃)的BR指令

将整个指令包转换成MIB指令包。

相对于PC的60位修正。如果重定位目标偏移不

超过一个25位域所能表示的范围(符号数),那

么就在1号指令槽中使用NOP.M指令、2号指令槽

中使用25位(最低4位全为0,舍弃)的BR指令

将整个指令包转换成MMB指令包。

相对于GP的64位修正。

CLR记号。

相对于GP的32位修正。

只有紧跟下列类型的重定位时这种重定位类型才

是合法的:IMAGE_REL_IA64_IMM14、

IMAGE_REL_IA64_IMM22、

IMAGE_REL_IA64_IMM64、

IMAGE_REL_IA64_GPREL22、

IMAGE_REL_IA64_LTOFF22、

IMAGE_REL_IA64_LTOFF64、

IMAGE_REL_IA64_SECREL22、

IMAGE_REL_IA64_SECREL64I或

IMAGE_REL_IA64_SECREL32。它的值是应用到指令

包中的指令上的加数,而不是用于数据。

IMAGE_REL_IA64_SREL22 0x0012

IMAGE_REL_IA64_SREL32 0x0013

IMAGE_REL_IA64_UREL32 0x0014

IMAGE_REL_IA64_PCREL60X

IMAGE_REL_IA64_PCREL60B

0x0015

0x0016

IMAGE_REL_IA64_PCREL60F 0x0017

IMAGE_REL_IA64_PCREL60I 0x0018

IMAGE_REL_IA64_PCREL60M 0x0019

IMAGE_REL_IA64_IMMGPREL64

IMAGE_REL_IA64_TOKEN

IMAGE_REL_IA64_GPREL32

IMAGE_REL_IA64_ADDEND

0x001A

0x001B

0x001C

0x001F

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 24

MIPS处理器

为MIPS处理器定义了以下重定位类型指示符:

常量

IMAGE_REL_MIPS_ABSOLUTE

IMAGE_REL_MIPS_REFHALF

IMAGE_REL_MIPS_REFWORD

IMAGE_REL_MIPS_JMPADDR

IMAGE_REL_MIPS_REFHI

0x0000

0x0001

0x0002

0x0003

0x0004

描述

重定位被忽略。

重定位目标32位VA的高16位。

重定位目标的32位VA。

重定位目标VA的低26位。用于支持MIPS平台的

J和JAL指令。

重定位目标32位VA的高16位。它用于加载一个

完整地址所需的两指令序列中的第一条指令。这

种重定位类型后面必须紧跟IMAGE_REL_MIPS_PAIR

类型的重定位项,而后者的SymbolTableIndex域

包含的是一个16位偏移(符号数),这个偏移要

被加到重定位目标位置的高16位。

重定位目标VA的低16位。

重定位目标相对于GP寄存器的16位偏移(符号

数)。

与IMAGE_REL_MIPS_GPREL相同。

包含重定位目标的节的16位索引。用于支持调试

信息。

重定位目标相对于它所在节开头的32位偏移。用

于支持调试信息和静态线程局部存储。

重定位目标相对于它所在节开头的32位偏移的低

16位。

重定位目标相对于它所在节开头的32位VA的高

16位。这种重定位类型后面必须紧跟

IMAGE_REL_MIPS_PAIR类型的重定位项,而后者的

SymbolTableIndex域包含的是一个16位偏移(符

号数),这个偏移要被加到重定位符号位置的高

16位。

重定位目标VA的低26位。用于支持MIPS16的

JAL指令。

重定位目标的32位RVA。

只有紧跟IMAGE_REL_MIPS_REFHI或

IMAGE_REL_MIPS_SECRELHI类型的重定位时这种重

定位类型才是合法的。此重定位项的

SymbolTableIndex域包含的是偏移而不是符号表

索引。

IMAGE_REL_MIPS_REFLO

IMAGE_REL_MIPS_GPREL

IMAGE_REL_MIPS_LITERAL

IMAGE_REL_MIPS_SECTION

IMAGE_REL_MIPS_SECREL

IMAGE_REL_MIPS_SECRELLO

IMAGE_REL_MIPS_SECRELHI

0x0005

0x0006

0x0007

0x000A

0x000B

0x000C

0x000D

IMAGE_REL_MIPS_JMPADDR16

IMAGE_REL_MIPS_REFWORDNB

IMAGE_REL_MIPS_PAIR

0x0010

0x0022

0x0025

Mitsubishi M32R处理器

为Mitsubishi M32R处理器定义了以下重定位类型指示符:

常量

IMAGE_REL_M32R_ABSOLUTE

IMAGE_REL_M32R_ADDR32

IMAGE_REL_M32R_ADDR32NB

IMAGE_REL_M32R_ADDR24

IMAGE_REL_M32R_GPREL16

IMAGE_REL_M32R_PCREL24

0x0000

0x0001

0x0002

0x0003

0x0004

0x0005

描述

重定位被忽略。

重定位目标的32位VA。

重定位目标的32位RVA。

重定位目标的24位VA。

重定位目标相对于GP寄存器的16位偏移。

重定位目标相对于程序计数器(PC)的24位偏

移,已经左移2位并按符号扩展。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 25

常量

IMAGE_REL_M32R_PCREL16

IMAGE_REL_M32R_PCREL8

IMAGE_REL_M32R_REFHALF

IMAGE_REL_M32R_REFHI

0x0006

0x0007

0x0008

0x0009

描述

重定位目标相对于PC的16位偏移,已经左移2

位并按符号扩展。

重定位目标相对于PC的8位偏移,已经左移2位

并按符号扩展。

重定位目标VA的16位MSB。

重定位目标VA的16位MSB,已经按LSB符号扩展

调整。它用于加载一个完整的32位地址所需的两

指令序列中的第一条指令。这种重定位类型后面

必须紧跟IMAGE_REL_M32R_PAIR类型的重定位

项,而后者的SymbolTableIndex域包含的是一个

16位偏移(符号数),这个偏移要被加到重定位

符号位置的高16位。

重定位目标VA的16位LSB。

这种类型的重定位必须紧跟类型为

IMAGE_REL_M32R_REFHI的重定位项。此重定位项

的SymbolTableIndex域包含的是偏移而不是符号

表索引。

包含重定位目标的节的16位索引。用于支持调试

信息。

重定位目标相对于它所在节开头的32位偏移。用

于支持调试信息和静态线程局部存储。

CLR记号。

IMAGE_REL_M32R_REFLO

IMAGE_REL_M32R_PAIR

0x000A

0x000B

IMAGE_REL_M32R_SECTION

IMAGE_REL_M32R_SECREL

IMAGE_REL_M32R_TOKEN

0x000C

0x000D

0x000E

5.3 COFF行号信息(不赞成使用)

Microsoft的工具已经不再生成COFF行号信息,并且以后也不会再使用它了。

COFF行号信息给出了源文件中代码与行号之间的关系。Microsoft的COFF行号

信息格式与标准COFF行号信息格式类似,但已经被扩展,以便用单个节就可以与多

个源文件中的行号关联。

COFF行号信息由长度固定的记录组成的数组构成。数组的位置(文件偏移)与

大小由节头给出。每个行号记录格式如下:

偏移

0

大小

4

Type (*)

描述

这是由SymbolTableIndex和VirtualAddress两个域组

成的共用体。使用SymbolTableIndex还是RVA依赖于

Linenumber域的值。

如果此值非零,那么它表示行号(从1开始)。如果它

为零,那么Type域表示一个函数在符号表中的索引。

4

2 Linenumber

Type域是由SymbolTableIndex和VirtualAddress这两个4字节长的域组成的

共用体:

偏移

0

大小

4

SymbolTableIndex

描述

当Linenumber为零时使用此域,它表示一个函数在符

号表中的索引。此格式用来指明一组行号记录与哪个

函数相关。

当Linenumber非零时使用此域,它表示与源代码中由

Linenumber指定的那行代码对应的可执行代码的

RVA。在目标文件中,它表示节中的VA。

0

4 VirtualAddress

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 26

一个行号记录,或者是将其Linenumber域设置为零,同时(另一个域)指向符

号表中的一个函数;或者是作为一个标准的行号记录:给出一个正整数(行号)以及

在目标代码中相应的地址。

一组行号记录总是以前一种格式——符号表中函数的索引开头。如果这个行号记

录是节中的第一个行号记录,并且节的COMDAT标志设置的话,那么它同时也是函数

的COMDAT符号名。详细信息请参考5.5.6节“COMDAT节(仅适用于目标文件)”。

此函数在符号表中的辅助记录有一个PointerToLinenumber域,它指向这个行号记

录。

标识函数的记录后面跟着一些行号记录,它们给出了实际的行号信息(也就是

说,这些记录的Linenumber域都大于0)。这些项(中的Linenumber域)从1开始

(相对于函数的开头),每一个表示函数源代码中的一行(除了第一行)。

例如在下面的例子中,第一个行号记录会列出ReverseSign函数(ReverseSign

函数的SymbolTableIndex和被设置为0的Linenumber域)。它后面的记录的

Linenumber域的值依次为1、2和3,它们分别对应着源代码中相应的行,如下所

示:

// ReverseSign函数前面的代码

int ReverseSign(int i)

1: {

2: return -1 * i;

3: }

5.4 COFF符号表

本节中提到的符号表继承自传统的COFF格式。它与Microsoft Visual C++®调

试信息截然不同。一个文件可以同时包含COFF符号表和Visual C++调试信息,二者

是分开的。一些Microsoft的工具出于有限但重要的目的使用符号表,例如用于向链

接器传递COMDAT信息。符号表中列出了节名、文件名以及代码与数据符号。

符号表的位置由COFF文件头给出。

符号表是一个由记录组成的数组,每个记录长18字节。它们或者是标准符号表

记录,或者是辅助符号表记录。标准符号表记录定义了一个符号或名称,格式如下:

偏移

0

大小

8

Name (*)

描述

符号名称,这是一个由三个成员组成的共用体。如果

名称的长度不超过8个字节,那么它就是一个8字节

长的数组。要获取更多信息,请参考5.4.1节“符号

名称表示”。

与符号相关的值。其意义依赖于SectionNumber和

StorageClass这两个域。它通常表示可重定位的地

址。

这个带符号整数是节表的索引(从1开始),用以标

识定义此符号的节。一些值有特殊的含义,详细信息

请参考5.4.2节“SectionNumber域的值”。

一个表示类型的数字。Microsoft的工具将它设置为

0x20(如果是函数)或者0x0(如果不是函数)。要

获取更多信息,请参考5.4.3节“类型表示”。

这是一个表示存储类别的枚举类型值。要获取更多信

息,请参考5.4.4节“存储类别”。

跟在本记录后面的辅助符号表项的个数。

8 4 Value

12 2 SectionNumber

14 2 Type

16

17

1

1

StorageClass

NumberOfAuxSymbols

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 27

每个标准符号表记录后面紧跟着零个或多个辅助符号表记录,但通常情况下并不

会超过一个(除了带长文件名的.file记录)。每个辅助符号表记录的大小与标准符

号表记录相同(都是18字节),但它并不是又定义了一个新的符号,而是给出了与

上一个定义的符号相关的附加信息。辅助符号表记录有好几种格式,使用哪一种取决

于StorageClass域的值。当前已经为辅助符号表记录定义的格式将在5.5节“辅助

符号表记录”中列出。

处理COFF符号表的工具必须忽略意义不明的辅助符号表记录。这样允许日后对

符号表的格式进行扩展以便添加新的辅助符号表记录而不会使现存的工具失效。

5.4.1 符号名称表示

如果符号名称长度不超过8个字节,那么符号表的ShortName域就是包含符号名

本身的一个8字节长的数组;否则的话,它给出了字符串表中的一个偏移地址。要确

定它到底是名称本身还是偏移地址,测试一下它的前4个字节是否等于0。

通常名称都被认为是以NULL结尾的UTF-8格式的字符串。

偏移

0

0

4

大小

8

4

4

ShortName

Zeroes

Offset

描述

8字节长的数组。如果名称长度小于8字节,在它的右边用

NULL填充。

如果名称长度大于8字节,那么这个域被设置为全0。

字符串表中的一个偏移地址。

5.4.2 SectionNumber域的值

通常符号表项中的SectionNumber域是节表的索引(从1开始)。但是这个域是

带符号整数,因此它可以为负值。下面这些小于1的值有特殊含义:

常量

IMAGE_SYM_UNDEFINED

0

描述

尚未为此符号记录分配一个节。这个零值表明引用了一

个定义在其它地方的外部符号;而非零值则表明是一个

普通符号,其大小由Value域给出。

此符号是个绝对符号(不可重定位),并且不是地址。

此符号提供普通类型信息或者调试信息,但它并不对应

于某一个节。Microsoft的工具将.file记录(存储类别

为FILE)设置为这个值。

IMAGE_SYM_ABSOLUTE

IMAGE_SYM_DEBUG

-1

-2

5.4.3 类型表示

符号表项的Type域占2个字节,其中的每一个字节都表示类型信息。低位字节

(LSB)表示简单(基本)数据类型,高位字节(MSB)表示复杂类型(如果存在):

MSB

复杂类型:无、指针、函数、数组。

LSB

基本类型:整数、浮点数等。

尽管Microsoft的工具通常不使用这个域并将LSB设置为0,但还是为基本类型

定义了以下这些值。Microsoft的工具使用Visual C++调试信息来指明类型。但是出

于完整性考虑,将可能出现的值列于下表:

常量

IMAGE_SYM_TYPE_NULL

IMAGE_SYM_TYPE_VOID

IMAGE_SYM_TYPE_CHAR

IMAGE_SYM_TYPE_SHORT

0

1

2

3

描述

类型信息不存在,或者是未知的基本类型。

Microsoft的工具使用这个值。

不是合法类型;用于void指针和函数。

字符(带符号的1个字节)。

长度为2个字节的带符号整数。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 28

常量

IMAGE_SYM_TYPE_INT

IMAGE_SYM_TYPE_LONG

IMAGE_SYM_TYPE_FLOAT

IMAGE_SYM_TYPE_DOUBLE

IMAGE_SYM_TYPE_STRUCT

IMAGE_SYM_TYPE_UNION

IMAGE_SYM_TYPE_ENUM

IMAGE_SYM_TYPE_MOE

IMAGE_SYM_TYPE_BYTE

IMAGE_SYM_TYPE_WORD

IMAGE_SYM_TYPE_UINT

IMAGE_SYM_TYPE_DWORD

4

5

6

7

8

9

10

11

12

13

14

15

描述

自然的整数类型(在Windows中通常为4个字节)。

长度为4个字节的带符号整数。

长度为4个字节的浮点数。

长度为8个字节的浮点数。

结构体。

共用体。

枚举类型。

枚举类型成员(具体值)。

字节;长度为1个字节的无符号整数。

字;长度两个字节的无符号整数。

长度为自然尺寸的无符号整数(通常为4个字节)。

长度为4个字节的无符号整数。

高位字节指出符号是指向由LSB指定的基本类型的指针、返回由LSB指定的基本

类型的函数还是由LSB指定的基本类型组成的数组。Microsoft的工具仅使用这个域

来指出这个符号是不是函数,因此最后的Type域只有0x0和0x20这两个值。但是其

它工具可以使用这个域来传递更多信息。

正确地指定函数属性非常重要。增量链接需要这个信息才能正确地工作。对于某

些平台而言,可能会出于其它目的而使用这个信息。

常量

IMAGE_SYM_DTYPE_NULL

IMAGE_SYM_DTYPE_POINTER

IMAGE_SYM_DTYPE_FUNCTION

IMAGE_SYM_DTYPE_ARRAY

0

1

2

3

描述

非导出类型;此符号是简单的标量变量。

此符号是指向基本类型的指针。

此符号是返回基本类型的函数。

此符号是由基本类型组成的数组。

5.4.4 存储类别

符号表中的StorageClass域指出符号具体的存储类别。下表列出了所有可能的

取值。注意StorageClass域是长度为1个字节的无符号整数。因此如果这个域的值

为-1的话,实际上应该被看作是与它相等的无符号数,也就是0xFF。

尽管传统的COFF格式使用许多存储类别,但是Microsoft的工具使用Visual

C++调试信息来表示大部分符号信息,它通常仅使用四种存储类别:EXTERNAL(2)、

STATIC(3)、FUNCTION(101)和FILE(103)。下表中出现的“Value”都表示符

号表记录中的Value域(它的意义依赖于存储类别的值)。

常量

IMAGE_SYM_CLASS_END_OF_FUNCTION

IMAGE_SYM_CLASS_NULL

IMAGE_SYM_CLASS_AUTOMATIC

IMAGE_SYM_CLASS_EXTERNAL

-1

(0xFF)

0

1

2

描述以及对Value域的解释

表示函数结尾的特殊符号,用于调试。

未被赋予存储类别。

自动(堆栈)变量。Value域指出此变量在

栈帧中的偏移。

Microsoft的工具使用此值来表示外部符

号。如果SectionNumber域为0

(IMAGE_SYM_UNDEFINED),那么Value域

给出大小;如果SectionNumber 域不为0,

那么Value域给出节中的偏移。

符号在节中的偏移。如果Value域为0,那

么此符号表示节名。

IMAGE_SYM_CLASS_STATIC 3

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 29

常量

IMAGE_SYM_CLASS_REGISTER

IMAGE_SYM_CLASS_EXTERNAL_DEF

IMAGE_SYM_CLASS_LABEL

IMAGE_SYM_CLASS_UNDEFINED_LABEL

IMAGE_SYM_CLASS_MEMBER_OF_STRUCT

IMAGE_SYM_CLASS_ARGUMENT

IMAGE_SYM_CLASS_STRUCT_TAG

IMAGE_SYM_CLASS_MEMBER_OF_UNION

IMAGE_SYM_CLASS_UNION_TAG

IMAGE_SYM_CLASS_TYPE_DEFINITION

IMAGE_SYM_CLASS_UNDEFINED_STATIC

IMAGE_SYM_CLASS_ENUM_TAG

IMAGE_SYM_CLASS_MEMBER_OF_ENUM

IMAGE_SYM_CLASS_REGISTER_PARAM

IMAGE_SYM_CLASS_BIT_FIELD

IMAGE_SYM_CLASS_BLOCK

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

100

描述以及对Value域的解释

寄存器变量。Value域给出寄存器编号。

在外部定义的符号。

模块中定义的代码标号。Value域给出此符

号在节中的偏移。

引用的未定义的代码标号。

结构体成员。Value域指出是第几个成员。

函数的形式参数(形参)。Value域指出是

第几个参数。

结构体名。

共用体成员。Value域指出是第几个成员。

共用体名。

Typedef项。

静态数据声明。

枚举类型名。

枚举类型成员。Value域指出是第几个成

员。

寄存器参数。

位域。Value域指出是位域中的第几个位。

.bb(beginning of block,块开头) 或

.eb记录(end of block,块结尾)。Value

域是代码位置,它是一个可重定位的地址。

Microsoft的工具用此值来表示定义函数范

围的符号记录,这些符号记录分别是:.bf

(begin function,函数开头)、.ef(end

function,函数结尾)以及.lf(lines in

function,函数中的行)。对于

.lf 记录来

说,Value域给出了源代码中此函数所占的

行数。对于

.ef记录来说,Value域给出了函

数代码的大小。

结构体末尾。

Microsoft的工具以及传统COFF格式都使用

此值来表示源文件符号记录。这种符号表记

录后面跟着给出文件名的辅助符号表记录。

节的定义(Microsoft的工具使用STATIC存

储类别代替)。

弱外部符号。要获取更多信息,请参考

5.5.3节“辅助符号表记录格式之三:弱外

部符号”。

表示CLR记号的符号。它的名称是这个记号

的十六进制值的ASCII码表示。要获取更多

信息,请参考5.5.7节“CLR记号定义”。

IMAGE_SYM_CLASS_FUNCTION 101

IMAGE_SYM_CLASS_END_OF_STRUCT

IMAGE_SYM_CLASS_FILE

102

103

IMAGE_SYM_CLASS_SECTION

IMAGE_SYM_CLASS_WEAK_EXTERNAL

104

105

IMAGE_SYM_CLASS_CLR_TOKEN 107

5.5 辅助符号表记录

辅助符号表记录总是跟在一些标准符号表记录之后并应用于这些符号表记录。它

的格式并不固定,只要处理它的工具能够识别就可以了,但必须保证其长度是18个

字节,以便整个符号表可以被当作一个数组来处理。当前Microsoft的工具可以识别

以下类型的辅助符号表记录:函数定义、函数开头和结尾符号(.bf和.ef)、弱外

部符号、文件名以及节的定义。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 30

传统的COFF格式中还包括用于数组和结构体的辅助符号表记录。但是Microsft

的工具并不使用它们,而是将符号信息按照Visual C++调试信息格式存储在调试节

中。

5.5.1 辅助符号表记录格式之一:函数定义

如果一个符号表记录拥有下列属性:存储类别为EXTERNAL(2)、Type域的值表

明它是一个函数(0x20)以及SectionNumber域的值大于0,它就标志着函数的开

头。注意如果一个符号表记录SectionNumber域的值为IMAGE_SYM_UNDEFINED

(0),那么它并不定义一个函数,也没有相应的辅助符号表记录。能够定义函数的

符号表记录后面跟着如下格式的辅助符号表记录:

偏移

0

4

大小 域

4

4

TagIndex

TotalSize

描述

相应的.bf(函数开头)记录在符号表中的索引。

函数经编译后生成的可执行代码的大小。如果此

函数单独成节,那么根据对齐值的不同,节头中

的SizeOfRawData域可能大于或等于这个域。

如果此函数存在行号记录,那么这个值表示它的

第一个COFF行号记录的文件偏移;如果不存在,

那么这个值为0。要获取更多信息,请参考5.3

节“COFF行号信息(不赞成使用)”。

对应于下一个函数的符号表记录在符号表中的索

引。如果此函数是符号表中的最后一个函数,那

么这个域的值为0。

8 4 PointerToLinenumber

12 4 PointerToNextFunction

16 2 未用

5.5.2 辅助符号表记录格式之二:.bf和.ef符号

对于符号表中的每个函数定义,有三个相应的符号表记录分别用来描述函数开

头、函数结尾以及此函数在源文件中所占的行数。这三个符号表记录的存储类别都是

FUNCTION(101):

一个名为.bf的符号表记录。此记录的Value域未用。

一个名为.lf的符号表记录。此记录的Value域给出了这个函数所占的行数。

一个名为.ef的符号表记录。此记录的Value域的值与定义函数的符号表记录的

TotalSize域的值相同。

.bf和.ef符号表记录(不包括.lf记录)后面跟着如下格式的辅助符号表记录:

偏移

0

4

6

12

大小

4

2

6

4

未用

Linenumber

未用

PointerToNextFunction

(仅用于.bf 符号表记

录)

未用

下一个.bf符号表记录在符号表中的索引。如果

此函数是符号表中的最后一个函数,那么这个

域的值为0。

.ef记录并不使用这个域。

源文件中实际的行号,按顺序排列(1、2、3等

等)。.bf和.ef记录都使用这个域。

描述

16 2

5.5.3 辅助符号表记录格式之三:弱外部符号

“弱外部符号”是为了在链接时能获得更大的灵活性而应用于目标文件的一种机

制。模块中可以包含一个无法解析的外部符号(假设为sym1),但它也可以同时包

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 31

含一个相应的辅助符号表记录来指明当链接时找不到sym1时可以用另外一个外部符

号(假设为sym2)来代替。

如果链接时能找到sym1的定义,那么外部对它的引用可以正常解析。否则所有

对sym1这个弱外部符号的引用都用sym2来代替。而sym2这个外部符号在链接时必

须能够找到;通常它就被定义在对sym1进行弱外部引用的模块中。

表示弱外部符号的符号表记录,其存储类别是EXTERNAL,SectionNumber域的值

为IMAGE_SYM_UNDEFINED(0),Value域的值为0。弱外部符号记录后面跟着如下格

式的辅助符号表记录:

偏移 大小 域

0

4

4

4

TagIndex

描述

sym2在符号表中的索引。如果链接时找不到sym1就用它

代替。

Characteristics 如果这个值为IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY,

表明链接时不在库中查找sym1。

如果这个值为IMAGE_WEAK_EXTERN_SEARCH_LIBRARY,表

明链接时在库中查找sym1。

如果这个值为IMAGE_WEAK_EXTERN_SEARCH_ALIAS,表明

sym1是sym2的别名。

8

10 未用

注意在WINNT.H文件中并没有定义这个 Characteristics域,而是用TotalSize

域来代替。

5.5.4 辅助符号表记录格式之四:文件

此格式的辅助符号表记录跟在存储类别为FILE(103)的符号表记录之后。这个

符号表记录的符号名本身应该是.file,而跟着它的辅助记录给出了源文件名。

偏移

0

大小

18

File Name

描述

表示源文件名的ANSI字符串。如果源文件名的长度小于最

大长度,用NULL填充。

5.5.5 辅助符号表记录格式之五:节定义

此格式的辅助符号表记录跟在定义节的符号表记录之后。对于定义节的符号表记

录来说,其符号名就是相应的节名(例如.text或.drectve)且存储类别为STATIC

(3)。而相应的辅助记录提供了关于这个节的信息。因此这样的辅助符号表记录中

的一些信息与节头中的信息是重复的。

偏移

0

4

6

8

大小

4

2

2

4

Length

NumberOfRelocations

NumberOfLinenumbers

CheckSum

描述

节中数据的大小。与节头的SizeOfRawData域

一样。

此节中重定位项的数目。

此节中行号信息项的数目。

公共数据的校验和。只有节头中设置了

IMAGE_SCN_LNK_COMDAT标志时才使用此域。要

获取更多信息,请参考5.5.6节“COMDAT节

(仅适用于目标文件)”。

与此节相关的节在节表中的索引(从1开

始)。当COMDAT的Selection域为5时才使用

这个域。

表示COMDAT选择方式的数字。这个域只用于

COMDAT节。

12 2 Number

14 1 Selection

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 32

偏移

15

大小

3

未用

描述

5.5.6 COMDAT节(仅适用于目标文件)

如果一个节为COMDAT节,那么定义这个节的符号表记录后跟着的辅助记录中的

Selection域是可用的。COMDAT节是一种可以由多个目标文件定义的节。(节头中的

Characteristics域设置了IMAGE_SCN_LNK_COMDAT标志)。Selection域的值决定了

链接器在解析多个COMDAT节定义时所采用的方式。

第一个其SectionNumber域指向COMDAT节的符号必须是定义节的符号。这个符

号的名称就是节名,其Value域的值为0,SectionNumber域指向我们正在讨论的

COMDAT节,Type域的值为IMAGE_SYM_TYPE_NULL,StorageClass域的值为

IMAGE_SYM_CLASS_STATIC,并且有一个辅助记录。第二个符号被称为“COMDAT符

号”,链接器将它与Selection域配合起来使用。

Selection域的值如下所示:

常量

IMAGE_COMDAT_SELECT_NODUPLICATES

1

描述

如果此符号已经被定义过,链接器将生成一个

“multiply defined symbol(符号多重定

义)”错误。

链接器从这些定义同一个COMDAT符号的节中任

选一个,其余(未被选中)的节都被移除。

链接器从定义这个符号的多个节中任选一个。

如果所有这些定义大小不等,链接器将生成一

个“符号多重定义”错误。

链接器从定义这个符号的多个节中任选一个。

如果所有这些定义不严格一致,链接器将生成

一个“符号多重定义”错误。

如果“其它某个”COMDAT节被链接的话,此节

也要被链接。这里的“其它某个”节由与定义

此节的符号表记录相关的辅助符号表记录的

Number域给出。这个设置对于那些在多个节中

都有其相关部分(例如代码在一个节中而数据

在另一个节中)但必须作为一个整体进行链接

或丢弃的定义非常有用。与此节关联的这个

“其它某个”节必须也是COMDAT节并且它不能

再与其它COMDAT节关联(也就是说,这个“其

它某个”节不能将Selection域设置为

IMAGE_COMDAT_SELECT_ASSOCIATIVE)。

链接器从这个符号的所有定义中选取长度最大

的进行链接。如果长度最大的不止一个,那么

就在这几个最大的中任选一个。

IMAGE_COMDAT_SELECT_ANY

IMAGE_COMDAT_SELECT_SAME_SIZE

2

3

IMAGE_COMDAT_SELECT_EXACT_MATCH 4

IMAGE_COMDAT_SELECT_ASSOCIATIVE 5

IMAGE_COMDAT_SELECT_LARGEST 6

5.5.7 CLR记号定义(仅适用于目标文件)

这种辅助符号表记录通常跟在存储类别为IMAGE_SYM_CLASS_CLR_TOKEN的符号表

记录之后。它用来联系CLR记号与COFF符号表的名称空间。

偏移

0

1

2

大小

1

1

4

bAuxType

bReserved

SymbolTableIndex

描述

必须为IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF(1)。

保留,必须为0。

此CLR记号定义涉及的COFF符号在符号表中的索引。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 33

偏移

6

大小

12

保留,必须为0。

描述

5.6 COFF字符串表

COFF符号表后紧跟着的是COFF字符串表。它的位置可以通过将COFF文件头中

符号表的地址加上符号总数乘以每个符号的大小得到。

COFF字符串表开头的4个字节存储的是字符串表的总大小(以字节计)。这个

大小包括这个域本身。因此如果字符串表中不包含任何字符串时,这个值应该为4。

大小后面是一些以NULL结尾的字符串,COFF符号表中的符号指向这些字符串。

5.7 属性证书表(仅适用于映像文件)

可以给映像文件添加属性证书表使它与属性证书相关联。属性证书表由一组连续

的按八进制字(从任意字节边界开始的16个连续字节)边界对齐的属性证书表项组

成。每个属性证书表项格式如下:

偏移

0

4

6

8

大小

4

2

2

参考后面

的内容

dwLength

wRevision

wCertificateType

bCertificate

描述

指出bCertificate域的长度。

证书版本号。要获取详细信息,请参考本表后面

的内容。

指出bCertificate内容的类型。要获取详细信

息,请参考本表后面的内容。

这个域包含一个证书,例如Authenticode签名。

要获取详细信息,请参考本表后面的内容。

可选文件头中的数据目录中的Certificate Table(证书表)项中的

VirtualAddress域给出了属性证书表中第一个属性证书表项的文件偏移。对于后续

的属性证书表项,可以通过将当前属性证书表项的文件偏移加上其dwLength域的值

并将结果向上舍入为8字节的倍数来访问。后续的属性证书表项可以一直以这种方式

访问直到这些dwLength域(已经向上舍入为8字节的倍数)的和等于可选文件头中

的数据目录中的Certificate Table项中的Size域的值。如果这些dwLength域(已

经向上舍入为8字节的倍数)的和最后不等于Size域的值,那要么属性证书表被破

坏了,要么Size域被破坏了。

例如如果可选文件头中的数据目录中的Certificate Table项内容如下:

virtual address = 0x5000

size = 0x1000

那么第一个证书从文件偏移0x5000处开始。要访问后续的属性证书表项,按以下步

骤进行:

1. 将第一个属性证书的dwLength域的值加到前面提到的开始地址(0x5000)处。

2. 将第一步得到的结果向上舍入到与它最接近的8字节的倍数,这个倍数就是第二

个属性证书项的文件偏移。

3. 将第二步得到的文件偏移加上第二个属性证书项的dwLength域的值并将结果向

上舍入到与它最接近的8字节的倍数,这个倍数就是第三个属性证书项的文件偏

移。

4. 重复第三步的操作以访问后续的属性证书项,直到计算出的偏移等于0x6000

(开始地址0x5000 + 总大小0x1000),它表示你已经遍历了整个属性证书表。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 34

你也可以在一个循环中调用Win32®函数ImageEnumerateCertificates来枚举属

性证书表项。本规范最后的“参考信息”中给出了此函数信息的链接。

属性证书表项可以包含任何类型的证书,只要它有正确的dwLength值、惟一的

wRevision值和惟一的wCertificateType值。最常用的类型是WIN_CERTIFICATE结

构,Wintrust.h文件给出了它的内容,本节后面将要讨论它。

WIN_CERTIFICATE结构的wRevision域可以选用(但不限于)以下值:

0x0100

0x0200

名称

WIN_CERT_REVISION_1_0

WIN_CERT_REVISION_2_0

注意

版本1,WIN_CERTIFICATE结构的遗留版本。支持它只

是为了校验以前的Authenticode签名。

版本2是WIN_CERTIFICATE结构的当前版本。

WIN_CERTIFICATE结构的wCertificateType域可以选用(但不限于)的值列于

下表。注意其中一些值当前并不支持。

值 名称 注意

bCertificate包含的是X.509证书。不

支持。

bCertificate包含的是PKCS#7

SignedData结构。

保留。

终端服务器协议栈证书签名。不支持。

0x0001 WIN_CERT_TYPE_X509

0x0002 WIN_CERT_TYPE_PKCS_SIGNED_DATA

0x0003 WIN_CERT_TYPE_RESERVED_1

0x0004 WIN_CERT_TYPE_TS_STACK_SIGNED

WIN_CERTIFICATE结构的bCertificate域是一个长度可变的字节数组,其中内

容的类型由wCertificateType域指定。Authenticode支持的类型是

WIN_CERT_TYPE_PKCS_SIGNED_DATA,它是一个PKCS#7 SignedData结构。要获取更多

信息,请参考“Windows Authenticode可移植可执行签名格式”。

如果bCertificate的内容并不在八进制字边界结束,那么从bCertificate的内

容最后到八进制字边界之间用0填充。

dwLength域的值指出了bCertificate的大小,它并不包括填充的内容。

可选文件头中的数据目录(3.4.3节)中的Certificates Table 项的Size域指

出了属性证书表的大小,它包括填充的内容。

要获取关于如何使用ImageHlp API来枚举、添加和删除PE文件中的证书方面的

详细信息,请参考“ImageHlp函数”。

5.7.1 证书数据

如上节所述,属性证书表中可以包含任何类型的证书。用于确保PE文件完整性

的证书可以包含PE映像散列。

PE映像散列(或者称为文件散列)与文件校验和类似,它们的散列算法都生成

一个与文件完整性有关消息摘要。但是校验和是用简单的算法生成的,它主要用来检

测保存在磁盘上的一块内存是否已经被破坏以及存储在那里的值是否已经被改变。文

件散列与校验和的相同之处在于它也检测文件是否被破坏。但与大多数校验和算法不

同的是,要对一个文件进行修改并同时保持它的文件散列与原始(未修改的)形式一

致是极其困难的。因此文件散列可以用来检测诸如一些病毒、黑客或者木马程序对文

件进行的有意的、甚至是非常细微的修改。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 35

当将映像中的内容包含进证书时,映像摘要必须排除PE映像中的某些域,例如

Checksum域以及可选文件头中的数据目录中的Certificate Table项。这是因为给

PE文件添加一个证书会改变这些域的值,并且文件的散列值也不相同。

Win32函数ImageGetDigestStream为散列函数提供了一个目标PE文件的数据

流。当为PE文件添加或删除证书时这个数据流保持不变。根据传递给

ImageGetDigestStream函数的参数的不同,PE映像中的一些数据可能会在散列计算

时被忽略。本规范最后的“参考信息”中给出了此函数信息的链接。

5.8 延迟加载导入表(仅适用于映像文件)

将这些表添加到映像文件中是为了给“应用程序直到首次调用某个DLL中的函数

或数据时才加载这个DLL(即延迟加载)”这种行为提供一种通一的机制。这些表的

格式与将要在6.4节“.idata节”中描述的传统导入表的格式一致。这里仅讨论少

许细节。

5.8.1 延迟加载目录表

延迟加载目录表是导入目录表的副本,可以从可选文件头中的数据目录中的

Delay Import Descriptor(延迟导入描述符)域(偏移200处)获取它。其格式如

下:

偏移

0

4

8

12

16

大小

4

4

4

4

4

Attributes

Name

Module Handle

Delay Import

Address Table

Delay Import

Name Table

Bound Delay

Import Table

Unload Delay

Import Table

描述

必须为0。

被加载DLL名称的RVA。这个名称位于映像文件的只

读数据节中。

被延迟加载DLL模块句柄(在映像的数据节中)的

RVA。它供管理延迟加载的例程存储之用。

延迟加载导入地址表的RVA。要获取更多信息,请参

考5.8.5节“延迟导入地址表(IAT)”。

延迟加载名称表的RVA。这个表包含了需要被加载的

导入符号的名称。它与导入名称表的格式一致。要获

取更多信息,请参考6.4.3节“提示/名称表”。

绑定延迟加载地址表(如果存在)的RVA。

卸载延迟加载地址表(如果存在)的RVA。这个表是

延迟导入地址表的精确副本。如果调用者卸载了这个

DLL,应该将这个表复制回去以覆盖延迟导入地址表,

以便后续对这个DLL的调用可以继续正确地使用形实

转换机制。

此映像绑定到的DLL的时间戳。

20

24

4

4

28

4 Time Stamp

对于这个结构中使用到的表来说,它们的组织形式与存储格式与传统的导入表一

样,就像是它们的副本。要获取更多信息,请参考4.6节“.idata节”。

5.8.2 属性

至今尚未定义属性标志。链接器在生成映像文件时将此域设置为0。我们可以在

将来扩展这个结构时用它来指明添加了新域,或者用它来指明延迟加载或卸载辅助函

数的行为。

5.8.3 名称

需要被延迟加载的DLL的名称被存储在映像文件的只读数据节中。可以通过

szName域引用它。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 36

5.8.4 模块句柄

要被延迟加载的DLL的句柄被存储在映像文件的数据节中。phmod域指向这个

句柄。延迟加载辅助函数使用这个位置存储要被延迟加载的DLL的模块句柄。

5.8.5 延迟导入地址表

可以通过延迟导入描述符的pIAT域引用延迟导入地址表(IAT)。延迟加载辅助

函数用导入符号的实际地址来更新这些指针,以便起转换作用的这部分代码不会陷入

循环调用之中。可以通过表达式

pINT->on

来访问

这些函数指针

5.8.6 延迟导入名称表

延迟导入名称表(INT)包含了可能需要被加载的导入符号的名称。它们的排列

方式与IAT中的函数指针一样。它们的结构与标准的INT一样,可以通过表达式

pINT-

>sOfData->Name[0]进行访问

5.8.7 延迟绑定导入地址表和时间戳

延迟绑定导入地址表(BIAT)是由IMAGE_THUNK_DATA结构组成的数组,它是可

选的。它与延迟加载目录表中的Time Stamp域一起被用于后处理绑定阶段。

5.8.8 延迟卸载导入地址表

延迟卸载导入地址表(UIAT)是由IMAGE_THUNK_DATA结构组成的数组,它是可选

的。卸载代码用它来处理明确的卸载请求。它由只读节中已初始化的数据组成,这些

数据是原始IAT的精确副本。在处理卸载请求时,可以释放这个DLL,同时将

*phmod

清零,并用UIAT覆盖IAT,以便将一切都还原到预加载时的状态。

6 特殊的节

典型的COFF节包含的是普通代码或数据,链接器与Microsoft Win32®加载器并

不需要知道其中的内容就可以处理它们。这些内容只与将要链接的或执行的应用程序

有关。

但是目标文件与映像文件中的某些COFF节却有特殊含义。由于在节头中为这些

节设置了特殊的标志,或者可选文件头中的某些域指向这些节,或者节名本身指出了

节的特殊作用,所以工具和加载器可以识别它们。(尽管节名本身并不表明节的特殊

作用,但节名都是约定俗成的,因此本规范的作者在任何情况下都可以使用节名。)

下表描述了保留的节以及它们的属性,后面是对出现在可执行文件中的节以及包

含元数据用于扩展目的的节的详细描述。

节名

.bss

内容

未初始化的数据(自由格式)

特征

IMAGE_SCN_CNT_UNINITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_WRITE

IMAGE_SCN_LNK_INFO

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_WRITE

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_DISCARDABLE

.cormeta

.data

CLR元数据,它表明目标文件中

包含托管代码

已初始化的数据(自由格式)

.debug$F生成的FPO调试信息(仅适用于

目标文件,仅用于x86平台,

现已被舍弃)

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 37

节名

.debug$P

内容

预编译的调试类型信息(仅适

用于目标文件)

调试符号信息(仅适用于目标

文件)

调试类型信息(仅适用于目标

文件)

链接器选项

导出表

导入表

特征

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_DISCARDABLE

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_DISCARDABLE

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_DISCARDABLE

IMAGE_SCN_LNK_INFO

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_WRITE

IMAGE_SCN_LNK_INFO

.debug$S

.debug$T

.drectve

.edata

.idata

.idlsym包含已注册的SEH(仅适用于映

像文件),它们用以支持IDL属

性。要获取更多信息,请参考

本规范最后“参考信息”中的

“IDL属性”。

异常信息

只读的已初始化数据

映像文件的重定位信息

.pdata

.rdata

.reloc

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_DISCARDABLE

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ

IMAGE_SCN_CNT_UNINITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_WRITE |

IMAGE _SCN_GPREL

其中IMAGE_SCN_GPREL标志仅用于IA64平台,

不能用于其它平台。此标志只能用于目标文

件。当映像文件中出现这种类型的节时,一定

不能设置这个标志。

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_WRITE |

IMAGE _SCN_GPREL

其中IMAGE_SCN_GPREL标志仅用于IA64平台,

不能用于其它平台。此标志只能用于目标文

件。当映像文件中出现这种类型的节时,一定

不能设置这个标志。

.rsrc

.sbss

资源目录

与GP相关的未初始化数据(自

由格式)

.sdata与GP相关的已初始化数据(自

由格式)

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 38

节名

.srdata

内容

与GP相关的只读数据(自由格

式)

特征

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE _SCN_GPREL

其中IMAGE_SCN_GPREL标志仅用于IA64平台,

不能用于其它平台。此标志只能用于目标文

件。当映像文件中出现这种类型的节时,一定

不能设置这个标志。

IMAGE_SCN_LNK_INFO

这个节中包含目标文件中的代码所涉及到的所

有异常处理程序在符号表中的索引。这些符号

可以是IMAGE_SYM_UNDEFINED类型的符号,也

可以是定义在那个模块中的符号。

IMAGE_SCN_CNT_CODE |

IMAGE_SCN_MEM_EXECUTE |

IIMAGE_SCN_MEM_READ

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_WRITE

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_WRITE

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ |

IMAGE_SCN_MEM_WRITE

IMAGE_SCN_CNT_INITIALIZED_DATA |

IMAGE_SCN_MEM_READ

.sxdata已注册的异常处理程序数据

(自由格式,仅适用于目标文

件,仅用于x86平台)

.text可执行代码(自由格式)

.tls线程局部存储(仅适用于目标

文件)

线程局部存储(仅适用于目标

文件)

与GP相关的已初始化数据(自

由格式,仅适用于ARM、SH4和

Thumb平台)

异常信息(自由格式)

.tls$

.vsdata

.xdata

上表中列出的一些节被标记为“仅适用于目标文件”或 “仅适用于映像文

件”,它们表示这些节的特殊含义只是分别对于目标文件或者映像文件来说的。标记

为“仅适用于映像文件”的节仍然可以首先出现在目标文件中,最后再成为映像文件

的一部分,但这个节对于链接器来说并没有特殊含义,它仅对于映像文件加载器才有

特殊含义。

6.1 .debug节

在目标文件中,.debug节包含编译器生成的调试信息;在映像文件中,它包含

生成的全部调试信息。本节描述了目标文件和映像文件中调试信息的封装。

下一节描述调试目录的格式,它可以被放在映像文件中的任何地方。后面几节描

述目标文件中包含调试信息的成组的节。

默认情况下调试信息并不映射到映像的地址空间中。只有当调试信息被映射到地

址空间中时.debug节才会存在。

6.1.1 调试目录(仅适用于映像文件)

映像文件中包含一个可选的调试目录,它给出了调试信息的格式及位置。这个目

录是一个由调试目录项组成的数组,它的位置和大小由可选文件头给出。

调试目录可以位于一个可丢弃的.debug 节(如果存在)中,或者位于映像文件

的其它节中,或者不在任何节中。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 39

每个调试目录项给出了一块调试信息的位置和大小。如果调试信息没有被节头包

含(也就是说,它位于映像文件中但并没有被映射到运行时地址空间中)的话,那么

这个指定的RVA可以为0。如果被映射的话,这个RVA就是它的实际地址。

调试目录项格式如下:

偏移

0

4

8

10

12

大小 域

4

4

2

2

4

Characteristics

TimeDateStamp

MajorVersion

MinorVersion

Type

描述

保留,必须为0。

调试数据被创建的日期和时间。

调试数据格式的主版本号。

调试数据格式的次版本号。

调试信息的格式。这个域的存在使得可以支持多个调

试器。要获取更多信息,请参考6.1.2节“调试类

型”。

调试数据(不包括调试目录本身)的大小。

当被加载时调试数据相对于映像基址的偏移地址。

指向调试数据的文件指针。

16

20

24

4

4

4

SizeOfData

AddressOfRawData

PointerToRawData

6.1.2 调试类型

为调试目录项的Type域定义了以下值:

常量

IMAGE_DEBUG_TYPE_UNKNOWN

IMAGE_DEBUG_TYPE_COFF

0

1

描述

未知值,所有工具均忽略此值。

COFF调试信息(行号信息、符号表和字符串

表)。文件头中也有相关域指向这种类型的调

试信息。

Visual C++调试信息。

帧指针省略(FPO)信息。这种信息告诉调试

器如何解释非标准栈帧,这种帧将EBP寄存器

用于其它目的而不是作为帧指针。

DBG文件的位置。

.pdata节的副本。

保留。

从经过代码重排后的映像中的RVA到原映像中

的RVA的映射。

从原映像中的RVA到经过代码重排后的映像中

的RVA的映射。

保留,供Borland公司使用。

保留。

保留。

IMAGE_DEBUG_TYPE_CODEVIEW

IMAGE_DEBUG_TYPE_FPO

2

3

IMAGE_DEBUG_TYPE_MISC

IMAGE_DEBUG_TYPE_EXCEPTION

IMAGE_DEBUG_TYPE_FIXUP

IMAGE_DEBUG_TYPE_OMAP_TO_SRC

IMAGE_DEBUG_TYPE_OMAP_FROM_SRC

IMAGE_DEBUG_TYPE_BORLAND

IMAGE_DEBUG_TYPE_RESERVED10

IMAGE_DEBUG_TYPE_CLSID

4

5

6

7

8

9

10

11

如果Type域被设置为IMAGE_DEBUG_TYPE_FPO,那么原始的调试数据是一个数

组,它的每个元素都描述了一个函数的栈帧。即使调试类型为FPO,也不是映像文件

中的每个函数都必须有相应的FPO信息。没有相应FPO信息的那些函数的栈帧被当作

正常的栈帧对待。FPO信息的格式如下:

#define FRAME_FPO 0

#define FRAME_TRAP 1

#define FRAME_TSS 2

typedef struct _FPO_DATA {

DWORD ulOffStart; // 函数代码第一个字节的偏移

DWORD cbProcSize; // 函数代码所占的字节数

DWORD cdwLocals; // 局部变量所占字节数除以4

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 40

WORD cdwParams; // 参数所占字节数除以4

WORD cbProlog : 8; // 函数prolog代码所占字节数

WORD cbRegs : 3; // 保存的寄存器数

WORD fHasSEH : 1; // 如果函数中有SEH,此值为TRUE

WORD fUseBP : 1; // 如果EBP寄存器已经被分配,此值为TRUE

WORD reserved : 1; // 保留供将来使用

WORD cbFrame : 2; // 帧类型

} FPO_DATA;

6.1.3 .debug$F节(仅适用于目标文件)

在Visual C++ 7.0及其后续版本中,这个节中的数据已经被保存在.debug$S节

中一组更详尽的数据取代。

目标文件可以包含内容为一个或多个FPO_DATA记录(帧指针省略信息)

的.debug$F节。要获取更多信息,请参考6.1.2节“调试类型”中的

“IMAGE_DEBUG_TYPE_FPO”。

链接器能够识别这些.debug$F 记录。如果指定要生成调试信息的话,链接器根

据函数的RVA将相应的FPO_DATA记录排序并分别为它们生成一个调试目录项。

编译器不应该为具有标准帧格式的过程生成FPO记录。

6.1.4 .debug$S节(仅适用于目标文件)

这个节中包含的是Visual C++调试信息(符号信息)。

6.1.5 .debug$P节(仅适用于目标文件)

这个节中包含的是Visual C++调试信息(预编译信息)。它们是在所有使用由

这个目标文件生成的预编译头编译生成的目标文件之间共享的类型信息。

6.1.6 .debug$T节(仅适用于目标文件)

这个节中包含的是Visual C++调试信息(类型信息)。

6.1.7 链接器对Microsoft调试信息的支持

为了支持调试信息,链接器需要:

收集.debug$F、debug$S、.debug$P和.debug$T这些节中所有相关的调试数据。

将这些数据连同链接器生成的调试信息综合处理,生成一个PDB文件,同时创建

一个指向这个文件的调试目录项。

6.2 .drectve节(仅适用于目标文件)

如果在节头中将一个节设置了IMAGE_SCN_LNK_INFO标志,并且这个节被命名为

.drectve,那么它就是一个指令节。链接器在处理完其中的信息后就会移除这个节,

因此它并不会出现在链接生成的映像文件中。

.drectve节由ANSI格式或UTF-8格式的文本字符串组成。如果UTF-8字节顺序

标记(BOM,由0xEF、0xBB和0xBF组成的三字节前缀)不存在,那么指令字符串就

被当作ANSI字符串。指令字符串是由空格分隔的一串链接器选项。每个选项包括一

个连字符、选项名称以及相应的属性。如果某个选项包含空格,必须用双引号将整个

选项括起来。.drectve节一定不能有重定位或行号信息。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 41

6.3 .edata节(仅适用于映像文件)

导出数据节被命名为.edata,它包含的是与其它映像通过动态链接可以访问的符

号相关的信息。导出符号通常出现在DLL中,但DLL也可以导入符号。

下表描述了导出节的一般结构。其中提到的各种表通常都是按下表中所示的顺序

在文件中连续分布的(尽管这并不是必须的)。只需要导出目录表和导出地址表这两

个表就可以将序数作为导出符号导出。(序数是一个导出符号,可以把它作为导出地

址表中的索引直接引用。)导出名称指针表、导出序数表和导出名称表的存在都是为

了支持使用导出名称。

表名

导出目录表

导出地址表

描述

一个只有一行的表(与调试目录不同)。它给出了其它各种导出表

的位置和大小。

一个由导出符号的RVA组成的数组。它们是导出的函数和数据在可

执行代码节和数据节内的实际地址。其它映像文件可以通过使用这

个表的索引(序数)来导入符号,或者如果定义了一个与序数对应

的公用名称的话,也可以用这个公用名称来导入符号。

一个由指向导出符号名称的指针组成的数组,按升序排列。

一个由对应于导出名称指针表中各个成员的序数组成的数组。它们

的对应是通过位置来体现的,因此导出名称指针表与导出序数表成

员数目必须相同。每个序数都是导出地址表的一个索引。

一系列以NULL结尾的ASCII码字符串。导出名称指针表中的成员都

指向这个区域。它们都是公用名称,符号导入与导出就是通过它

们。这些公用名称并不需要与映像文件内部使用的私有名称相同。

导出名称指针表

导出序数表

导出名称表

当其它映像文件通过名称导入符号时,Win32加载器通过导出名称指针表来查找

匹配的字符串。如果找到,它就查找导出序数表中相应的成员(也就是说,将找到的

导出名称指针表的索引作为导出序数表的索引来使用)来获取与导入符号相关联的序

数。获取的这个序数是导出地址表的索引,这个索引对应的元素给出了所需符号的实

际位置。每个导出符号都可以通过序数进行访问。

当其它映像文件通过序数导入符号时,就不再需要通过导出名称指针表来查找匹

配的字符串了。因此直接使用序数效率会更高。但是导出名称容易记忆,它不需要用

户记住各个符号在表中的索引。

6.3.1 导出目录表

导出目录表是导出符号信息的开始部分,它描述了导出符号信息中其余部分的内

容。导出目录表包含了有关将导入符号解析为相应入口点地址的信息。

偏移

0

4

8

10

12

16

20

24

大小 域

4

4

2

2

4

4

4

4

Export Flags

Time/Date Stamp

Major Version

Minor Version

Name RVA

Ordinal Base

Address Table

Entries

Number of Name

Pointers

描述

保留,必须为0。

导出数据被创建的日期和时间。

主版本号。用户可以自行设置主版本号和次版本号。

次版本号。

包含这个DLL名称的ASCII码字符串相对于映像基址的

偏移地址。

映像中导出符号的起始序数值。这个域指定了导出地址

表的起始序数值。它通常被设置为1。

导出地址表中元素的数目。

导出名称指针表中元素的数目。它同时也是导出序数表

中元素的数目。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 42

偏移

28

32

36

大小 域

4

4

4

Export Address

Table RVA

Name Pointer

RVA

Ordinal Table

RVA

描述

导出地址表相对于映像基址的偏移地址。

导出名称指针表相对于映像基址的偏移地址。它的大小

由Number of Name Pointers域给出。

导出序数表相对于映像基址的偏移地址。

6.3.2 导出地址表

导出地址表包含导出函数、导出数据以及绝对符号的地址。序数值是作为导出地

址表的索引来使用的。

导出地址表的每一个元素都是一个域,其格式为下表所述的两种格式之一。如果

指定的地址

不是

位于导出节(其地址和长度由可选文件头给出)中,那么这个域就是

一个Export RVA,这个地址就是导出符号在代码或数据中的实际地址;否则这个域

是一个Forwarder RVA,它给出了一个位于其它DLL中的符号的名称。

偏移

0

0

大小

4

4

Export RVA

Forwarder

RVA

描述

当加载进内存时,导出符号相对于映像基址的偏移地址。例

如导出函数的地址。

这是指向导出节中一个以NULL结尾的ASCII码字符串的指

针。这个字符串必须位于Export Table(导出表)数据目录

项给出的范围之内。要获取更多信息,请参考3.4.3节“可

选文件头中的数据目录(仅适用于映像文件)”。这个字符

串给出了导出符号所在DLL的名称以及导出符号的名称(例

如“c”),或者DLL的名称以及导出符号的序

数值(例如“MYDLL.#27”)。

Forwarder RVA导出了其它映像中定义的符号,使它看起来好像是当前映像导出

的一样。因此对于当前映像来说,这个符号同时既是导入符号又是导出符号。

例如对于Windows XP系统中的文件来说,它导出的

“HeapAlloc”被转发到“ocateHeap”。这样就允许应用程序使用

Windows XP系统中的模块而不需要实际包含任何相关的导入信息。应用

程序的导入表只与有关。这样应用程序就不是特定于Windows XP,它

可以运行于任何Win32系统之上。

6.3.3 导出名称指针表

导出名称指针表是由导出名称表中的字符串的地址(RVA)组成的数组。每个地

址都是相对于映像基址的32位指针。它们按词法顺序排列以便进行折半查找。

只有当导出名称指针表中包含指向某个导出名称的指针时,这个导出名称才算被

定义。

6.3.4 导出序数表

导出序数表是由导出地址表的索引组成的一个数组,每个序数长16位。但是这

个序数是移码形式,相应的偏移量由导出目录表中的Ordinal Base域给出。换句话

说,必须从序数值中减去Ordinal Base域的值得到的才是导出地址表真正的索引。

导出名称指针表和导出序数表是两个并列的数组,将它们分开是为了使它们可以

分别按照各自的自然边界(前者是4个字节,后者是2个字节)对齐。在进行操作

时,这两个表等效于一个表(在这个等效的新表中,这两个表分别相当于新表中的两

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 43

列),由导出名称指针这一列给出公共(导出)符号的名称,而由导出序数这一列给

出这个导出符号对应的序数。导出名称指针表的成员和导出序数表的成员通过同一个

索引相关联。

因此,当在导出名称指针表中查找并找到匹配字符串的索引为

i

时,查找符号

对应地址的算法如下:

i = Search_ExportNamePointerTable (ExportName);

ordinal = ExportOrdinalTable [i];

SymbolRVA = ExportAddressTable [ordinal - OrdinalBase];

6.3.5 导出名称表

导出名称表包含的是导出名称指针表实际指向的字符串。这个表中的字符串都是

公用名称,其它映像可以通过它们导入这些符号。这些公用导出名称并不需要与这些

符号所在的映像文件和源代码中的私有符号名称相同,尽管它们可以相同。

每个导出符号都有一个相应的序数值,这个值是导出地址表的索引(加上

Ordinal Base域的值)。但是使用导出名称(来导出符号)是可选的。可以全部导

出符号都有导出名称,也可以部分导出符号有导出名称,也可以全部导出符号都没有

导出名称。对于那些有导出名称的导出符号来说,导出名称指针表和导出序数表中相

应的项配合起来使每个名称与一个序数相关联。

导出名称表的结构就是长度可变的一系列以NULL结尾的ASCII码字符串。

所有导入符号的映像文件,实际上几乎包括所有的可执行(EXE)文件,都

有.idata节。文件中导入信息的典型布局如下:

目录表

空目录项

DLL1的导入查找表

空表项

DLL2的导入查找表

空表项

DLL3的导入查找表

空表项

提示/名称表

图3. 典型的导入节布局

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 44

6.4.1 导入目录表

导入目录表是导入信息的开始部分,它描述了导入信息中其余部分的内容。导入

目录表包含地址信息,这些地址信息用来修正对DLL映像中的相应函数的引用。导入

目录表是由导入目录项组成的数组,每个导入目录项对应着一个导入的DLL。最后一

个导入目录项是空的(全部域的值都为NULL),用来指明目录表的结尾。

每个导入目录项的格式如下:

偏移

0

大小 域

4 Import Lookup

Table RVA

(Characteristics)

Time/Date Stamp

Forwarder Chain

Name RVA

Import Address

Table RVA (Thunk

Table)

描述

导入查找表的RVA。这个表包含了每一个导入符号的名

称或序数。(这个域在Winnt.h文件中的名称是

“Characteristics”,但已经名不副实了。)

这个域一直被设置为0,直到映像被绑定。当映像被绑

定之后,这个域被设置为这个DLL的日期/时间戳。

第一个转发项的索引。

包含DLL名称的ASCII码字符串相对于映像基址的偏移

地址。

导入地址表的RVA。这个表的内容与导入查找表的内容

完全一样,直到映像被绑定。

4

8

12

16

4

4

4

4

6.4.2 导入查找表

导入查找表是由长度为32位(PE32)或64位(PE32+)的数字组成的数组。其

中的每一个元素都是位域,其格式如下表所示。在这种格式中,位31(PE32)或位

63(PE32+)是最高位。这些项描述了从给定的DLL导入的所有符号。最后一个项被

设置为0(NULL),用来指明表的结尾。

31/63

大小

1

位域

Ordinal/Name

Flag

Ordinal

Number

Hint/Name

Table RVA

描述

如果这个位为1,说明是通过序数导入的。否则是

通过名称导入的。测试这个位的掩码为0x80000000

(PE32)或0x8000(PE32+)。

序数值(16位长)。只有当Ordinal/Name Flag域

为1(即通过序数导入)时才使用这个域。位30-15

(PE32)或62-15(PE32+)必须为0。

提示/名称表项的RVA(31位长)。只有当

Ordinal/Name Flag域为0(即通过名称导入)时才

使用这个域。对于PE32+来说,位62-31必须为0。

15-0 16

30-0

31

6.4.3 提示/名称表

一个提示/名称表就能满足整个导入节的需要。提示/名称表中的每一个元素结构

如下:

偏移

0

大小

2

Hint

描述

导出名称指针表的索引。当查找匹配字符串时首选使用这个

值。如果匹配失败,再在DLL的导出名称指针表中进行折半查

找。

包含导入符号名称的ASCII码字符串。这个字符串必须与DLL

导出的公用名称匹配。同时这个字符串区分大小写并且以NULL

结尾。

为了让提示/名称表的下一个元素出现在偶数地址,这里可能需

要填充0个或1个NULL字节。

2 可变 Name

* 0 或1 Pad

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 45

6.4.4 导入地址表

导入地址表的结构和内容与导入查找表完全一样,直到文件被绑定。在绑定过程

中,用导入符号的32位(PE32)或64位(PE32+)地址覆盖导入地址表中的相应

项。这些地址是导入符号的实际内存地址,尽管技术上仍把它们称为“虚拟地址”。

加载器通常会处理绑定。

6.5 .pdata节

.pdata节是由用于异常处理的函数表项组成的数组。可选文件头中的Exception

Table(异常表)域指向它。在将它们放进最终的映像文件之前,这些项必须按函数

地址(下列每个结构的第一个域)排序。下面描述了函数表项的三种格式,使用哪一

种取决于目标平台。

对于32位的MIPS映像来说,其函数表项格式如下:

偏移

0

4

8

12

16

大小

4

4

4

4

4

Begin Address

End Address

Exception Handler

Handler Data

Prolog End Address

描述

相应函数的VA。

函数结尾的VA。

指向要执行的异常处理程序的指针。

指向要传递给异常处理程序的附加数据的指针。

函数prolog代码结尾的VA。

对于ARM、PowerPC、SH3和SH4 Windows CE平台来说,其函数表项格式如下:

偏移

0

4

4

4

4

大小

4

8位

22位

1位

1位

Begin Address

Prolog Length

Function Length

32-bit Flag

Exception Flag

描述

相应函数的VA。

函数prolog代码包含的指令数。

函数代码包含的指令数。

如果此位为1,表明函数由32位指令组成。否则,

函数由16位指令组成。

如果此位为1,表明存在用于此函数的异常处理程

序;否则,不存在异常处理程序。

对于x64和Itanium平台来说,其函数表项格式如下:

偏移

0

4

8

大小

4

4

4

Begin Address

End Address

Unwind Information

描述

相应函数的RVA。

函数结尾的RVA。

用于异常处理的展开(Unwind)信息的RVA。

6.6 .reloc节(仅适用于映像文件)

基址重定位表包含了映像中所有需要重定位的内容。可选文件头中的数据目录中

的Base Relocation Table(基址重定位表)域给出了基址重定位表所占的字节数。

要获取更多信息,请参考3.4.3节“可选文件头中的数据目录(仅适用于映像文

件) ”。基址重定位表被划分成许多块,每一块表示一个4K页面范围内的基址重定

位信息,它必须从32位边界开始。

加载器不需要处理由链接器解析的基址重定位信息,除非映像不能被加载到PE

文件头中指定的映像基地址处。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 46

6.6.1 基址重定位块

每个基址重定位块的开头都是如下结构:

偏移

0

4

大小

4

4

Page RVA

描述

将映像基址与这个域(页面RVA)的和加到每个偏移地址处

最终形成一个VA,这个VA就是要进行基址重定位的地方。

Block Size 基址重定位块所占的总字节数,其中包括Page RVA域和

Block Size域以及跟在它们后面的Type/Offset域。

Block Size域后面跟着数目不定的Type/Offset位域。它们中的每一个都是一

个WORD(2字节),其结构如下:

偏移

0

大小

4位

Type

描述

它占这个WORD的最高4位,这个值指出需要应用的基址重定

位类型。要获取更多信息,请参考6.6.2节“基址重定位类

型”。

它占这个WORD的其余12位,这个值是从基址重定位块的

Page RVA域指定的地址处开始的偏移。这个偏移指出需要进

行基址重定位的位置。

0

12位 Offset

为了进行基址重定位,需要计算映像的首选基地址与实际被加载到的基地址之

差。如果映像本身就被加载到了其首选基地址,那么这个差为零,因此也就不需要进

行基址重定位了。

6.6.2 基址重定位类型

常量

IMAGE_REL_BASED_ABSOLUTE

IMAGE_REL_BASED_HIGH

0

1

描述

基址重定位被忽略。这种类型可以用来对其它

块进行填充。

进行基址重定位时将差值的高16位加到指定

偏移处的一个16位域上。这个16位域是一个

32位字的高半部分。

进行基址重定位时将差值的低16位加到指定

偏移处的一个16位域上。这个16位域是一个

32位字的低半部分。

进行基址重定位时将所有的32位差值加到指

定偏移处的一个32位域上。

进行基址重定位时将差值的高16位加到指定

偏移处的一个16位域上。这个16位域是一个

32位字的高半部分,而这个32位字的低半部

分被存储在紧跟在这个Type/Offset位域后面

的一个16位字中。也就是说,这一个基址重

定位项占了两个Type/Offset位域的位置。

对MIPS平台的跳转指令进行基址重定位。

保留,必须为0。

保留,必须为0。

对MIPS16平台的跳转指令进行基址重定位。

进行基址重定位时将差值加到指定偏移处的一

个64位域上。

IMAGE_REL_BASED_LOW 2

IMAGE_REL_BASED_HIGHLOW

IMAGE_REL_BASED_HIGHADJ

3

4

IMAGE_REL_BASED_MIPS_JMPADDR

IMAGE_REL_BASED_MIPS_JMPADDR16

IMAGE_REL_BASED_DIR64

5

6

7

9

10

6.7 .tls节

.tls节为PE和COFF文件的静态线程局部存储(TLS)提供了直接支持。TLS是

Windows支持的一种特殊存储类别,它里面的数据对象不是自动(堆栈)变量,而是

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 47

局限于运行相应代码的单个线程,因此每个线程都可以为使用TLS定义的变量维护一

个不同的值。

通过调用TlsAlloc、TlsFree、TlsSetValue和TlsGetValue这些API可以支持

任意数量的TLS数据。PE和COFF对此的实现是变相地调用这些API,其优点就是从

高级语言程序员的观点来看这样更简单。这种实现方式使得TLS数据的定义与初始化

就像程序中普通的静态变量那样。例如在Visual C++中,对静态TLS变量的定义方

式如下,不需要调用Windows API函数:

__declspec (thread) int tlsFlag = 1;

为了支持这种编程模式,PE和COFF文件的.tls节包含了以下信息:初始化数

据、用于每个线程初始化和终止的回调函数以及下面将要讨论的TLS索引。

注意

静态定义的TLS数据对象只能用于静态加载的映像文件。这使得在DLL中使用静

态TLS数据并不可靠,除非你能确定这个DLL以及静态链接到这个DLL的其它DLL永

远不会被通过调用LoadLibrary这个API函数的方式动态加载。

可执行代码访问静态TLS数据需要经过以下步骤:

1. 在链接时,链接器设置TLS目录(见下文)中的Address of Index域。这个域

指向一个位置,在这个位置保存程序用到的TLS索引。

Microsoft运行时库为了处理方便就定义了一个TLS目录的内存映像并给它

取名为“__tls_used”(Intel x86平台)或“_tls_used”(其它平台)。链接

器查找这个内存映像并直接使用其中的数据创建TLS目录。其它支持TLS并与

Microsoft的链接器配合使用的编译器必须使用这种技术。

2. 当创建线程时,加载器通过将线程环境块(TEB)的地址放入FS寄存器来传递线

程的TLS数组地址。距TEB开头0x2C的位置处有一个指针指向TLS数组。这是

特定于Intel x86平台的。

3. 加载器将TLS索引值保存到Address of Index域指向的位置处。

4. 可执行代码获取TLS索引以及TLS数组的位置。

5. 可执行代码使用TLS索引和TLS数组的位置(将索引乘以4并作为这个数组内的

偏移地址来使用)来获取给定程序和模块的TLS数据区的地址。每个线程拥有它

自己的TLS数据区,但这对于程序是透明的,它并不需要知道是如何为单个线程

分配数据的。

6. 单个的TLS数据对象都位于TLS数据区的某个固定偏移处,因此可以用这种方式

访问。

TLS数组是系统为每个线程维护的一个地址数组。这个数组中的每个地址指出了

程序中给定模块(EXE或DLL)的TLS数据区的位置。TLS索引指出了是这个数组的

哪个元素。这个索引是一个用来标识具体模块的数字(仅对系统有意义)。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 48

6.7.1 TLS目录

TLS目录结构如下:

偏移 大小 域

(PE32/ (PE32/

PE32+) PE32+)

0 4/8 Raw Data Start

VA

描述

TLS模板的起始地址。这个模板是一块数据,用于对

TLS数据进行初始化。每当创建线程时,系统都要复

制所有这些数据,因此这些数据一定不能出错。注意

这个地址并不是一个RVA,

.reloc节中应当有一个基

址重定位信息是用于这个地址的。

TLS的最后一个字节的地址,不包括用于填充的0。

与Raw Data Start VA域一样,它是一个VA而不是

RVA。

用于保存TLS索引的位置,索引的具体值由加载器确

定。这个位置在普通的数据节中,因此可以给它取一

个容易理解的符号名,便于在程序中访问。

这是一个指针,它指向由TLS回调函数组成的数组。

这个数组是以NULL结尾的,因此如果没有回调函数

的话,这个域指向的位置处应该是4个字节的0。要

获取有关这些函数原型方面的信息,请参考6.7.2节

“TLS回调函数”。

TLS模板中除了由Raw Data Start VA 和Raw Data

End VA域组成的已初始化数据界限之外的大小(以

字节计)。TLS模板的总大小应该与映像文件中TLS

数据的总大小一致。用0填充的数据就是已初始化的

非零数据后面的那些数据。

保留,可能将来用作TLS标志。

4/8 4/8 Raw Data End VA

8/16 4/8 Address of

Index

Address of

Callbacks

12/24 4/8

16/32 4 Size of Zero

Fill

20/36 4 Characteristics

6.7.2 TLS回调函数

程序可以提供一个或多个TLS回调函数,用以支持对TLS数据进行附加的初始化

和终止操作。调用对象的构造函数和析构函数应该算是对这种回调函数的典型应用。

尽管回调函数通常不超过一个,但还是将其作为一个数组来实现,以便在需要时

可以另外添加回调函数。如果回调函数超过一个,将会按照它们的地址在数组中出现

的顺序调用每个函数。一个空指针表示这个数组的结尾。让这个列表空着(不提供回

调函数)也是完全合法的,这时这个数组就只有一个元素——一个空指针。

回调函数(由类型为PIMAGE_TLS_CALLBACK的函数指针指向)的原型与DLL入口

点函数参数相同:

typedef VOID

(NTAPI *PIMAGE_TLS_CALLBACK) (

PVOID DllHandle,

DWORD Reason,

PVOID Reserved

);

Reserved参数应该被设置为0。Reason参数可以取以下值:

设置

DLL_PROCESS_ATTACH

DLL_THREAD_ATTACH

1

2

描述

启动了一个新进程,包括第一个线程。

创建了一个新线程。创建所有线程时都会发送这个通

知,除了第一个线程。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 49

设置

DLL_THREAD_DETACH

DLL_PROCESS_DETACH

3

0

描述

线程将要被终止。终止所有线程时都会发送这个通

知,除了第一个线程。

进程将要被终止,包括第一个线程。

6.8 加载配置结构(仅适用于映像文件)

加载配置结构(IMAGE_LOAD_CONFIG_DIRECTORY)最初用于Windows NT操作系

统自身几种非常有限的场合——在映像文件头或可选文件头中描述各种特性太困难

或这些信息尺寸太大。当前版本的Microsoft链接器和Windows XP以及后续版本的

Windows使用的是这个结构的新版本,将之用于包含保留的SEH技术的基于x86的

32位系统上。它提供了一个安全的结构化异常处理程序列表,操作系统在进行异常

派送时要用到这些异常处理程序。如果异常处理程序的地址在映像的VA范围之内,

并且映像被标记为支持保留的SEH(也就是说可选文件头中的DllCharacteristics

域没有设置IMAGE_DLLCHARACTERISTICS_NO_SEH标志,前面已经提到过),那么这

个异常处理程序必须在映像的已知安全异常处理程序列表中,否则操作系统将终止

这个应用程序。这是为了防止利用“x86异常处理程序劫持”来控制操作系统,它

在以前已经被利用过。

Microsoft的链接器自动提供一个默认的加载配置结构来包含保留的SEH数据。

如果用户的代码已经提供了一个加载配置结构,那么它必须包含新添加的保留的SEH

域。否则,链接器将不能包含保留的SEH数据,这样映像文件就不能被标记为包含保

留的SEH。

6.8.1 加载配置目录

对应于预保留的SEH加载配置结构的数据目录项必须为加载配置结构指定一个特

别的大小,因为操作系统加载器总是希望它为这样一个特定值。事实上,这个大小只

是用于检查这个结构的版本。为了与Windows XP以及以前版本的Windows兼容,x86

映像文件中这个结构的大小必须为64。

6.8.2 加载配置结构布局

用于32位和64位PE文件的加载配置结构布局如下:

偏移

0

4

大小

4

4

Characteristics

TimeDateStamp

描述

指示文件属性的标志,当前未用。

日期/时间戳。这个值表示从UTC时

间1970年1月1日午夜

(00:00:00)以来经过的总秒数,它

是根据系统时钟算出的。可以用C运

行时函数time来获取这个时间戳。

主版本号。

次版本号。

当加载器启动进程时,需要被清除的

全局加载器标志。

当加载器启动进程时,需要被设置的

全局加载器标志。

用于这个进程处于无约束状态的临界

区的默认超时值。

返回到系统之前必须释放的内存数量

(以字节计)。

空闲内存总量(以字节计)。

8

10

12

16

20

24

32

2

2

4

4

4

8

8

MajorVersion

MinorVersion

GlobalFlagsClear

GlobalFlagsSet

CriticalSectionDefaultTimeout

DeCommitFreeBlockThreshold

DeCommitTotalFreeThreshold

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 50

偏移

40

大小

8

LockPrefixTable

描述

[仅适用于x86平台]这是一个地址

列表的VA。这个地址列表中保存的是

使用LOCK前缀的指令的地址,这样

便于在单处理器机器上将这些LOCK

前缀替换为NOP指令。

最大的分配粒度(以字节计)。

最大的虚拟内存大小(以字节计)。

将这个域设置为非零值等效于在进程

启动时将这个设定的值作为参数去调

SetProcessAffinityMask函数(仅

适用于.exe文件)。

进程堆的标志,相当于HeapCreate函

数的第一个参数。这些标志用于在进

程启动过程中创建的堆。

Service Pack版本标识。

必须为0。

保留,供系统使用。

指向cookie的指针。cookie由

Visual C++编译器的GS实现所使

用。

[仅适用于x86平台]这是一个地址

列表的VA。这个地址列表中保存的是

映像中每个合法的、独一无二的SE

处理程序的RVA,并且它们已经按

RVA排序。

[仅适用于x86平台]表中独一无二

的SE处理程序的数目。

48

56

64

8

8

8

MaximumAllocationSize

VirtualMemoryThreshold

ProcessAffinityMask

72 4 ProcessHeapFlags

76

78

80

60/88

2

2

8

4/8

CSDVersion

Reserved

EditList

SecurityCookie

64/96 4/8 SEHandlerTable

68/104 4/8

SEHandlerCount

6.9 .rsrc节

一个多层的二叉排序树指向各种资源,树的深度可达2

31

层。但是Windows通常使

用如下3层:

类型

名称

语言

一系列资源目录表按如下方式与各层相联系:每个目录表后面跟着一系列目录

项,它们给出那个层(类型、名称或语言)的名称或标识(ID)及其数据描述或另一

个目录表的地址。如果这个地址指向一个数据描述,那么那个数据就是这棵树的叶

子。如果这个地址指向另一个目录表,那么那个目录表列出了下一层的目录项。

一个叶子的类型、名称和语言ID由从目录表到这个叶子的路径决定。第一个表

决定类型ID,第二个表(由第一个表中的目录项指向)决定名称ID,第三个表决定

语言ID。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 51

.rsrc节的一般结构如下:

数据

资源目录表(以及资源

目录项)

描述

这是一系列表,其中每一个表都对应着树中的一组结点。所有的顶

层(类型)结点都被列于第一个表中。这个表中的项指向第二层

表。每个第二层树的类型ID相同但是名称ID不同。第三层树的类

型ID和名称ID都相同但语言ID不同。

每个单个的表后面紧跟着目录项,每一项都有一个名称或数字标识

和一个指向数据描述或下一层表的指针。

按2字节边界对齐的Unicode字符串,它是作为由目录项指向的字

符串数据来使用的。

一个由记录组成的数组,由表指向它,描述了资源数据的实际大小

和位置。这些记录是资源描述树中的叶子。

资源节的原始数据。资源数据描述域中的大小和位置信息将资源数

据分成单个的区域。

资源目录字符串

资源数据描述

资源数据

6.9.1 资源目录表

每个资源目录表格式如下。此结构应该被看作是表头,因为这个表实际上是由多

个目录项(在6.9.2节“资源目录项”中详细描述)和这个结构组成:

偏移

0

4

8

10

12

大小 域

4

4

2

2

2

Characteristics

Time/Date Stamp

Major Version

Minor Version

Number of Name

Entries

Number of ID

Entries

描述

资源标志。保留供将来使用。当前它被设置为0。

资源数据被资源编译器创建的时间。

主版本号,由用户设定。

次版本号,由用户设定。

紧跟着这个表的目录项的个数,这些目录项使用名称

字符串来标识类型、名称或语言项(依赖于表的层

次)。

紧跟着名称项的目录项的个数,这些目录项使用数字

ID来标识类型、名称或语言项。

14 2

6.9.2 资源目录项

这些目录项组成了表中的各行。每个资源目录项格式如下。这个项是名称项还是

ID项取决于资源目录表,这个表指出跟着它的名称项和ID项各有多少个(表中所有

的名称项在所有的ID项前面)。表中的所有项按升序排列:名称项是按不区分大小

写的字符串,而ID项则是按数值。

偏移

0

0

4

4

大小 域

4

4

4

4

Name RVA

Integer ID

Data Entry RVA

Subdirectory RVA

描述

表示类型、名称或语言ID项(依赖于表的层次)的名

称字符串的地址。

标识类型、名称或语言ID项的32位整数。

最高位为0。资源数据项(叶子)的地址。

最高位为1。低31位是另一个资源目录表(下一层)

的地址。

6.9.3 资源目录字符串

资源目录字符串区由按字边界对齐的Unicode字符串组成。这些字符串被存储在

最后一个资源目录项之后、第一个资源数据项之前。这样能够使这些长度可变的字符

串对长度固定的目录项的对齐情况影响最小。每个资源目录字符串格式如下:

偏移

0

大小

2

Length

描述

字符串的长度,不包括Length域本身。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 52

偏移

2

大小

可变

Unicode String

描述

按字边界对齐的可变长度的Unicode字符串。

6.9.4 资源数据项

每个资源数据项描述了资源数据区中一个实际单元的原始数据。资源数据项格式

如下:

偏移

0

4

8

12

大小

4

4

4

4

Data RVA

Size

Codepage

保留,必须为0。

描述

资源数据区中一个单元的资源数据的地址。

由Data RVA域指向的资源数据的大小(以字节计)。

用于解码资源数据中的代码点值的代码页。通常这个代

码页应该是Unicode代码页。

6.10 .cormeta节(仅适用于目标文件)

CLR元数据被存储在这个节中。它用来指明目标文件中包含托管代码。虽然元数

据的格式并未公开,但是可以使用处理元数据的CLR接口来处理它们。

6.11 .sxdata节

目标文件中合法的异常处理程序被列于这个目标文件的.sxdata节中。这个节被

标记为IMAGE_SCN_LNK_INFO。它包含了每个合法的异常处理程序在COFF符号表中的索

引,每个索引占4个字节。

另外,编译器通过生成一个名为“@feat.00”且其Value域的LSB为1的绝对符号

来标识这个COFF目标文件中有已注册的SEH。没有已注册的SEH的COFF目标文件有

“@feat.00”符号,但没有

.sxdata 节。

7 档案(库)文件格式

COFF档案文件格式提供了一种存储目标文件集合的标准机制。这些目标文件集

合在编程文档中通常被称为库(Library)。

档案文件的前8个字节是文件签名。其余部分是一系列档案文件成员,如下所示:

• 第一个和第二个成员是“链接器成员”。它们的格式如8.3节“导入名称类型”

所述。通常链接器会将信息放在这些档案文件成员中。链接器成员包含了档案文

件目录。

第三个成员是“长名称”成员。它由一系列以NULL结尾的ASCII码字符串组

成,其中的每一个字符串都是其它档案文件成员的名称。

其余的都是标准成员(目标文件)。它们中的每一个都包含一个完整的目标文

件。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 53

每个档案文件成员前面都有一个头部。下图显示的就是一个普通档案文件的结构:

签名:“!n”

头部

第一个链接器成员

头部

第二个链接器成员

头部

长名称成员

头部

目标文件1的内容

(COFF格式)

头部

目标文件2的内容

(COFF格式)

.

.

.

头部

目标文件N的内容

(COFF格式)

图4. 档案文件结构

7.1 档案文件签名

档案文件签名标识了文件类型。任何处理档案文件的工具(例如链接器)都可以

通过读取这个签名来检查文件类型。这个签名由下面的ASCII码字符组成,其中除了

换行符(n)为转义字符外其余的字符都是普通字符:

!n

7.2 档案文件成员头部

每个成员(链接器成员、长名称成员或者目标文件成员)前面都是头部。档案文

件成员头部格式如下表所示。其中的每个域都是一个左对齐的ASCII码字符串,长度

不足的用空格填充。所有这些域都没有结尾的NULL字符。

每个档案文件成员头部都是从前一个档案文件成员结束后的首个偶数地址开始。

偏移

0

大小 域

16 Name

描述

档案文件成员的名称,最后添加一个斜杠(/)作为结束。

如果它的第一个字符就是斜杠,那么这个名称具有特殊含

义,将在后面的表中详细描述。

此档案文件成员创建的日期与时间:这是一个用ASCII码

表示的十进制数,它代表从UTC时间1970年1月1日午夜

(00:00:00)开始的总秒数。

16 12 Date

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 54

偏移

28

大小 域

6 User ID

描述

这是一个用ASCII码表示的十进制数,它代表用户ID。在

Windows平台上这个域并不包含任何有意义的值,因为

Microsoft的工具将这个域全部用空格填充。

这是一个用ASCII码表示的十进制数,它代表组ID。在

Windows平台上这个域并不包含任何有意义的值,因为

Microsoft的工具将这个域全部用空格填充。

这是一个用ASCII码表示的八进制数,它代表档案文件成

员的文件模式。它是C运行时函数_wstat返回的_stat结

构中的st_mode域的值。

这是一个用ASCII码表示的十进制数,它表示档案文件成

员的大小,不包括头部。

两字节的C语言格式字符串“`n”(0x60 0x0A)。

34 6 Group ID

40 8 Mode

48

58

10

2

Size

End of Header

Name域的几种格式如下表所示。 如前文所述,每个字符串都向左对齐并且不足

16字节的部分用空格填充:

Name域的内容 描述

名称/

/

//

这个档案文件成员的名称。

这个档案文件成员是两个链接器成员之一。两个链接器成员都是这个名称。

这个档案文件成员是“长名称”成员,它由一系列以NULL结尾的ASCII码字

符串组成。“长名称”成员是第三个档案文件成员,即使内容为空它也必须

存在。

这个档案文件成员的名称在“长名称”成员内的偏移n处。数字n是用十进

制数表示的偏移。例如“/26”表明该档案文件成员的名称位于距“长名称”

成员内容开头26字节的位置处。

/n

7.3 第一个链接器成员

第一个链接器成员的名称是“/”。包含它是为了向后兼容。当前的链接器并不

使用它,但是它的格式必须正确。这个链接器成员与第二个链接器成员一样,都提供

了一个符号名称目录。对于其中的每个符号,相应的信息指出到哪里能够找到包含这

个符号的档案文件成员。

第一个链接器成员格式如下,它位于档案文件成员头部之后:

偏移

0

大小

4

Number of

Symbols

Offsets

描述

这是一个无符号长整型数,表示被索引的符号数目。它是按大

尾格式存储的。通常每个目标文件成员都会定义一个或多个外

部符号。

这是一个由档案文件成员头部在文件中的偏移地址组成的数

组,它的大小(4 * n)中的n指的是Number of Symbols域的

值。这个数组中的每个元素都是一个按大尾格式存储的无符号

长整型数。对于String Table域中命名的每个符号,这个数组

中相应的元素给出了包含这个符号的档案文件成员的位置。

一系列以NULL结尾的字符串,它们给出了目录中所有符号的名

称。每个字符串都紧跟前一个字符串最后的NULL字符。字符串

的数目必须与Number of Symbols域的值相等。

4 4 * n

*

* String

Table

偏移数组(上面的第二个域)中的元素必须按升序排列。这意味着字符串表(上

面的第三个域)中的符号也必须根据档案文件成员的顺序进行排列。例如第一个目标

文件成员中的符号都排在第二个目标文件成员中的符号之前。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 55

7.4 第二个链接器成员

第二个链接器成员的名称与第一个链接器成员的名称一样,也是“/”。尽管这

两个链接器成员都提供了符号目录以及包含这些符号的档案文件成员目录,但是第二

个链接器成员是当前所有链接器的首选。它包含的符号名称是按词法顺序排列的,这

样按照名称进行查找会更快。

第二个链接器成员格式如下,它位于档案文件成员头部之后:

偏移

0

4

大小

4

4 * m

Number of

Members

Offsets

描述

这是一个表示档案文件成员数目的无符号长整型数。

这是一个由档案文件成员头部在文件中的偏移地址组成的

数组,这些偏移地址是按升序排列的,其中的每一个偏移

地址都是一个无符号长整型数。它的大小(4 * m)中的m

指的是Number of Members域的值。

这是一个无符号长整型数,表示被索引的符号数目。通常

每个目标文件成员都会定义一个或多个外部符号。

这是一个将符号名称映射到档案文件成员偏移的数组,它

的索引(无符号短整型数)从1开始。它的大小(2 * n)

中的n指的是Number of Symbols域的值。对于String

Table域中命名的每一个符号,这个数组中相应的元素给

出了偏移数组(第二个域)中的一个索引,而偏移数组中

这个索引对应的元素最终给出了包含这个符号的档案文件

成员的位置。

一系列以NULL结尾的字符串,它们给出了目录中所有符号

的名称。每个字符串都紧跟前一个字符串最后的NULL字

符。字符串的数目必须与Number of Symbols域的值相

等。这个表按词法顺序且升序列出了所有符号的名称。

*

*

4

2 * n

Number of

Symbols

Indices

* * String Table

7.5 长名称成员

长名称成员的名称是“//”。它由一系列档案文件成员名称字符串组成。只有当

Name域(长度为16字节)没有足够的空间来保存名称字符串时它才会出现在这里。

尽管长名称成员的头部必须存在,但它本身却可以为空。

所有这些字符串都是以NULL结尾。每个字符串都紧跟前一个字符串最后的NULL

字符。

8 导入库格式

传统的导入库,也就是描述由一个映像导出供其它映像使用的符号的库,其格式

通常如7节“档案(库)文件格式”所示。主要区别是导入库成员包含的是伪造的目

标文件而不是真正的目标文件,这些伪造的目标文件中仅包含用于创建6.4节

.idata节”中描述的导入表所需的信息。链接器在创建需要导出符号的应用程序时

会生成这种档案文件。

节中用于一个导入符号的部分可以从一小组信息中推断出来。在创建导入库时链

接器可以为每一个成员生成完整且详细的信息,也可以仅写入一些标准信息而让以后

使用这个库的应用程序很快生成所需的信息。

在长格式的导入库中,单个成员包含以下信息:

档案成员头

文件头

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 56

节头

对应于每个节头的数据

COFF符号表

字符串

而短格式的导入库格式如下:

档案成员头

导入头

以NULL结尾的导入名称字符串

以NULL结尾的DLL名称字符串

有了这些信息就足以在使用这个成员时精确地重构它的整个内容。

8.1 导入头

导入头格式如下:

偏移

0

2

4

6

8

12

16

18

大小

2

2

2

2

4

4

2

2位

3位

11位

Sig1

Sig2

Version

Machine

Time/Date Stamp

Size Of Data

Ordinal/Hint

Type

Name Type

Reserved

描述

必须为IMAGE_FILE_MACHINE_UNKNOWN。要获取更多

信息,请参考3.3.1节“机器类型”。

必须为0xFFFF。

此结构的版本号。

标识目标机器类型的数字。要获取更多信息,请参

考3.3.1节“机器类型”。

此文件被创建的时间和日期。

此头后面跟着的字符串的长度。

或者是导入符号的序数,或者是导入符号的提示

值,具体是哪一个取决于Name Type域的值。

导入类型。要获取具体值以及相应的描述,请参考

8.2节“导入类型”。

导入名称类型。要获取具体值以及相应的描述,请

参考8.3节“导入名称类型”。

保留,必须为0。

此结构后面跟着两个以NULL结尾的字符串,它们分别是导入符号的名称和这个

导入符号所在的DLL的名称。

8.2 导入类型

为导入头中的Type域定义了以下值:

常量

IMPORT_CODE

IMPORT_DATA

IMPORT_CONST

0

1

2

描述

可执行代码。

数据。

在.def文件中指定为CONST。

这些值用来确定如果使用这个库的工具要访问那种数据时必须生成什么信息。

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 57

8.3 导入名称类型

以NULL结尾的导入符号名称字符串紧跟着与它相关的导入头。为导入头中的

Name Type域定义了以下值。它们用来指明如何利用名称来生成表示导入符号的正确

符号。

常量

IMPORT_ORDINAL

0

描述

通过序数导入。这表明导入头中Ordinal/Hint

域的值是导入符号的序数。如果未指定这个

值,那么Ordinal/Hin域的值就是导入符号的

提示值。

导入符号的名称与公用符号名称相同。

导入符号名称是公用符号名称,但是没有前导

的?、@或可选的_。

导入符号名称是公用符号名称,但是没有前导

的?、@或可选的_,并且在第一个@处截断。

IMPORT_NAME

IMPORT_NAME_NOPREFIX

IMPORT_NAME_UNDECORATE

1

2

3

参考信息

IDL属性

/en-US/library/

创建、查看和管理证书

/en-us/library/

内核模式代码签名方案

/whdc/winlogo/drvsign/kmcs_

SignTool

/en-us/library/

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。

Microsoft可移植可执行文件和通用目标文件格式文件规范 - 58

Microsoft Windows Software Development Kit (SDK) for Windows Server 2008

and .NET Framework 3.5

/downloads/?FamilyID=74DD6E2D-

89C6-4E1E-AF00-FC7D70F15439&displaylang=en

Windows Authenticode可移植可执行签名格式

/whdc/winlogo/drvsign/Authenticode_

ImageHlp函数

/en-us/library/ms680181(VS.85).aspx

ImageGetDigestStream函数

/en-us/library/

ImageEnumerateCertificates函数

/en-us/library/ms680152(VS.85).aspx

修订版8.1 - 2008年2月15日

© 2005-2008 Microsoft Corporation。保留所有权利。


本文标签: 文件 目标 符号 映像