struct _IMAGE_DATA_DIRECTORY {
DWORD VirtualAddress;
DWORD Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;
#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
值
|
描述
|
IMAGE_DIRECTORY_ENTRY_EXPORT
|
指向导出表(IMAGE_EXPORT_DIRECTORY结构)。
|
IMAGE_DIRECTORY_ENTRY_IMPORT
|
指向导入表(IMAGE_IMPORT_DESCRIPTOR结构数组)。
|
IMAGE_DIRECTORY_ENTRY_RESOURCE
|
指向资源(IMAGE_RESOURCE_DIRECTORY结构)。
|
IMAGE_DIRECTORY_ENTRY_EXCEPTION
|
指向异常处理程序表(IMAGE_RUNTIME_FUNCTION_ENTRY结构数组)。它特定于CPU,用于基于表的异常处理。适用于除x86之外所有类型的CPU。
|
IMAGE_DIRECTORY_ENTRY_SECURITY
|
指向WIN_CERTIFICATE结构列表。此结构定义在WinTrust.H文件中。它并不作为映像的一部分被映射进内存。因此VirtualAddress域是文件偏移,而不是RVA。
|
IMAGE_DIRECTORY_ENTRY_BASERELOC
|
指向基址重定位信息。
|
IMAGE_DIRECTORY_ENTRY_DEBUG
|
指向IMAGE_DEBUG_DIRECTORY结构数组。其中的每个元素描述了映像中的一些调试信息。要获得IMAGE_DEBUG_DIRECTORY结构的数目,用Size域除以IMAGE_DEBUG_DIRECTORY结构的大小。早期的Borland链接器将这个IMAGE_DATA_DIRECTORY项的Size域设置成IMAGE_DEBUG_DIRECTORY结构的数目,而不是数组的大小。
|
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE
|
指向与平台相关的数据,这个数据是一个IMAGE_ARCHITECTURE_HEADER结构数组。x86平台和IA-64平台并不使用,但好像已经用于DEC/Compaq Alpha平台。
|
IMAGE_DIRECTORY_ENTRY_GLOBALPTR
|
在某些平台上,其VirtualAddress域保存的是全局指针(Global Pointer ,GP)的RVA。x86平台上不使用,但IA-64平台上使用。Size域并未使用。要获取更多关于IA-64 GP方面的信息,可以参考2000年11月的Under The Hood专栏。
|
IMAGE_DIRECTORY_ENTRY_TLS
|
指向线程局部存储(Thread Local Storage)初始化节。
|
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
|
指向IMAGE_LOAD_CONFIG_DIRECTORY结构。此结构中的信息特定于Windows NT、Windows 2000和Windows XP(例如GlobalFlag值)。如果你的可执行文件要使用这个结构,需要定义一个名称为__load_config_used,类型为IMAGE_LOAD_CONFIG_DIRECTORY的全局结构体。对于非x86平台,这个名称需要被定义成_load_config_used(单下划线)。如果你想使用IMAGE_LOAD_CONFIG_DIRECTORY结构,必须使用这个技巧才能在你的C++代码中得到正确的名字。链接器看到的符号名一定要是__load_config_used(带两个下划线)。C++编译器要在全局符号前加一个下划线。另外,它还使用类型信息来修饰(decorate)全局符号。因此要使一切正常,你应该像下面这个样子使用:
extern "C"
IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = {...}
|
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
|
指向IMAGE_BOUND_IMPORT_DESCRIPTOR结构数组。每个结构对应于这个映像已经绑定的一个DLL。这个结构中的日期/时间戳(
TimeDateStamp
域
)可以让加载器快速确定这个绑定是否是最新的。如果不是,加载器将忽略绑定信息,并正常地解析导入的函数。
|
IMAGE_DIRECTORY_ENTRY_IAT
|
指向第一个导入地址表(IAT)的开头。对应于每一个导入的DLL都有一个相应的IAT,并且它们在内存中依次排列。Size域指出了所有IAT的总大小。加载器在解析导入符号期间使用这个地址和大小临时将包含IAT的页面标记为可读/可写。
|
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
|
指向延迟加载信息,它是CImgDelayDescr结构数组,这个结构被定义在Visual C++的DELAYIMP.H文件中。直到首次调用延迟加载的DLL中的函数时这个DLL才会被加载。特别需要注意的是:Windows并不知道关于延迟加载DLL方面的任何信息。延迟加载特性完全是由链接器与运行时库来实现的。
|
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
|
这个值在最新的系统头文件(CorHdr.h)中被更名为IMAGE_DIRECTORY_ENTRY_COMHEADER。它指向可执行文件中的.NET信息中的顶层信息,包括元数据。这个信息保存在IMAGE_COR20_HEADER结构中。
|
大小
|
域
|
描述
|
WORD
|
Machine
|
目标平台CPU的类型。常用的值有:
IMAGE_FILE_MACHINE_I386 0x014c // Intel 386
IMAGE_FILE_MACHINE_IA64 0x0200 // Intel 64
|
WORD
|
NumberOfSections
|
指示节表中节的数目。节表紧跟着IMAGE_NT_HEADERS结构。
|
DWORD
|
TimeDateStamp
|
指示文件创建时间。这个值是从格林尼治时间(GMT)1970年1
月1日00:00以来的总秒数。它比文件系统所指明的日期/时间
更精确。使用_ctime函数可以很容易地把这个值转换成可读性
比较好的字符串(这个函数与时区相关)。另一个可用于这个
值的函数gmtime也比较有用。
|
DWORD
|
PointerToSymbolTable
|
COFF
符号表的文件偏移。Microsoft的PECOFF规范5.4节描述
了COFF符号表。COFF符号表在PE文件中非常少见,因为新的
调试符号格式已经取代了它。在Visual Studio .NET之前,可
以使用/DEBUGTYPE:COFF这个链接器选项来指定创建COFF符号
表。它总是存在于OBJ文件中。如果不存在符号表的话,将它
设置为0。
|
DWORD
|
NumberOfSymbols
|
符号表中的符号数(如果存在的话)。COFF符号是一个大小固
定的结构,这个域用来定位COFF符号表的结尾。紧跟着COFF
符号表的是一个字符串表,它用来保存长符号名。
|
WORD
|
SizeOfOptionalHeader
|
IMAGE_FILE_HEADER
结构后面的可选数据的大小。在PE文件中,
这个可选数据就是IMAGE_OPTIONAL_HEADER。这个大小在32位
和64位文件中是不同的。对于32位PE文件来说,它通常是224;
对于64位PE32+文件来说,它通常是240。但是,它们只是最
小值,可能有更大的值。
|
WORD
|
Characteristics
|
指示文件属性的一组位标志。这些标志的合法值就是WINNT.H
文件中定义的IMAGE_FILE_xxx值。一些常见的值列于下表。
|
标志
|
描述
|
IMAGE_FILE_RELOCS_STRIPPED
|
重定位信息已经从文件中移除。
|
IMAGE_FILE_EXECUTABLE_IMAGE
|
文件是可执行映像。
|
IMAGE_FILE_AGGRESSIVE_WS_TRIM
|
让操作系统尽量减小工作集(working set)。
|
IMAGE_FILE_LARGE_ADDRESS_AWARE
|
此应用程序可以处理大于2GB的地址。
|
IMAGE_FILE_32BIT_MACHINE
|
需要字长为32位的机器。
|
IMAGE_FILE_DEBUG_STRIPPED
|
调试信息已经被移到.DBG文件中。
|
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP
|
如果可执行映像在可移动媒体上,把它复制到交换文件中并从交换文件中运行。
|
IMAGE_FILE_NET_RUN_FROM_SWAP
|
如果可执行映像在网络上,把它复制到交换文件中并从交换文件中运行。
|
IMAGE_FILE_DLL
|
文件是DLL。
|
IMAGE_FILE_UP_SYSTEM_ONLY
|
只能运行于单处理器机器上。
|
大小
|
域
|
描述
|
WORD
|
Magic
|
一个特征字,用于表明文件头的类型。两个常用的值为: IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b |
BYTE
|
MajorLinkerVersion
|
用于创建这个可执行文件的链接器的主版本号。对于由Microsoft链接器生成的可执行文件来说,这个版本号对应于Visual Studio的版本号(例如Visual Studio 6.0就是版本6)。
|
BYTE
|
MinorLinkerVersion
|
用于创建这个可执行文件的链接器的次版本号
|
DWORD
|
SizeOfCode
|
带有IMAGE_SCN_CNT_CODE 属性的所有节的总大小。
|
DWORD
|
SizeOfInitializedData
|
所有由已初始化的数据组成的节的总大小。
|
DWORD
|
SizeOfUninitializedData
|
所有由未初始化的数据组成的节的总大小。它通常是0,因为链接器经常把未初始化的数据添加到正常的数据节的末尾。
|
DWORD
|
AddressOfEntryPoint
|
文件中首先被执行的代码的第一个字节的RVA。对于DLL来说,入口点在进程初始化和退出期间,以及线程创建和退出期间都会被调用。在大多数可执行文件中,这个地址并不是直接指向main、WinMain或者DllMain,而是指向调用上述函数的运行时库代码。对于DLL来说,这个域可以设为0,这样它就接收不到前面说的四个通知。/NOENTRY链接器选项可以将这个域设置为0
|
DWORD
|
BaseOfCode
|
加载进内存之后代码的第一个字节的RVA。
|
DWORD
|
BaseOfData
|
理论上这是加载进内存之后数据的第一个字节的RVA。但是这个域的值在不同版本的Microsoft链接器间是不一致的。64位可执行文件中并不存在这个域。
|
DWORD
|
ImageBase
|
这个文件在内存中的首选加载地址。如果有可能的话(也就是说这个内存当前并未被占用,并且它是对齐的,同时是一个合法的地址等等),加载器尽量把PE文件加载到这个地址。如果可执行文件被加载到这个地址,加载器就可以跳过基址重定位(将在本文的第二部分中描述)。对于EXE来说,默认的ImageBase为0x400000;对于DLL来说,它是0x10000000。可以在链接时使用/BASE选项或者以后使用REBASE工具来设定此值。
|
DWORD
|
SectionAlignment
|
加载进内存之后节的对齐值。这个对齐值必须大于或等于文件对齐值(下面将要讲到)。默认的对齐值是目标平台的页面大小。对于运行于Windows 9x或Windows Me上的用户模式的可执行文件来说,最小的对齐值是一个页面(4KB)。这个域的值可以使用/ALIGN链接器选项来设定。
|
DWORD
|
FileAlignment
|
节在PE文件中的对齐值。对于x86可执行文件来说,它或者是0x200,或者是0x1000。不同版本的Microsoft链接器的默认值不一样。这个值必须是2的幂,并且如果SectionAlignment域的值小于CPU的页面大小,这个值必须与SectionAlignment域的值匹配。链接器选项/OPT:WIN98将x86平台上的可执行文件的对齐值设为0x1000,而/OPT:NOWIN98选项将它设为0x200。
|
WORD
|
MajorOperatingSystemVersion
|
所需的操作系统的主版本号。随着众多版本Windows的到来,这个域已失去了它最初的意义。
|
WORD
|
MinorOperatingSystemVersion
|
所需的操作系统的次版本号。
|
WORD
|
MajorImageVersion
|
此文件的主版本号。系统并未使用这个域,可以设置为0。使用/VERSION链接器选项可以设定这个域的值。
|
WORD
|
MinorImageVersion
|
此文件的次版本号。
|
WORD
|
MajorSubsystemVersion
|
可执行文件所需的子系统的主版本号。以前相对于旧版本的Windows NT界面来说,用它来指明需要新的Windows 95或Windows NT 4.0用户界面。现在由于Windows版本繁多,这个域已经不使用了,通常被设为4。使用链接器选项/SUBSYSTEM可以设置这个域的值。
|
WORD
|
MinorSubsystemVersion
|
可执行文件所需的子系统的次版本号。
|
DWORD
|
Win32VersionValue
|
一个从来不用的域,通常设为0。
|
DWORD
|
SizeOfImage
|
SizeOfImage
包含了假设存在于最后一个节之后的那个节的RVA。这等效于把此文件加载进内存时系统需要保留的内存数量。这个域的值必须是节的对齐值的倍数。
|
DWORD
|
SizeOfHeaders
|
MS-DOS
文件头、PE文件头和节表的总大小。在PE文件中,这些内容出现于任何代码或数据节之前。这个域的值被向上舍入到文件对齐值的倍数。
|
DWORD
|
CheckSum
|
映像的校验和。IMAGEHLP.DLL中的CheckSumMappedFile API可以计算这个值。对于内核模式的驱动程序和一些系统DLL来说,校验和是必须的。否则这个域被设置为0。当使用/RELEASE链接器选项时,校验和会被放在文件中。
|
WORD
|
Subsystem
|
指示可执行文件所需子系统(用户界面类型)的一个枚举值。在EXE文件中这个值比较重要。一些重要的值如下:
IMAGE_SUBSYSTEM_NATIVE
//
不需要子系统
IMAGE_SUBSYSTEM_WINDOWS_GUI
//
使用Windows GUI
IMAGE_SUBSYSTEM_WINDOWS_CUI
//
控制台应用程序。当它运行时,操作系统为其创一
//
个控制台并提供stdin、stdout和stderr文件句柄。
|
WORD
|
DllCharacteristics
|
指示DLL特征的标志。这些值对应于WINNT.H文件中的IMAGE_DLLCHARACTERISTICS_xxx定义。当前值如下:
IMAGE_DLLCHARACTERISTICS_NO_BIND
// 不绑定映像
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER
// 使用WDM模型的驱动程序
IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE // 当终端服务器加载一个并没有准备运行于终端服务 // 器上的应用程序时,它同时加载包含兼容代码的DLL |
DWORD
|
SizeOfStackReserve
|
在EXE文件中,它表示进程中的线程堆栈最初可以增长到的最大值。默认是1MB。并不是初始化时就提交这里指定的所有内存。
|
DWORD
|
SizeOfStackCommit
|
在EXE文件中,它表示初始化时提交的堆栈的大小。默认是4KB。
|
DWORD
|
SizeOfHeapReserve
|
在EXE文件中,它表示最初为默认进程堆保留的内存数量。默认是1MB。然而对于当前版本的Windows,在没有用户干预的情况下,堆可以超过这个值。
|
DWORD
|
SizeOfHeapCommit
|
在EXE文件中,它表示提交的堆的大小。默认是4KB。
|
DWORD
|
LoaderFlags
|
此域已经废弃不用。
|
DWORD
|
NumberOfRvaAndSizes
|
在IMAGE_NT_HEADERS结构末尾处是一个IMAGE_DATA_DIRECTORY结构数组。这个域包含了这个数组的元素数目。由于以前发行的Windows NT的原因,它被设置为16。
|
IMAGE_ DATA_ DIRECTORY |
DataDirectory[16]
|
IMAGE_DATA_DIRECTORY
结构数组。每个结构包含可执行文件中一些重要部分(例如导入表、导出表以及资源等)的RVA和大小。
|
大小
|
域
|
描述
|
BYTE
|
Name[8]
|
节的名称(ASCII码)。节名并不保证以NULL结尾。如果你指定的节名大于8个字节,链接器在生成可执行文件时将其截断为8个字符。在OBJ文件中存在一种机制可以让节名更长。节名通常以圆点开始,但这并不是必需的。对于带有$字符的节名链接器会特殊对待。如果几个节名中$字符以前的部分相同,那么这些节会被合并。它们按$字符后面的部分在字母表中的顺序出现于最终的节中。关于节名中带有$字符的节和它们如何被合并方面还有很多内容,但对它的详细讨论已经超出了本文的范围。
|
DWORD
|
VirtualSize
|
指示节实际占用的内存大小。这个域的值可能比SizeOfRawData域的值大或小。如果大,SizeOfRawData域表示可执行文件中已初始化的数据的大小,VirtualSize域比它大的部分用0填充。在OBJ文件中,此域的值为0。
|
DWORD
|
VirtualAddress
|
在可执行文件中,它表示在内存中节的起始RVA。在OBJ文件中它被设置为0。
|
DWORD
|
SizeOfRawData
|
可执行文件或OBJ文件中的节中存储的数据的大小(以字节计)。对于可执行文件来说,它必须是PE文件头中给出的文件对齐值的倍数。如果它被设置为0,表示这个节中是未初始化的数据。
|
DWORD
|
PointerToRawData
|
节中数据起始的文件偏移。对于可执行文件来说,它必须是PE文件头中给出的文件对齐值的倍数。
|
DWORD
|
PointerToRelocations
|
节的重定位信息的文件偏移。它只用于OBJ文件,在可执行文件中它被设置为0。在OBJ文件中,如果它不为0,那么它指向一个IMAGE_RELOCATION结构。
|
DWORD
|
PointerToLinenumbers
|
节中COFF行号信息的文件偏移。如果它不为0,那么它指向一个IMAGE_LINENUMBER结构。
|
WORD
|
NumberOfRelocations
|
PointerToRelocations
域指向的重定位信息的数目。在可执行文件中应该为0。
|
WORD
|
NumberOfLinenumbers
|
PointerToLinenumbers
域指向的行号信息的数目。只有当生成COFF行号信息时才使用。
|
DWORD
|
Characteristics
|
指示节属性的标志(可以用“或”连接)。这些标志中的大部分可以使用链接器的/SECTION选项来设置。常用的值列于下表。
|
标志
|
描述
|
IMAGE_SCN_CNT_CODE
|
节中包含代码。
|
IMAGE_SCN_MEM_EXECUTE
|
节是可执行的。
|
IMAGE_SCN_CNT_INITIALIZED_DATA
|
节中包含已初始化的数据。
|
IMAGE_SCN_CNT_UNINITIALIZED_DATA
|
节中包含未初始化的数据。
|
IMAGE_SCN_MEM_DISCARDABLE
|
这个节在最终的可执行文件中可以被丢弃。用于保存链接器使用的信息,包括.debug$节。
|
IMAGE_SCN_MEM_NOT_PAGED
|
这个节不能被交换到页面文件中,因此它应该总是存在于物理内存中。经常用于内核模式驱动程序。
|
IMAGE_SCN_MEM_SHARED
|
包含这个节的物理页面将在加载这个可执行文件的所有进程之间共享。因此每个进程看到的这个节中的数据的值完全一样。对于在进程的所有实例之间共享全局变量比较有用。要共享某个节,使用/SECTION:节名,S链接器选项。
|
IMAGE_SCN_MEM_READ
|
节是可读的。几乎总是设置这个值。
|
IMAGE_SCN_MEM_WRITE
|
节是可写的。
|
IMAGE_SCN_LNK_INFO
|
节中包含链接器使用的信息。仅存在于OBJ文件中。
|
IMAGE_SCN_LNK_REMOVE
|
这个节中的内容将不成为最终的映像的一部分。仅用于OBJ文件。
|
IMAGE_SCN_LNK_COMDAT
|
节中的内容是公共数据(comdat)。公共数据(Communal data)是可以被定义在多个OBJ文件中的数据(或代码)。链接器只将其中的一份副本包含进最终的可执行文件中。Comdats对于支持C++的模板函数和函数级的链接至关重要。它仅存在于OBJ文件中。
|
IMAGE_SCN_ALIGN_xBYTES
|
这个节中的数据在最终的可执行文件中的对齐值。有各种各样的值(_4BYTES,_8BYTES,_16BYTES等)。如果不指定,默认为16字节。仅在OBJ文件中才设置这些标志。
|