PE 格式

此規格描述 Windows 系列作業系統下的可執行檔 (image) 檔案和物件檔結構。 這些檔案分別稱為可攜式可執行檔 (PE) 和通用物件檔格式 (COFF) 檔案。

注意

本檔旨在協助開發適用於 Windows 的工具和應用程式,但不保證在所有方面都是完整的規格。 Microsoft 保留未經通知變更此文件的權利。

這個 Microsoft 可攜式可執行檔和通用物件檔格式規格的修訂會取代此規格的所有先前修訂。

一般概念

本檔會指定 Microsoft Windows 作業系統系列下可執行檔(image)檔案和物件檔案的結構。 這些檔案分別稱為可攜式可執行檔 (PE) 和通用物件檔格式 (COFF) 檔案。 「可攜式可執行檔」名稱是指格式不是架構特定的事實。

下表說明此規格中出現的某些概念:

名稱 描述
屬性憑證
用來將可驗證語句與映像產生關聯的憑證。 許多不同的可驗證語句可以與檔案相關聯;其中一個最有用的是軟體製造商的語句,指出影像的訊息摘要預期是什麼。 訊息摘要類似於總和檢查碼,但很難偽造。 因此,很難修改檔案,使其與源檔具有相同的訊息摘要。 您可以使用公用或私鑰密碼編譯配置,驗證語句是否由製造商進行驗證。 本文件說明屬性憑證的詳細數據,除了允許將憑證插入圖像檔之外。
日期/時間戳
用於 PE 或 COFF 檔案中數個位置不同用途的戳記。 在大部分情況下,每個戳記的格式與 C 執行時間連結庫中的時間函式所使用的格式相同。 如需例外狀況,請參閱偵錯類型中的IMAGE_DEBUG_TYPE_REPRO描述元。 如果戳記值為 0 或0xFFFFFFFF,則它不代表實際或有意義的日期/時間戳。
檔案指標
在鏈接器處理之前,檔案本身內專案的位置(在物件檔案的情況下)或載入器(在圖像文件的情況下)。 換句話說,這是檔案中儲存在磁碟上的位置。
連接
Microsoft Visual Studio 所提供的連結器參考。
物件檔案
作為連結器輸入的檔案。 鏈接器會產生圖像檔,接著會當做載入器輸入使用。 “object file” 一詞不一定表示任何與面向物件程式設計的連接。
保留,必須是 0
欄位的描述,指出產生器之字段的值必須為零,取用者必須忽略字段。
相對虛擬位址 (RVA)
在圖像檔案中,這是專案載入記憶體之後的位址,映像檔的基位址會從中減去。 專案的 RVA 幾乎一律與它在磁碟上檔案中的位置(檔案指標)不同。
在對象檔中,RVA 較不有意義,因為未指派記憶體位置。 在此情況下,RVA 會是區段內的位址(本表稍後所述),稍後會在鏈接期間套用重新配置。 為了簡單起見,編譯程式應該只會將每個區段中的第一個 RVA 設定為零。
部分
PE 或 COFF 檔案內程式代碼或數據的基本單位。 例如,對象檔中的所有程式代碼都可以在單一區段內合併,或者每個函式都可以佔用自己的區段。。 使用更多區段時,檔案額外負荷較多,但連結器可以更選擇性地連結程序代碼。 區段類似於 Intel 8086 架構中的區段。 區段中的所有原始數據都必須連續載入。 此外,圖像檔可以包含數個區段,例如 .tls 或 .reloc ,這些區段有特殊用途。
虛擬位址 (VA)
與 RVA 相同,不同之處在於映像檔的基位址不會減去。 地址稱為 VA,因為 Windows 會為每個進程建立不同的 VA 空間,與物理記憶體無關。 針對幾乎所有目的,VA 應該只被視為位址。 VA 不如 RVA 那麼可預測,因為載入器可能不會在其慣用位置載入映像。

概觀

下列清單描述 Microsoft PE 可執行檔案格式,其中影像標頭的基底位於頂端。 MS-DOS 2.0 Compatible EXE Header 到 PE 標頭之前未使用的區段的 區段是 MS-DOS 2.0 區段,而且僅用於 MS-DOS 相容性。

  • MS-DOS 2.0 相容的 EXE 標頭

  • 閑置

  • OEM 識別碼

    OEM 資訊

    位移至PE標頭

  • MS-DOS 2.0 Stub 程式和重新配置數據表

  • 閑置

  • PE 標頭 (對齊 8 位元組界限)

  • 區段標頭

  • 影像頁面:

    匯入資訊

    匯出資訊

    基底重新配置

    資源資訊

下列清單描述 Microsoft COFF 物件模組格式:

  • Microsoft COFF 標頭

  • 區段標頭

  • 原始資料:

    code

    資料

    偵錯資訊

    重新配置

檔案標頭

PE 檔案標頭包含 Microsoft MS-DOS 存根、PE 簽章、COFF 檔案標頭,以及選擇性標頭。 COFF 物件文件標頭是由 COFF 檔案標頭和選擇性標頭所組成。 在這兩種情況下,檔案標頭會緊接在區段標頭後面。

MS-DOS 存根 (僅限影像)

MS-DOS 存根是在 MS-DOS 下執行的有效應用程式。 它會放在 EXE 映像的前面。 鏈接器在此放置預設存根,當映像在 MS-DOS 中執行時,會列印出「此程式無法以 DOS 模式執行」訊息。 用戶可以使用 /STUB 鏈接器選項來指定不同的存根。

在位置0x3c,存根具有PE簽章的檔案位移。 這項資訊可讓 Windows 正確執行映像檔,即使它有 MS-DOS 存根。 此檔案位移位於連結期間的位置0x3c。

簽章 (僅限影像)

MS-DOS 存根之後,在位移0x3c指定的檔案位移,是 4 位元組簽章,會將檔案識別為 PE 格式影像檔。 此簽章為 「PE\0\0」 (字母 “P” 和 “E” 後面接著兩個 Null 位元組)。

COFF 檔案標頭 (物件和影像)

在物件檔案的開頭,或圖像檔簽章之後,是標準 COFF 檔案標頭,格式如下。 請注意,Windows 載入器會將區段數目限制為96。

位移 大小 欄位 描述
0
2

識別目標計算機類型的數位。 如需詳細資訊,請參閱 機器類型
2
2
NumberOfSections
區段數目。 這指出區段表 (緊接在標頭之後) 的大小。
4
4
TimeDateStamp
自 1970 年 1 月 1 日 00:00 起的秒數低 32 位(C 運行時間time_t值),指出檔案的建立時間。
8
4
PointerToSymbolTable
COFF 符號數據表的檔案位移,如果沒有 COFF 符號數據表,則為零。 映射的這個值應該是零,因為 COFF 偵錯資訊已被取代。
12
4
NumberOfSymbols
符號表中的項目數。 此資料可以用來尋找字串表 (緊接在符號表之後)。 映射的這個值應該是零,因為 COFF 偵錯資訊已被取代。
16
2
SizeOfOptionalHeader
選擇性標頭的大小,這是可執行檔所需的,但不適用於對象檔。 物件檔案的這個值應該為零。 如需標頭格式的描述,請參閱選擇性標頭(僅限影像)。
18
2
特徵
指出檔案屬性的旗標。 如需特定旗標值,請參閱 特性

機器類型

[機器] 欄位具有下列其中一個值,可指定 CPU 類型。 映像檔只能在指定的計算機上或模擬指定計算機的系統上執行。

常數 Description
IMAGE_FILE_MACHINE_UNKNOWN
0x0
此欄位的內容假設適用於任何電腦類型
IMAGE_FILE_MACHINE_ALPHA
0x184
Alpha AXP,32 位位址空間
IMAGE_FILE_MACHINE_ALPHA64
0x284
Alpha 64、64 位位址空間
IMAGE_FILE_MACHINE_AM33
0x1d3
松下田AM33
IMAGE_FILE_MACHINE_AMD64
0x8664
x64
IMAGE_FILE_MACHINE_ARM
0x1c0
ARM 小端
IMAGE_FILE_MACHINE_ARM64
0xaa64
ARM64 小 endian
IMAGE_FILE_MACHINE_ARMNT
0x1c4
ARM Thumb-2 小 endian
IMAGE_FILE_MACHINE_AXP64
0x284
AXP 64 (與 Alpha 64 相同)
IMAGE_FILE_MACHINE_EBC
0xebc
EFI 位元組程序代碼
IMAGE_FILE_MACHINE_I386
0x14c
Intel 386 或更新版本的處理器和相容的處理器
IMAGE_FILE_MACHINE_IA64
0x200
Intel Itanium 處理器系列
IMAGE_FILE_MACHINE_LOONGARCH32
0x6232
LoongArch 32 位處理器系列
IMAGE_FILE_MACHINE_LOONGARCH64
0x6264
LoongArch 64 位處理器系列
IMAGE_FILE_MACHINE_M32R
0x9041
三菱 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
Power PC 小端
IMAGE_FILE_MACHINE_POWERPCFP
0x1f1
支援浮點支援的PowerPC
IMAGE_FILE_MACHINE_R4000
0x166
MIPS 小 endian
IMAGE_FILE_MACHINE_RISCV32
0x5032
RISC-V 32 位位址空間
IMAGE_FILE_MACHINE_RISCV64
0x5064
RISC-V 64 位位址空間
IMAGE_FILE_MACHINE_RISCV128
0x5128
RISC-V 128 位位址空間
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
拇指
IMAGE_FILE_MACHINE_WCEMIPSV2
0x169
MIPS 小端 WCE v2

特性

[特性] 欄位包含旗標,指出物件或圖像檔的屬性。 目前已定義下列旗標:

旗標 Description
IMAGE_FILE_RELOCS_STRIPPED
0x0001
僅限映像、Windows CE 和 Microsoft Windows NT 和更新版本。 這表示檔案不包含基底重新配置,因此必須載入其慣用的基位址。 如果基位址無法使用,載入器會報告錯誤。 連結器的預設行為是從可執行檔 (EXE) 檔案移除基底重新配置。
IMAGE_FILE_EXECUTABLE_IMAGE
0x0002
僅限影像。 這表示映像檔有效且可執行。 如果未設定此旗標,表示連結器錯誤。
IMAGE_FILE_LINE_NUMS_STRIPPED
0x0004
已移除COFF行號。 此旗標已被取代,且應該是零。
IMAGE_FILE_LOCAL_SYMS_STRIPPED
0x0008
已移除本機符號的 COFF 符號數據表專案。 此旗標已被取代,且應該是零。
IMAGE_FILE_AGGRESSIVE_WS_TRIM
0x0010
已過時。 積極修剪工作集。 此旗標已被取代為 Windows 2000 和更新版本,且必須是零。
IMAGE_FILE_LARGE_ADDRESS_ AWARE
0x0020
應用程式可以處理 > 2 GB 位址。
0x0040
此旗標保留供日後使用。
IMAGE_FILE_BYTES_REVERSED_LO
0x0080
小尾:最小有效位 (LSB) 在記憶體中最重要的位 (MSB) 之前。 此旗標已被取代,且應該是零。
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 之前。 此旗標已被取代,且應該是零。

選擇性標頭(僅限影像)

每個圖像檔都有選擇性標頭,可提供載入器的資訊。 從某種意義上說,這個標頭是選擇性的,即某些檔案(特別是物件檔案)沒有它。 對於圖像檔,此標頭是必要的。 物件檔案可以有選擇性的標頭,但一般而言,這個標頭在對象檔中沒有函式,但是為了增加其大小。

請注意,選擇性標頭的大小不是固定的。 COFF 標頭中的 SizeOfOptionalHeader 字段必須用來驗證特定資料目錄檔案的探查未超過 SizeOfOptionalHeader。 如需詳細資訊,請參閱 COFF 檔案標頭(物件和影像)。

選擇性標頭的 NumberOfRvaAndSizes 字段也應該用來確保不會探查特定數據目錄專案超出選擇性標頭。 此外,請務必驗證選擇性標頭魔術編號,以取得格式相容性。

選擇性標頭魔術數位會決定影像是PE32或PE32+可執行檔。

魔術數位 PE 格式
0x10b
PE32
0x20b
PE32+

PE32+ 映像允許 64 位位址空間,同時將影像大小限制為 2 GB。 其他PE32+修改會在各自的區段中加以解決。

選擇性標頭本身有三個主要部分。

位移 (PE32/PE32+) 大小 (PE32/PE32+) 頁首部分 描述
0
28/24
標準欄位
針對 COFF 的所有實作所定義的欄位,包括 UNIX。
28/24
68/88
Windows 特定欄位
支援 Windows 特定功能的其他欄位(例如子系統)。
96/112
變數
數據目錄
在映像檔中找到的特殊數據表位址/大小組,並由操作系統使用(例如,匯入數據表和匯出數據表)。

選擇性標頭標準欄位 (僅限影像)

選擇性標頭的前八個字段是針對 COFF 的每個實作所定義的標準欄位。 這些欄位包含適用於載入和執行可執行檔的一般資訊。 PE32+ 格式不會變更它們。

位移 大小 欄位 描述
0
2
魔法
識別圖像文件狀態的不帶正負號整數。 最常見的數位是0x10B,它會將其識別為一般可執行檔。 0x107將其識別為 ROM 映射,0x20B將其識別為 PE32+ 可執行檔。
2
1
MajorLinkerVersion
連結器主要版本號碼。
3
1
MinorLinkerVersion
連結器次要版本號碼。
4
4
SizeOfCode
如果有多個區段,則程式代碼區段的大小或所有程式代碼區段的總和。
8
4
SizeOfInitializedData
初始化的數據區段大小,如果有多個數據區段,則為所有這類區段的總和。
12
4
SizeOfUninitializedData
未初始化的數據區段大小(BSS),如果有多個 BSS 區段,則為所有這類區段的總和。
16
4
AddressOfEntryPoint
當可執行檔載入記憶體時,相對於映像基底的進入點位址。 針對程式映像,這是起始位址。 針對設備驅動器,這是初始化函式的位址。 DLL 的進入點是選擇性的。 當沒有任何進入點存在時,此欄位必須是零。
20
4
BaseOfCode
當程式代碼開頭區段載入記憶體時,相對於映像基底的位址。

PE32 包含此額外的欄位,此欄位在 PE32+ 中不存在,請遵循 BaseOfCode。

位移 大小 欄位 描述
24
4
BaseOfData
當數據開頭區段載入記憶體時,相對於影像基底的位址。

選擇性標頭 Windows 特定欄位 (僅限影像)

接下來的 21 個字段是 COFF 選擇性標頭格式的延伸模組。 它們包含 Windows 中連結器和載入器所需的其他資訊。

位移 (PE32/ PE32+) 大小 (PE32/ PE32+) 欄位 描述
28/24
4/8
ImageBase
載入記憶體時,影像第一個字節的慣用位址;必須是 64 K 的倍數。DLL 的預設值為 0x10000000。 Windows CE EXE 的預設值為 0x00010000。 Windows NT、Windows 2000、Windows XP、Windows 95、Windows 98 和 Windows Me 的預設值為 0x00400000。
32/32
4
SectionAlignment
載入至記憶體時對齊區段 (以位元組為單位)。 它必須大於或等於 FileAlignment。 預設值為架構的頁面大小。
36/36
4
FileAlignment
對齊因素 (以位元組為單位),用來對齊映像檔中的區段原始資料。 此值應該是介於 512 到 64 K 之間的 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
保留的 必須是零。
56/56
4
SizeOfImage
映射的大小(以位元組為單位),包括所有標頭,因為映像會載入記憶體中。 它必須是 SectionAlignment 的倍數。
60/60
4
SizeOfHeaders
MS-DOS 存根、PE 標頭和區段標頭的合併大小會四捨五入為 FileAlignment 的倍數。
64/64
4
校驗
圖像檔總和檢查碼。 計算總和檢查碼的演算法會併入IMAGHELP.DLL。 以下是在載入時間檢查驗證:所有驅動程序、在開機時間載入的任何 DLL,以及載入至重要 Windows 進程的任何 DLL。
68/68
2
子系統
執行此映像所需的子系統。 如需詳細資訊,請參閱 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
保留的 必須是零。
92/108
4
NumberOfRvaAndSizes
選擇性標頭其餘部分的數據目錄項目數目。 每一個都描述位置和大小。
Windows 子系統

為選擇性標頭的子系統字段定義的下列值會決定執行映射所需的 Windows 子系統(如果有的話)。

常數 Description
IMAGE_SUBSYSTEM_UNKNOWN
0
未知的子系統
IMAGE_SUBSYSTEM_NATIVE
1
設備驅動器和原生 Windows 進程
IMAGE_SUBSYSTEM_WINDOWS_GUI
2
Windows 圖形使用者介面 (GUI) 子系統
IMAGE_SUBSYSTEM_WINDOWS_CUI
3
Windows 字元子系統
IMAGE_SUBSYSTEM_OS2_CUI
5
OS/2 字元子系統
IMAGE_SUBSYSTEM_POSIX_CUI
7
Posix 字元子系統
IMAGE_SUBSYSTEM_NATIVE_WINDOWS
8
原生 Win9x 驅動程式
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
IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
16
Windows 開機應用程式。
DLL 特性

下列值是針對選擇性標頭的 DllCharacteristics 字段所定義。

常數 Description
0x0001
保留的 必須是零。
0x0002
保留的 必須是零。
0x0004
保留的 必須是零。
0x0008
保留的 必須是零。
IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
0x0020
映像可以處理高 entropy 64 位虛擬位址空間。
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
請勿系結映像。
IMAGE_DLLCHARACTERISTICS_APPCONTAINER
0x1000
映像必須在 AppContainer 中執行。
IMAGE_DLLCHARACTERISTICS_ WDM_DRIVER
0x2000
WDM 驅動程式。
IMAGE_DLLCHARACTERISTICS_GUARD_CF
0x4000
映像支援控制流程防護。
IMAGE_DLLCHARACTERISTICS_ TERMINAL_SERVER_AWARE
0x8000
終端伺服器感知。

選擇性標頭資料目錄(僅限影像)

每個資料目錄都會提供 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
匯出數據表
匯出數據表位址和大小。 如需詳細資訊,請參閱 .edata 區段(僅限影像)。
104/120
8
匯入數據表
匯入數據表位址和大小。 如需詳細資訊,請參閱 .idata 區段
112/128
8
資源數據表
資源數據表位址和大小。 如需詳細資訊,請參閱 .rsrc 區段
120/136
8
例外狀況數據表
例外狀況數據表位址和大小。 如需詳細資訊,請參閱 .pdata 區段
128/144
8
憑證數據表
屬性憑證數據表位址和大小。 如需詳細資訊,請參閱屬性憑證數據表(僅限映射)。
136/152
8
基礎重新配置數據表
基底重新配置數據表位址和大小。 如需詳細資訊,請參閱 .reloc 區段(僅限映射)。
144/160
8
調試
偵錯數據起始位址和大小。 如需詳細資訊,請參閱 .debug 區段
152/168
8
建築
保留,必須是 0
160/176
8
Global Ptr
要儲存在全域指標緩存器中之值的 RVA。 這個結構的大小成員必須設定為零。
168/184
8
TLS 數據表
線程本機記憶體 (TLS) 資料表位址和大小。 如需詳細資訊,請參閱 .tls 區段
176/192
8
載入設定數據表
載入組態數據表位址和大小。 如需詳細資訊,請參閱載入組態結構(僅限映像)。
184/200
8
系結匯入
系結的匯入數據表位址和大小。
192/208
8
Iat
匯入地址數據表位址和大小。 如需詳細資訊,請參閱 匯入位址表
200/216
8
延遲匯入描述元
延遲匯入描述元位址和大小。 如需詳細資訊,請參閱延遲載入匯入資料表(僅限映像)。
208/224
8
CLR 運行時間標頭
CLR 執行時間標頭位址和大小。 如需詳細資訊,請參閱 .cormeta 區段(僅限物件)。
216/232
8
保留,必須是零

憑證數據表進入會指向屬性憑證的數據表。 這些憑證不會載入記憶體作為映像的一部分。 因此,此專案的第一個字段通常是 RVA,而是檔案指標。

區段表格(區段標頭)

區段數據表的每個數據列實際上都是區段標頭。 如果有的話,此數據表會緊接在選擇性標頭後面。 此位置是必要的,因為檔案標頭不包含區段數據表的直接指標。 相反地,區段數據表的位置取決於計算標頭之後第一個字節的位置。 請務必使用檔案標頭中指定的選擇性標頭大小。

區段數據表中的項目數是由檔案標頭中的 NumberOfSections 欄位所指定。 區段數據表中的專案是從一個 (1) 開始編號。 程式代碼和數據記憶體區段專案的順序由連結器選擇。

在圖像檔案中,區段的 VA 必須由連結器指派,使其依遞增順序和相鄰順序指派,而且它們必須是選擇性標頭中 SectionAlignment 值的倍數。

每個區段標頭(區段數據表專案)都有下列格式,每個項目總共 40 個字節。

位移 大小 欄位 描述
0
8
名字
8 位元組、Null 填補的UTF-8編碼字串。 如果字串長度正好為8個字元,則不會終止Null。 對於較長的名稱,此欄位組包含斜線 (/) ,後面接著 ASCII 表示的十進位數,這是字串數據表中的位移。 可執行檔映像不使用字串數據表,且不支援長度超過8個字元的區段名稱。 對象檔中的長名稱會在發出至可執行檔時遭到截斷。
8
4
VirtualSize
載入記憶體時區段的總大小。 如果此值大於 SizeOfRawData,則區段會以零填補。 此欄位僅適用於可執行影像,而且應該針對物件檔設定為零。
12
4
VirtualAddress
針對可執行檔映像,當區段載入記憶體時,相對於映像基底區段的第一個字節位址。 對於對象檔,此欄位是套用重新配置之前第一個字節的位址;為了簡單起見,編譯程式應該將此設定為零。 否則,它是在重新配置期間從位移減去的任意值。
16
4
SizeOfRawData
區段的大小(適用於物件檔)或磁碟上初始化數據的大小(針對映像檔)。 針對可執行的映像,這必須是選擇性標頭中的多個 FileAlignment。 如果這小於 VirtualSize,則區段的其餘部分會以零填滿。 因為 SizeOfRawData 欄位會四捨五入,但 VirtualSize 字段不是,因此 SizeOfRawData 也可以大於 VirtualSize。 當區段只包含未初始化的數據時,此欄位應為零。
20
4
PointerToRawData
COFF 檔案中區段第一頁的檔案指標。 針對可執行的映像,這必須是選擇性標頭中的多個 FileAlignment。 針對物件檔案,值應該對齊 4 位元組界限,以獲得最佳效能。 當區段只包含未初始化的數據時,此欄位應為零。
24
4
PointerToRelocations
區段重新配置項目開頭的檔案指標。 如果沒有重新配置,則可執行檔映像會設定為零。
28
4
PointerToLinenumbers
區段行號項目開頭的檔案指標。 如果沒有 COFF 行號,這會設定為零。 映射的這個值應該是零,因為 COFF 偵錯資訊已被取代。
32
2
NumberOfRelocations
區段的重新配置項目數目。 對於可執行的映像,這會設定為零。
34
2
NumberOfLinenumbers
區段的行號項目數。 映射的這個值應該是零,因為 COFF 偵錯資訊已被取代。
36
4
特徵
描述區段特性的旗標。 如需詳細資訊,請參閱一節。

 

區段旗標

區段標頭之 [特性] 字段中的區段旗標表示區段的特性。

旗標 Description
0x00000000
保留供未來使用。
0x00000001
保留供未來使用。
0x00000002
保留供未來使用。
0x00000004
保留供未來使用。
IMAGE_SCN_TYPE_NO_PAD
0x00000008
區段不應填補到下一個界限。 此旗標已經過時,且已由IMAGE_SCN_ALIGN_1BYTES取代。 這隻適用於物件檔。
0x00000010
保留供未來使用。
IMAGE_SCN_CNT_CODE
0x00000020
區段包含可執行的程序代碼。
IMAGE_SCN_CNT_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 資料。 如需詳細資訊,請參閱 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,則實際重新配置計數會儲存在第一次重新配置的 32 位 VirtualAddress 欄位中。 如果已設定IMAGE_SCN_LNK_NRELOC_OVFL,而且區段中的重新配置少於0xffff,就會發生錯誤。

群組區段 (僅限物件)

“$” 字元 (dollar sign) 在物件檔的區段名稱中具有特殊的解譯。

判斷將包含物件區段內容的影像區段時,鏈接器會捨棄 「$」 及其後面的所有字元。 因此,名為的物件區段。text$X 實際上會 參與影像中的 .text 區段。

不過,“$” 後面的字元會決定對影像區段的貢獻順序。 具有相同物件區段名稱的所有貢獻都會在影像中連續配置,而貢獻區塊會依物件區段名稱依語匯順序排序。 因此,在 .text$W 貢獻之後,以及 .text$Y 參與之前,對象檔案中具有 .text$X 區段名稱的所有項目最後會一起。

圖像檔案中的區段名稱絕不包含 「$」 字元。

檔案的其他內容

到目前為止所描述的數據結構,最多和包括選擇性標頭,都位於檔案開頭的固定位移(如果檔案是包含 MS-DOS 存根的映像,則位於PE標頭的固定位移。

COFF 物件或圖像檔案的其餘部分包含不一定位於任何特定檔案位移的數據區塊。 相反地,位置是由選擇性標頭或區段標頭中的指標所定義。

例外狀況是,具有 SectionAlignment 值的影像小於架構的頁面大小(Intel x86 和 MIPS 為 4 K,而 Itanium 則為 8 K)。 如需 SectionAlignment 的描述,請參閱選擇性標頭(僅限影像)。 在此情況下,區段數據的檔案位移有條件約束,如一節所述。另一個例外狀況是,屬性憑證和偵錯信息必須放在映像檔的結尾,而屬性憑證數據表緊接在偵錯區段之前,因為載入器不會將這些信息對應到記憶體中。 不過,屬性憑證和偵錯資訊的相關規則不適用於對象檔。

區段數據

區段的初始化數據是由簡單的位元組區塊所組成。 不過,對於包含所有零的區段,不需要包含區段數據。

每個區段的數據位於區段標頭中 PointerToRawData 字段所提供的檔案位移。 檔案中此數據的大小會以 SizeOfRawData 字段表示。 如果 SizeOfRawData 小於 VirtualSize,則餘數會以零填補。

在圖像檔案中,區段數據必須對齊界限,如選擇性標頭中的 FileAlignment 字段所指定。 區段數據必須依對應區段的 RVA 值順序顯示(區段數據表中的個別區段標頭也一樣)。

如果選擇性標頭中的 SectionAlignment 值小於架構的頁面大小,則圖像檔案會有額外的限制。 對於這類檔案,檔案中區段數據的位置必須符合載入映射時記憶體中的位置,讓區段數據的實體位移與 RVA 相同。

COFF 重新設定 (僅限物件)

對象檔包含 COFF 重新配置,指定在影像檔中放置區段數據時應如何修改區段數據,並隨後載入記憶體中。

圖像檔不包含 COFF 重新配置,因為所有參考的符號都已獲指派一般位址空間中的位址。 影像包含 .reloc 區段中基底重新配置的形式重新配置資訊(除非影像具有 IMAGE_FILE_RELOCS_STRIPPED 屬性)。 如需詳細資訊,請參閱 .reloc 區段(僅限映射)。

對於對象檔中的每個區段,固定長度記錄的陣列會保留區段的COFF重新配置。 陣列的位置和長度是在區段標頭中指定。 陣列的每個元素都有下列格式。

位移 大小 欄位 描述
0
4
VirtualAddress
套用重新配置之項目的位址。 這是區段開頭的位移,加上區段 RVA/Offset 字段的值。 請參閱一節。 例如,如果區段的第一個字節有0x10位址,則第三個字節的位址為 0x12。
4
4
SymbolTableIndex
符號數據表中以零起始的索引。 此符號會提供要用於重新配置的位址。 如果指定的符號具有區段儲存類別,則符號的位址是具有相同名稱之第一個區段的位址。
8
2
輸入
值,表示應該執行的重新配置類型。 有效的重新配置類型取決於機器類型。 請參閱 類型指標

 

如果 SymbolTableIndex 欄位所參考的符號具有儲存類別IMAGE_SYM_CLASS_SECTION,符號的位址就是區段的開頭。 區段通常位於相同的檔案中,但對象檔是封存(連結庫)的一部分時除外。 在此情況下,您可以在封存中任何其他具有與目前物件檔案相同封存成員名稱的物件檔案中找到 區段。 (與封存成員名稱的關聯性用於匯入數據表的連結,也就是 .idata 區段。

類型指標

重新設定記錄的 [類型] 字段表示應該執行何種重新配置。 針對每種類型的電腦定義不同的重新配置類型。

x64 處理器

下列重新配置類型指標是針對 x64 和相容的處理器所定義。

常數 Description
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處理器所定義的。

常數 Description
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
子程式呼叫的參考。 參考包含兩個具有11位位位移的16位指令。
IMAGE_REL_ARM_REL32
0x000A
重新配置之後位元組的32位相對位址。
IMAGE_REL_ARM_SECTION
0x000E
包含目標的區段的16位區段索引。 這可用來支援偵錯資訊。
IMAGE_REL_ARM_SECREL
0x000F
目標從區段開頭的32位位移。 這可用來支援偵錯資訊和靜態線程本機記憶體。
IMAGE_REL_ARM_MOV32
0x0010
目標的32位 VA。 此重新配置會針對低 16 位套用 MOVW 指令,後面接著高 16 位的 MOVT。
IMAGE_REL_THUMB_MOV32
0x0011
目標的32位 VA。 此重新配置會針對低 16 位套用 MOVW 指令,後面接著高 16 位的 MOVT。
IMAGE_REL_THUMB_BRANCH20
0x0012
指令會以21位相對於2位元組對齊的目標位移來修正。 位移的最小有效位一律為零,而且不會儲存。 此重新配置對應到 Thumb-2 32 位條件 B 指令。
閑置
0x0013
IMAGE_REL_THUMB_BRANCH24
0x0014
指令會以25位相對於2位元組對齊的目標位移來修正。 位移的最小有效位為零,而且不會儲存。此重新配置對應至 Thumb-2 B 指令。
IMAGE_REL_THUMB_BLX23
0x0015
指令會以 25 位相對於 4 位元組對齊的目標位移來修正。 位移的低 2 位為零,且不會儲存。
此重新配置對應至 Thumb-2 BLX 指示。
IMAGE_REL_ARM_PAIR
0x0016
只有在重新配置緊接著ARM_REFHI或THUMB_REFHI時才有效。 其 SymbolTableIndex 包含位移,而不是符號數據表中的索引。

 

ARM64 處理器

ARM64 處理器定義了下列重新配置類型指標。

常數 Description
IMAGE_REL_ARM64_ABSOLUTE
0x0000
會忽略重新配置。
IMAGE_REL_ARM64_ADDR32
0x0001
目標的32位 VA。
IMAGE_REL_ARM64_ADDR32NB
0x0002
目標的32位 RVA。
IMAGE_REL_ARM64_BRANCH26
0x0003
B 和 BL 指示的 26 位相對於目標位移。
IMAGE_REL_ARM64_PAGEBASE_REL21
0x0004
目標的頁面基底,用於 ADRP 指示。
IMAGE_REL_ARM64_REL21
0x0005
指示 ADR 的 12 位相對位移至目標
IMAGE_REL_ARM64_PAGEOFFSET_12A
0x0006
目標的12位分頁位移,適用於具有零位移的ADD/ADDS指示。
IMAGE_REL_ARM64_PAGEOFFSET_12L
0x0007
目標的12位分頁位移,用於指示 LDR(已編制索引、不帶正負號的立即)。
IMAGE_REL_ARM64_SECREL
0x0008
目標從區段開頭的32位位移。 這可用來支援偵錯資訊和靜態線程本機記憶體。
IMAGE_REL_ARM64_SECREL_LOW12A
0x0009
目標區段位移的位 0:11,適用於具有零移位的 ADD/ADDS (immediate) 指示。
IMAGE_REL_ARM64_SECREL_HIGH12A
0x000A
目標區段位移的位 12:23,適用於具有零移位的 ADD/ADDS 指示。
IMAGE_REL_ARM64_SECREL_LOW12L
0x000B
目標區段位移的位 0:11,用於指示 LDR(索引、未帶正負號的立即)。
IMAGE_REL_ARM64_TOKEN
0x000C
CLR 令牌。
IMAGE_REL_ARM64_SECTION
0x000D
包含目標的區段的16位區段索引。 這可用來支援偵錯資訊。
IMAGE_REL_ARM64_ADDR64
0x000E
重新配置目標的64位 VA。
IMAGE_REL_ARM64_BRANCH19
0x000F
條件式 B 指令的 19 位位移移目標。
IMAGE_REL_ARM64_BRANCH14
0x0010
14 位位移轉至重新配置目標,以取得 TBZ 和 TBNZ 的指示。
IMAGE_REL_ARM64_REL32
0x0011
重新配置之後位元組的32位相對位址。
Hitachi SuperH 處理器

下列重新配置類型指標是針對SH3和SH4處理器所定義。 SH5 特定的搬遷被指出為SHM(SH Media)。

常數 Description
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
8 位指令的參考,其中包含目標符號的有效 16 位 VA。
IMAGE_REL_SH3_DIRECT8_LONG
0x0005
8 位指令的參考,其中包含目標符號的有效 32 位 VA。
IMAGE_REL_SH3_DIRECT4
0x0006
8 位位置的參考,其低 4 位包含目標符號的 VA。
IMAGE_REL_SH3_DIRECT4_WORD
0x0007
8 位指令的參考,其低 4 位包含目標符號的有效 16 位 VA。
IMAGE_REL_SH3_DIRECT4_LONG
0x0008
8 位指令的參考,其低 4 位包含目標符號的有效 32 位 VA。
IMAGE_REL_SH3_PCREL8_WORD
0x0009
8 位指令的參考,其中包含目標符號的有效 16 位相對位移。
IMAGE_REL_SH3_PCREL8_LONG
0x000A
包含目標符號之有效 32 位相對位移的 8 位指令參考。
IMAGE_REL_SH3_PCREL12_WORD
0x000B
16 位指令的參考,其低 12 位包含目標符號的有效 16 位相對位移。
IMAGE_REL_SH3_STARTOF_SECTION
0x000C
32 位位置的參考,該位置是包含目標符號之區段的 VA。
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
longwords 中目前指令的位移。 如果未設定 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
只有在重新配置緊接在 REFHALF、RELHALF 或 RELLO 重新配置之後時才有效。 重新配置的 SymbolTableIndex 欄位元包含位移,而不是符號數據表中的索引。
IMAGE_REL_SHM_NOMODE
0x8000
重新配置會忽略區段模式。

 

IBM PowerPC 處理器

PowerPC 處理器定義了下列重新配置類型指標。

常數 Description
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
符號位置的 24 位電腦相對位移。
IMAGE_REL_PPC_REL14
0x0007
符號位置的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 位。 這用於載入完整位址的雙指令序列中的第一個指令。 這個重新配置必須緊接在 PAIR 重新配置之後,其 SymbolTableIndex 包含帶正負號的 16 位位移位,該位移轉會新增至從要重新放置的位置擷取的上 16 位移轉。
IMAGE_REL_PPC_REFLO
0x0011
目標 VA 的低 16 位。
IMAGE_REL_PPC_PAIR
0x0012
只有在重新配置緊接 REFHI 或 SECRELHI 重新配置時才有效。 其 SymbolTableIndex 包含位移,而不是符號數據表中的索引。
IMAGE_REL_PPC_SECRELLO
0x0013
目標 32 位位移的低 16 位,從其區段的開頭開始。
IMAGE_REL_PPC_GPREL
0x0015
相對於 GP 快取器的目標 16 位帶正負號位移。
IMAGE_REL_PPC_TOKEN
0x0016
CLR 令牌。

 

Intel 386 處理器

下列重新配置類型指標是針對 Intel 386 和相容的處理器所定義。

常數 Description
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 相對分支和呼叫指示。

 

Intel Itanium 處理器系列 (IPF)

下列重新配置類型指標是針對 Intel Itanium 處理器系列和相容的處理器所定義。 請注意,指示上的重新配置會針對重新配置位移使用套件組合的位移和位置編號。

常數 Description
IMAGE_REL_IA64_ABSOLUTE
0x0000
會忽略重新配置。
IMAGE_REL_IA64_IMM14
0x0001
指令重新配置可以接著新增至目標位址的 ADDEND 重新配置,再將其插入 IMM14 套件組合中指定的位置。 重新配置目標必須是絕對目標,或必須固定影像。
IMAGE_REL_IA64_IMM22
0x0002
指令重新配置後面接著 ADDEND 重新配置,其值會在插入 IMM22 套件組合中的指定位置之前新增至目標位址。 重新配置目標必須是絕對目標,或必須固定影像。
IMAGE_REL_IA64_IMM64
0x0003
這個重新配置的位置編號必須是一個 (1)。 重新配置可以接著新增至目標位址的ADDEND重新配置,再將其值儲存在IMM64套件組合的所有三個位置中。
IMAGE_REL_IA64_DIR32
0x0004
目標的32位 VA。 只有 /LARGEADDRESSAWARE:NO 映射才支援此功能。
IMAGE_REL_IA64_DIR64
0x0005
目標的64位 VA。
IMAGE_REL_IA64_PCREL21B
0x0006
指令會以25位相對於16位對齊的目標位移來修正。 位移的低 4 位為零,且不會儲存。
IMAGE_REL_IA64_PCREL21M
0x0007
指令會以25位相對於16位對齊的目標位移來修正。 位移的低 4 位,即零,不會儲存。
IMAGE_REL_IA64_PCREL21F
0x0008
此重新配置位移的 LSB 必須包含位置編號,而其餘的則是配套位址。 套件組合會以 25 位相對位移來修正 16 位對齊的目標。 位移的低 4 位為零,且不會儲存。
IMAGE_REL_IA64_GPREL22
0x0009
指令重新配置可以接著新增至目標位址的 ADDEND 重新配置,然後是計算並套用至GPREL22套件組合的 22 位 GP 相對位移。
IMAGE_REL_IA64_LTOFF22
0x000A
指令會使用目標符號常值數據表專案的 22 位 GP 相對位移來修正。 鏈接器會根據這個重新配置和可能遵循的 ADDEND 重新配置,建立此常值數據表專案。
IMAGE_REL_IA64_SECTION
0x000B
區段的16位區段索引包含目標。 這可用來支援偵錯資訊。
IMAGE_REL_IA64_SECREL22
0x000C
指令會從其區段開頭修正目標的 22 位位位移。 這個重新配置可以緊接著 ADDEND 重新配置,其 Value 欄位包含區段開頭目標 32 位未帶正負號的位移。
IMAGE_REL_IA64_SECREL64I
0x000D
這個重新配置的位置號碼必須是一個 (1)。 指令會從其區段開頭修正目標的64位位位移。 這個重新配置可以緊接著 ADDEND 重新配置,其 Value 欄位包含區段開頭目標 32 位未帶正負號的位移。
IMAGE_REL_IA64_SECREL32
0x000E
要從其區段開頭之目標 32 位位移來修正的數據位址。
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
一個 60 位的電腦相對修正,一律會保留為 MLX 套件組合的一個美孚指令。
IMAGE_REL_IA64_PCREL60B
0x0016
60 位電腦相對修正。 如果目標位移符合帶正負號的 25 位字段,請將整個套件組合轉換成具有 NOP 的 MBB 套件組合。插槽 1 中的 B 和 25 位 BR 指令(具有 4 個最低位全部為零並捨棄)插槽 2。
IMAGE_REL_IA64_PCREL60F
0x0017
60 位電腦相對修正。 如果目標位移符合帶正負號的 25 位字段,請將整個套件組合轉換成具有 NOP 的 MFB 套件組合。插槽 1 中的 F 和 25 位 (4 個最低位全部為零和已捨棄) BR 指令在插槽 2 中。
IMAGE_REL_IA64_PCREL60I
0x0018
60 位電腦相對修正。 如果目標位移符合帶正負號的 25 位字段,請將整個套件組合轉換成具有 NOP 的 MIB 套件組合。我位於插槽 1 和 25 位 (4 個最低位全部為零和已卸除) BR 指令插槽 2 中。
IMAGE_REL_IA64_PCREL60M
0x0019
60 位電腦相對修正。 如果目標位移符合帶正負號的 25 位字段,請將整個套件組合轉換成具有 NOP 的 MMB 套件組合。插槽 1 中的 M 和 25 位 (4 個最低位全部為零和已捨棄) BR 指令在插槽 2 中。
IMAGE_REL_IA64_IMMGPREL64
0x001a
64 位 GP 相對修正。
IMAGE_REL_IA64_TOKEN
0x001b
CLR 令牌。
IMAGE_REL_IA64_GPREL32
0x001c
32 位 GP 相對修正。
IMAGE_REL_IA64_ADDEND
0x001F
只有在重新配置緊接著下列其中一個重新配置時才有效:IMM14、IMM22、IMM64、GPREL22、LTOFF22、LTOFF64、SECREL22、SECREL64I或SECREL32。 其值包含要套用至套件組合內指示的附加元件,不適用於數據。

 

MIPS 處理器

MIPS 處理器定義了下列重新配置類型指標。

常數 Description
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 位。 這用於載入完整位址的雙指令序列中的第一個指令。 這個重新配置必須緊接著一個 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 位位位移的高 16 位。 重新配置IMAGE_REL_MIPS_PAIR必須緊接在此位置之後。 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
只有在重新配置緊接在 REFHI 或 SECRELHI 重新配置之後時才有效。 其 SymbolTableIndex 包含位移,而不是符號數據表中的索引。

 

三菱 M32R

三菱 M32R 處理器定義了下列重新配置類型指標。

常數 Description
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
目標從計算機移出16位位移,由2位移位並帶正負號
IMAGE_REL_M32R_PCREL8
0x0007
目標從計算機的8位位位移,由2位左移並帶正負號
IMAGE_REL_M32R_REFHALF
0x0008
目標 VA 的 16 個 MSB。
IMAGE_REL_M32R_REFHI
0x0009
目標 VA 的 16 個 MSB,已針對 LSB 符號延伸調整。 這用於載入完整 32 位位址的雙指令序列中的第一個指令。 這個重新配置必須緊接著一個 PAIR 重新配置,其 SymbolTableIndex 包含帶正負號的 16 位位移位,該位移轉會新增至從要重新放置的位置取用的上 16 位移轉。
IMAGE_REL_M32R_REFLO
0x000A
目標 VA 的 16 個 LSB。
IMAGE_REL_M32R_PAIR
0x000B
重新配置必須遵循 REFHI 重新配置。 其 SymbolTableIndex 包含位移,而不是符號數據表中的索引。
IMAGE_REL_M32R_SECTION
0x000C
包含目標的區段的16位區段索引。 這可用來支援偵錯資訊。
IMAGE_REL_M32R_SECREL
0x000D
目標從區段開頭的32位位移。 這可用來支援偵錯資訊和靜態線程本機記憶體。
IMAGE_REL_M32R_TOKEN
0x000E
CLR 令牌。

 

COFF 行號 (已淘汰)

不再產生 COFF 行號,未來將不會取用。

COFF 行號表示原始程式檔中的程式代碼與行號之間的關聯性。 COFF 行號的 Microsoft 格式與標準 COFF 類似,但已擴充為允許單一區段與多個來源檔案中的行號相關。

COFF行號是由固定長度記錄的陣列所組成。 區段標頭中會指定位置(檔案位移)和陣列的大小。 每個行號記錄的格式如下。

位移 大小 欄位 描述
0
4
類型 \
這是兩個字段的聯集:SymbolTableIndex 和 VirtualAddress。 是否使用 SymbolTableIndex 或 RVA 取決於 Linenumber 的值。
4
2
布隆伯
當非零時,此欄位會指定一個以單一為基礎的行號。 當為零時,Type 字段會解譯為函式的符號表索引。

 

[類型] 字段是兩個 4 位元組位元段的聯集:SymbolTableIndex 和 VirtualAddress。

位移 大小 欄位 描述
0
4
SymbolTableIndex
當 Linenumber 為零時使用:為函式符號數據表專案的索引。 這個格式是用來指出一組行號記錄所參考的函式。
0
4
VirtualAddress
當 Linenumber 不是零時使用:對應至所指出來源行之可執行程式代碼的 RVA。 在對象檔中,這包含 區段中的 VA。

 

行號記錄可以將 [Linenumber] 欄位設定為零,並指向符號表中的函式定義,也可以藉由提供正整數(行號)和對象程式代碼中的對應位址,以做為標準行號專案。

一組行號專案一律以第一種格式開頭:函式符號的索引。 如果這是區段中的第一個行號記錄,則如果設定區段的 COMDAT 旗標,它也是函式的 COMDAT 符號名稱。 請參閱 COMDAT 區段(僅限物件)。 符號表中函式的輔助記錄具有指向這個相同行號記錄的Linenumber欄位指標。

識別函式的記錄後面接著任意數目的行號專案,以提供實際行號資訊(也就是說,具有 Linenumber 大於零的專案)。 這些專案是以單一為基礎,相對於函式的開頭,而且代表函式中除了第一行以外的每個來源行。

例如,下列範例的第一個行號記錄會指定 ReverseSign 函式 (ReverseSign 的 SymbolTableIndex 和 Linenumber 設定為零)。 接著,具有 1、2 和 3 之布建伯值的記錄會跟在後面,對應至來源行,如下所示:

// some code precedes ReverseSign function
int ReverseSign(int i)
1: {
2:  return -1 * i;
3: }

COFF 符號數據表

本節中的符號表繼承自傳統的 COFF 格式。 這與 Microsoft Visual C++ 偵錯資訊不同。 檔案可以同時包含 COFF 符號數據表和 Visual C++ 偵錯資訊,而且兩者會保持分開。 某些 Microsoft 工具會針對有限但重要的用途使用符號表,例如將 COMDAT 資訊傳達給連結器。 區段名稱和檔名以及程式代碼和數據符號會列在符號數據表中。

符號表的位置會在 COFF 標頭中指出。

符號表是記錄陣列,每18個字節長。 每個記錄都是標準或輔助符號數據表記錄。 標準記錄會定義符號或名稱,並具有下列格式。

位移 大小 欄位 描述
0
8
名稱 \
符號的名稱,以三個結構的聯集表示。 如果名稱長度不超過 8 個字節,則會使用 8 個字節的陣列。 如需詳細資訊,請參閱 符號名稱表示法
8
4
價值
與符號相關聯的值。 此欄位的解譯取決於 SectionNumber 和 儲存體 Class。 典型的意義是可重新放置的位址。
12
2
SectionNumber
識別區段的帶正負號整數,使用一個基底索引進入區段數據表。 某些值具有特殊意義,如一節 5.4.2 中所定義。
14
2
輸入
表示類型的數位。 Microsoft 工具將此字段設定為0x20(函式)或0x0(不是函式)。 如需詳細資訊,請參閱 類型表示
16
1
儲存體 Class
表示記憶體類別的列舉值。 如需詳細資訊,請參閱 儲存體 類別
17
1
NumberOfAuxSymbols
追蹤此記錄的輔助符號數據表項目數目。

 

零個或多個輔助符號數據表記錄會緊接著每個標準符號數據表記錄。 不過,通常不超過一個輔助符號數據表記錄遵循標準符號數據表記錄(除了擴展名為的 .file 記錄除外)。 每個輔助記錄的大小與標準符號數據表記錄(18 個字節)相同,但是輔助記錄會提供最後一個定義符號的其他資訊,而不是定義新的符號。 要使用哪些格式的選擇取決於 [儲存體 Class] 欄位。 目前定義的輔助符號數據表記錄格式會顯示在「輔助符號記錄」第 5.5 節中。

讀取 COFF 符號數據表的工具必須忽略其解譯未知的輔助符號記錄。 這可讓符號表格式擴充以新增新的輔助記錄,而不會中斷現有的工具。

符號名稱表示法

符號數據表中的 ShortName 欄位包含包含名稱本身的 8 個字節,如果長度不超過 8 個字節,或 ShortName 欄位會提供字串數據表的位移。 若要判斷是否指定名稱本身或位移,請測試前 4 個字節是否等於零。

依照慣例,名稱會被視為以零結尾的 UTF-8 編碼字串。

位移 大小 欄位 描述
0
8
ShortName
8 個字節的陣列。 如果名稱長度小於8個字節,則此陣列會填補右邊的 Null。
0
4

如果名稱超過8個字節,則為所有零的欄位。
4
4
抵消
字串數據表中的位移。

 

區段編號值

一般而言,符號數據表專案中的 [區段值] 字段是區段數據表中的單一索引。 不過,此欄位是帶正負號的整數,而且可以接受負值。 下列值小於一個,具有特殊意義。

常數 Description
IMAGE_SYM_UNDEFINED
0
符號記錄尚未指派區段。 值為零表示外部符號的參考定義於別處。 非零的值是具有值所指定大小的通用符號。
IMAGE_SYM_ABSOLUTE
1-
符號具有絕對值(不可重新放置)值,且不是位址。
IMAGE_SYM_DEBUG
2-
符號提供一般類型或偵錯資訊,但未對應至區段。 Microsoft 工具會搭配 .file 記錄使用此設定(記憶體類別 FILE)。

 

類型表示法

符號數據表專案的 [類型] 字段包含 2 個字節,其中每個位元組都代表類型資訊。 LSB 代表簡單 (基底) 數據類型,而 MSB 代表複雜類型,如果有的話:

MSB Lsb
複雜類型:無、指標、函式、陣列。
基底類型:整數、浮點數等等。

 

下列值是針對基底類型所定義,不過 Microsoft 工具通常不會使用此欄位,並將 LSB 設定為 0。 相反地,Visual C++ 偵錯資訊會用來指出類型。 不過,此處列出可能的 COFF 值,以達到完整性。

常數 Description
IMAGE_SYM_TYPE_NULL
0
沒有類型資訊或未知的基底類型。 Microsoft 工具會使用此設定
IMAGE_SYM_TYPE_VOID
1
沒有有效的類型;與 void 指標和函式搭配使用
IMAGE_SYM_TYPE_CHAR
2
字元(帶正負號的位元組)
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
單字;不帶正負號的 2 位元組整數
IMAGE_SYM_TYPE_UINT
14
自然大小的不帶正負號整數(通常為 4 個字節)
IMAGE_SYM_TYPE_DWORD
15
不帶正負號的 4 位元組整數

 

最重要的位元組會指定符號是 LSB 中所指定基底類型的指標、函式傳回或數位。 Microsoft 工具只會使用此欄位來指出符號是否為函式,因此唯一的兩個結果值會0x0並0x20類型欄位。 不過,其他工具可以使用此欄位來傳達詳細資訊。

請務必正確指定函式屬性。 增量鏈接必須具備這項資訊,才能正常運作。 對於某些架構,可能需要此資訊才能用於其他用途。

常數 Description
IMAGE_SYM_DTYPE_NULL
0
沒有衍生類型;符號是簡單的純量變數。
IMAGE_SYM_DTYPE_POINTER
1
符號是基底類型的指標。
IMAGE_SYM_DTYPE_FUNCTION
2
符號是傳回基底類型的函式。
IMAGE_SYM_DTYPE_ARRAY
3
符號是基底類型的陣列。

 

儲存類別

符號數據表的 儲存體 Class 欄位會指出符號所代表的定義類型。 下表顯示可能的值。 請注意,儲存體 Class 字段是不帶正負號的 1 位元組整數。 因此,應採用特殊值 -1 來表示其不帶正負號的對等值,0xFF。

雖然傳統的 COFF 格式使用許多儲存類別值,但 Microsoft 工具依賴 Visual C++ 偵錯格式來取得大部分的符號資訊,而且通常只使用四個儲存類別值:EXTERNAL (2)、STATIC (3)、FUNCTION (101)和 FILE (103)。 除了下方第二個數據行標題中,「值」應該採用來表示符號記錄的 Value 欄位(其解譯取決於儲存類別找到的數位)。

常數 [值] 欄位的描述/解譯
IMAGE_SYM_CLASS_END_OF_FUNCTION
-1 (0xFF)
代表函式結尾的特殊符號,用於偵錯。
IMAGE_SYM_CLASS_NULL
0
沒有指派的記憶體類別。
IMAGE_SYM_CLASS_AUTOMATIC
1
自動 (stack) 變數。 [值] 欄位會指定堆疊框架位移。
IMAGE_SYM_CLASS_EXTERNAL
2
Microsoft 工具用於外部符號的值。 [值] 欄位會指出區段編號是否為 IMAGE_SYM_UNDEFINED (0) 的大小。 如果區段編號不是零,則 Value 欄位會指定區段內的位移。
IMAGE_SYM_CLASS_STATIC
3
區段內符號的位移。 如果 [值] 欄位為零,則符號代表區段名稱。
IMAGE_SYM_CLASS_REGISTER
4
緩存器變數。 [值] 欄位會指定快取器編號。
IMAGE_SYM_CLASS_EXTERNAL_DEF
5
外部定義的符號。
IMAGE_SYM_CLASS_LABEL
6
模組內定義的程式代碼標籤。 [值] 欄位會指定區段內符號的位移。
IMAGE_SYM_CLASS_UNDEFINED_LABEL
7
未定義的程式代碼標籤參考。
IMAGE_SYM_CLASS_MEMBER_OF_STRUCT
8
結構成員。 [值] 欄位會指定第 n 個成員。
IMAGE_SYM_CLASS_ARGUMENT
9
函式的正式自變數(參數)。 [值] 欄位會指定第 n 個自變數。
IMAGE_SYM_CLASS_STRUCT_TAG
10
結構標籤名稱專案。
IMAGE_SYM_CLASS_MEMBER_OF_UNION
11
等位成員。 [值] 欄位會指定第 n 個成員。
IMAGE_SYM_CLASS_UNION_TAG
12
Union 標籤名稱專案。
IMAGE_SYM_CLASS_TYPE_DEFINITION
13
Typedef 專案。
IMAGE_SYM_CLASS_UNDEFINED_STATIC
14
靜態數據宣告。
IMAGE_SYM_CLASS_ENUM_TAG
15
列舉型別 tagname 專案。
IMAGE_SYM_CLASS_MEMBER_OF_ENUM
16
列舉的成員。 [值] 欄位會指定第 n 個成員。
IMAGE_SYM_CLASS_REGISTER_PARAM
17
緩存器參數。
IMAGE_SYM_CLASS_BIT_FIELD
18
位欄位參考。 [值] 欄位會指定位欄位中的第 n 個位。
IMAGE_SYM_CLASS_BLOCK
100
.bb (區塊開頭) 或 .eb (區塊結尾) 記錄。 [值] 欄位是程式代碼位置的可重新定位位址。
IMAGE_SYM_CLASS_FUNCTION
101
Microsoft 工具用於定義函式範圍的符號記錄值:begin 函式 (.bf)、end function (.ef)和 function (.lf) 中的行。 針對 .lf 記錄,[值] 字段會提供函式中的來源行數。 針對 .ef 記錄,[值] 字段會提供函式程式代碼的大小。
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
弱式外部。 如需詳細資訊,請參閱 輔助格式 3:弱式外部
IMAGE_SYM_CLASS_CLR_TOKEN
107
CLR 令牌符號。 名稱是 ASCII 字串,其中包含令牌的十六進位值。 如需詳細資訊,請參閱CLR令牌定義(僅限物件)。

 

輔助符號記錄

輔助符號數據表記錄一律遵循並套用至某些標準符號數據表記錄。 輔助記錄可以具有工具可辨識的任何格式,但必須為其配置 18 個字節,以便將符號表維持為一般大小的陣列。 目前,Microsoft 工具可辨識下列記錄類型的輔助格式:函式定義、函式開始和結束符號 (.bf 和 .ef)、弱式外部、檔名和區段定義。

傳統的 COFF 設計也包含數位和結構的輔助記錄格式。 Microsoft 工具不會使用這些專案,而是將符號資訊放在偵錯區段中的 Visual C++ 偵錯格式中。

輔助格式 1:函數定義

如果函式定義具有下列所有專案,符號數據表記錄會標示函式定義的開頭:EXTERNAL (2) 的儲存類別、指出它是函式的 Type 值(0x20),以及大於零的區段編號。 請注意,具有 UNDEFINED 區段編號的符號數據表記錄未定義函式,而且沒有輔助記錄。 函式定義符號記錄後面接著下列格式的輔助記錄:

位移 大小 欄位 描述
0
4
TagIndex
對應 .bf (begin 函式) 符號記錄的符號數據表索引。
4
4
TotalSize
函式本身可執行程式碼的大小。 如果函式位於自己的區段中,區段標頭中的 SizeOfRawData 會根據對齊考慮而大於或等於此字段。
8
4
PointerToLinenumber
函式中第一個 COFF 行號項目的檔案位移,如果沒有,則為零。 如需詳細資訊,請參閱 COFF 行號 (已淘汰)。
12
4
PointerToNextFunction
下一個函式記錄的符號數據表索引。 如果函式是符號數據表中的最後一個,此欄位會設定為零。
16
2
閑置

 

輔助格式 2:.bf 和 .ef 符號

對於符號數據表中的每個函式定義,有三個專案描述開頭、結尾和行數。 每個符號都有儲存類別 FUNCTION (101):

名為 .bf 的符號記錄(begin 函式)。 [值] 欄位未使用。

名為 .lf 的符號記錄(函式中的行)。 [值] 欄位會提供函式中的行數。

名為 .ef 的符號記錄(函式結尾)。 [值] 欄位的數位與函數定義符號記錄中的 [大小總計] 字段相同。

.bf 和 .ef 符號記錄(但不是 .lf 記錄)後面接著具有下列格式的輔助記錄:

位移 大小 欄位 描述
0
4
閑置
4
2
布隆伯
原始程式檔內的實際序數位 (1、2、3 等等),對應至 .bf 或 .ef 記錄。
6
6
閑置
12
4
PointerToNextFunction (僅限 .bf)
下一個 .bf 符號記錄的符號數據表索引。 如果函式是符號數據表中的最後一個,此欄位會設定為零。 它不適用於 .ef 記錄。
16
2
閑置

 

輔助格式 3:弱式外部

「弱式外部」是物件檔案的機制,可在連結時提供彈性。 模組可以包含未解析的外部符號 (sym1),但它也可以包含輔助記錄,指出如果符號1 不存在於鏈接時間,則會改用另一個外部符號 (sym2) 來解析參考。

如果符號1的定義已連結,則通常會解析符號的外部參考。 如果 sym1 的定義未連結,則 sym1 對弱式外部的所有參考都會改為參考 sym2。 外部符號 sym2 必須一律連結;通常會在模組中定義,其中包含 sym1 的弱式參考。

弱式外部是由具有 EXTERNAL 儲存類別、UNDEF 區段編號和值為零的符號數據表記錄來表示。 弱式外部符號記錄後面接著具有下列格式的輔助記錄:

位移 大小 欄位 描述
0
4
TagIndex
符號2 的符號數據表索引,如果找不到 sym1,則為要連結的符號。
4
4
特徵
IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY值表示不應執行符號1的連結庫搜尋。
IMAGE_WEAK_EXTERN_SEARCH_LIBRARY值表示應該執行符號1的連結庫搜尋。
IMAGE_WEAK_EXTERN_SEARCH_ALIAS 的值表示 sym1 是 sym2 的別名。
8
10
閑置

 

請注意,WINNT 中未定義 [特性] 欄位。H;會改用 [大小總計] 欄位。

輔助格式 4:檔案

此格式會遵循具有儲存類別 FILE 的符號數據表記錄 (103)。 符號名稱本身應該是 .file,後面接著的輔助記錄會提供原始程式碼檔的名稱。

位移 大小 欄位 描述
0
18
檔名
提供原始程式檔名稱的 ANSI 字串。 如果其長度小於最大長度,則會以 Null 填補。

 

輔助格式 5:區段定義

此格式會遵循定義區段的符號數據表記錄。 這類記錄的符號名稱是區段的名稱(例如 .text 或 .drectve),而且具有儲存類別 STATIC (3)。 輔助記錄會提供其所參考區段的相關信息。 因此,它會複製區段標頭中的一些資訊。

位移 大小 欄位 描述
0
4
長度
區段數據的大小;與區段標頭中的 SizeOfRawData 相同。
4
2
NumberOfRelocations
區段的重新配置項目數目。
6
2
NumberOfLinenumbers
區段的行號項目數。
8
4
校驗
公用數據的總和檢查碼。 如果區段標頭中已設定IMAGE_SCN_LNK_COMDAT旗標,則適用。 如需詳細資訊,請參閱 COMDAT 區段(僅限物件)。
12
2
數量
關聯區段的區段數據表中,以一個為基底的索引。 當 COMDAT 選取範圍設定為 5 時,會使用此設定。
14
1
選取項目
COMDAT 選取編號。 如果區段是 COMDAT 區段,則適用此專案。
15
3
閑置

 

COMDAT 區段 (僅限物件)

區段定義輔助格式的 Selection 欄位適用於區段是 COMDAT 區段。 COMDAT 區段是一個區段,可由多個對象檔定義。 (旗標IMAGE_SCN_LNK_COMDAT是在區段標題的 [區段旗標] 字段中設定。[選取範圍] 字段會決定鏈接器解析 COMDAT 區段之多個定義的方式。

具有 COMDAT 區段值的第一個符號必須是區段符號。 此符號具有區段的名稱、Value 欄位等於零、有問題的 COMDAT 區段的區段編號、類型欄位等於 IMAGE_SYM_TYPE_NULL、Class 欄位等於 IMAGE_SYM_CLASS_STATIC,以及一個輔助記錄。 第二個符號稱為「COMDAT 符號」,由連結器搭配 [選取範圍] 字段使用。

[選取範圍] 欄位的值如下所示。

常數 Description
IMAGE_COMDAT_SELECT_NODUPLICATES
1
如果已經定義此符號,連結器就會發出「相乘符號」錯誤。
IMAGE_COMDAT_SELECT_ANY
2
任何定義相同 COMDAT 符號的區段都可以連結;其餘部分會移除。
IMAGE_COMDAT_SELECT_SAME_SIZE
3
連結器會在此符號的定義中選擇任意區段。 如果所有定義的大小都不同,則會發出「相乘定義的符號」錯誤。
IMAGE_COMDAT_SELECT_EXACT_MATCH
4
連結器會在此符號的定義中選擇任意區段。 如果所有定義不完全相符,則會發出「相乘定義的符號」錯誤。
IMAGE_COMDAT_SELECT_ASSOCIATIVE
5
如果連結特定其他 COMDAT 區段,則會連結區段。 此其他區段會以區段定義之輔助符號記錄的 [數位] 字段表示。 此設定適用於具有多個區段中元件的定義(例如,一個區段中的程式代碼和另一個區段中的程序代碼),但所有專案都必須連結或捨棄為集合。 本節相關聯的另一個區段必須是 COMDAT 區段,這可以是另一個關聯的 COMDAT 區段。 關聯 COMDAT 區段的區段關聯鏈結無法形成迴圈。 區段關聯鏈結最終必須來到未設定IMAGE_COMDAT_SELECT_ASSOCIATIVE的 COMDAT 區段。
IMAGE_COMDAT_SELECT_LARGEST
6
連結器會從此符號的所有定義中選擇最大的定義。 如果多個定義具有這個大小,則兩者之間的選擇是任意的。

 

CLR 令牌定義 (僅限物件)

此輔助符號通常會遵循IMAGE_SYM_CLASS_CLR_TOKEN。 它用來將令牌與 COFF 符號數據表的命名空間產生關聯。

位移 大小 欄位 描述
0
1
bAuxType
必須是IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF(1)。
1
1
bReserved
保留的 必須是零。
2
4
SymbolTableIndex
這個 CLR 令牌定義所參考之 COFF 符號的符號索引。
6
12
保留的 必須是零。

 

COFF 字串數據表

緊接在 COFF 符號數據表之後是 COFF 字串數據表。 找到此資料表的位置,方法是在 COFF 標頭中取得符號數據表位址,並新增符號數目乘以符號的大小。

COFF 字串數據表的開頭是 4 個字節,其中包含字元串數據表其餘部分的總大小(以位元組為單位)。 此大小包含大小欄位本身,因此如果沒有字串,則此位置中的值會是 4。

大小之後是 COFF 符號數據表中符號所指向的 Null 終止字串。

屬性憑證資料表 (僅限影像)

屬性憑證可以藉由新增屬性憑證數據表來與映像產生關聯。 屬性憑證數據表是由一組連續、四字對齊的屬性憑證專案所組成。 零填補會在檔案的原始結尾與屬性憑證數據表的開頭之間插入,以達到此對齊。 每個屬性憑證專案都包含下列欄位。

位移 大小 欄位 描述
0
4
dwLength
指定屬性憑證項目的長度。
4
2
wRevision
包含憑證版本號碼。 如需詳細資訊,請參閱下列文字。
6
2
wCertificateType
指定 bCertificate 中內容類型。 如需詳細資訊,請參閱下列文字。
8
請參閱下列內容
bCertificate
包含憑證,例如 Authenticode 簽章。 如需詳細資訊,請參閱下列文字。

 

選擇性標頭數據目錄中憑證數據表專案的虛擬位址值是第一個屬性憑證項目的檔案位移。 從目前屬性憑證專案的開頭,將該專案的 dwLength 位元組進位至 8 位元組倍數,以存取後續專案。 這會繼續執行,直到四捨五入 dwLength 值的總和等於 [選擇性標頭數據目錄] 中 [憑證數據表] 專案的 Size 值。 如果四捨五入 dwLength 值的總和不等於 Size 值,則屬性憑證數據表或 Size 字段已損毀。

例如,如果選擇性標頭資料目錄的憑證數據表專案包含:

virtual address = 0x5000
size = 0x1000

第一個憑證會從磁碟上的檔案開頭開始0x5000位移開始。 若要前進到所有屬性憑證專案:

  1. 將第一個屬性憑證的 dwLength 值新增至起始位移。
  2. 將步驟 1 的值四捨五入至最接近的 8 位元組倍數,以尋找第二個屬性憑證專案的位移。
  3. 將步驟 2 的位移值新增至第二個屬性憑證專案的 dwLength 值,並四捨五入至最接近的 8 位元組倍數,以判斷第三個屬性憑證專案的位移。
  4. 針對每個連續憑證重複步驟 3,直到計算位移等於 0x6000 (0x5000 start + 0x1000 total size),這表示您已逐步執行整個數據表。

或者,您也可以在迴圈中呼叫 Win32 ImageEnumerateCertificates 函式來列舉憑證專案。 如需函式參考頁面的連結,請參閱 參考

只要專案具有正確的 dwLength 值、唯一 wRevision 值和唯一的 wCertificateType 值,屬性憑證數據表專案就可以包含任何憑證類型。 最常見的憑證數據表項目類型是WIN_CERTIFICATE結構,其記載於Wintrust.h中,並在本節的其餘部分討論。

WIN_CERTIFICATE wRevision 成員的選項包括下列專案(但不限於)。

名稱 備註
0x0100
WIN_CERT_REVISION_1_0
第 1 版,舊版的 Win_Certificate 結構。 僅支持驗證舊版 Authenticode 簽章
0x0200
WIN_CERT_REVISION_2_0
第 2 版是Win_Certificate結構的目前版本。

 

WIN_CERTIFICATE 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 支援的型別是 PKCS#7 SignedData 結構WIN_CERT_TYPE_PKCS_SIGNED_DATA。 如需 Authenticode 數位簽名格式的詳細資訊,請參閱 Windows Authenticode 可攜式可執行簽章格式

如果 bCertificate 內容未在四字界限上結束,則屬性憑證專案會以零填補,從 bCertificate 的結尾到下一個四字界限。

dwLength 值是完成WIN_CERTIFICATE結構的長度,並計算為:

dwLength = offsetof(WIN_CERTIFICATE, bCertificate) + (size of the variable-length binary array contained within bCertificate)

此長度應包含用來滿足每個WIN_CERTIFICATE結構的四字對齊需求的任何填補大小:

dwLength += (8 - (dwLength & 7)) & 7;

選擇性標頭資料目錄的 [憑證數據表] 專案中指定的 [憑證數據表大小] 包含填補。

如需使用 ImageHlp API 列舉、新增和移除 PE 檔案憑證的詳細資訊,請參閱 ImageHlp 函式

憑證數據

如上一節所述,屬性憑證數據表中的憑證可以包含任何憑證類型。 確保PE檔案完整性的憑證可能包含PE映像哈希。

PE 映射哈希(或檔案哈希)類似於檔案總和檢查碼,該哈希演算法會產生與檔案完整性相關的訊息摘要。 不過,總和檢查碼是由簡單的演算法所產生,主要用於偵測磁碟上的記憶體區塊是否已損毀,而儲存在那裡的值已損毀。 檔案哈希類似於總和檢查碼,因為它也會偵測檔案損毀。 不過,與大部分總和檢查碼演算法不同,修改檔案非常困難,而不需從原始未修改的值變更檔案哈希。 因此,檔案哈希可用來偵測檔案的刻意甚至細微修改,例如病毒、駭客或特洛伊木馬程式所引進的檔案。

當包含在憑證中時,映射摘要必須排除PE映像中的特定欄位,例如選擇性標頭資料目錄中的總和檢查碼和憑證數據表專案。 這是因為新增憑證的行為會變更這些字段,並會導致計算不同的哈希值。

Win32 ImageGetDigestStream 函式會從要哈希函式的目標 PE 檔案提供數據流。 當憑證新增至PE檔案或從PE檔案移除時,此數據流會保持一致。 根據傳遞至 ImageGetDigestStream 的參數,可以從哈希計算中省略 PE 映射的其他數據。 如需函式參考頁面的連結,請參閱 參考

延遲載入資料表 (僅限影像 )

這些數據表已新增至映像,以支援應用程式的統一機制,以延遲載入 DLL,直到第一次呼叫該 DLL 為止。 數據表的配置符合 6.4 節 .idata 區段中所述的傳統匯入數據表。這裡只會討論幾個詳細數據。

延遲載入目錄數據表

延遲載入目錄數據表是匯入目錄數據表的對應專案。 它可以透過選擇性標頭資料目錄清單中的延遲匯入描述元專案擷取(位移 200)。 資料表的排列方式如下:

位移 大小 欄位 描述
0
4
屬性
必須是零。
4
4
名字
要載入之 DLL 名稱的 RVA。 此名稱位於映像的唯讀數據區段中。
8
4
模組句柄
要延遲載入之 DLL 之模組句柄的 RVA(在影像的數據區段中)。 它是由提供來管理延遲載入的例程所使用。
12
4
延遲匯入位址表
延遲載入位址資料表的 RVA。 如需詳細資訊,請參閱延遲匯入位址表(IAT)。
16
4
延遲匯入名稱數據表
延遲載入名稱數據表的 RVA,其中包含可能需要載入的匯入名稱。 這符合匯入名稱數據表的配置。 如需詳細資訊,請參閱 提示/名稱數據表
20
4
系結延遲匯入數據表
如果系結延遲載入位址表存在,則為 RVA。
24
4
卸除延遲匯入數據表
如果卸除延遲載入地址數據表存在,則為 RVA。 這是延遲匯入位址表的確切複本。 如果呼叫端卸除 DLL,此數據表應該複製回延遲匯入地址數據表,以便後續呼叫 DLL 繼續正確使用指紋機制。
28
4
時間戳
這個映像已系結至之 DLL 的時間戳。

 

此數據結構中所參考的數據表會組織並排序,就像其對應專案用於傳統匯入一樣。 如需詳細資訊,請參閱 .idata 區段

屬性

到目前為止,尚未定義任何屬性旗標。 鏈接器會將影像中的此欄位設定為零。 這個欄位可用來藉由指出新欄位的存在來擴充記錄,或者可用來指出延遲或卸除協助程式函式的行為。

名稱

要延遲載入的 DLL 名稱位於映像的唯讀數據區段中。 它會透過 szName 欄位來參考。

模組句柄

要延遲載入之 DLL 的句柄位於影像的數據區段中。 phmod 欄位會指向控點。 提供的延遲載入協助程式會使用此位置來儲存載入 DLL 的句柄。

延遲匯入位址表

延遲匯入位址表 (IAT) 是由延遲匯入描述元透過 pIAT 字段參考。 延遲載入協助程式會使用實際的進入點來更新這些指標,讓 Thunk 不再位於呼叫迴圈中。 函式指標是使用 表達式 pINT->u1.Function來存取的。

延遲匯入名稱數據表

延遲匯入名稱數據表 (INT) 包含可能需要載入的匯入名稱。 它們會以與 IAT 中的函式指標相同的方式排序。 它們是由與標準 INT 相同的結構所組成,而且是使用 表達式 pINT->u1.AddressOfData->Name[0]來存取的。

延遲系結匯入位址表和時間戳

延遲系結匯入位址表 (BIAT) 是IMAGE_THUNK_DATA項目的選擇性數據表,由後續處理系結階段搭配延遲載入目錄數據表的時間戳字段使用。

延遲卸除匯入位址表

延遲卸除匯入位址表 (UIAT) 是卸載程式代碼用來處理明確卸除要求之IMAGE_THUNK_DATA專案的選擇性數據表。 它是由只讀區段中的初始化數據所組成,這是參考程式代碼至延遲載入 Thunks 之原始 IAT 的確切復本。 在卸除要求上,可以釋放連結庫、清除 *phmod,以及透過 IAT 撰寫的 UIAT,以將所有專案還原至其預先載入狀態。

特殊區段

一般 COFF 區段包含連結器和 Microsoft Win32 載入器處理的程式代碼或數據,而不需要特別瞭解區段內容。 內容僅與正在連結或執行的應用程式相關。

不過,某些COFF區段在物件檔或圖像檔中找到時具有特殊意義。 工具和載入器會辨識這些區段,因為它們在區段標頭中設定了特殊旗標,因為影像選擇性標頭中的特殊位置會指向這些區段,或因為區段名稱本身表示區段的特殊功能。 (即使區段名稱本身沒有指出區段的特殊功能,區段名稱也會依慣例來指定,因此此規格的作者在所有情況下都可以參考區段名稱。

下表說明保留區段及其屬性,後面接著保存至可執行檔的區段類型的詳細描述,以及包含延伸模組元數據的區段類型。

區段名稱 Content 特性
。Bss
未初始化的資料 (免費格式)
IMAGE_SCN_CNT_UNINITIALIZED_DATA |IMAGE_SCN_MEM_READ |IMAGE_SCN_MEM_WRITE
.cormeta
指出對象檔包含 Managed 程式代碼的 CLR 元數據
IMAGE_SCN_LNK_INFO
。資料
初始化的資料(免費格式)
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
.drective
連結器選項
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 屬性。 如需詳細資訊,請參閱本主題結尾的參考中的
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 應該只針對 IA64 架構設定IMAGE_SCN_GPREL旗標;此旗標對其他架構無效。 IMAGE_SCN_GPREL旗標僅適用於物件檔;當此區段類型出現在圖像檔案中時,不得設定IMAGE_SCN_GPREL旗標。
.sdata
GP 相對初始化的資料 (免費格式)
IMAGE_SCN_CNT_INITIALIZED_DATA |IMAGE_SCN_MEM_READ |IMAGE_SCN_MEM_WRITE |IMAGE _SCN_GPREL 應該只針對 IA64 架構設定IMAGE_SCN_GPREL旗標;此旗標對其他架構無效。 IMAGE_SCN_GPREL旗標僅適用於物件檔;當此區段類型出現在圖像檔案中時,不得設定IMAGE_SCN_GPREL旗標。
.srdata
GP 相對唯讀資料(免費格式)
IMAGE_SCN_CNT_INITIALIZED_DATA |IMAGE_SCN_MEM_READ |IMAGE _SCN_GPREL 應該只針對 IA64 架構設定IMAGE_SCN_GPREL旗標;此旗標對其他架構無效。 IMAGE_SCN_GPREL旗標僅適用於物件檔;當此區段類型出現在圖像檔案中時,不得設定IMAGE_SCN_GPREL旗標。
.sxdata
已註冊的例外狀況處理程式數據(僅限免費格式和 x86/object)
IMAGE_SCN_LNK_INFO 包含該物件檔中程式代碼所參考之每個例外狀況處理程式的符號索引。 符號可以是 UNDEF 符號或該模組中定義的符號。
。文字
可執行程式代碼 (免費格式)
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

 

此處列出的部分區段會標示為「僅限物件」或「僅限影像」,以指出其特殊語意分別與對象檔或圖像文件相關。 標示為「僅限影像」的區段仍可能會以進入圖像檔的方式出現在物件檔中,但區段對連結器沒有特殊意義,只有圖像檔載入器。

.debug 區段

.debug 區段用於物件檔,以包含編譯程式產生的偵錯資訊,以及映像檔中,以包含產生的所有偵錯資訊。 本節描述物件和映像檔中的偵錯資訊封裝。

下一節描述偵錯目錄的格式,它可以是映像中的任何位置。 後續章節描述包含偵錯資訊之對象檔中的「群組」。

連結器的預設是偵錯資訊不會對應至影像的位址空間。 只有在位址空間中對應偵錯資訊時,才會有 .debug 區段。

偵錯目錄 (僅限映像)

圖像檔案包含選擇性的偵錯目錄,指出偵錯資訊的形式存在,以及其所在位置。 此目錄是由偵錯目錄項目的陣列所組成,其位置和大小會以影像選擇性標頭表示。

偵錯目錄可以位於可捨棄的 .debug 區段(如果有的話),或者它可以包含在圖像檔的任何其他區段中,或完全不在區段中。

每個偵錯目錄項目都會識別偵錯資訊區塊的位置和大小。 如果區段標頭未涵蓋偵錯資訊,則指定的 RVA 可以是零(也就是說,它位於映像檔中,且未對應至運行時間位址空間)。 如果對應,RVA 就是其位址。

偵錯目錄項目的格式如下:

位移 大小 欄位 描述
0
4
特徵
保留的 必須是零。
4
4
TimeDateStamp
偵錯數據建立的時間和日期。
8
2
MajorVersion
偵錯數據格式的主要版本號碼。
10
2
MinorVersion
偵錯數據格式的次要版本號碼。
12
4
輸入
偵錯資訊的格式。 此欄位可支援多個調試程式。 如需詳細資訊,請參閱 偵錯類型
16
4
SizeOfData
偵錯數據的大小(不包括偵錯目錄本身)。
20
4
AddressOfRawData
載入時偵錯數據的位址,相對於映像基底。
24
4
PointerToRawData
偵錯數據的檔案指標。

 

偵錯類型

針對偵錯目錄專案的 [類型] 字段定義下列值:

常數 Description
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
保留給博爾蘭。
IMAGE_DEBUG_TYPE_RESERVED10
10
已保留。
IMAGE_DEBUG_TYPE_CLSID
11
已保留。
IMAGE_DEBUG_TYPE_REPRO
16
PE 決定性或重現性。
未定義
17
偵錯資訊會內嵌在PointerToRawData所指定位置的PE檔案中。
未定義
19
儲存用來建置PE/COFF檔案之符號檔內容的加密哈希。
IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS 20 擴充 DLL 特性位。

 

如果 [類型] 欄位設定為 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;            // offset 1st byte of function code
    DWORD       cbProcSize;            // # bytes in function
    DWORD       cdwLocals;             // # bytes in locals/4
    WORD        cdwParams;             // # bytes in params/4
    WORD        cbProlog : 8;          // # bytes in prolog
    WORD        cbRegs   : 3;          // # regs saved
    WORD        fHasSEH  : 1;          // TRUE if SEH in func
    WORD        fUseBP   : 1;          // TRUE if EBP has been allocated
    WORD        reserved : 1;          // reserved for future use
    WORD        cbFrame  : 2;          // frame type
} FPO_DATA;

IMAGE_DEBUG_TYPE_REPRO類型的專案存在表示PE檔案是以達到決定性或重現性的方式建置。 如果輸入沒有變更,則不論產生PE的時機或位置,輸出PE檔案都保證為位 for-bit 相同。 PE 檔案中的各種日期/時間戳字段會填入使用 PE 檔案內容做為輸入之匯出哈希值的一部分或所有位,因此不再代表產生 PE 檔案或 PE 內相關特定數據的實際日期和時間。 這個偵錯專案的原始數據可能是空的,或可能包含以四位元組值表示哈希值長度的四位元組值之前計算的哈希值。

如果 [類型] 欄位元設定為 IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS,偵錯原始數據會包含擴充的 DLL 特性位,除了可以在影像的選擇性標頭中設定的位之外。 請參閱選擇性標頭 Windows 特定欄位一節中的 DLL 特性(僅限影像)。

擴充 DLL 特性

下列值是針對擴充 DLL 特性位所定義。

常數 Description
IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT 0x0001 影像與控制流程強制執行技術 (CET) 陰影堆疊相容。
IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT 0x0040 所有映射代碼區段中的所有分支目標都會以正向控制流程完整性防護指示標註,例如 x86 CET-Indirect Branch Tracking (IBT) 或 ARM 分支目標識別 (BTI) 指示。 Windows 不會使用此位。

.debug$F (僅限物件)

本節中的數據已被 Visual C++ 7.0 版和更新版本取代為一組更廣泛的數據,而這些數據會發出至 .debug$S 子區段。

對象檔可以包含 .debug$F 區段,其內容為一或多個FPO_DATA記錄(框架指標遺漏資訊)。 請參閱偵錯類型中的「IMAGE_DEBUG_TYPE_FPO」。

鏈接器可辨識這些 .debug$F 記錄。 如果正在產生偵錯資訊,連結器會依程式 RVA 排序FPO_DATA記錄,併為其產生偵錯目錄專案。

編譯程式不應該針對具有標準框架格式的程序產生 FPO 記錄。

.debug$S (僅限物件)

本節包含 Visual C++ 偵錯資訊(符號資訊)。

.debug$P (僅限物件)

本節包含 Visual C++ 偵錯資訊(先行編譯的資訊)。 這些是使用此物件所產生之先行編譯標頭所編譯之所有對象的共享類型。

.debug$T (僅限物件)

本節包含 Visual C++ 偵錯資訊(類型資訊)。

Microsoft 偵錯資訊的連結器支援

若要支援偵錯資訊連結器:

  • 從 .debug$F、debug$S.debug$P.debug$T 區段收集所有相關偵錯數據。

  • 處理數據以及連結器產生的偵錯資訊到 PDB 檔案,並建立偵錯目錄項目來參考它。

.drectve 區段 (僅限物件)

區段是指示詞區段,如果區段標頭中已設定IMAGE_SCN_LNK_INFO旗標,且具有 .drectve 區段名稱。 鏈接器會在處理資訊之後移除 .drectve 區段,因此區段不會出現在所連結的影像檔中。

.drectve 區段是由可編碼為 ANSI 或 UTF-8 的文字字串所組成。 如果UTF-8位元組順序標記(BOM,由0xEF、0xBB和0xBF組成的三位元組前置詞)不存在,指示詞字串會解譯為ANSI。 指示詞字串是以空格分隔的一系列連結器選項。 每個選項都包含連字元、選項名稱和任何適當的屬性。 如果選項包含空格,選項必須以引弧括住。 .drectve 區段不能有重新配置或行號。

.edata 區段 (僅限影像)

名為 .edata 的導出數據區段包含其他影像可透過動態連結存取之符號的相關信息。 導出的符號通常位於 DLL 中,但 DLL 也可以匯入符號。

以下是導出區段的一般結構概觀。 所描述的數據表通常會依顯示的順序在檔案中連續(雖然這並非必要)。 只有匯出目錄數據表和匯出位址表才能將符號匯出為序數。 (序數是匯出位址表索引直接存取的匯出。名稱指標數據表、序數數據表和匯出名稱數據表全都存在,以支援使用匯出名稱。

資料表名稱 描述
匯出目錄數據表
只有一個數據列的數據表(不同於偵錯目錄)。 下表指出其他導出數據表的位置和大小。
匯出位址表
匯出符號的 RVA 陣列。 這些是可執行程式代碼和數據區段中匯出函式和數據的實際位址。 如果定義了公用名稱,其他圖像檔可以使用索引來匯入符號(序數),或是選擇性地使用對應至序數的公用名稱。
名稱指標數據表
公用導出名稱的指標數位列,依遞增順序排序。
序數數據表
對應至名稱指標數據表成員之序數的陣列。 對應是依位置;因此,名稱指標數據表和序數數據表必須具有相同的成員數目。 每個序數都是匯出位址表中的索引。
匯出名稱數據表
一系列以 Null 結尾的 ASCII 字串。 名稱指標數據表的成員會指向這個區域。 這些名稱是匯入和匯出符號的公用名稱;它們不一定與映像檔內所使用的私用名稱相同。

 

當另一個圖像檔依名稱匯入符號時,Win32 載入器會搜尋名稱指標數據表中的相符字串。 如果找到相符的字串,則會藉由查閱序數數據表中的對應成員來識別相關聯的序數(亦即,序數數據表的成員,其索引與名稱指標數據表中找到的字串指標相同)。 產生的序數是導出位址表中的索引,可提供所需符號的實際位置。 序數可以存取每個匯出符號。

當另一個圖像檔依序數匯入符號時,就不需要搜尋名稱指標數據表來尋找相符的字串。 因此,直接使用序數會更有效率。 不過,導出名稱更容易記住,而且不需要使用者知道符號的數據表索引。

匯出目錄數據表

匯出符號資訊會以匯出目錄數據表開頭,其中描述匯出符號信息的其餘部分。 匯出目錄數據表包含位址資訊,可用來解析此影像內進入點的匯入。

位移 大小 欄位 描述
0
4
匯出旗標
保留的 必須是 0。
4
4
時間/日期戳記
匯出數據建立的時間和日期。
8
2
主要版本
主要版本號碼。 主要和次要版本號碼可由用戶設定。
10
2
次要版本
次要版本號碼。
12
4
名稱 RVA
包含 DLL 名稱的 ASCII 字串位址。 此位址相對於映像基底。
16
4
序數基底
此影像中導出的起始序號。 此欄位會指定匯出位址表的起始序號。 它通常設定為 1。
20
4
位址表專案
匯出位址表中的項目數。
24
4
名稱指標數目
名稱指標數據表中的項目數。 這也是序數表中的項目數。
28
4
匯出位址表 RVA
匯出地址數據表的位址,相對於影像基底。
32
4
名稱指標 RVA
匯出名稱指標數據表的位址,相對於映像基底。 數據表大小是由 [名稱指標數目] 字段所指定。
36
4
序數表 RVA
相對於映像基底的序數字表位址。

 

匯出位址表

匯出地址數據表包含匯出進入點的位址,以及匯出的數據和絕對值。 序數會當做匯出位址表中的索引使用。

匯出位址表中的每個專案都是使用下表中兩種格式之一的欄位。 如果指定的位址不在匯出區段內(如選擇性標頭中所指出的位址和長度所定義),則字段是匯出 RVA,這是程式碼或數據中的實際位址。 否則,欄位是轉寄站 RVA,它會為另一個 DLL 中的符號命名。

位移 大小 欄位 描述
0
4
匯出 RVA
載入記憶體時匯出符號的位址,相對於映像基底。 例如,匯出函式的位址。
0
4
轉寄站 RVA
匯出區段中以 Null 終止 ASCII 字串的指標。 此字串必須位於匯出數據表資料目錄專案所提供的範圍內。 請參閱選擇性的標頭數據目錄(僅限影像)。 此字串會提供 DLL 名稱和導出的名稱(例如 “MYDLL.expfunc”) 或 DLL 名稱和匯出序號(例如 “MYDLL.#27” )。

 

轉寄站 RVA 會從其他映射導出定義,使其看起來就像是目前映射匯出一樣。 因此,符號會同時匯入和導出。

例如,在 Windows XP 中的Kernel32.dll中,名為 「HeapAlloc」 的匯出會轉送至字串 「NTDLL」。RtlAllocateHeap。」這可讓應用程式使用 Windows XP 特定模組Ntdll.dll,而不需要實際包含其匯入參考。 應用程式的匯入數據表只會參考Kernel32.dll。 因此,應用程式並非專屬於 Windows XP,而且可以在任何 Win32 系統上執行。

匯出名稱指標數據表

匯出名稱指標數據表是匯出名稱數據表中的位址陣列(RVA)。 指標各為32位,與影像基底相對。 指標會依語彙排序,以允許二進位搜尋。

只有在匯出名稱指標數據表包含它的指標時,才會定義匯出名稱。

匯出序數數據表

匯出序數數據表是匯出位址表中 16 位不偏不偏索引的陣列。 序數是由匯出目錄數據表的序數基底欄位所偏差。 換句話說,序數基底必須從序數減去,才能取得匯出地址數據表中真正的索引。

匯出名稱指標數據表和匯出序數數據表會形成兩個平行陣列,以允許自然欄位對齊。 這兩個數據表實際上會以一個數據表的形式運作,其中 [匯出名稱指標] 數據行指向公用 (exported) 名稱,而 [匯出序數] 數據行會提供該公用名稱的對應序數。 匯出名稱指標數據表的成員和匯出序數數據表的成員,會在其各自的陣列中具有相同的位置(index)。

因此,當搜尋導出名稱指標數據表,並在位置 i 找到相符字串時,尋找符號的 RVA 和偏差序數的演算法為:

i = Search_ExportNamePointerTable (name);
ordinal = ExportOrdinalTable [i];

rva = ExportAddressTable [ordinal];
biased_ordinal = ordinal + OrdinalBase;

藉由 (biased) 序數搜尋符號時,尋找符號 RVA 且名稱的演算法為:

ordinal = biased_ordinal - OrdinalBase;
i = Search_ExportOrdinalTable (ordinal);

rva = ExportAddressTable [ordinal];
name = ExportNameTable [i];

匯出名稱數據表

匯出名稱數據表包含匯出名稱指標數據表所指向的實際字串數據。 此數據表中的字串是其他影像可用來匯入符號的公用名稱。 這些公用匯出名稱不一定與符號本身的映像檔和原始程式碼中具有的私人符號名稱相同,不過這些名稱可以是 。

每個導出的符號都有序數值,這隻是匯出位址表中的索引。 不過,使用導出名稱是選擇性的。 部分、全部或沒有任何匯出符號可以有導出名稱。 對於具有匯出名稱的匯出符號,匯出名稱指標數據表和匯出序數數據表中的對應專案會一起運作,讓每個名稱與序數產生關聯。

匯出名稱數據表的結構是可變長度的 Null 終止 ASCII 字串系列。

.idata 區段

匯入符號的所有圖像檔,包括幾乎所有可執行檔 (EXE) 檔案,都有 .idata 區段。 匯入資訊的典型檔案設定如下:

  • 目錄數據表

    Null 目錄專案

  • DLL1 匯入查閱表格

    Null

  • DLL2 匯入查閱表格

    Null

  • DLL3 匯入查閱表格

    Null

  • Hint-Name 數據表

匯入目錄數據表

匯入資訊會從匯入目錄數據表開始,其中描述匯入資訊的其餘部分。 匯入目錄數據表包含位址資訊,可用來解析 DLL 映射內進入點的修正參考。 匯入目錄數據表是由匯入目錄項目的陣列所組成,映像所參考的每個 DLL 各有一個專案。 最後一個目錄專案是空的(填入 Null 值),表示目錄數據表的結尾。

每個匯入目錄專案都有下列格式:

位移 大小 欄位 描述
0
4
匯入查閱表格 RVA (特性)
匯入查閱表格的 RVA。 此資料表包含每個匯入的名稱或序數。 (名稱 “Characteristics” 用於 Winnt.h,但不再描述此欄位。
4
4
時間/日期戳記
設定為零的戳記,直到影像系結為止。 系結映射之後,此欄位會設定為 DLL 的時間/資料戳記。
8
4
轉寄站鏈結
第一個轉寄站參考的索引。
12
4
名稱 RVA
包含 DLL 名稱的 ASCII 字串位址。 此位址相對於映像基底。
16
4
匯入位址表 RVA (Thunk 資料表)
匯入位址表的 RVA。 此表格的內容與匯入查閱表格的內容相同,直到影像系結為止。

 

匯入查閱表格

匯入查閱表格是PE32的32位數位數位數組,或PE32+的64位數位數位數組。 每個項目都會使用下表所述的位欄位格式。 在此格式中,位 31 是 PE32 的最大有效位,而位 63 是 PE32+ 的最大有效位。 這些專案的集合描述所有從指定的 DLL 匯入。 最後一個項目會設定為零 (NULL), 表示數據表的結尾。

Bit(s) 大小 位元欄位 描述
31/63
1
序數/名稱旗標
如果設定此位,請依序數匯入。 否則,請依名稱匯入。 BIT 會遮罩為PE32的0x80000000,而PE32+ 0x8000000000000000。
15-0
16
序數
16 位序數。 只有當 Ordinal/Name 旗標位欄位欄位為 1 時,才會使用此欄位(依序數匯入)。 位 30-15 或 62-15 必須是 0。
30-0
31
Hint/Name Table RVA
提示/名稱數據表專案的 31 位 RVA。 只有當 Ordinal/Name 旗標位欄位欄位是 0 時,才會使用此欄位(依名稱匯入)。 針對PE32+位62-31,必須是零。

 

Hint/Name 數據表

整個匯入區段的一個提示/名稱數據表就足夠了。 hint/name 資料表中的每個專案都有下列格式:

位移 大小 欄位 描述
0
2
提示
匯出名稱指標數據表中的索引。 第一次嘗試比對值。 如果失敗,則會在 DLL 的匯出名稱指標數據表上執行二進位搜尋。
2
變數
名字
包含要匯入之名稱的 ASCII 字串。 這是必須與 DLL 中的公用名稱相符的字串。 此字串會區分大小寫,並以 Null 位元組終止。
*
0 或 1

尾端零位位元組,視需要出現在尾端 Null 位元組之後,以對齊偶數界限上的下一個專案。

 

匯入位址表

匯入位址表的結構和內容與匯入查閱表格的結構和內容相同,直到檔案系結為止。 在系結期間,匯入位址表中的專案會以 32 位(適用於 PE32)或 64 位位址來覆寫要匯入之符號的 32 位(適用於 PE32+)。 這些位址是符號的實際記憶體位址,但技術上仍稱為「虛擬位址」。載入器通常會處理系結。

.pdata 區段

.pdata 區段包含用於例外狀況處理的函式數據表項目陣列。 它是由映像數據目錄中的例外狀況數據表專案所指向。 項目必須根據函式位址(每個結構中的第一個字段)排序,才能發出至最終影像。 目標平台會決定使用下列三個函式數據表專案格式變化中的哪一個。

針對 32 位 MIPS 影像,函式數據表專案的格式如下:

位移 大小 欄位 描述
0
4
開始位址
對應函式的 VA。
4
4
結束位址
函式結尾的 VA。
8
4
例外狀況處理程式
要執行的例外狀況處理程序指標。
12
4
處理程序數據
要傳遞至處理程式之其他資訊的指標。
16
4
初構結束位址
函式初構結尾的 VA。

 

針對 ARM、PowerPC、SH3 和 SH4 Windows CE 平臺,函式數據表專案的格式如下:

位移 大小 欄位 描述
0
4
開始位址
對應函式的 VA。
4
8 位
初構長度
函式初構中的指令數目。
4
22 位
函式長度
函式中的指令數目。
4
1 位
32 位旗標
如果設定,則函式包含 32 位指令。 如果清楚,函式會包含16位指令。
4
1 位
例外狀況旗標
如果已設定,函式就會有例外狀況處理程式。 否則,沒有任何例外狀況處理程式存在。

 

針對 x64 和 Itanium 平臺,函式數據表專案的格式如下:

位移 大小 欄位 描述
0
4
開始位址
對應函式的 RVA。
4
4
結束位址
函式結尾的 RVA。
8
4
回溯資訊
回溯資訊的 RVA。

 

.reloc 區段 (僅限影像)

基底重新配置數據表包含影像中所有基底重新配置的專案。 選擇性標頭資料目錄中的 [基礎重新配置資料表] 欄位元位會提供基底重新配置資料表中的位元組數目。 如需詳細資訊,請參閱選擇性標頭數據目錄(僅限映射)。 基底重新配置數據表分成區塊。 每個區塊都代表 4K 頁面的基底重新配置。 每個區塊都必須在32位界限上啟動。

載入器不需要處理連結器所解析的基底重新配置,除非無法在PE標頭中指定的映像基底載入載映像。

基底重新配置區塊

每個基底重新配置區塊都會以下列結構開頭:

位移 大小 欄位 描述
0
4
頁面 RVA
映射基底加上頁面 RVA 會新增至每個位移,以建立必須套用基底重新配置的 VA。
4
4
區塊大小
基底重新配置區塊中的位元組總數,包括 [頁面 RVA] 和 [區塊大小] 欄位段,以及後續的 [類型/位移] 字段。

 

[區塊大小] 字段接著任意數目的 [類型] 或 [位移] 字段專案。 每個專案都是 WORD (2 個字節),且具有下列結構:

位移 大小 欄位 描述
0
4 位
輸入
儲存在 WORD 的高 4 位中,這個值表示要套用的基底重新配置類型。 如需詳細資訊,請參閱 基底重新配置類型
0
12 位
抵消
儲存在 WORD 的其餘 12 位中,與區塊的 Page RVA 欄位中指定的起始位址位移。 此位移會指定要套用基底重新配置的位置。

 

若要套用基底重新配置,則會計算慣用基地址與實際載入影像的基底之間的差異。 如果影像在慣用的基底載入,則差異為零,因此不需要套用基底重新配置。

基底重新配置類型

常數 Description
IMAGE_REL_BASED_ABSOLUTE
0
會略過基底重新配置。 此類型可用來填補區塊。
IMAGE_REL_BASED_HIGH
1
基底重新配置會將高16位的差異新增至位移的16位字段。 16 位欄位欄位代表 32 位單字的高值。
IMAGE_REL_BASED_LOW
2
基底重新配置會將16位差異的低位新增至位移的16位字段。 16 位欄位欄位代表 32 位單字的下半部分。
IMAGE_REL_BASED_HIGHLOW
3
基底重新配置會將所有 32 位的差異套用至位移的 32 位字段。
IMAGE_REL_BASED_HIGHADJ
4
基底重新配置會將高16位的差異新增至位移的16位字段。 16 位欄位欄位代表 32 位單字的高值。 32 位值的低 16 位會儲存在此基底重新配置之後的 16 位字中。 這表示這個基礎重新配置佔用兩個位置。
IMAGE_REL_BASED_MIPS_JMPADDR
5
重新配置解譯取決於機器類型。
當機器類型為 MIPS 時,基底重新配置會套用至 MIPS 跳躍指示。
IMAGE_REL_BASED_ARM_MOV32
5
只有在計算機類型為 ARM 或 Thumb 時,此重新配置才有意義。 基底重新配置會將符號的 32 位位址套用到連續的 MOVW/MOVT 指令組。
IMAGE_REL_BASED_RISCV_HIGH20
5
只有在計算機類型為 RISC-V 時,此重新配置才有意義。 基底重新配置適用於 32 位絕對位址的高 20 位。
6
保留的 必須是零。
IMAGE_REL_BASED_THUMB_MOV32
7
只有在計算機類型為 Thumb 時,此重新配置才有意義。 基底重新配置會將符號的 32 位位址套用至連續的 MOVW/MOVT 指令組。
IMAGE_REL_BASED_RISCV_LOW12I
7
只有在計算機類型為 RISC-V 時,此重新配置才有意義。 基底重新配置適用於 32 位絕對位址的低 12 位,格式為 RISC-V I-type 指令格式。
IMAGE_REL_BASED_RISCV_LOW12S
8
只有在計算機類型為 RISC-V 時,此重新配置才有意義。 基底重新配置適用於 32 位絕對位址的低 12 位,格式為 RISC-V S-type 指令格式。
IMAGE_REL_BASED_LOONGARCH32_MARK_LA
8
只有在計算機類型為 LoongArch 32 位時,此重新配置才有意義。 基底重新配置適用於以兩個連續指令形成的32位絕對位址。
IMAGE_REL_BASED_LOONGARCH64_MARK_LA
8
只有在計算機類型為 LoongArch 64 位時,此重新配置才有意義。 基底重新配置適用於以四個連續指示形成的64位絕對位址。
IMAGE_REL_BASED_MIPS_JMPADDR16
9
只有在機器類型為MIPS時,重新配置才有意義。 基礎重新配置適用於 MIPS16 跳躍指示。
IMAGE_REL_BASED_DIR64
10
基底重新配置會將差異套用至位移的64位欄位元。

 

.tls 區段

.tls 區段提供靜態線程本機記憶體 (TLS) 的直接 PE 和 COFF 支援。 TLS 是 Windows 支援的特殊儲存類別,其中數據物件不是自動(堆疊)變數,但對於執行程式碼的每個個別線程都是本機的。 因此,每個線程都可以針對使用 TLS 所宣告的變數維護不同的值。

請注意,您可以使用 API 呼叫 TlsAlloc、TlsFree、TlsSetValue 和 TlsGetValue 來支援任何數量的 TLS 數據。 PE 或 COFF 實作是使用 API 的替代方法,並具有從高階語言程式設計人員的觀點來看更簡單的優點。 此實作可讓 TLS 資料定義和初始化,類似於程式中的一般靜態變數。 例如,在 Visual C++ 中,靜態 TLS 變數可以定義如下,而不使用 Windows API:

__declspec (thread) int tlsFlag = 1;

為了支援此程式設計建構,PE 和 COFF .tls 區段會指定下列資訊:初始化數據、每個線程初始化和終止的回呼例程,以及下列討論中說明的 TLS 索引。

注意

在 Windows Vista 之前,靜態宣告的 TLS 資料物件只能在靜態載入的影像檔中使用。 這個事實使得在 DLL 中使用靜態 TLS 數據不可靠,除非您知道 DLL 或以靜態方式連結的任何專案,永遠不會以 LoadLibrary API 函式動態載入。 不過,從 Windows Vista 開始,已改善 Windows 載入器,以更好地支援使用靜態 TLS 動態載入 DLL。 這項變更表示,即使使用 LoadLibrary 以動態方式載入 DLL,使用靜態宣告的 TLS 數據對象現在可以更可靠地使用。 載入器能夠在載入時配置這類 DLL 的 TLS 位置,以減輕舊版 Windows 中存在的限制。

 

注意

32 位位移和索引乘數 4 的參考會套用至具有 32 位架構的系統。 在以64位架構為基礎的系統中,視需要調整它們。

可執行的程式代碼會透過下列步驟存取靜態 TLS 資料物件:

  1. 在連結時,鏈接器會設定 TLS 目錄的 [索引位址] 字段。 此欄位會指向程式預期要接收 TLS 索引的位置。

    Microsoft 運行時間連結庫藉由定義 TLS 目錄的記憶體映射,併為其提供特殊名稱 “__tls_used” (Intel x86 平臺) 或 “_tls_used” (其他平臺)來協助此程式。 鏈接器會尋找此記憶體映射,並使用該處的數據來建立 TLS 目錄。 支援 TLS 及使用 Microsoft 連結器的其他編譯程式必須使用這個相同的技術。

  2. 建立線程時,載入器會在 FS 快取器中放置線程環境區塊 (TEB) 的位址,以傳達線程 TLS 陣列的位址。 TLS 陣列的指標位於 TEB 開頭0x2C位移。 此行為為 Intel x86 特定。

  3. 載入器會將 TLS 索引的值指派給 [索引位址] 字段所指示的位置。

  4. 可執行文件程式代碼會擷取 TLS 索引,以及 TLS 陣列的位置。

  5. 程序代碼會使用 TLS 索引和 TLS 陣列位置(將索引乘以 4,並將其作為數位移)來取得指定程式和模組的 TLS 數據區位址。 每個線程都有自己的 TLS 數據區域,但這對程式而言是透明的,這不需要知道如何為個別線程配置數據。

  6. 個別的 TLS 資料物件會存取為 TLS 數據區域的一些固定位移。

TLS 陣列是系統針對每個線程維護的位址陣列。 此陣列中的每個位址都會提供程式內指定模組 (EXE 或 DLL) 的 TLS 資料位置。 TLS 索引會指出要使用的數位成員。 索引是識別模組的數位(只對系統有意義)。

TLS 目錄

TLS 目錄的格式如下:

位移 (PE32/ PE32+) 大小 (PE32/ PE32+) 欄位 描述
0
4/8
原始數據啟動 VA
TLS 範本的起始位址。 此範本是用來初始化 TLS 數據的數據區塊。 系統會在每次建立線程時複製所有這些數據,因此它不得損毀。 請注意,此位址不是 RVA;它是 .reloc 區段中應該有基底重新配置的位址。
4/8
4/8
原始數據結束 VA
TLS 最後一個字節的位址,但零填滿除外。 如同 [原始數據開始 VA] 字段,這是 VA,而不是 RVA。
8/16
4/8
索引位址
要接收載入器指派之 TLS 索引的位置。 此位置位於一般數據區段中,因此可以指定程式可存取的符號名稱。
12/24
4/8
回呼位址
TLS 回呼函式陣列的指標。 陣列是以 Null 終止,因此如果不支援回呼函式,此欄位會指向設定為零的 4 個字節。 如需這些函式原型的相關信息,請參閱 TLS 回呼函式
16/32
4
零填滿的大小
範本的大小,超出以原始數據開始 VA 和原始數據結束 VA 字段分隔的初始化數據。 範本大小總計應該與映像檔中的 TLS 數據總大小相同。 零填滿是初始化的非零數據之後的數據量。
20/36
4
特徵
四個位 [23:20] 描述對齊資訊。 可能的值為定義為 IMAGE_SCN_ALIGN_*的值,這些值也用來描述物件檔中區段的對齊方式。 其他 28 位則保留供日後使用。

 

TLS 回呼函式

程式可以提供一或多個 TLS 回呼函式,以支援 TLS 資料物件的額外初始化和終止。 這類回呼函式的一般用法是呼叫 物件的建構函式和解構函式。

雖然通常沒有一個以上的回呼函式,但回呼會實作為數位,以便視需要新增其他回呼函式。 如果有多個回呼函式,則會依其位址出現在陣列中的順序呼叫每個函式。 Null 指標會終止陣列。 擁有空白清單(不支援回呼),在此情況下,回呼陣列只有一個成員-null指標,這完全有效。

回呼函式的原型(由類型為 PIMAGE_TLS_CALLBACK 的指標所指向)具有與 DLL 進入點函式相同的參數:

typedef VOID
(NTAPI *PIMAGE_TLS_CALLBACK) (
    PVOID DllHandle,
    DWORD Reason,
    PVOID Reserved
    );

Reserved 參數應該設定為零。 Reason 參數可以採用下列值:

設定 Description
DLL_PROCESS_ATTACH
1
已開始新的進程,包括第一個線程。
DLL_THREAD_ATTACH
2
已建立新的線程。 除了第一個線程,所有線程都傳送此通知。
DLL_THREAD_DETACH
3
線程即將終止。 除了第一個線程,所有線程都傳送此通知。
DLL_PROCESS_DETACH
0
進程即將終止,包括原始線程。

 

載入組態結構 (僅限映像)

載入組態結構(IMAGE_LOAD_CONFIG_DIRECTORY)以前用於 Windows NT 作業系統本身非常有限的案例中,以描述各種功能太困難或太大而無法描述映像的檔案標頭或選擇性標頭。 目前版本的 Microsoft 連結器和 Windows XP 和更新版本的 Windows 會針對包含保留 SEH 技術的 32 位 x86 型系統,使用這個結構的新版本。 這會提供操作系統在例外狀況分派期間使用的安全結構化例外狀況處理程序清單。 如果處理程式位址位於影像的 VA 範圍中,且標示為保留的 SEH 感知功能(也就是說,IMAGE_DLLCHARACTERISTICS_NO_SEH在選擇性標頭的 DllCharacteristics 欄位中清楚,如先前所述),則處理程式必須位於該映像的已知安全處理程式清單中。 否則,操作系統會終止應用程式。 這有助於防止過去用來控制作業系統的「x86 例外狀況處理程式劫持」惡意探索。

Microsoft 連結器會自動提供預設的負載組態結構,以包含保留的 SEH 數據。 如果使用者程式代碼已經提供負載組態結構,它必須包含新的保留 SEH 字段。 否則,連結器不能包含保留的 SEH 數據,且映像未標示為包含保留的 SEH。

載入組態目錄

預先保留 SEH 載入組態結構的數據目錄項目必須指定負載組態結構的特定大小,因為作業系統載入器一律預期它是特定值。 在這方面,大小實際上只是版本檢查。 為了與 Windows XP 和舊版 Windows 相容,x86 映像的大小必須為 64。

載入組態配置

負載組態結構具有 32 位和 64 位 PE 檔案的下列配置:

位移 大小 欄位 描述
0
4
特徵
旗標,指出檔案的屬性,目前未使用。
4
4
TimeDateStamp
日期和時間戳值。 根據系統時鐘,此值是以自午夜(00:00:00:00)起經過的秒數表示,1970 年 1 月 1 日,通用國際標準時間。 您可以使用 C 執行時間 (CRT) 時間函式來列印時間戳。
8
2
MajorVersion
主要版本號碼。
10
2
MinorVersion
次要版本號碼。
12
4
GlobalFlagsClear
當載入器啟動進程時,要清除此進程的全域載入器旗標。
16
4
GlobalFlagsSet
當載入器啟動進程時,要為此進程設定的全域載入器旗標。
20
4
CriticalSectionDefaultTimeout
要用於此程式的重要區段的預設逾時值。
24
4/8
DeCommitFreeBlockThreshold
記憶體必須在系統傳回之前釋放,以位元組為單位。
28/32
4/8
DeCommitTotalFreeThreshold
可用記憶體總數,以位元組為單位。
32/40
4/8
LockPrefixTable
[僅限 x86]使用 LOCK 前置詞之位址清單的 VA,以便將其取代為單一處理器電腦上的 NOP。
36/48
4/8
MaximumAllocationSize
配置大小上限,以位元組為單位。
40/56
4/8
VirtualMemoryThreshold
虛擬記憶體大小上限,以位元組為單位。
44/64
4/8
ProcessAffinityMask
將此欄位設定為非零值相當於在行程啟動期間使用此值呼叫 SetProcessAffinityMask (僅限.exe)
48/72
4
ProcessHeapFlags
處理對應於 HeapCreate 函式第一個自變數的堆積旗標。 這些旗標適用於進程啟動期間建立的進程堆積。
52/76
2
CSDVersion
Service Pack 版本標識碼。
54/78
2
保留
必須是零。
56/80
4/8
EditList
保留供系統使用。
60/88
4/8
SecurityCookie
Visual C++ 或 GS 實作所使用的 Cookie 指標。
64/96
4/8
SEHandlerTable
[僅限 x86]影像中每個有效唯一 SE 處理程式之 RVA 排序數據表的 VA。
68/104
4/8
SEHandlerCount
[僅限 x86]數據表中唯一處理程式的計數。
72/112
4/8
GuardCFCheckFunctionPointer
儲存控制流程防護檢查函式指標的 VA。
76/120
4/8
GuardCFDispatchFunctionPointer
儲存控制流程防護分派函式指標的 VA。
80/128
4/8
GuardCFFunctionTable
影像中每個控制流程防護功能之 RVA 排序數據表的 VA。
84/136
4/8
GuardCFFunctionCount
上表中唯一的 RVA 計數。
88/144
4
GuardFlags
控制流程防護相關旗標。
92/148
12
CodeIntegrity
程序代碼完整性資訊。
104/160
4/8
GuardAddressTakenIatEntryTable
儲存控制流程防護位址的 VA。
108/168
4/8
GuardAddressTakenIatEntryCount
上表中唯一的 RVA 計數。
112/176
4/8
GuardLongJumpTargetTable
儲存控制流程防護長跳目標數據表的 VA。
116/184
4/8
GuardLongJumpTargetCount
上表中唯一的 RVA 計數。

 

GuardFlags 字段包含下列一或多個旗標和子字段的組合:

  • 模組會使用系統提供的支持來執行控制流程完整性檢查。

    #define IMAGE_GUARD_CF_INSTRUMENTED 0x00000100

  • 模組會執行控制流程和寫入完整性檢查。

    #define IMAGE_GUARD_CFW_INSTRUMENTED 0x00000200

  • 模組包含有效的控制流程目標元數據。

    #define IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT 0x00000400

  • 模組不會使用 /GS 安全性 Cookie。

    #define IMAGE_GUARD_SECURITY_COOKIE_UNUSED 0x00000800

  • 模組支援只讀延遲載入 IAT。

    #define IMAGE_GUARD_PROTECT_DELAYLOAD_IAT 0x00001000

  • 延遲載入數據表在其本身的 .didat 區段中(不含任何其他專案),可以自由重新保護。

    #define IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION 0x00002000

  • 模組包含隱藏的導出資訊。 這也會推斷所取得 IAT 數據表的位址也會出現在負載設定中。

    #define IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT 0x00004000

  • 模組可抑制導出。

    #define IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION 0x00008000

  • 模組包含longjmp目標資訊。

    #define IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT 0x00010000

  • 子欄位的遮罩,其中包含控制流程防護函式數據表專案的步幅(也就是每個數據表專案的額外位元組計數)。

    #define IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK 0xF0000000

此外,Windows SDK winnt.h 標頭會定義此宏,以將 GuardFlags 值向右移位,讓控制流程防護函式數據表大步調整:

#define IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT 28

.rsrc 區段

資源會以多層級二進位排序樹狀結構編製索引。 一般設計可以納入 2**31 層級。 不過,依照慣例,Windows 會使用三個層級:

類型名稱語言

一系列的資源目錄數據表會以下列方式關聯所有層級:每個目錄數據表後面接著一系列目錄專案,該層級的名稱或標識元(ID)以及數據描述或其他目錄數據表的位址。 如果位址指向數據描述,則數據會是樹狀結構中的分葉。 如果位址指向另一個目錄數據表,則該數據表會向下列出下一個層級的目錄專案。

分葉的 [類型]、[名稱] 和 [語言標識符] 取決於透過目錄數據表取得分葉的路徑。 第一個數據表會決定類型標識碼、第二個數據表(由第一個數據表中的目錄專案指向)會決定名稱標識碼,而第三個數據表則決定語言標識碼。

.rsrc 區段的一般結構為:

資料 描述
資源目錄資料表(和資源目錄專案)
一系列的數據表,樹狀結構中的每個節點群組各一個。 所有最上層節點都會列在第一個數據表中。 此數據表中的專案指向第二層數據表。 每個第二層樹狀結構都有相同的類型標識碼,但不同的名稱標識碼。 第三層樹狀結構具有相同的類型和名稱標識碼,但不同的語言標識碼。
每個個別數據表緊接著目錄專案,其中每個專案都有名稱或數值標識元,以及下一個較低層級的數據描述或數據表指標。
資源目錄字串
雙位元組對齊的 Unicode 字串,做為目錄專案所指向的字串數據。
資源數據描述
數據表所指向的記錄陣列,描述資源數據的實際大小和位置。 這些記錄是資源描述樹狀結構中的樹葉。
資源數據
資源區段的原始數據。 [資源數據描述] 欄位中的大小和位置資訊會分隔資源數據的個別區域。

 

資源目錄數據表

每個資源目錄數據表都有下列格式。 此數據結構應該視為數據表的標題,因為數據表實際上包含目錄專案(如 6.9.2,「資源目錄專案」一節所述)和這個結構:

位移 大小 欄位 描述
0
4
特徵
資源旗標。 此欄位保留供日後使用。 它目前設定為零。
4
4
時間/日期戳記
資源編譯程式建立資源數據的時間。
8
2
主要版本
用戶設定的主要版本號碼。
10
2
次要版本
用戶所設定的次要版本號碼。
12
2
名稱項目數目
緊接在數據表後面的目錄項目數目,這些目錄專案會使用字串來識別類型、名稱或語言專案(視數據表的層級而定)。
14
2
標識碼數目
緊接在名稱項目之後的目錄項目數目,這些專案會針對 Type、Name 或 Language 專案使用數值識別碼。

 

資源目錄專案

目錄項目組成數據表的數據列。 每個資源目錄專案都有下列格式。 專案是否為 [名稱] 或 [標識符] 專案是由資源目錄數據表所指出,這表示後面有多少 Name 和 ID 專案(請記住,所有 Name 專案都位於數據表的所有識別符專案之前)。 數據表的所有項目都會依遞增順序排序:依區分大小寫的字串命名專案,並以數值排序標識符專案。 位移相對於 IMAGE_DIRECTORY_ENTRY_RESOURCE DataDirectory 中的位址。 如需詳細資訊,請參閱 PE內部對等互連:Win32 可攜式可執行檔格式 導覽。

位移 大小 欄位 描述
0
4
名稱位移
根據數據表層級,提供 Type、Name 或 Language ID 專案的字串位移。
0
4
整數標識碼
識別類型、名稱或語言標識碼專案的32位整數。
4
4
數據輸入位移
高位 0。 資源數據項的位址(分葉)。
4
4
子目錄位移
高位 1。 較低的31位是另一個資源目錄資料表的位址(下一個層級向下)。

 

資源目錄字串

資源目錄字串區域是由 Unicode 字串所組成,這些字串是文字對齊的。 這些字串會一起儲存在最後一個 Resource Directory 項目之後,以及第一個資源數據專案之前。 這樣會將這些可變長度字串對固定大小目錄專案的對齊影響降到最低。 每個資源目錄字串都有下列格式:

位移 大小 欄位 描述
0
2
長度
字串的大小,不包括長度欄位本身。
2
變數
Unicode 字串
可變長度的 Unicode 字串數據,單字對齊。

 

資源數據輸入

每個資源數據項目都會描述資源數據區域中原始數據的實際單位。 資源資料專案的格式如下:

位移 大小 欄位 描述
0
4
數據 RVA
資源數據區域中資源數據的單位位址。
4
4
大小
Data RVA 欄位所指向之資源數據的大小,以位元組為單位。
8
4
Codepage
用來譯碼資源數據內代碼點值的代碼頁。 一般而言,代碼頁會是 Unicode 代碼頁。
12
4
保留的 必須是 0。

 

.cormeta 區段 (僅限物件)

CLR 元數據會儲存在本節中。 它用來指出物件檔包含Managed程式碼。 元數據的格式不會記載,但可以交給CLR介面來處理元數據。

.sxdata 區段

物件的有效例外狀況處理程式會列在該 物件的 .sxdata 區段中。 區段標示為IMAGE_SCN_LNK_INFO。 它包含每個有效處理程式的 COFF 符號索引,每個索引使用 4 個字節。

此外,編譯程式會發出絕對符號 「@feat.00」,並將值欄位的 LSB 設為 1,將 COFF 物件標示為已註冊 SEH。 沒有已註冊 SEH 處理程式的 COFF 物件會有 「@feat.00」 符號,但沒有 .sxdata 區段。

封存 (連結庫) 檔案格式

COFF 封存格式提供儲存物件檔案集合的標準機制。 這些集合通常稱為程式設計檔中的連結庫。

封存的前8個字節是由檔案簽章所組成。 封存的其餘部分包含一系列封存成員,如下所示:

  • 第一個和第二個成員是「連結器成員」。每個成員都有自己的格式,如匯入名稱類型一節所述。 一般而言,鏈接器會將資訊放入這些封存成員中。 鏈接器成員包含封存的目錄。

  • 第三個成員是 「longnames」 成員。 這個選擇性成員是由一系列以 Null 終止的 ASCII 字串所組成,其中每個字串都是另一個封存成員的名稱。

  • 封存的其餘部分是由標準 (物件檔案) 成員所組成。 每個成員都包含整個物件檔案的內容。

封存成員標頭位於每個成員之前。 下列清單顯示封存的一般結構:

簽章 :“!<arch>\n”
頁首
第 1 個連結器成員
頁首
第2個連結器成員
頁首
Longnames 成員
頁首
OBJ 檔案 1 的內容
(COFF 格式)
頁首
OBJ 檔案 2 的內容
(COFF 格式)

...

頁首
OBJ 檔案 N 的內容
(COFF 格式)

封存盤案簽章

封存盤案簽章會識別文件類型。 任何接受封存盤案做為輸入的公用程式(例如連結器)都可以藉由讀取此簽章來檢查檔類型。 簽章是由下列 ASCII 字元所組成,除了換行符 (\n) 字元之外,下列每個字元都會以常值表示:

!<arch>\n

Windows SDK winnt.h 標頭會定義下列宏:

#define IMAGE_ARCHIVE_START_SIZE             8
#define IMAGE_ARCHIVE_START                  "!<arch>\n"
#define IMAGE_ARCHIVE_END                    "`\n"
#define IMAGE_ARCHIVE_PAD                    "\n"
#define IMAGE_ARCHIVE_LINKER_MEMBER          "/               "
#define IMAGE_ARCHIVE_LONGNAMES_MEMBER       "//              "
#define IMAGE_ARCHIVE_HYBRIDMAP_MEMBER       "/<HYBRIDMAP>/   "

封存成員標頭

每個成員(linker、longnames 或 object-file 成員)前面都會加上標頭。 封存成員標頭具有下列格式,其中每個欄位都是 ASCII 文字字串,其靠左對齊,並填補欄位結尾的空格。 這些欄位中沒有任何終止的 Null 字元。

每個成員標頭都會在上一個封存成員結尾之後的第一個偶數地址開始,一個字節 '\n' (IMAGE_ARCHIVE_PAD) 可能會在封存成員之後插入,讓下列成員在偶數地址上啟動。

位移 大小 欄位 描述
0
16
名字
封存成員的名稱,並附加斜線 (/) 以終止名稱。 如果第一個字元是斜線,則名稱具有特殊的解譯,如下表所述。
16
12
日期
封存成員建立的日期和時間:這是自 1/1/1970 UCT 起的秒數十進位表示法。
28
6
用戶標識碼
用戶標識碼的 ASCII 十進位表示法。 此欄位不包含 Windows 平臺上有意義的值,因為 Microsoft 工具會發出所有空白。
34
6
群組標識碼
群組標識碼的 ASCII 十進位表示法。 此欄位不包含 Windows 平臺上有意義的值,因為 Microsoft 工具會發出所有空白。
40
8
模式
成員檔案模式的 ASCII 八進位表示法。 這是 C 執行時間函式_wstat中的ST_MODE值。
48
10
大小
封存成員大小總計的 ASCII 十進位表示法,不包括標頭的大小。
58
2
標頭結尾
C 字串 “'\n” 中的兩個字節 (0x60 0x0A) (IMAGE_ARCHIVE_END)。

[名稱] 欄位具有下表所示的其中一種格式。 如先前所述,這些字串中每個字串都保持對齊,並在 16 個字節的欄位中填補尾端空格:

[名稱] 欄位的內容 描述
名稱/
封存成員的名稱。
/
封存成員是兩個連結器成員之一。 這兩個連結器成員都有這個名稱。
//
封存成員是longnames成員,其中包含一連串以Null終止的ASCII字串。 longnames 成員是第三個封存成員,而且是選擇性的。
/n
封存成員的名稱位於longnames成員內的 offset n。 數位 n 是位移的十進位表示法。 例如:「/26」 表示封存成員的名稱位於 longnames 成員內容的開頭以外的 26 個字節。

 

第一個連結器成員

第一個連結器成員的名稱是 “/” (IMAGE_ARCHIVE_LINKER_MEMBER)。 包含第一個連結器成員以取得回溯相容性。 目前連結器不會使用它,但其格式必須正確。 此連結器成員提供符號名稱的目錄,第二個連結器成員也一樣。 對於每個符號,資訊會指出要在哪裡尋找包含符號的封存成員。

第一個連結器成員的格式如下。 此資訊會出現在標頭後面:

位移 大小 欄位 描述
0
4
符號數目
不帶正負號的long,其中包含索引符號的數目。 此數位會以大端格式儲存。 每個物件檔案成員通常會定義一或多個外部符號。
4
4 * n
補償
封存成員標頭的檔案位移數位,其中 n 等於 [符號數目] 字段。 陣列中的每個數位都是以 big-endian 格式儲存的不帶正負號長。 針對字串數據表中命名的每個符號,offsets 陣列中的對應專案會提供包含符號之封存成員的位置。
*
*
字串數據表
一連串以 Null 結尾的字串,這個字串會命名目錄中的所有符號。 每個字串都會在上一個字串中的 Null 字元後面立即開始。 字串數目必須等於 [符號數目] 欄位的值。

 

offsets 陣列中的元素必須以遞增順序排列。 這個事實表示字串數據表中的符號必須根據封存成員的順序排列。 例如,第一個對象檔成員中的所有符號都必須列在第二個對象檔中的符號之前。

第二個連結器成員

如同第一個連結器成員,第二個鏈接器成員的名稱為 “/” (IMAGE_ARCHIVE_LINKER_MEMBER)。 雖然這兩個連結器成員都提供包含符號和封存成員的目錄,但第二個連結器成員會優先使用所有目前連結器的第一個。 第二個連結器成員會以語彙順序包含符號名稱,以加快依名稱搜尋的速度。

第二個成員的格式如下。 此資訊會出現在標頭後面:

位移 大小 欄位 描述
0
4
成員數目
不帶正負號的long,其中包含封存成員的數目。
4
4 * m
補償
封存成員標頭的檔案位移數位,依遞增順序排列。 每個位移都是不帶正負號的長 。 數位 m 等於 [成員數目] 欄位的值。
*
4
符號數目
不帶正負號的long,其中包含已編製索引的符號數目。 每個物件檔案成員通常會定義一或多個外部符號。
*
2 * n
指標
以 1 為基底的索引數位,會將符號名稱對應至封存成員位移。 數字 n 等於 [符號數目] 欄位。 對於字串數據表中命名的每個符號,Indexes 陣列中的對應專案會提供位移陣列中的索引。 位移陣組接著會提供包含符號的封存成員位置。
*
*
字串數據表
一連串以 Null 結尾的字串,這個字串會命名目錄中的所有符號。 每個字串都會在上一個字串中的 Null 位元組之後立即開始。 字串數目必須等於 [符號數目] 欄位的值。 下表以遞增語匯順序列出所有符號名稱。

 

Longnames 成員

longnames 成員的名稱為 “@IMAGE_ARCHIVE_LONGNAMES_MEMBER”“”。。 longnames 成員是封存成員名稱的一系列字串。 只有當 [名稱] 欄位中的空間不足(16 個字節)時,才會顯示名稱。 longnames 成員是選擇性的。 它可以是空的,只有標頭,或者它完全不存在,甚至沒有標頭。

字串會以 Null 結束。 每個字串都會在上一個字串中的 Null 位元組之後立即開始。

匯入連結庫格式

傳統匯入連結庫,也就是描述從某個映射匯出以供另一個映射使用的連結庫,通常會遵循封存(連結庫)檔格式一節中所述的配置。 主要差異在於匯入連結庫成員包含虛擬物件檔案,而不是實際物件檔案,其中每個成員都包含建置匯入數據表所需的區段貢獻,而此匯入數據表會在建置導出應用程式時產生此封存。

您可以從一小組資訊推斷匯入的區段貢獻。 鏈接器可以在連結庫建立時產生完整的詳細資訊資訊到每個成員的匯入連結庫,或只將標準資訊寫入至連結庫,並讓稍後使用該連結庫的應用程式實時產生必要的數據。

在具有長格式的匯入連結庫中,單一成員包含下列資訊:

  • 封存成員標頭
  • 檔案標頭
  • 區段標頭
  • 對應至每個區段標頭的數據
  • COFF 符號表
  • 字串

相反地,簡短匯入連結庫的撰寫方式如下:

  • 封存成員標頭
  • 匯入標頭
  • Null 終止的匯入名稱字串
  • Null 終止的 DLL 名稱字串

這足以在成員使用時正確重新建構成員的整個內容。

匯入標頭

匯入標頭包含下列欄位移:

位移 大小 欄位 描述
0
2
Sig1
必須是IMAGE_FILE_MACHINE_UNKNOWN。 如需詳細資訊,請參閱 機器類型
2
2
Sig2
必須是0xFFFF。
4
2
版本
結構版本。
6
2

識別目標計算機類型的數位。 如需詳細資訊,請參閱 機器類型
8
4
時間戳
檔案建立的時間和日期。
12
4
數據大小
標頭後面的字串大小。
16
2
序數/提示
匯入的序數或提示,由 [名稱類型] 欄位中的值所決定。
18
2 位
輸入
匯入類型。 如需特定值和描述,請參閱 匯入類型
3 位
名稱類型
匯入名稱類型。 如需詳細資訊,請參閱 匯入名稱類型
11 位
保留
保留的 必須是 0。

 

此結構後面接著兩個以 Null 結尾的字串,描述匯入符號的名稱及其來源的 DLL。

匯入類型

下列值是針對匯入標頭中的 [類型] 欄位所定義:

常數 Description
IMPORT_OBJECT_CODE
0
可執行的程序代碼。
IMPORT_OBJECT_DATA
1
資料。
IMPORT_OBJECT_CONST
2
在 .def 檔案中指定為 CONST。

這些值可用來判斷如果工具必須存取該數據,則必須使用連結庫的工具產生哪些區段貢獻。

匯入名稱類型

以 Null 結尾的匯入符號名稱緊接在其相關聯的匯入標頭後面。 下列值是針對匯入標頭中的 [名稱類型] 欄位所定義。 它們會指出如何使用名稱來產生代表匯入的正確符號:

常數 Description
IMPORT_OBJECT_ORDINAL 0 匯入是序數。 這表示匯入標頭的 Ordinal/Hint 字段中的值是匯入的序數。 如果未指定這個常數,則序數/提示字段應該一律解譯為匯入的提示。
IMPORT_OBJECT_NAME 1 匯入名稱與公用符號名稱相同。
IMPORT_OBJECT_NAME_NOPREFIX 2 匯入名稱是公用符號名稱,但略過前置 ?、@或选择性 _。
IMPORT_OBJECT_NAME_UNDECORATE 3 匯入名稱是公用符號名稱,但略過前置 ?、@或选择性 _,並在第一個 @截断。

附錄 A:計算 Authenticode PE 映射哈希

預期會使用數個屬性憑證來驗證映像的完整性。 不過,最常見的是 Authenticode 簽章。 Authenticode 簽章可用來驗證 PE 圖像文件的相關區段從未從檔案的原始表單中以任何方式改變。 若要完成這項工作,Authenticode 簽章包含稱為PE映像哈希的內容

什麼是 Authenticode PE 映像哈希?

Authenticode PE 映射哈希或簡短檔案哈希類似於檔案總和檢查碼,因為它會產生與檔案完整性相關的小型值。 總和檢查碼是由簡單的演算法所產生,主要用於偵測記憶體失敗。 也就是說,它用來偵測磁碟上的記憶體區塊是否已損毀,而且儲存在那裡的值已損毀。 檔案哈希類似於總和檢查碼,因為它也會偵測檔案損毀。 不過,與大多數總和檢查碼演算法不同,修改檔案非常困難,因此其檔案哈希與原始的(未修改)形式相同。 也就是說,總和檢查碼的目的是偵測導致損毀的簡單記憶體失敗,但檔案哈希可用來偵測檔案的刻意甚至細微修改,例如病毒、駭客或特洛伊木馬程式所引進的檔案。

在 Authenticode 簽章中,檔案哈希會使用只有檔案簽署者已知的私鑰進行數字簽署。 軟體取用者可以計算檔案的哈希值,並將其與 Authenticode 數位簽名中包含的已簽署哈希值進行比較,以驗證檔案的完整性。 如果檔案哈希不相符,則PE映像哈希所涵蓋的檔案部分已修改。

Authenticode PE 映射哈希中涵蓋的內容為何?

在PE映像哈希的計算中,不可能或想要包含所有影像檔案數據。 有時它只是呈現不想要的特性(例如,無法從公開發行的檔案中移除偵錯資訊):有時候,這簡直是不可能的。 例如,不可能在 Authenticode 簽章中包含圖像檔案中的所有資訊,然後將包含該 PE 映射哈希的 Authenticode 簽章插入 PE 映射中,然後能夠再次在計算中包含所有影像檔案數據來產生相同的 PE 映射哈希,因為檔案現在包含原本不存在的 Authenticode 簽章。

產生 Authenticode PE 映像哈希的程式

本節說明如何計算 PE 映射哈希,以及可以修改 PE 映射哪些部分,而不會使 Authenticode 簽章失效。

注意

特定檔案的PE映像哈希可以包含在個別的目錄檔案中,而不需在哈希檔案中包含屬性憑證。 這很相關,因為修改實際上不包含 Authenticode 簽章簽章的 PE 映射,使 Authenticode 簽署目錄檔案中的 PE 映像哈希失效。

區段數據表中指定之PE映射區段中的所有數據,會全部哈希,但下列排除範圍除外:

  • 選擇性標頭之 Windows 特定欄位的檔案 CheckSum 字段。 此總和檢查碼包含整個檔案(包括檔案中的任何屬性憑證)。 在所有可能性中,總和檢查碼在插入 Authenticode 簽章之後,總和檢查碼會不同。

  • 與屬性憑證相關的資訊。 與 Authenticode 簽章相關的 PE 映射區域不會包含在 PE 影像哈希的計算中,因為可以新增或移除 Authenticode 簽章,而不會影響影像的整體完整性。 這不是問題,因為有一些使用者案例相依於重新簽署PE映像或新增時間戳。 Authenticode 會從哈希計算中排除下列資訊:

    • 選擇性標頭資料目錄的 [憑證數據表] 欄位。

    • [憑證數據表] 和正上方所列 [憑證數據表] 字段所指向的對應憑證。

    若要計算PE映像哈希,Authenticode 會依位址範圍排序區段數據表中指定的區段,然後哈希產生的位元組序列,並傳遞超過排除範圍。

  • 上一節結尾的過去資訊。 最後一個區段 (由最高位移定義) 的區域不會哈希。 此區域通常包含偵錯資訊。 偵錯資訊通常可視為調試程序的諮詢;它不會影響可執行程序的實際完整性。 在產品傳遞且不會影響程式的功能之後,從映像移除偵錯資訊是相當可能的。 事實上,這有時是以節省磁碟的量值來完成。 值得注意的是,無法移除PE映像指定區段中所包含的偵錯資訊,而不會使Authenticode簽章失效。

您可以使用 Windows 平台 SDK 中提供的 makecert 和 signtool 工具來實驗建立和驗證 Authenticode 簽章。 如需詳細資訊,請參閱下方的參考。

參考資料

適用於 Windows 的下載和工具(包括 Windows SDK)

建立、檢視和管理憑證

核心模式程式代碼簽署逐步解說 (.doc)

SignTool

Windows Authenticode 可攜式可執行檔簽章格式 (.docx)

ImageHlp 函式