Microsoft可移植可執行文件和通用目標文件格式文件規範

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
本規範最後列出了參考信息和相關資源。
本規範的最新版在萬維網的如下地址被維護:
http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
 
 
 
 
SmartTech譯
電子信箱:zhzhtst@163.com
 
法律聲明

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.7節,並將附錄A移到了「 Windows Authenticode 可移植可執行簽名格式」中
5/18/2006
建立
 

目錄
 
1基本概念
本文檔詳細說明了Microsoft® Windows®操做系統家族下的可執行文件(映像)和目標文件的結構。這些文件分別被稱爲可移植可執行(PE)文件和通用目標文件格式(COFF)文件。「可移植可執行」這個名稱道出了這種格式與平臺體系結構無關的事實。
下表描述了貫穿於本規範中的一些概念:
名稱
描述
屬性證書
用來將可校驗的聲明與映像關聯起來的證書。有許多不一樣的可校驗聲明能夠與文件關聯,最經常使用的一種就是軟件製造商用來指明映像的消息摘要是什麼的聲明。消息摘要與校驗和相似,但想要僞造它卻極其困難。所以對一個文件進行修改並保持它的消息摘要與原始文件一致是很是困難的。正如製造商所作的那樣,可使用公鑰或私鑰加密機制來校驗聲明。本文檔除了描述容許將它們插入到映像文件中外還描述了有關屬性證書的詳細信息。
日期/時間戳
因爲不一樣目的而用於PE或COFF文件中好幾個地方的戳。戳的格式與C運行時庫時間函數所使用的戳的格式相同。
文件指針
某項內容在文件被連接器處理前(若是是目標文件文件)或者被加載器處理前(若是是映像文件)在文件自身中的位置。換句話說,這是一個位於存儲在磁盤上的文件中的位置。
連接器
指的是隨 Microsoft Visual Studio® 提供的連接器。
映像文件
可執行文件:或者是.EXE文件,或者是DLL。映像文件能夠被認爲是「內存映像」。術語「映像文件」常常用來代替「可執行文件」,由於後者有時僅用來指代.EXE文件。
目標文件
做爲連接器的輸入的文件。連接器生成一個映像文件,而這個映像文件又做爲加載器的輸入。
保留,必須爲0
對一個域的這種描述代表,對於生成這個域的程序來講必須將這個域設置爲0,對於使用這個域的程序來講必須忽略它的值。
RVA
相對虛擬地址。對於映像文件來講,它是某項內容被加載進內存後的地址減去映像文件的基地址。某項內容的RVA幾乎老是與它在磁盤上的文件中的位置(文件指針)不一樣。
對於目標文件來講,RVA並無什麼意義,由於內存位置還沒有分配。在這種狀況下,RVA是一個節(後面將要描述)中的地址,這個地址在之後連接時要被重定位。爲了簡單起見,編譯器應該將每一個節的首個RVA設置爲0。
節是PE或COFF文件中代碼或數據的基本單元。例如一個目標文件中全部代碼能夠被組合成單個節,或者(依賴於編譯器的行爲)每一個函數獨佔一個節。增長節的數目會增長文件開銷,可是連接器在連接代碼時有更大的選擇餘地。節與Intel 8086體系結構中的段很是類似。一個節中的全部原始數據必須被加載到連續的內存中。另外,映像文件可能包含一些具備特殊用途的節,例如.tls節或.reloc節。
VA
虛擬地址。除了不減去映像文件的基地址外,與RVA相同。這個地址之因此被叫作「虛擬地址」是由於Windows爲每一個進程建立一個私有的虛擬地址空間,它獨立於物理內存。不管出於何種目的,VA都只應該被認爲是一個地址。VA並不能像RVA那樣可以預先獲得,由於加載器可能不把映像加載到它的首選位置上。
2概覽
 
1 解釋了Microsoft PE可執行文件格式:
MS-DOS 2.0 兼容
EXE 文件頭
 
映像頭基地址
未使用
 
 
OEM 標識
OEM 信息
 
PE文件頭偏移
 
 
 
MS‑DOS 2.0
(僅用於MS­‑DOS兼容)
MS‑DOS 2.0 佔位程序
 
重定位表
 
 
未使用
 
 
PE 文件頭
(按8字節邊界對齊)
 
 
 
節頭
 
 
 
 
 
映像頁:
導入信息
導出信息
基址重定位信息
資源信息
 
 
 
圖 1.典型的可移植EXE文件佈局
 
2 解釋了Microsoft COFF目標模塊格式:
Microsoft COFF文件頭
 
 
 
 
節頭
 
 
 
 
 
原始數據:
代碼
數據
調試信息
重定位信息
 
 
 
圖 2. 典型的COFF目標模塊佈局
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格式的映像文件。這個簽名是「PE/0/0」(字母「P」和「E」後跟着兩個空字節)。
3.3 COFF文件頭(適用於目標文件和映像文件)
在目標文件的開頭,或者緊跟着映像文件簽名以後,是一個以下格式的標準COFF文件頭。注意Windows加載器限制節的最大數目爲96。
偏移
大小
描述
0
2
Machine
標識目標機器類型的數字。要獲取更多信息,請參考3.3.1節「機器類型」。
2
2
NumberOfSections
節的數目。它給出了節表的大小,而節表緊跟着文件頭。
4
4
TimeDateStamp
從UTC時間1970年1月1日00:00起的總秒數(一個C運行時time_t類型的值)的低32位,它指出文件什麼時候被建立。
8
4
PointerToSymbolTable
COFF 符號表的文件偏移。若是不存在COFF符號表,此值爲0。對於映像文件來講,此值應該爲0,由於已經不同意使用COFF調試信息了。
12
4
NumberOfSymbols
符號表中的元素數目。因爲字符串表緊跟符號表,因此能夠利用這個值來定位字符串表。對於映像文件來講,此值應該爲0,由於已經不同意使用COFF調試信息了。
16
2
SizeOfOptionalHeader
可選文件頭的大小。可執行文件須要可選文件頭而目標文件並不須要。對於目標文件來講,此值應該爲0。要獲取可選文件頭格式的詳細描述,請參考3.4節「可選文件頭(僅適用於映像文件)」。
18
2
Characteristics
指示文件屬性的標誌。對於特定的標誌,請參考3.3.2節「特徵」。
3.3.1機器類型
Machine 域能夠取如下各值中的一個來指定CPU類型。 映像文件僅能運行於指定處理器或者可以模擬指定處理器的系統上。
常量
描述
IMAGE_FILE_MACHINE_UNKNOWN
0x0
適用於任何類型處理器
IMAGE_FILE_MACHINE_AM33
0x1d3
Matsushita AM33 處理器
IMAGE_FILE_MACHINE_AMD64
0x8664
x64 處理器
IMAGE_FILE_MACHINE_ARM
0x1c0
ARM 小尾處理器
IMAGE_FILE_MACHINE_EBC
0xebc
EFI 字節碼處理器
IMAGE_FILE_MACHINE_I386
0x14c
Intel 386 或後繼處理器及其兼容處理器
IMAGE_FILE_MACHINE_IA64
0x200
Intel Itanium 處理器家族
IMAGE_FILE_MACHINE_M32R
0x9041
Mitsubishi M32R 小尾處理器
IMAGE_FILE_MACHINE_MIPS16
0x266
MIPS16 處理器
IMAGE_FILE_MACHINE_MIPSFPU
0x366
FPU 的MIPS處理器
IMAGE_FILE_MACHINE_MIPSFPU16
0x466
FPU 的MIPS16處理器
IMAGE_FILE_MACHINE_POWERPC
0x1f0
PowerPC 小尾處理器
IMAGE_FILE_MACHINE_POWERPCFP
0x1f1
帶符點運算支持的 PowerPC 處理器
IMAGE_FILE_MACHINE_R4000
0x166
MIPS 小尾處理器
IMAGE_FILE_MACHINE_SH3
0x1a2
Hitachi SH3 處理器
IMAGE_FILE_MACHINE_SH3DSP
0x1a3
Hitachi SH3 DSP 處理器
IMAGE_FILE_MACHINE_SH4
0x1a6
Hitachi SH4 處理器
IMAGE_FILE_MACHINE_SH5
0x1a8
Hitachi SH5 處理器
IMAGE_FILE_MACHINE_THUMB
0x1c2
Thumb 處理器
IMAGE_FILE_MACHINE_WCEMIPSV2
0x169
MIPS 小尾 WCE v2 處理器
3.3.2特徵
Characteristics 域包含指示目標文件或映像文件屬性的標誌。當前定義瞭如下值:
標誌
描述
IMAGE_FILE_RELOCS_STRIPPED
0x0001
僅適用於映像文件,適用於 Windows CE Microsoft Windows NT® 及其後繼操做系統。它代表此文件不包含基址重定位信息,所以必須被加載到其首選基地址上。若是基地址不可用,加載器會報錯。連接器默認會移除可執行(EXE)文件中的重定位信息。
IMAGE_FILE_EXECUTABLE_IMAGE
0x0002
僅適用於映像文件。它代表此映像文件是合法的,能夠被運行。若是未設置此標誌,代表出現了連接器錯誤。
IMAGE_FILE_LINE_NUMS_STRIPPED
0x0004
COFF 行號信息已經被移除。不同意使用此標誌,它應該爲0。
IMAGE_FILE_LOCAL_SYMS_STRIPPED
0x0008
COFF 符號表中有關局部符號的項已經被移除。不同意使用此標誌,它應該爲0。
IMAGE_FILE_AGGRESSIVE_WS_TRIM
0x0010
此標誌已經被捨棄。它用於調整工做集。Windows 2000及其後繼操做系統不同意使用此標誌,它應該爲0。
IMAGE_FILE_LARGE_ADDRESS_AWARE
0x0020
應用程序能夠處理大於2GB的地址。
 
0x0040
此標誌保留供未來使用。
IMAGE_FILE_BYTES_REVERSED_LO
0x0080
小尾:在內存中,最不重要位(LSB)在最重要位(MSB)前面。不同意使用此標誌,它應該爲0。
IMAGE_FILE_32BIT_MACHINE
0x0100
機器類型基於32位字體系結構。
IMAGE_FILE_DEBUG_STRIPPED
0x0200
調試信息已經今後映像文件中移除。
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP
0x0400
若是此映像文件在可移動介質上,徹底加載它並把它複製到交換文件中。
IMAGE_FILE_NET_RUN_FROM_SWAP
0x0800
若是此映像文件在網絡介質上,徹底加載它並把它複製到交換文件中。
IMAGE_FILE_SYSTEM
0x1000
此映像文件是系統文件,而不是用戶程序。
IMAGE_FILE_DLL
0x2000
此映像文件是動態連接庫(DLL)。這樣的文件總被認爲是可執行文件,儘管它們並不能直接被運行。
IMAGE_FILE_UP_SYSTEM_ONLY
0x4000
此文件只能運行於單處理器機器上。
IMAGE_FILE_BYTES_REVERSED_HI
0x8000
大尾:在內存中,MSB在LSB前面。不同意使用此標誌,它應該爲0。
3.4可選文件頭(僅適用於映像文件)
每一個映像文件都有一個可選文件頭,用於爲加載器提供信息。這個文件頭之因此說是可選的是從一些文件(明確地說是目標文件)並不包含它這層意義上來講的。對於映像文件來講,這個文件頭是必須的。目標文件能夠包含一個可選文件頭,可是一般它除了增長文件的大小外並沒有其它做用。
注意可選文件頭的大小並不固定。COFF文件頭中的SizeOfOptionalHeader域用來驗證某個特別的數據目錄不超過SizeOfOptionalHeader。要獲取更多信息,請參考3.3節「COFF文件頭(適用於目標文件和映像文件)」
可選文件頭中的NumberOfRvaAndSizes域也應該被用來確保某個特別的數據目錄不超出可選文件頭。另外出于格式兼容目的而去校驗可選文件頭中的幻數也很重要。
可選文件頭中的幻數決定一個映像是PE32仍是PE32+格式的可執行文件:
幻數
PE 格式
0x10b
PE32
0x20b
PE32+
 
PE32+ 映像在限制映像大小最大爲2G時能夠訪問64位地址空間。PE32+的其它更改在它們各自的節中描述。
可選文件頭自身由三個主要部分組成:
偏移( PE32/PE32+
大小 PE32/PE32+
文件頭部分
描述
0
28/24
標準域
這些域被全部COFF實現所定義,其中包括UNIX。
28/24
68/88
Windows 特定域
支持Windows特性(例如子系統)的附加域。
96/112
Variable
數據目錄
映像文件中的特殊表(例如導入表和導出表)的地址/大小組合,它們供操做系統使用。
3.4.1可選文件頭中的標準域(僅適用於映像文件)
可選文件頭的前8個域爲標準域,它們被全部COFF實現所定義。這些域包含對加載和運行可執行文件有用的常規信息。它們在PE32+中並未改變。
偏移
大小
描述
0
2
Magic
這個無符號整數指出了映像文件的狀態。最經常使用的數字是0x10B,它代表這是一個正常的可執行文件。0x107代表這是一個ROM映像,0x20B代表這是一個PE32+可執行文件。
2
1
MajorLinkerVersion
連接器的主版本號。
3
1
MinorLinkerVersion
連接器的次版本號。
4
4
SizeOfCode
代碼節(.text)的大小。若是有多個代碼節的話,它是全部代碼節的和。
8
4
SizeOfInitializedData
已初始化數據節的大小。若是有多個這樣的數據節的話,它是全部這些數據節的和。
12
4
SizeOfUninitializedData
未初始化數據節(.bss)的大小。若是有多個.bss節的話,它是全部這些節的和。
16
4
AddressOfEntryPoint
當可執行文件被加載進內存時其入口點相對於映像基址的偏移地址。對於通常程序映像來講,它就是啓動地址。對於設備驅動程序來講,它是初始化函數的地址。入口點對於DLL來講是可選的。若是不存在入口點的話,這個域必須爲0。
20
4
BaseOfCode
當映像被加載進內存時代碼節的開頭相對於映像基址的偏移地址。
 
PE32 中在 BaseOfCode 域後面是下面這個附加域,它並不存在於PE32+中:
偏移
大小
描述
24
4
BaseOfData
當映像被加載進內存時數據節的開頭相對於映像基址的偏移地址。
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 9五、Windows 98和 Windows Me 默認是0x00400000。
32/32
4
SectionAlignment
當加載進內存時節的對齊值(以字節計)。它必須大於或等於 FileAlignment 。默認是相應系統的頁面大小。
36/36
4
FileAlignment
用來對齊映像文件的節中的原始數據的對齊因子(以字節計)。它應該是界於512和64K之間的2的冪(包括這兩個邊界值)。默認是512。若是SectionAlignment小於相應系統的頁面大小,那麼FileAlignment必須與SectionAlignment匹配。
40/40
2
MajorOperatingSystemVersion
所需操做系統的主版本號。
42/42
2
MinorOperatingSystemVersion
所需操做系統的次版本號。
44/44
2
MajorImageVersion
映像的主版本號。
46/46
2
MinorImageVersion
映像的次版本號。
48/48
2
MajorSubsystemVersion
子系統的主版本號。
50/50
2
MinorSubsystemVersion
子系統的次版本號。
52/52
4
Win32VersionValue
保留,必須爲0。
56/56
4
SizeOfImage
當映像被加載進內存時的大小(以字節計),包括全部的文件頭。它必須是 SectionAlignment 的倍數。
60/60
4
SizeOfHeaders
MS‑DOS 佔位程序、PE文件頭和節頭的總大小,向上舍入爲 FileAlignment 的倍數。
64/64
4
CheckSum
映像文件的校驗和。計算校驗和的算法被合併到了IMAGEHLP.DLL 中。如下程序在加載時被校驗以肯定其是否合法:全部的驅動程序、任何在引導時被加載的DLL以及加載進關鍵Windows進程中的DLL。
68/68
2
Subsystem
運行此映像所需的子系統。要獲取更多信息,請參考後面的「Windows子系統」部分。
70/70
2
DllCharacteristics
要獲取更多信息,請參考後面的「DLL特徵」部分。
72/72
4/8
SizeOfStackReserve
保留的堆棧大小。只有 SizeOfStackCommit 指定的部分被提交;其他的每次可用一頁,直到到達保留的大小爲止。
76/80
4/8
SizeOfStackCommit
提交的堆棧大小。
80/88
4/8
SizeOfHeapReserve
保留的局部堆空間大小。只有 SizeOfHeapCommit 指定的部分被提交;其他的每次可用一頁,直到到達保留的大小爲止。
84/96
4/8
SizeOfHeapCommit
提交的局部堆空間大小。
88/104
4
LoaderFlags
保留,必須爲0。
92/108
4
NumberOfRvaAndSizes
可選文件頭其他部分中數據目錄項的個數。每一個數據目錄描述了一個表的位置和大小。
Windows子系統
爲可選文件頭的 Subsystem 域定義瞭如下值以肯定運行映像所需的Windows子系統(若是存在):
常量
描述
IMAGE_SUBSYSTEM_UNKNOWN
0
未知子系統
IMAGE_SUBSYSTEM_NATIVE
1
設備驅動程序和N ative Windows 進程
IMAGE_SUBSYSTEM_WINDOWS_GUI
2
Windows 圖形用戶界面( GUI )子系統
IMAGE_SUBSYSTEM_WINDOWS_CUI
3
Windows 字符模式(CUI)子系統
IMAGE_SUBSYSTEM_POSIX_CUI
7
Posix 字符模式子系統
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI
9
Windows CE
IMAGE_SUBSYSTEM_EFI_APPLICATION
10
可擴展固件接口(EFI)應用程序
IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
11
帶引導服務的 EFI 驅動程序
IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
12
帶運行時服務的 EFI 驅動程序
IMAGE_SUBSYSTEM_EFI_ROM
13
EFI ROM 映像
IMAGE_SUBSYSTEM_XBOX
14
XBOX
DLL特徵
爲可選文件頭的 DllCharacteristics 域定義瞭如下值:
常量
描述
 
0x0001
保留,必須爲0。
 
0x0002
保留,必須爲0。
 
0x0004
保留,必須爲0。
 
0x0008
保留,必須爲0。
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
0x0040
DLL 能夠在加載時被重定位。
IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY
0x0080
強制進行代碼完整性校驗。
IMAGE_DLLCHARACTERISTICS_NX_COMPAT
0x0100
映像兼容於 NX
IMAGE_DLLCHARACTERISTICS_NO_ISOLATION
0x0200
能夠隔離,但並不隔離此映像。
IMAGE_DLLCHARACTERISTICS_NO_SEH
0x0400
不使用結構化異常(SE)處理。在此映像中不能調用SE處理程序。
IMAGE_DLLCHARACTERISTICS_NO_BIND
0x0800
不綁定映像。
 
0x1000
保留,必須爲0。
IMAGE_DLLCHARACTERISTICS_WDM_DRIVER
0x2000
WDM 驅動程序。
IMAGE_DLLCHARACTERISTICS_
TERMINAL_SERVER_AWARE
0x8000
能夠用於終端服務器。
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
8
Export Table
導出表的地址和大小。要獲取更多信息,請參考6.3節「.edata節(僅適用於映像文件)」。
104/120
8
Import Table
導入表的地址和大小。要獲取更多信息,請參考6.4節「.idata節」。
112/128
8
Resource Table
資源表的地址和大小。要獲取更多信息,請參考6.9節「.rsrc節」。
120/136
8
Exception Table
異常表的地址和大小。要獲取更多信息,請參考6.5節「.pdata節」。
128/144
8
Certificate Table
屬性證書表的地址和大小。要獲取更多信息,請參考5.7節「屬性證書表(僅適用於映像文件)」
136/152
8
Base Relocation Table
基址重定位表的地址和大小。要獲取更多信息,請參考6.6節「.reloc節(僅適用於映像文件)」。
144/160
8
Debug
調試數據起始地址和大小。要獲取更多信息,請參考6.1節「.debug節」。
152/168
8
Architecture
保留,必須爲0。
160/176
8
Global Ptr
將被存儲在全局指針寄存器中的一個值的RVA。這個結構的Size域必須爲0。
168/184
8
TLS Table
線程局部存儲(TLS)表的地址和大小。要獲取更多信息,請參考6.7節「.tls節」。
176/192
8
Load Config Table
加載配置表的地址和大小。要獲取更多信息,請參考6.8節「加載配置結構(僅適用於映像文件)」。
184/200
8
Bound Import
綁定導入表的地址和大小。
192/208
8
IAT
導入地址表的地址和大小。要獲取更多信息,請參考6.4.4節「導入地址表」。
200/216
8
Delay Import Descriptor
延遲導入描述符的地址和大小。要獲取更多信息,請參考5.8節「延遲加載導入表(僅適用於映像文件)」。
208/224
8
CLR Runtime Header
CLR 運行時頭部的地址和大小。要獲取更多信息,請參考6.10節「.cormeta節(僅適用於目標文件)」
216/232
8
保留,必須爲0。
 
Certificate Table 域指向屬性證書表。這些證書並不做爲映像的一部分被加載進內存。此時它的第一個域是一個文件指針,而不是一般的RVA。
4節表(節頭)
節表的每一行等效於一個節頭。這個表緊跟可選文件頭(若是存在的話)。之因此必須在這個位置是由於文件頭中並無一個直接指向節表的指針,節表的位置是經過計算文件頭後的第一個字節的位置來獲得的。必定要確保使用文件頭中指定的可選文件頭的大小(來進行計算)。
節表中的元素數目由文件頭中的NumberOfSections域給出。而元素的編號是從1開始的。表示代碼節和數據節的元素的順序由連接器決定。
在映像文件中,每一個節的VA值必須由連接器決定。這樣可以保證這些節位置相鄰且按升序排列,而且這些VA值必須是可選文件頭中SectionAlignment域的倍數。
每一個節頭(節表項)格式以下,共40個字節:
偏移
大小
描述
0
8
Name
這是一個8字節的UTF-8編碼的字符串,不足8字節時用NULL填充。若是它正好是8字節,那就沒有最後的NULL字符。若是名稱更長的話,這個域中是一個斜槓(/)後跟一個用ASCII碼錶示的十進制數,這個十進制數表示字符串表中的偏移。可執行映像不使用字符串表也不支持長度超過8字節的節名。若是目標文件中有長節名的節最後要出如今可執行文件中,那麼相應的長節名會被截斷。
8
4
VirtualSize
當加載進內存時這個節的總大小。若是此值比SizeOfRawData大,那麼多出的部分用0填充。這個域僅對可執行映像是合法的,對於目標文件來講,它應該爲0。
12
4
VirtualAddress
對於可執行映像來講,這個域的值是這個節被加載進內存以後它的第一個字節相對於映像基址的偏移地址。對於目標文件來講,這個域的值是沒有重定位以前其第一個字節的地址;爲了簡單起見,編譯器應該把此值設置爲0。不然這個值是個任意值,可是在重定位時應該從偏移地址中減去這個值。
16
4
SizeOfRawData
(對於目標文件來講)節的大小或者(對於映像文件來講)磁盤文件中已初始化數據的大小。對於可執行映像來講,它必須是可選文件頭中FileAlignment域的倍數。若是它小於VirtualSize域的值,餘下的部分用0填充。因爲SizeOfRawData域要向上舍入,可是VirtualSize域並不舍入,所以可能出現SizeOfRawData域大於VirtualSize域的狀況。當節中僅包含未初始化的數據時,這個域應該爲0。
20
4
PointerToRawData
指向COFF文件中節的第一個頁面的文件指針。對於可執行映像來講,它必須是可選文件頭中FileAlignment域的倍數。對於目標文件來講,要得到最好的性能,此值應該按4字節邊界對齊。當節中僅包含未初始化的數據時,這個域應該爲0。
24
4
PointerToRelocations
指向節中重定位項開頭的文件指針。對於可執行文件或者沒有重定位項的文件來講,此值應該爲0。
28
4
PointerToLinenumbers
指向節中行號項開頭的文件指針。若是沒有COFF行號信息的話,此值應該爲0。對於映像來講,此值應該爲0,由於已經不同意使用COFF調試信息了。
32
2
NumberOfRelocations
節中重定位項的個數。對於可執行映像來講,此值應該爲0。
34
2
NumberOfLinenumbers
節中行號項的個數。對於映像來講,此值應該爲0,由於已經不同意使用COFF調試信息了。
36
4
Characteristics
描述節特徵的標誌。要獲取更多信息,請參考4.1節「節標誌」。
4.1節標誌
節頭中的 Characteristics 域中的節標誌指出了節的屬性。
標誌
描述
 
0x00000000
保留供未來使用。
 
0x00000001
保留供未來使用。
 
0x00000002
保留供未來使用。
 
0x00000004
保留供未來使用。
IMAGE_SCN_TYPE_NO_PAD
0x00000008
從這個節結尾到下一個邊界之間不能填充。此標誌被捨棄,它已經被IMAGE_SCN_ALIGN_1BYTES標誌取代。此標誌僅對目標文件合法。
 
0x00000010
保留供未來使用。
IMAGE_SCN_CNT_CODE
0x00000020
此節包含可執行代碼。
IMAGE_SCN_C NT_INITIALIZED_DATA
0x00000040
此節包含已初始化的數據。
IMAGE_SCN_CNT_UNINITIALIZED_DATA
0x00000080
此節包含未初始化的數據。
IMAGE_SCN_LNK_OTHER
0x00000100
保留供未來使用。
IMAGE_SCN_LNK_INFO
0x00000200
此節包含註釋或者其它信息。.drectve 節具備這種屬性。 此標誌僅對目標文件合法。
 
0x00000400
保留供未來使用。
IMAGE_SCN_LNK_REMOVE
0x00000800
此節不會成爲最終造成的映像文件的一部分。此標誌僅對目標文件合法。
IMAGE_SCN_LNK_COMDAT
0x00001000
此節包含COMDAT數據。要獲取更多信息,請參考5.5.6節「COMDAT 節(僅適用於目標文件) 」。此標誌僅對目標文件合法。
IMAGE_SCN_GPREL
0x00008000
此節包含經過全局指針(GP)來引用的數據。
IMAGE_SCN_MEM_PURGEABLE
0x00020000
保留供未來使用。
IMAGE_SCN_MEM_16BIT
0x00020000
保留供未來使用。
IMAGE_SCN_MEM_LOCKED
0x00040000
保留供未來使用。
IMAGE_SCN_MEM_PRELOAD
0x00080000
保留供未來使用。
IMAGE_SCN_ALIGN_1BYTES
0x00100000
按1字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_2BYTES
0x00200000
按2字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_4BYTES
0x00300000
按4字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_8BYTES
0x00400000
按8字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_16BYTES
0x00500000
按16字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_32BYTES
0x00600000
按32字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_64BYTES
0x00700000
按64字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_128BYTES
0x00800000
按128字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_256BYTES
0x00900000
按256字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_512BYTES
0x00A00000
按512字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_1024BYTES
0x00B00000
按1024字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_2048BYTES
0x00C00000
按2048字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_4096BYTES
0x00D00000
按4096字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_ALIGN_8192BYTES
0x00E00000
按8192字節邊界對齊數據。此標誌僅對目標文件合法。
IMAGE_SCN_LNK_NRELOC_OVFL
0x01000000
此節包含擴展的重定位信息。
IMAGE_SCN_MEM_DISCARDABLE
0x02000000
此節能夠在須要時被丟棄。
IMAGE_SCN_MEM_NOT_CACHED
0x04000000
此節不能被緩存。
IMAGE_SCN_MEM_NOT_PAGED
0x08000000
此節不能被交換到頁面文件中。
IMAGE_SCN_MEM_SHARED
0x10000000
此節能夠在內存中共享。
IMAGE_SCN_MEM_EXECUTE
0x20000000
此節能夠做爲代碼執行。
IMAGE_SCN_MEM_READ
0x40000000
此節可讀。
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值的大小順序出如今文件中(節表中單個的節頭也是如此)。
若是可選文件頭的SectionAlignment域的值小於相應平臺的頁面大小,那麼映像文件有一些附加的限制。對於這種文件,當映像被加載到內存中時,節中數據在文件中的位置必須與它在內存中的位置匹配,所以節中數據的物理偏移與RVA相同。
5.2 COFF重定位信息(僅適用於目標文件)
目標文件中包含COFF重定位信息,它用來指出當節中的數據被放進映像文件以及未來被加載進內存時應如何修改這些數據。
映像文件中並不包含COFF重定位信息,這是由於全部被引用的符號都已經被賦予了一個在平坦內存空間中的地址。映像文件中包含的重定位信息是位於.reloc節中的基址重定位信息(除非映像具備IMAGE_FILE_RELOCS_STRIPPED屬性)。要獲取更多信息,請參考6.6節「.reloc節(僅適用於映像文件) 」。
對於目標文件中的每一個節,都有一個由長度固定的記錄組成的數組來保存此節的COFF重定位信息。此數組的位置和長度在節頭中指定。數組的每一個元素格式以下:
偏移
大小
描述
0
4
VirtualAddress
須要進行重定位的代碼或數據的地址。這是從節開頭算起的偏移,加上節的RVA/Offset域的值。請參考4節「節表(節頭)」。例如若是節的第一個字節的地址是0x10,那麼第三個字節的地址就是0x12。
4
4
SymbolTableIndex
符號表的索引(從0開始)。這個符號給出了用於重定位的地址。若是這個指定符號的存儲類別爲節,那麼它的地址就是第一個與它同名的節的地址。
8
2
Type
重定位類型。合法的重定位類型依賴於機器類型。請參考5.2.1節「類型指示符」
 
若是SymbolTableIndex域指定的符號存儲類別爲IMAGE_SYM_CLASS_SECTION,那麼這個符號的地址就是節的地址。這個節一般就在同一個文件中,除非這個目標文件是檔案(庫)文件的一部分。若是是這種狀況的話,那麼這個節可能位於檔案文件中與當前目標文件的檔案文件成員名稱相同的任何其它目標文件中。(與檔案文件成員名稱的聯繫用於連接生成導入表,即.idata 節。
5.2.1類型指示符
重定位記錄的Type域指出了重定位類型。對於每種類型的機器都定義了不一樣的重定位類型。
x64處理器
爲x64及其兼容處理器定義瞭如下重定位類型指示符:
常量
描述
IMAGE_REL_AMD64_ABSOLUTE
0x0000
重定位被忽略。
IMAGE_REL_AMD64_ADDR64
0x0001
重定位目標的64位VA。
IMAGE_REL_AMD64_ADDR32
0x0002
重定位目標的32位VA。
IMAGE_REL_AMD64_ADDR32NB
0x0003
不包含映像基址的32位地址(RVA)。
IMAGE_REL_AMD64_REL32
0x0004
相對於重定位目標的32位地址。
IMAGE_REL_AMD64_REL32_1
0x0005
相對於距重定位目標1字節處的32位地址。
IMAGE_REL_AMD64_REL32_2
0x0006
相對於距重定位目標2字節處的32位地址。
IMAGE_REL_AMD64_REL32_3
0x0007
相對於距重定位目標3字節處的32位地址。
IMAGE_REL_AMD64_REL32_4
0x0008
相對於距重定位目標4字節處的32位地址。
IMAGE_REL_AMD64_REL32_5
0x0009
相對於距重定位目標5字節處的32位地址。
IMAGE_REL_AMD64_SECTION
0x000A
包含重定位目標的節的16位索引。用於支持調試信息。
IMAGE_REL_AMD64_SECREL
0x000B
重定位目標相對於它所在節開頭的32位偏移。用於支持調試信息和 靜態線程局部存儲。
IMAGE_REL_AMD64_SECREL7
0x000C
相對於重定位目標所在節基地址的7位偏移(無符號數)。
IMAGE_REL_AMD64_TOKEN
0x000D
CLR 記號。
IMAGE_REL_AMD64_SREL32
0x000E
放入目標文件中的32位跨度依賴值(符號數)。
IMAGE_REL_AMD64_PAIR
0x000F
與跨度依賴值成對出現,它必須緊跟每個跨度依賴值。
IMAGE_REL_AMD64_SSPAN32
0x0010
連接時應用的32位跨度依賴值(符號數)。
ARM處理器
爲ARM處理器定義瞭如下重定位類型指示符:
常量
描述
IMAGE_REL_ARM_ABSOLUTE
0x0000
重定位被忽略。
IMAGE_REL_ARM_ADDR32
0x0001
重定位目標的32位VA。
IMAGE_REL_ARM_ADDR32NB
0x0002
重定位目標的32位RVA。
IMAGE_REL_ARM_BRANCH24
0x0003
重定位目標的24位相對偏移。
IMAGE_REL_ARM_BRANCH11
0x0004
對子程序調用的引用。這個引用由兩個16位指令與11位偏移組成。
IMAGE_REL_ARM_SECTION
0x000E
包含重定位目標的節的16位索引。用於支持調試信息。
IMAGE_REL_ARM_SECREL
0x000F
重定位目標相對於它所在節開頭的32位偏移。用於支持調試信息和 靜態線程局部存儲。
Hitachi SuperH處理器
爲SH3和SH4處理器定義瞭如下重定位類型指示符。專用於SH5處理器的重定位類型都標有「SHM」字樣,SHM表明SHMedia。
常量
描述
IMAGE_REL_SH3_ABSOLUTE
0x0000
重定位被忽略。
IMAGE_REL_SH3_DIRECT16
0x0001
對包含重定位目標符號VA的16位單元的引用。
IMAGE_REL_SH3_DIRECT32
0x0002
重定位目標符號的32位VA。
IMAGE_REL_SH3_DIRECT8
0x0003
對包含重定位目標符號VA的8位單元的引用。
IMAGE_REL_SH3_DIRECT8_WORD
0x0004
對包含重定位目標符號16位有效VA的8位指令的引用。
IMAGE_REL_SH3_DIRECT8_LONG
0x0005
對包含重定位目標符號32位有效VA的8位指令的引用。
IMAGE_REL_SH3_DIRECT4
0x0006
對其低4位包含重定位目標符號VA的8位單元的引用。
IMAGE_REL_SH3_DIRECT4_WORD
0x0007
對其低4位包含重定位目標符號16位有效VA的8位指令的引用。
IMAGE_REL_SH3_DIRECT4_LONG
0x0008
對其低4位包含重定位目標符號32位有效VA的8位指令的引用。
IMAGE_REL_SH3_PCREL8_WORD
0x0009
對包含重定位目標符號16位有效相對偏移的8位指令的引用。
IMAGE_REL_SH3_PCREL8_LONG
0x000A
對包含重定位目標符號32位有效相對偏移的8位指令的引用。
IMAGE_REL_SH3_PCREL12_WORD
0x000B
對其低12位包含重定位目標符號16位有效相對偏移的16位指令的引用。
IMAGE_REL_SH3_STARTOF_SECTION
0x000C
對包含重定位目標符號所在節VA的32位單元的引用。
IMAGE_REL_SH3_SIZEOF_SECTION
0x000D
對包含重定位目標符號所在節大小的32位單元的引用。
IMAGE_REL_SH3_SECTION
0x000E
包含重定位目標的節的16位索引。用於支持調試信息。
IMAGE_REL_SH3_SECREL
0x000F
重定位目標相對於它所在節開頭的32位偏移。用於支持調試信息和 靜態線程局部存儲。
IMAGE_REL_SH3_DIRECT32_NB
0x0010
重定位目標符號的32位RVA。
IMAGE_REL_SH3_GPREL4_LONG
0x0011
GP 相關。
IMAGE_REL_SH3_TOKEN
0x0012
CLR 記號。
IMAGE_REL_SHM_PCRELPT
0x0013
距當前指令的偏移(長字)。若是沒有設置IMAGE_REL_SHM_NOMODE標誌,那麼將低位取反插入到第32位以選擇PTA指令或PTB指令。
IMAGE_REL_SHM_REFLO
0x0014
32 位地址的低16位。
IMAGE_REL_SHM_REFHALF
0x0015
32 位地址的高16位。
IMAGE_REL_SHM_RELLO
0x0016
相對地址的低16位。
IMAGE_REL_SHM_RELHALF
0x0017
相對地址的高16位。
IMAGE_REL_SHM_PAIR
0x0018
只有緊跟 IMAGE_REL_SHM_ REFHALF IMAGE_REL_SHM_ RELLO IMAGE_REL_SHM_ RELHALF 類型的重定位項時這種重定位類型纔是合法的。此重定位項的SymbolTableIndex域包含的是偏移而不是符號表的索引。
IMAGE_REL_SHM_NOMODE
0x8000
重定位忽略節模式。
IBM PowerPC處理器
爲PowerPC處理器定義瞭如下重定位類型指示符:
常量
描述
IMAGE_REL_PPC_ABSOLUTE
0x0000
重定位被忽略。
IMAGE_REL_PPC_ADDR64
0x0001
重定位目標的64位VA。
IMAGE_REL_PPC_ADDR32
0x0002
重定位目標的32位VA。
IMAGE_REL_PPC_ADDR24
0x0003
重定位目標VA的低24位。只有當重定位目標符號是絕對符號且能夠按符號擴展到它的原始值時纔是合法的。
IMAGE_REL_PPC_ADDR16
0x0004
重定位目標VA的低16位。
IMAGE_REL_PPC_ADDR14
0x0005
重定位目標VA的低14位。只有當重定位目標符號是絕對符號且能夠按符號擴展到它的原始值時纔是合法的。
IMAGE_REL_PPC_REL24
0x0006
符號位置相對於PC的24位偏移。
IMAGE_REL_PPC_REL14
0x0007
符號位置相對於PC的14位偏移。
IMAGE_REL_PPC_ADDR32NB
0x000A
重定位目標的32位RVA。
IMAGE_REL_PPC_SECREL
0x000B
重定位目標相對於它所在節開頭的32位偏移。用於支持調試信息和 靜態線程局部存儲。
IMAGE_REL_PPC_SECTION
0x000C
包含重定位目標的節的16位索引。用於支持調試信息。
IMAGE_REL_PPC_SECREL16
0x000F
重定位目標相對於它所在節開頭的16位偏移。用於支持調試信息和 靜態線程局部存儲。
IMAGE_REL_PPC_REFHI
0x0010
重定位目標32位VA的高16位。它用於加載一個完整地址所需的兩指令序列中的第一條指令。這種重定位類型後面必須緊跟IMAGE_REL_PPC_PAIR類型的重定位項,然後者的SymbolTableIndex域包含的是一個16位偏移(符號數),這個偏移要被加到重定位目標位置的高16位。
IMAGE_REL_PPC_REFLO
0x0011
重定位目標VA的低16位。
IMAGE_REL_PPC_PAIR
0x0012
只有緊跟 IMAGE_REL_PPC_REFHI IMAGE_REL_PPC_SECREL HI 類型的重定位時這種重定位類型纔是合法的。此重定位項的SymbolTableIndex域包含的是偏移而不是符號表的索引。
IMAGE_REL_PPC_SECRELLO
0x0013
重定位目標相對於它所在節開頭的32位偏移的低16位。
IMAGE_REL_PPC_SECREL HI
0x001 4
重定位目標相對於它所在節開頭的32位偏移的高16位。
IMAGE_REL_PPC_GPREL
0x0015
重定位目標相對於GP寄存器的16位偏移(帶符號數)。
IMAGE_REL_PPC_TOKEN
0x0016
CLR 記號。
Intel 386處理器
爲Intel 386及其兼容處理器定義瞭如下重定位類型指示符:
常量
描述
IMAGE_REL_I386_ABSOLUTE
0x0000
重定位被忽略。
IMAGE_REL_I386_DIR16
0x0001
不支持。
IMAGE_REL_I386_REL16
0x0002
不支持。
IMAGE_REL_I386_DIR32
0x0006
重定位目標的32位VA。
IMAGE_REL_I386_DIR32NB
0x0007
重定位目標的32位RVA。
IMAGE_REL_I386_SEG12
0x0009
不支持。
IMAGE_REL_I386_SECTION
0x000A
包含重定位目標的節的16位索引。用於支持調試信息。
IMAGE_REL_I386_SECREL
0x000B
重定位目標相對於它所在節開頭的32位偏移。用於支持調試信息和 靜態線程局部存儲。
IMAGE_REL_I386_TOKEN
0x000C
CLR 記號。
IMAGE_REL_I386_SECREL7
0x000D
相對於重定位目標所在節基地址的7位偏移。
IMAGE_REL_I386_REL32
0x0014
重定位目標的32位相對偏移。用於支持x86的相對分支和CALL指令。
Intel Itanium處理器家族(IPF)
爲Intel Itanium處理器家族及其兼容處理器定義瞭如下重定位類型指示符。注意指令重定位使用它所在的指令包的偏移以及相應的指令槽編號做爲它的偏移:
常量
描述
IMAGE_REL_IA64_ABSOLUTE
0x0000
重定位被忽略。
IMAGE_REL_IA64_IMM14
0x0001
這種指令重定位後面能夠跟着 IMAGE_REL_IA64_ADDEND 類型的重定位項,然後者的值在被插入到IMM14指令包的指定的指令槽中以前被加到目標地址上。這種重定位目標必須是絕對符號,不然這個映像必須被修正。
IMAGE_REL_IA64_IMM22
0x0002
這種指令重定位後面能夠跟着 IMAGE_REL_IA64_ADDEND 類型的重定位項,然後者的值在被插入到IMM22指令包的指定的指令槽中以前被加到目標地址上。這種重定位目標必須是絕對符號,不然這個映像必須被修正。
IMAGE_REL_IA64_IMM64
0x0003
這種重定位項的指令槽編號必須爲1。這種重定位後面能夠跟着 IMAGE_REL_IA64_ADDEND 類型的重定位項,然後者的值在被 存儲 到IMM64指令包的三個指令槽中以前被加到目標地址上。
IMAGE_REL_IA64_DIR32
0x0004
重定位目標的32位VA。僅支持使用 /LARGEADDRESSAWARE:NO 連接器選項生成的映像。
IMAGE_REL_IA64_DIR64
0x0005
重定位目標的64位VA。
IMAGE_REL_IA64_PCREL21B
0x0006
使用按16位邊界對齊的重定位目標的25位相對偏移來修正指令。這個偏移的低4位全爲0,所以並無被存儲。
IMAGE_REL_IA64_PCREL21M
0x0007
使用按16位邊界對齊的重定位目標的25位相對偏移來修正指令。這個偏移的低4位全爲0,所以並無被存儲。
IMAGE_REL_IA64_PCREL21F
0x0008
這種重定位目標偏移的LSB部分包含的是指令槽編號,其他部分包含的是指令包的地址。 使用按16位邊界對齊的重定位目標的25位相對偏移來修正指令。這個偏移的低4位全爲0,所以並無被存儲。
IMAGE_REL_IA64_GPREL22
0x0009
這種指令重定位後面能夠跟着 IMAGE_REL_IA64_ADDEND 類型的重定位項,後者的值被加到目標地址上,然後計算 GPREL22 指令包相對於GP的偏移並應用。
IMAGE_REL_IA64_LTOFF22
0x000A
使用重定位目標符號的常量表項相對於GP的22位偏移來修正指令。連接器根據這個重定位項以及可能跟着它的IMAGE_REL_IA64_ADDEND類型的重定位項來建立這個常量表項。
IMAGE_REL_IA64_SECTION
0x000B
包含重定位目標的節的16位索引。用於支持調試信息。
IMAGE_REL_IA64_SECREL22
0x000C
使用重定位目標相對於它所在節開頭的22位偏移來修正指令。這種類型的重定位項後面能夠緊跟着IMAGE_REL_IA64_ADDEND類型的重定位項,後者的Value域包含重定位目標相對於它所在節開頭的32位偏移(無符號數)。
IMAGE_REL_IA64_SECREL64I
0x000D
這種重定位項的指令槽編號必須爲1。 使用重定位目標相對於它所在節開頭的64位偏移來修正指令。這種類型的重定位項後面能夠緊跟着IMAGE_REL_IA64_ADDEND類型的重定位項,後者的Value域包含重定位目標相對於它所在節開頭的32位偏移(無符號數)。
IMAGE_REL_IA64_SECREL32
0x000E
使用重定位目標相對於它所在節開頭的32位偏移來修正的數據的地址。
IMAGE_REL_IA64_LTOFF 64
0x000 F
 
IMAGE_REL_IA64_DIR32NB
0x0010
目標的32位RVA。
IMAGE_REL_IA64_SREL14
0x0011
用於包含兩個重定位目標之差的14位當即數(符號數)。對於連接器來講這是一個說明域,代表編譯器已經生成了這個值。
IMAGE_REL_IA64_SREL22
0x0012
用於包含兩個重定位目標之差的22位當即數(符號數)。對於連接器來講這是一個說明域,代表編譯器已經生成了這個值。
IMAGE_REL_IA64_SREL32
0x0013
用於包含兩個重定位目標之差的32位當即數(符號數)。對於連接器來講這是一個說明域,代表編譯器已經生成了這個值。
IMAGE_REL_IA64_UREL32
0x0014
用於包含兩個重定位目標之差的32位當即數(無符號數)。對於連接器來講這是一個說明域,代表編譯器已經生成了這個值。
IMAGE_REL_IA64_PCREL60X
0x0015
相對於PC的60位修正,用於MLX指令包的BRL指令。
IMAGE_REL_IA64_PCREL60B
0x0016
相對於PC的60位修正。若是重定位目標偏移不超過一個25位域所能表示的範圍(符號數),那麼就在1號指令槽中使用NOP.B指令、2號指令槽中使用25位(最低4位全爲0,捨棄)的BR指令將整個指令包轉換成MBB指令包。
IMAGE_REL_IA64_PCREL60F
0x0017
相對於PC的60位修正。若是重定位目標偏移不超過一個25位域所能表示的範圍(符號數),那麼就在1號指令槽中使用NOP.F指令、2號指令槽中使用25位(最低4位全爲0,捨棄)的BR指令將整個指令包轉換成MFB指令包。
IMAGE_REL_IA64_PCREL60I
0x0018
相對於PC的60位修正。若是重定位目標偏移不超過一個25位域所能表示的範圍(符號數),那麼就在1號指令槽中使用NOP.I指令、2號指令槽中使用25位(最低4位全爲0,捨棄)的BR指令將整個指令包轉換成MIB指令包。
IMAGE_REL_IA64_PCREL60M
0x0019
相對於PC的60位修正。若是重定位目標偏移不超過一個25位域所能表示的範圍(符號數),那麼就在1號指令槽中使用NOP.M指令、2號指令槽中使用25位(最低4位全爲0,捨棄)的BR指令將整個指令包轉換成MMB指令包。
IMAGE_REL_IA64_IMMGPREL64
0x001 A
相對於GP的64位修正。
IMAGE_REL_IA64_TOKEN
0x001 B
CLR 記號。
IMAGE_REL_IA64_GPREL32
0x001 C
相對於GP的32位修正。
IMAGE_REL_IA64_ADDEND
0x001F
只有緊跟下列類型的重定位時這種重定位類型纔是合法的: 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 。它的值是應用到指令包中的指令上的加數,而不是用於數據。
MIPS處理器
爲MIPS處理器定義瞭如下重定位類型指示符:
常量
描述
IMAGE_REL_MIPS_ABSOLUTE
0x0000
重定位被忽略。
IMAGE_REL_MIPS_REFHALF
0x0001
重定位目標32位VA的高16位。
IMAGE_REL_MIPS_REFWORD
0x0002
重定位目標的32位VA。
IMAGE_REL_MIPS_JMPADDR
0x0003
重定位目標VA的低26位。用於支持MIPS平臺的J和JAL指令。
IMAGE_REL_MIPS_REFHI
0x0004
重定位目標32位VA的高16位。它用於加載一個完整地址所需的兩指令序列中的第一條指令。這種重定位類型後面必須緊跟IMAGE_REL_MIPS_PAIR類型的重定位項,然後者的SymbolTableIndex域包含的是一個16位偏移(符號數),這個偏移要被加到重定位目標位置的高16位。
IMAGE_REL_MIPS_REFLO
0x0005
重定位目標VA的低16位。
IMAGE_REL_MIPS_GPREL
0x0006
重定位目標相對於GP寄存器的16位偏移(符號數)。
IMAGE_REL_MIPS_LITERAL
0x0007
IMAGE_REL_MIPS_GPREL 相同。
IMAGE_REL_MIPS_SECTION
0x000A
包含重定位目標的節的16位索引。用於支持調試信息。
IMAGE_REL_MIPS_SECREL
0x000B
重定位目標相對於它所在節開頭的32位偏移。用於支持調試信息和 靜態線程局部存儲。
IMAGE_REL_MIPS_SECRELLO
0x000C
重定位目標相對於它所在節開頭的32位偏移的低16位。
IMAGE_REL_MIPS_SECRELHI
0x000D
重定位目標 相對於它所在節開頭的 32 位VA的高16位。這種重定位類型後面必須緊跟 IMAGE_REL_MIPS_PAIR 類型的重定位項,然後者的SymbolTableIndex域包含的是一個16位偏移(符號數),這個偏移要被加到重定位符號位置的高16位。
IMAGE_REL_MIPS_JMPADDR16
0x0010
重定位目標VA的低26位。用於支持MIPS16的JAL指令。
IMAGE_REL_MIPS_REFWORDNB
0x0022
重定位目標的32位RVA。
IMAGE_REL_MIPS_PAIR
0x0025
只有緊跟 IMAGE_REL_MIPS_REFHI IMAGE_REL_MIPS_SECRELHI 類型的重定位時這種重定位類型纔是合法的。此重定位項的SymbolTableIndex域包含的是偏移而不是符號表索引。
Mitsubishi M32R處理器
爲Mitsubishi M32R處理器定義瞭如下重定位類型指示符:
常量
描述
IMAGE_REL_M32R_ABSOLUTE
0x0000
重定位被忽略。
IMAGE_REL_M32R_ADDR32
0x0001
重定位目標的32位VA。
IMAGE_REL_M32R_ADDR32NB
0x0002
重定位目標的32位RVA。
IMAGE_REL_M32R_ADDR24
0x0003
重定位目標的24位VA。
IMAGE_REL_M32R_GPREL16
0x0004
重定位目標相對於GP寄存器的16位偏移。
IMAGE_REL_M32R_PCREL24
0x0005
重定位目標相對於程序計數器(PC)的24位偏移,已經左移2位並按符號擴展。
IMAGE_REL_M32R_PCREL16
0x0006
重定位目標相對於PC的16位偏移,已經左移2位並按符號擴展。
IMAGE_REL_M32R_PCREL8
0x0007
重定位目標相對於PC的8位偏移,已經左移2位並按符號擴展。
IMAGE_REL_M32R_REFHALF
0x0008
重定位目標VA的16位MSB。
IMAGE_REL_M32R_REFHI
0x0009
重定位目標VA的16位MSB,已經按LSB符號擴展調整。它用於加載一個完整的32位地址所需的兩指令序列中的第一條指令。這種重定位類型後面必須緊跟IMAGE_REL_M32R_PAIR類型的重定位項,然後者的SymbolTableIndex域包含的是一個16位偏移(符號數),這個偏移要被加到重定位符號位置的高16位。
IMAGE_REL_M32R_REFLO
0x000A
重定位目標VA的16位LSB。
IMAGE_REL_M32R_PAIR
0x000B
這種類型的重定位必須緊跟類型爲 IMAGE_REL_M32R_REFHI 的重定位項。此重定位項的SymbolTableIndex域包含的是偏移而不是符號表索引。
IMAGE_REL_M32R_SECTION
0x000C
包含重定位目標的節的16位索引。用於支持調試信息。
IMAGE_REL_M32R_SECREL
0x000D
重定位目標相對於它所在節開頭的32位偏移。用於支持調試信息和 靜態線程局部存儲。
IMAGE_REL_M32R_TOKEN
0x000E
CLR 記號。
5.3 COFF行號信息(不同意使用)
Microsoft 的工具已經再也不生成COFF行號信息,而且之後也不會再使用它了。
COFF 行號信息給出了源文件中代碼與行號之間的關係。Microsoft的COFF行號信息格式與標準COFF行號信息格式相似,但已經被擴展,以便用單個節就能夠與多個源文件中的行號關聯。
COFF 行號信息由長度固定的記錄組成的數組構成。數組的位置(文件偏移)與大小由節頭給出。每一個行號記錄格式以下:
偏移
大小
描述
0
4
Type (*)
這是由 SymbolTableIndex VirtualAddress 兩個域組成的共用體。使用 SymbolTableIndex 仍是 RVA 依賴於 Linenumber 域的值。
4
2
Linenumber
若是此值非零,那麼它表示行號(從1開始)。若是它爲零,那麼Type域表示一個函數在符號表中的索引。
 
Type 域是由 SymbolTableIndex VirtualAddress 兩個4字節長的域組成的共用體:
偏移
大小
描述
0
4
SymbolTableIndex
當Linenumber 爲零時使用此域,它表示一個函數在符號表中的索引。此格式用來指明一組行號記錄與哪一個函數相關。
0
4
VirtualAddress
當Linenumber非零時使用此域,它表示與源代碼中由Linenumber指定的那行代碼對應的可執行代碼的RVA。在目標文件中,它表示節中的VA。
 
一個行號記錄,或者是將其Linenumber域設置爲零, 同時(另外一個域) 指向符號表中的一個函數;或者是做爲一個標準的行號記錄:給出一個正整數(行號)以及在目標代碼中相應的地址。
一組行號記錄老是之前一種格式——符號表中函數的索引開頭。若是這個行號記錄是節中的第一個行號記錄,而且節的COMDAT標誌設置的話,那麼它同時也是函數的COMDAT符號名。詳細信息請參考5.5.6節「COMDAT節(僅適用於目標文件)」。此函數在符號表中的輔助記錄有一個PointerToLinenumber域,它指向這個行號記錄。
標識函數的記錄後面跟着一些行號記錄,它們給出了實際的行號信息(也就是說,這些記錄的Linenumber域都大於0)。這些項(中的Linenumber域)從1開始(相對於函數的開頭),每個表示函數源代碼中的一行(除了第一行)。
例如在下面的例子中,第一個行號記錄會列出 ReverseSign 函數( ReverseSign 函數的 SymbolTableIndex 和被設置爲0的 Linenumber 域)。它後面的記錄的Linenumber域的 值依次爲一、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節「符號名稱表示」。
8
4
Value
與符號相關的值。其意義依賴於 SectionNumber StorageClass 兩個域。它一般表示可重定位的地址。
12
2
SectionNumber
這個帶符號整數是節表的索引(從1開始),用以標識定義此符號的節。一些值有特殊的含義,詳細信息請參考5.4.2節「 SectionNumber 域的 值」。
14
2
Type
一個表示類型的數字。Microsoft的工具將它設置爲0x20(若是是函數)或者0x0(若是不是函數)。要獲取更多信息,請參考5.4.3節「類型表示」。
16
1
StorageClass
這是一個表示存儲類別的枚舉類型值。要獲取更多信息,請參考5.4.4節「存儲類別」。
17
1
NumberOfAuxSymbols
跟在本記錄後面的輔助符號表項的個數。
每一個標準符號表記錄後面緊跟着零個或多個輔助符號表記錄,但一般狀況下並不會超過一個(除了帶長文件名的.file記錄)。每一個輔助符號表記錄的大小與標準符號表記錄相同(都是18字節),但它並非又定義了一個新的符號,而是給出了與上一個定義的符號相關的附加信息。輔助符號表記錄有好幾種格式,使用哪種取決於StorageClass域的值。當前已經爲輔助符號表記錄定義的格式將在5.5節「輔助符號表記錄」中列出。
處理COFF符號表的工具必須忽略意義不明的輔助符號表記錄。這樣容許往後對符號表的格式進行擴展以便添加新的輔助符號表記錄而不會使現存的工具失效。
5.4.1符號名稱表示
若是符號名稱長度不超過8個字節,那麼符號表的ShortName域就是包含符號名自己的一個8字節長的數組;不然的話,它給出了字符串表中的一個偏移地址。要肯定它究竟是名稱自己仍是偏移地址,測試一下它的前4個字節是否等於0。
一般名稱都被認爲是以NULL結尾的UTF-8格式的字符串。

偏移
大小
描述
0
8
ShortName
8 字節長的數組。若是名稱長度小於8字節,在它的右邊用NULL填充。
0
4
Zeroes
若是名稱長度大於8字節,那麼這個域被設置爲全0。
4
4
Offset
字符串表中的一個偏移地址。
5.4.2 SectionNumber域的
一般符號表項中的SectionNumber域是節表的索引(從1開始)。可是這個域是帶符號整數,所以它能夠爲負值。下面這些小於1的值有特殊含義:
常量
描述
IMAGE_SYM_UNDEFINED
0
還沒有爲此符號記錄分配一個節。這個零值代表引用了一個定義在其它地方的外部符號;而非零值則代表是一個普通符號,其大小由Value域給出。
IMAGE_SYM_ABSOLUTE
-1
此符號是個絕對符號(不可重定位),而且不是地址。
IMAGE_SYM_DEBUG
-2
此符號提供普通類型信息或者調試信息,但它並不對應於某一個節。Microsoft的工具將.file記錄(存儲類別爲FILE)設置爲這個值。
5.4.3類型表示
符號表項的Type域佔2個字節,其中的每個字節都表示類型信息。低位字節(LSB)表示簡單(基本)數據類型,高位字節(MSB)表示複雜類型(若是存在):
MSB
LSB
複雜類型:無、指針、函數、數組。
基本類型:整數、浮點數等。
 
儘管Microsoft的工具一般不使用這個域並將LSB設置爲0,但仍是爲基本類型定義瞭如下這些值。Microsoft的工具使用Visual C++調試信息來指明類型。可是出於完整性考慮,將可能出現的值列於下表:
常量
描述
IMAGE_SYM_TYPE_NULL
0
類型信息不存在,或者是未知的基本類型。Microsoft的工具使用這個值。
IMAGE_SYM_TYPE_VOID
1
不是合法類型;用於void指針和函數。
IMAGE_SYM_TYPE_CHAR
2
字符(帶符號的1個字節)。
IMAGE_SYM_TYPE_SHORT
3
長度爲2個字節的帶符號整數。
IMAGE_SYM_TYPE_INT
4
天然的整數類型(在Windows中一般爲4個字節)。
IMAGE_SYM_TYPE_LONG
5
長度爲4個字節的帶符號整數。
IMAGE_SYM_TYPE_FLOAT
6
長度爲4個字節的浮點數。
IMAGE_SYM_TYPE_DOUBLE
7
長度爲8個字節的浮點數。
IMAGE_SYM_TYPE_STRUCT
8
結構體。
IMAGE_SYM_TYPE_UNION
9
共用體。
IMAGE_SYM_TYPE_ENUM
10
枚舉類型。
IMAGE_SYM_TYPE_MOE
11
枚舉類型成員(具體值)。
IMAGE_SYM_TYPE_BYTE
12
字節;長度爲1個字節的無符號整數。
IMAGE_SYM_TYPE_WORD
13
字;長度兩個字節的無符號整數。
IMAGE_SYM_TYPE_UINT
14
長度爲天然尺寸的無符號整數(一般爲4個字節)。
IMAGE_SYM_TYPE_DWORD
15
長度爲4個字節的無符號整數。
 
高位字節指出符號是指向由LSB指定的基本類型的指針、返回由LSB指定的基本類型的函數仍是由LSB指定的基本類型組成的數組。Microsoft的工具僅使用這個域來指出這個符號是否是函數,所以最後的Type域只有0x0和0x20這兩個值。可是其它工具可使用這個域來傳遞更多信息。
正確地指定函數屬性很是重要。增量連接須要這個信息才能正確地工做。對於某些平臺而言,可能會出於其它目的而使用這個信息。
常量
描述
IMAGE_SYM_DTYPE_NULL
0
非導出類型;此符號是簡單的標量變量。
IMAGE_SYM_DTYPE_POINTER
1
此符號是指向基本類型的指針。
IMAGE_SYM_DTYPE_FUNCTION
2
此符號是返回基本類型的函數。
IMAGE_SYM_DTYPE_ARRAY
3
此符號是由基本類型組成的數組。
5.4.4存儲類別
符號表中的StorageClass域指出符號具體的存儲類別。下表列出了全部可能的取值。注意StorageClass域是長度爲1個字節的無符號整數。所以若是這個域的值爲-1的話,實際上應該被看做是與它相等的無符號數,也就是0xFF。
儘管傳統的COFF格式使用許多存儲類別,可是Microsoft的工具使用Visual C++調試信息來表示大部分符號信息,它一般僅使用四種存儲類別: EXTERNAL (2)、 STATIC (3)、 FUNCTION (101)和FILE(103)。下表中出現的「Value」都表示符號表記錄中的Value域(它的意義依賴於存儲類別的值)。
常量
描述以及對Value域的解釋
IMAGE_SYM_CLASS_END_OF_FUNCTION
-1
(0xFF)
表示函數結尾的特殊符號,用於調試。
IMAGE_SYM_CLASS_NULL
0
未被賦予存儲類別。
IMAGE_SYM_CLASS_AUTOMATIC
1
自動(堆棧)變量。Value域指出此變量在棧幀中的偏移。
IMAGE_SYM_CLASS_EXTERNAL
2
Microsoft 的工具使用此值來表示外部符號。若是SectionNumber域爲0(IMAGE_SYM_UNDEFINED),那麼Value域給出大小;若是SectionNumber 域不爲0,那麼Value域給出節中的偏移。
IMAGE_SYM_CLASS_STATIC
3
符號在節中的偏移。若是Value域爲0,那麼此符號表示節名。
IMAGE_SYM_CLASS_REGISTER
4
寄存器變量。Value域給出寄存器編號。
IMAGE_SYM_CLASS_EXTERNAL_DEF
5
在外部定義的符號。
IMAGE_SYM_CLASS_LABEL
6
模塊中定義的代碼標號。Value域給出此符號在節中的偏移。
IMAGE_SYM_CLASS_UNDEFINED_LABEL
7
引用的未定義的代碼標號。
IMAGE_SYM_CLASS_MEMBER_OF_STRUCT
8
結構體成員。Value域指出是第幾個成員。
IMAGE_SYM_CLASS_ARGUMENT
9
函數的形式參數(形參)。Value域指出是第幾個參數。
IMAGE_SYM_CLASS_STRUCT_TAG
10
結構體名。
IMAGE_SYM_CLASS_MEMBER_OF_UNION
11
共用體成員。Value域指出是第幾個成員。
IMAGE_SYM_CLASS_UNION_TAG
12
共用體名。
IMAGE_SYM_CLASS_TYPE_DEFINITION
13
Typedef
IMAGE_SYM_CLASS_UNDEFINED_STATIC
14
靜態數據聲明。
IMAGE_SYM_CLASS_ENUM_TAG
15
枚舉類型名。
IMAGE_SYM_CLASS_MEMBER_OF_ENUM
16
枚舉類型成員。Value域指出是第幾個成員。
IMAGE_SYM_CLASS_REGISTER_PARAM
17
寄存器參數。
IMAGE_SYM_CLASS_BIT_FIELD
18
位域。Value域指出是位域中的第幾個位。
IMAGE_SYM_CLASS_BLOCK
100
 .bb beginning of block ,塊開頭 ) .eb記錄 end of block ,塊結尾)。Value域是代碼位置,它是一個可重定位的地址。
IMAGE_SYM_CLASS_FUNCTION
101
Microsoft 的工具用此值來表示定義函數範圍的符號記錄,這些符號記錄分別是: .bf (begin fu nction ,函數開頭)、 .ef end function ,函數結尾)以及 .lf lines in function ,函數中的行)。對於.lf 記錄來講,Value域給出了源代碼中此函數所佔的行數。對於.ef記錄來講,Value域給出了函數代碼的大小。
IMAGE_SYM_CLASS_END_OF_STRUCT
102
結構體末尾。
IMAGE_SYM_CLASS_FILE
103
Microsoft 的工具以及傳統COFF格式都使用此值來表示源文件符號記錄。這種符號表記錄後面跟着給出文件名的輔助符號表記錄。
IMAGE_SYM_CLASS_SECTION
104
節的定義(Microsoft的工具使用STATIC存儲類別代替)。
IMAGE_SYM_CLASS_WEAK_EXTERNAL
105
弱外部符號。要獲取更多信息,請參考5.5.3節「輔助符號表記錄格式之三:弱外部符號」。
IMAGE_SYM_CLASS_CLR_TOKEN
107
表示CLR記號的符號。它的名稱是這個記號的十六進制值的ASCII碼錶示。要獲取更多信息,請參考5.5.7節「CLR記號定義」。
5.5輔助符號表記錄
輔助符號表記錄老是跟在一些標準符號表記錄以後並應用於這些符號表記錄。它的格式並不固定,只要處理它的工具可以識別就能夠了,但必須保證其長度是18個字節,以便整個符號表能夠被看成一個數組來處理。當前Microsoft的工具能夠識別如下類型的輔助符號表記錄:函數定義、函數開頭和結尾符號(.bf.ef)、弱外部符號、文件名以及節的定義。
傳統的COFF格式中還包括用於數組和結構體的輔助符號表記錄。可是Microsft的工具並不使用它們,而是將符號信息按照Visual C++調試信息格式存儲在調試節中。
5.5.1輔助符號表記錄格式之一:函數定義
若是一個符號表記錄擁有下列屬性:存儲類別爲EXTERNAL(2)、Type域的值代表它是一個函數(0x20)以及SectionNumber域的值大於0,它就標誌着函數的開頭。注意若是一個符號表記錄SectionNumber域的值爲IMAGE_SYM_UNDEFINED(0),那麼它並不定義一個函數,也沒有相應的輔助符號表 記錄。可以定義函數的符號表記錄後面跟着以下格式的輔助符號表記錄:

偏移
大小
描述
0
4
TagIndex
相應的.bf(函數開頭)記錄在符號表中的索引。
4
4
TotalSize
函數經編譯後生成的可執行代碼的大小。若是此函數單獨成節,那麼根據對齊值的不一樣,節頭中的SizeOfRawData域可能大於或等於這個域。
8
4
PointerToLinenumber
若是此函數存在行號記錄,那麼這個值表示它的第一個COFF行號記錄的文件偏移;若是不存在,那麼這個值爲0。要獲取更多信息,請參考5.3節「COFF行號信息(不同意使用)」。
12
4
PointerToNextFunction
對應於下一個函數的符號表記錄在符號表中的索引。若是此函數是符號表中的最後一個函數,那麼這個域的值爲0。
16
2
未用
5.5.2輔助符號表記錄格式之二:.bf和.ef符號
對於符號表中的每一個函數定義,有三個相應的符號表記錄分別用來描述函數開頭、函數結尾以及此函數在源文件中所佔的行數。這三個符號表記錄的存儲類別都是FUNCTION(101):
·         一個名爲.bf的符號表記錄。此記錄的Value域未用。
·         一個名爲.lf的符號表記錄。此記錄的Value域給出了這個函數所佔的行數。
·         一個名爲.ef的符號表記錄。此記錄的Value域的值與定義函數的符號表記錄的TotalSize域的值相同。
 
.bf .ef符號表記錄(不包括.lf記錄)後面跟着以下格式的輔助符號表記錄:
偏移
大小
描述
0
4
未用
4
2
Linenumber
源文件中實際的行號,按順序排列(一、二、3等等)。.bf.ef記錄都使用這個域。
6
6
未用
12
4
PointerToNextFunction (僅用於 .bf 符號表記錄)
下一個.bf符號表記錄在符號表中的索引。若是此函數是符號表中的最後一個函數,那麼這個域的值爲0。.ef記錄並不使用這個域。
16
2
未用
5.5.3輔助符號表記錄格式之三:弱外部符號
「弱外部符號」是爲了在連接時能得到更大的靈活性而應用於目標文件的一種機制。模塊中能夠包含一個沒法解析的外部符號(假設爲sym1),但它也能夠同時包含一個相應的輔助符號表記錄來指明當連接時找不到sym1時能夠用另一個外部符號(假設爲sym2)來代替。
若是連接時能找到sym1的定義,那麼外部對它的引用能夠正常解析。不然全部對sym1這個弱外部符號的引用都用sym2來代替。而sym2這個外部符號在連接時必須可以找到;一般它就被定義在對sym1進行弱外部引用的模塊中。
表示弱外部符號的符號表記錄,其存儲類別是 EXTERNAL SectionNumber 域的值爲 IMAGE_SYM_UNDEFINED (0),Value域的值爲0。弱外部符號記錄後面跟着以下格式的輔助符號表記錄:
偏移
大小
描述
0
4
TagIndex
sym2 在符號表中的索引。若是連接時找不到sym1就用它代替。
4
4
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
Length
節中數據的大小。與節頭的 SizeOfRawData 域同樣。
4
2
NumberOfRelocations
此節中重定位項的數目。
6
2
NumberOfLinenumbers
此節中行號信息項的數目。
8
4
CheckSum
公共數據的校驗和。只有節頭中設置了IMAGE_SCN_LNK_COMDAT標誌時才使用此域。要獲取更多信息,請參考5.5.6節「COMDAT節(僅適用於目標文件)」。
12
2
Number
與此節相關的節在節表中的索引(從1開始)。當COMDAT的Selection域 爲5時才使用這個域。
14
1
Selection
表示COMDAT選擇方式的數字。 這個域只用於 COMDAT 節。
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 (符號多重定義)」錯誤。
IMAGE_COMDAT_SELECT_ANY
2
連接器從這些定義同一個COMDAT符號的節中任選一個,其他(未被選中)的節都被移除。
IMAGE_COMDAT_SELECT_SAME_SIZE
3
連接器從定義這個符號的多個節中任選一個。若是全部這些定義大小不等,連接器將生成一個「符號多重定義」錯誤。
IMAGE_COMDAT_SELECT_EXACT_MATCH
4
連接器從定義這個符號的多個節中任選一個。若是全部這些定義不嚴格一致,連接器將生成一個「符號多重定義」錯誤。
IMAGE_COMDAT_SELECT_ASSOCIATIVE
5
若是「其它某個」COMDAT節被連接的話,此節也要被連接。這裏的「其它某個」節由與定義此節的符號表記錄相關的輔助符號表記錄的Number域給出。這個設置對於那些在多個節中都有其相關部分(例如代碼在一個節中而數據在另外一個節中)但必須做爲一個總體進行連接或丟棄的定義很是有用。與此節關聯的這個「其它某個」節必須也是COMDAT節而且它不能再與其它COMDAT節關聯(也就是說,這個「其它某個」節不能將Selection域設置爲IMAGE_COMDAT_SELECT_ASSOCIATIVE)。
IMAGE_COMDAT_SELECT_LARGEST
6
連接器從這個符號的全部定義中選取長度最大的進行連接。若是長度最大的不止一個,那麼就在這幾個最大的中任選一個。
5.5.7 CLR記號定義(僅適用於目標文件)
這種輔助符號表記錄一般跟在存儲類別爲IMAGE_SYM_CLASS_CLR_TOKEN的符號表記錄以後。它用來聯繫CLR記號與COFF符號表的名稱空間。
偏移
大小
描述
0
1
bAuxType
必須爲 IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF (1)。
1
1
bReserved
保留,必須爲0。
2
4
SymbolTableIndex
此CLR記號定義涉及的COFF符號在符號表中的索引。
6
12
保留,必須爲0。
5.6 COFF字符串表
COFF 符號表後緊跟着的是COFF字符串表。它的位置能夠經過將COFF文件頭中符號表的地址加上符號總數乘以每一個符號的大小獲得。
COFF 字符串表開頭的4個字節存儲的是字符串表的總大小(以字節計)。這個大小包括這個域自己。所以若是字符串表中不包含任何字符串時,這個值應該爲4。
大小後面是一些以NULL結尾的字符串,COFF符號表中的符號指向這些字符串。
5.7屬性證書表(僅適用於映像文件)
能夠給映像文件添加屬性證書表使它與屬性證書相關聯。屬性證書表由一組連續的按八進制字(從任意字節邊界開始的16個連續字節)邊界對齊的屬性證書表項組成。每一個屬性證書表項格式以下:
偏移
大小
描述
0
4
dwLength
指出 bCertificate 域的長度。
4
2
wRevision
證書版本號。要獲取詳細信息,請參考本表後面的內容。
6
2
wCertificateType
指出 bCertificate 內容的類型。要獲取詳細信息,請參考本表後面的內容。
8
參考後面的內容
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 ),它表示你已經遍歷了整個屬性證書表。
 
你也能夠在一個循環中調用 Win32® 函數 ImageEnumerateCertificates 來枚舉屬性證書表項。本規範最後的「參考信息」中給出了此函數信息的連接。
屬性證書表項能夠包含任何類型的證書,只要它有正確的 dwLength 值、唯一的 wRevision 值和唯一的 wCertificateType 值。最經常使用的類型是 WIN_CERTIFICATE 結構,Wintrust.h文件給出了它的內容,本節後面將要討論它。
WIN_CERTIFICATE 結構的wRevision域能夠選用(但不限於)如下值:
名稱
注意
0x0100
WI N_CERT_REVISION_1_0
版本1, WIN_CERTIFICATE 結構的遺留版本。支持它只是爲了校驗之前的Authenticode簽名。
0x0200
WIN_CERT_REVISION_2_0
版本2是 WIN_CERTIFICATE 結構的當前版本。
 
WIN_CERT IFICATE 結構的 wCertificateType 域能夠選用(但不限於)的值列於下表。注意其中一些值當前並不支持。
名稱
注意
0x0001
WIN_CERT_TYPE_X509 
bCertificate 包含的是 X.509 證書。不支持。
0x0002
WIN_CERT_TYPE_PKCS_SIGNED_DATA
bCertificate 包含的是 PKCS#7 SignedData 結構。
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 映像散列(或者稱爲文件散列)與文件校驗和相似,它們的散列算法都生成一個與文件完整性有關消息摘要。可是校驗和是用簡單的算法生成的,它主要用來檢測保存在磁盤上的一塊內存是否已經被破壞以及存儲在那裏的值 是否已經被改變。文件散列與校驗和的相同之處在於它也檢測文件是否被破壞。但與大多數校驗和算法不一樣的是,要對一個文件進行修改並同時保持它的文件散列與原始(未修改的)形式一致是極其困難的。所以文件散列能夠用來檢測諸如一些病毒、黑客或者木馬程序對文件進行的有意的、甚至是很是細微的修改。
當將映像中的內容包含進證書時,映像摘要必須排除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
Attributes
必須爲0。
4
4
Name
被加載DLL名稱的RVA。這個名稱位於映像文件的只讀數據節中。
8
4
Module Handle
被延遲加載DLL模塊句柄(在映像的數據節中)的RVA。它供管理延遲加載的例程存儲之用。
12
4
Delay Import Address Table
延遲加載導入地址表的RVA。要獲取更多信息,請參考5.8.5節「延遲導入地址表(IAT)」。
16
4
Delay Import Name Table
延遲加載名稱表的RVA。這個表包含了須要被加載的導入符號的名稱。它與導入名稱表的格式一致。要獲取更多信息,請參考6.4.3節「提示/名稱表」。
20
4
Bound Delay Import Table
綁定延遲加載地址表(若是存在)的RVA。
24
4
Unload Delay Import Table
卸載延遲加載地址表(若是存在)的RVA。這個表是延遲導入地址表的精確副本。若是調用者卸載了這個DLL,應該將這個表複製回去以覆蓋延遲導入地址表,以便後續對這個DLL的調用能夠繼續正確地使用形實轉換機制。
28
4
Time Stamp
此映像綁定到的DLL的時間戳。
 
對於這個結構中使用到的表來講,它們的組織形式與存儲格式與傳統的導入表同樣,就像是它們的副本。要獲取更多信息,請參考4.6節「.idata節」。
5.8.2屬性
至今還沒有定義屬性標誌。連接器在生成映像文件時將此域設置爲 0 。咱們能夠在未來擴展這個結構時用它來指明添加了新域,或者用它來指明延遲加載或卸載輔助函數的行爲。
5.8.3名稱
須要被延遲加載的DLL的名稱被存儲在映像文件的只讀數據節中。能夠經過 szName 域引用它。
5.8.4模塊句柄
要被延遲加載的DLL的句柄被存儲在映像文件的數據節中。 phmod 域指向這個 句柄。延遲加載輔助函數使用這個位置存儲要被延遲加載的DLL的模塊句柄。
5.8.5延遲導入地址表
能夠經過延遲導入描述符的 pIAT 域引用延遲導入地址表(IAT)。延遲加載輔助函數用導入符號的實際地址來更新這些指針,以便起轉換做用的這部分代碼不會陷入 循環調用之中。能夠經過表達式 pINT->u1.Function 來訪問 這些函數指針
5.8.6延遲導入名稱表
延遲導入名稱表(INT)包含了可能須要被加載的導入符號的名稱。它們的排列方式與IAT中的函數指針同樣。它們的結構與標準的INT同樣,能夠經過表達式 pINT->u1.AddressOfData->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
.cormeta
CLR 元數據,它代表目標文件中包含託管代碼
IMAGE_SCN_LNK_INFO
.data
已初始化的數據(自由格式)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |          IMAGE_SCN_MEM_WRITE
.debug$F
生成的FPO調試信息(僅適用於目標文件,僅用於x86平臺,現已被捨棄)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |          IMAGE_SCN_MEM_DISCARDABLE
.debug$P
預編譯的調試類型信息(僅適用於目標文件)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |          IMAGE_SCN_MEM_DISCARDABLE
.debug$S
調試符號信息(僅適 用於目標文件)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |          IMAGE_SCN_MEM_DISCARDABLE
.debug$T
調試類型信息(僅適用於目標文件)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |          IMAGE_SCN_MEM_DISCARDABLE
.drectve
連接器選項
IMAGE_SCN_LNK_INFO
.edata
導出表
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
.idata
導入表
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |
IMAGE_SCN_MEM_WRITE
.idlsym
包含已註冊的SEH(僅適用於映像文件),它們用以支持IDL屬性。要獲取更多信息,請參考本規範最後「參考信息」中的「IDL屬性」。
IMAGE_SCN_LNK_INFO
.pdata
異常信息
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
.rdata
只讀的已初始化數據
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
.reloc
映像文件的重定位信息
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |                IMAGE_SCN_MEM_DISCARDABLE
.rsrc
資源目錄
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
.sbss
GP相關的未初始化數據(自由格式)
IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ |                 IMAGE_SCN_MEM_WRITE |                IMAGE _SCN_GPREL
其中 IMAGE_SCN_GPREL 標誌僅用於IA64平臺,不能用於其它平臺。此標誌只能用於目標文件。當映像文件中出現這種類型的節時,必定不能設置這個標誌。
.sdata
GP相關的已初始化數據(自由格式)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |                IMAGE_SCN_MEM_WRITE |                IMAGE _SCN_GPREL
其中 IMAGE_SCN_GPREL 標誌僅用於IA64平臺,不能用於其它平臺。此標誌只能用於目標文件。當映像文件中出現這種類型的節時,必定不能設置這個標誌。
.srdata
GP相關的只讀數據(自由格式)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |                IMAGE _SCN_GPREL
其中 IMAGE_SCN_GPREL 標誌僅用於IA64平臺,不能用於其它平臺。此標誌只能用於目標文件。當映像文件中出現這種類型的節時,必定不能設置這個標誌。
.sxdata
已註冊的異常處理程序數據(自由格式,僅適用於目標文件,僅用於x86平臺)
IMAGE_SCN_LNK_INFO
這個節中包含目標文件中的代碼所涉及到的全部異常處理程序在符號表中的索引。這些符號能夠是IMAGE_SYM_UNDEFINED類型的符號,也能夠是定義在那個模塊中的符號。
.text
可執行代碼(自由格式)
IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE |                 IIMAGE_SCN_MEM_READ
.tls
線程局部存儲(僅適用於目標文件)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |                IMAGE_SCN_MEM_WRITE
.tls$
線程局部存儲(僅適用於目標文件)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |                IMAGE_SCN_MEM_WRITE
.vsdata
GP相關的已初始化數據(自由格式,僅適用於ARM、SH4和Thumb平臺)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ |                IMAGE_SCN_MEM_WRITE
.xdata
異常信息(自由格式)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
 
上表中列出的一些節被標記爲「僅適用於目標文件」或 「僅適用於映像文件」,它們表示這些節的特殊含義只是分別對於目標文件或者映像文件來講的。標記爲「僅適用於映像文件」的節仍然能夠首先出如今目標文件中,最後再成爲映像文件的一部分,但這個節對於連接器來講並無特殊含義,它僅對於映像文件加載器纔有特殊含義。
6.1 .debug
在目標文件中,.debug 節包含編譯器生成的調試信息;在映像文件中,它包含生成的所有調試信息。本節描述了目標文件和映像文件中調試信息的封裝。
下一節描述調試目錄的格式,它能夠被放在映像文件中的任何地方。後面幾節描述目標文件中包含調試信息的成組的節。
默認狀況下調試信息並不映射到映像的地址空間中。只有當調試信息被映射到地址空間中時.debug節纔會存在。
6.1.1調試目錄(僅適用於映像文件)
映像文件中包含一個可選的調試目錄,它給出了調試信息的格式及位置。這個目錄是一個由調試目錄項組成的數組,它的位置和大小由可選文件頭給出。
調試目錄能夠位於一個可丟棄的.debug 節(若是存在)中,或者位於映像文件的其它節中,或者不在任何節中。
每一個調試目錄項給出了一塊調試信息的位置和大小。若是調試信息沒有被節頭包含(也就是說,它位於映像文件中但並無被映射到運行時地址空間中)的話,那麼這個指定的RVA能夠爲0。若是被映射的話,這個RVA就是它的實際地址。
調試目錄項格式以下:
偏移
大小
描述
0
4
Characteristics
保留,必須爲0。
4
4
TimeDateStamp
調試數據被建立的日期和時間。
8
2
MajorVersion
調試數據格式的主版本號。
10
2
MinorVersion
調試數據格式的次版本號。
12
4
Type
調試信息的格式。這個域的存在使得能夠支持多個調試器。要獲取更多信息,請參考6.1.2節「調試類型」。
16
4
SizeOfData
調試數據(不包括調試目錄自己)的大小。
20
4
AddressOfRawData
當被加載時調試數據相對於映像基址的偏移地址。
24
4
PointerToRawData
指向調試數據的文件指針。
6.1.2調試類型
爲調試目錄項的Type域定義瞭如下值:

常量
描述
IMAGE_DEBUG_TYPE_UNKNOWN
0
未知值,全部工具均忽略此值。
IMAGE_DEBUG_TYPE_COFF
1
COFF 調試信息(行號信息、符號表和字符串表)。文件頭中也有相關域指向這種類型的調試信息。
IMAGE_DEBUG_TYPE_CODEVIEW
2
Visual C++ 調試信息。
IMAGE_DEBUG_TYPE_FPO
3
幀指針省略(FPO)信息。這種信息告訴調試器如何解釋非標準棧幀,這種幀將EBP寄存器用於其它目的而不是做爲幀指針。
IMAGE_DEBUG_TYPE_MISC
4
DBG 文件的位置。
IMAGE_DEBUG_TYPE_EXCEPTION
5
.pdata 節的副本。
IMAGE_DEBUG_TYPE_FIXUP
6
保留。
IMAGE_DEBUG_TYPE_OMAP_TO_SRC
7
從通過代碼重排後的映像中的RVA到原映像中的RVA的映射。
IMAGE_DEBUG_TYPE_OMAP_FROM_SRC
8
從原映像中的RVA到通過代碼重排後的映像中的RVA的映射。
IMAGE_DEBUG_TYPE_BORLAND
9
保留,供 Borland 公司使用。
IMAGE_DEBUG_TYPE_RESERVED10
10
保留。
IMAGE_DEBUG_TYPE_CLSID
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
    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 節必定不能有重定位或行號信息。
6.3 .edata節(僅適用於映像文件)
導出數據節被命名爲.edata,它包含的是與其它映像經過動態連接能夠訪問的符號相關的信息。導出符號一般出如今DLL中,但DLL也能夠導入符號。
下表描述了導出節的通常結構。其中提到的各類表一般都是按下表中所示的順序在文件中連續分佈的(儘管這並非必須的)。只須要導出目錄表和導出地址表這兩個表就能夠將序數做爲導出符號導出。(序數是一個導出符號,能夠把它做爲導出地址表中的索引直接引用。)導出名稱指針表、導出序數表和導出名稱表的存在都是爲了支持使用導出名稱。
表名
描述
導出目錄表
一個只有一行的表(與調試目錄不一樣)。它給出了其它各類導出表的位置和大小。
導出地址表
一個由導出符號的RVA組成的數組。它們是導出的函數和數據在可執行代碼節和數據節內的實際地址。其它映像文件能夠經過使用這個表的索引(序數)來導入符號,或者若是定義了一個與序數對應的公用名稱的話,也能夠用這個公用名稱來導入符號。
導出名稱指針表
一個由指向導出符號名稱的指針組成的數組,按升序排列。
導出序數表
一個由對應於導出名稱指針表中各個成員的序數組成的數組。它們的對應是經過位置來體現的,所以導出名稱指針表與導出序數表成員數目必須相同。每一個序數都是導出地址表的一個索引。
導出名稱表
一系列以NULL結尾的ASCII碼字符串。導出名稱指針表中的成員都指向這個區域。它們都是公用名稱,符號導入與導出就是經過它們。這些公用名稱並不須要與映像文件內部使用的私有名稱相同。
 
當其它映像文件經過名稱導入符號時,Win32加載器經過導出名稱指針表來搜索匹配的字符串。若是找到,它就查找導出序數表中相應的成員(也就是說,將找到的導出名稱指針表的索引做爲導出序數表的索引來使用)來獲取與導入符號相關聯的序數。獲取的這個序數是導出地址表的索引,這個索引對應的元素給出了所需符號的實際位置。每一個導出符號均可以經過序數進行訪問。
當其它映像文件經過序數導入符號時,就再也不須要經過導出名稱指針表來搜索匹配的字符串了。所以直接使用序數效率會更高。可是導出名稱容易記憶,它不須要用戶記住各個符號在表中的索引。
6.3.1導出目錄表
導出目錄表是導出符號信息的開始部分,它描述了導出符號信息中其他部分的內容。導出目錄表包含了有關將導入符號解析爲相應入口點地址的信息。
偏移
大小
描述
0
4
Export Flags
保留,必須爲0。
4
4
Time/Date Stamp
導出數據被建立的日期和時間。
8
2
Major Version
主版本號。用戶能夠自行設置主版本號和次版本號。
10
2
Minor Version
次版本號。
12
4
Name RVA
包含這個DLL名稱的ASCII碼字符串相對於映像基址的偏移地址。
16
4
Ordinal Base
映像中導出符號的起始序數值。這個域指定了導出地址表的起始序數值。它一般被設置爲1。
20
4
Address Table Entries
導出地址表中元素的數目。
24
4
Number of Name Pointers
導出名稱指針表中元素的數目。它同時也是導出序數表中元素的數目。
28
4
Export Address Table RVA
導出地址表相對於映像基址的偏移地址。
32
4
Name Pointer RVA
導出名稱指針表相對於映像基址的偏移地址。它的大小由Number of Name Pointers域給出。
36
4
Ordinal Table RVA
導出序數表相對於映像基址的偏移地址。
6.3.2導出地址表
導出地址表包含導出函數、導出數據以及絕對符號的地址。序數值是做爲導出地址表的索引來使用的。
導出地址表的每個元素都是一個域,其格式爲下表所述的兩種格式之一。若是指定的地址不是位於導出節(其地址和長度由可選文件頭給出)中,那麼這個域就是一個Export RVA,這個地址就是導出符號在代碼或數據中的實際地址;不然這個域是一個Forwarder RVA,它給出了一個位於其它DLL中的符號的名稱。
偏移
大小
描述
0
4
Export RVA
當加載進內存時,導出符號相對於映像基址的偏移地址。例如導出函數的地址。
0
4
Forwarder RVA
這是指向導出節中一個以NULL結尾的ASCII碼字符串的指針。這個字符串必須位於Export Table(導出表)數據目錄項給出的範圍以內。要獲取更多信息,請參考3.4.3節「可選文件頭中的數據目錄(僅適用於映像文件)」。這個字符串給出了導出符號所在DLL的名稱以及導出符號的名稱(例如「MYDLL.expfunc」),或者DLL的名稱以及導出符號的序數值(例如「MYDLL.#27」)。
 
Forwarder RVA 導出了其它映像中定義的符號,使它看起來好像是當前映像導出的同樣。所以對於當前映像來講,這個符號同時既是導入符號又是導出符號。
例如對於Windows XP系統中的Kernel32.dll文件來講,它導出的「HeapAlloc」被轉發到「 NTDLL.RtlAllocateHeap 」。這樣就容許應用程序使用Windows XP系統中的Ntdll.dll模塊而不須要實際包含任何相關的導入信息。應用程序的導入表只與Kernel32.dll有關。這樣應用程序就不是特定於Windows XP,它能夠運行於任何Win32系統之上。
6.3.3導出名稱指針表
導出名稱指針表是由導出名稱表中的字符串的地址(RVA)組成的數組。每一個地址都是相對於映像基址的32位指針。它們按詞法順序排列以便進行二進制搜索。
只有當導出名稱指針表中包含指向某個導出名稱的指針時,這個導出名稱纔算被定義。
6.3.4導出序數表
導出序數表是由導出地址表的索引組成的一個數組,每一個序數長16位。可是這個序數是移碼形式,相應的偏移量由導出目錄表中的Ordinal Base域給出。換句話說,必須從序數值中減去Ordinal Base域的值獲得的纔是導出地址表真正的索引。
導出名稱指針表和導出序數表是兩個並列的數組,將它們分開是爲了使它們能夠分別按照各自的天然邊界(前者是4個字節,後者是2個字節)對齊。在進行操做時,這兩個表等效於一個表(在這個等效的新表中,這兩個表分別至關於新表中的兩列),由導出名稱指針這一列給出公共(導出)符號的名稱,而由導出序數這一列給出這個導出符號對應的序數。導出名稱指針表的成員和導出序數表的成員經過同一個索引相關聯。
所以,當在導出名稱指針表中搜索並找到匹配字符串的索引爲i 時,查找符號對應地址的算法以下:
i = Search_ExportNamePointerTable (ExportName);
ordinal = ExportOrdinalTable [i];
SymbolRVA = ExportAddressTable [ordinal - OrdinalBase];
6.3.5導出名稱表
導出名稱表包含的是導出名稱指針表實際指向的字符串。這個表中的字符串都是公用名稱,其它映像能夠經過它們導入這些符號。這些公用導出名稱並不須要與這些符號所在的映像文件和源代碼中的私有符號名稱相同,儘管它們能夠相同。
每一個導出符號都有一個相應的序數值,這個值是導出地址表的索引(加上 Ordinal Base 域的值)。可是使用導出名稱(來導出符號)是可選的。能夠所有導出符號都有導出名稱,也能夠部分導出符號有導出名稱,也能夠所有導出符號都沒有導出名稱。對於那些有導出名稱的導出符號來講,導出名稱指針表和導出序數表中相應的項配合起來使每一個名稱與一個序數相關聯。
導出名稱表的結構就是長度可變的一系列以NULL結尾的ASCII碼字符串。
6.4.idata
全部導入符號的映像文件,實際上幾乎包括全部的可執行(EXE)文件,都有.idata節。文件中導入信息的典型佈局以下:
目錄表
 
 
 
空目錄項
 
DLL1的導入查找表
 
空表項
 
DLL2的導入查找表
 
空表項
 
DLL3的導入查找表
 
空表項
 
提示/名稱表
 
圖3. 典型的導入節佈局
6.4.1導入目錄表
導入目錄表是導入信息的開始部分,它描述了導入信息中其他部分的內容。導入目錄表包含地址信息,這些地址信息用來修正對DLL映像中的相應函數的引用。導入目錄表是由導入目錄項組成的數組,每一個導入目錄項對應着一個導入的DLL。最後一個導入目錄項是空的(所有域的值都爲NULL),用來指明目錄表的結尾。
每一個導入目錄項的格式以下:
偏移
大小
描述
0
4
Import Lookup Table RVA (Characteristics)
導入查找表的RVA。這個表包含了每個導入符號的名稱或序數。(這個域在Winnt.h文件中的名稱是「Characteristics」,但已經名存實亡了。)
4
4
Time/Date Stamp
這個域一直被設置爲0,直到映像被綁定。當映像被綁定以後,這個域被設置爲這個DLL的日期/時間戳。
8
4
Forwarder Chain
第一個轉發項的索引。
12
4
Name RVA
包含DLL名稱的ASCII碼字符串相對於映像基址的偏移地址。
16
4
Import Address Table RVA (Thunk Table)
導入地址表的RVA。這個表的內容與導入查找表的內容徹底同樣,直到映像被綁定。
6.4.2導入查找表
導入查找表是由長度爲32位(PE32)或64位(PE32+)的數字組成的數組。其中的每個元素都是位域,其格式以下表所示。在這種格式中,位31(PE32)或位63(PE32+)是最高位。這些項描述了從給定的DLL導入的全部符號。最後一個項被設置爲0(NULL),用來指明表的結尾。
大小
位域
描述
31/63
1
Ordinal/Name Flag
若是這個位爲1,說明是經過序數導入的。不然是經過名稱導入的。測試這個位的掩碼爲0x80000000(PE32)或0x8000000000000000(PE32+)。
15-0
16
Ordinal Number
序數值(16位長)。只有當Ordinal/Name Flag域爲1(即經過序數導入)時才使用這個域。位30-15(PE32)或62-15(PE32+)必須爲0。
30 - 0
31
Hint/Name Table RVA
提示/名稱表項的RVA(31位長)。只有當Ordinal/Name Flag域爲0(即經過名稱導入)時才使用這個域。對於PE32+來講,位62-31必須爲0。
 
6.4.3提示/名稱表
一個提示/名稱表就能知足整個導入節的須要。提示/名稱表中的每個元素結構以下:
偏移
大小
描述
0
2
Hint
導出名稱指針表的索引。當搜索匹配字符串時首選使用這個值。若是匹配失敗,再在DLL的導出名稱指針表中進行二進制搜索。
2
可變
Name
包含導入符號名稱的ASCII碼字符串。這個字符串必須與DLL導出的公用名稱匹配。同時這個字符串區分大小寫而且以NULL結尾。
*
0 1
Pad
爲了讓提示/名稱表的下一個元素出如今偶數地址,這裏可能須要填充0個或1個NULL字節。
6.4.4導入地址表
導入地址表的結構和內容與導入查找表徹底同樣,直到文件被綁定。在綁定過程當中,用導入符號的32位(PE32)或64位(PE32+)地址覆蓋導入地址表中的相應項。這些地址是導入符號的實際內存地址,儘管技術上仍把它們稱爲「虛擬地址」。加載器一般會處理綁定。
6.5 .pdata
.pdata 節是由用於異常處理的函數表項組成的數組。可選文件頭中的 Exception Table (異常表)域指向它。在將它們放進最終的映像文件以前,這些項必須按函數地址(下列每一個結構的第一個域)排序。下面描述了函數表項的三種格式,使用哪種取決於目標平臺。
對於32位的MIPS映像來講,其函數表項格式以下:
偏移
大小
描述
0
4
Begin Address
相應函數的VA。
4
4
End Address
函數結尾的VA。
8
4
Exception Handler
指向要執行的異常處理程序的指針。
12
4
Handler Data
指向要傳遞給異常處理程序的附加數據的指針。
16
4
Prolog End Address
函數prolog代碼結尾的VA。
 
對於 ARM PowerPC SH3 SH4 Windows CE 平臺來講,其函數表項格式以下:
偏移
大小
描述
0
4
Begin Address
相應函數的VA。
4
8
Prolog Length
函數prolog代碼包含的指令數。
4
22
Function Length
函數代碼包含的指令數。
4
1
32-bit Flag
若是此位爲1,代表函數由32位指令組成。不然,函數由16位指令組成。
4
1
Exception Flag
若是此位爲1,代表存在用於此函數的異常處理程序;不然,不存在異常處理程序。
 
對於x64和Itanium平臺來講,其函數表項格式以下:
偏移
大小
描述
0
4
Begin Address
相應函數的RVA。
4
4
End Address
函數結尾的RVA。
8
4
Unwind Information
用於異常處理的展開( Unwind )信息的RVA。
6.6 .reloc節(僅適用於映像文件)
基址重定位表包含了映像中全部須要重定位的內容。可選文件頭中的數據目錄中的Base Relocation Table(基址重定位表)域給出了基址重定位表所佔的字節數。要獲取更多信息,請參考3.4.3節「可選文件頭中的數據目錄(僅適用於映像文件) 」。基址重定位表被劃分紅許多塊,每一塊表示一個4K頁面範圍內的基址重定位信息,它必須從32位邊界開始。
加載器不須要處理由連接器解析的基址重定位信息,除非映像不能被加載到PE文件頭中指定的映像基地址處。
6.6.1基址重定位塊
個基址重定位塊的開頭都是以下結構:
偏移
相關文章
相關標籤/搜索