PE-Format

Diese Spezifikation beschreibt die Struktur von ausführbaren Dateien (Images) und Objektdateien unter der Windows-Betriebssystemfamilie. Diese Dateien werden als Portable Executable (PE)- und Common Object File Format (COFF)-Dateien bezeichnet.

Hinweis

Dieses Dokument soll die Entwicklung von Werkzeugen und Anwendungen für Windows unterstützen, erhebt aber keinen Anspruch auf Vollständigkeit in jeder Hinsicht. Microsoft behält sich das Recht vor, dieses Dokument ohne vorherige Ankündigung zu ändern.

Diese Revision der Microsoft Portable Executable and Common Object File Format Specification ersetzt alle früheren Revisionen dieser Spezifikation.

Allgemeine Konzepte

Dieses Dokument spezifiziert die Struktur von ausführbaren (Image-)Dateien und Objektdateien unter der Microsoft Windows-Betriebssystemfamilie. Diese Dateien werden als Portable Executable (PE)- und Common Object File Format (COFF)-Dateien bezeichnet. Der Name „Portable Executable“ bezieht sich auf die Tatsache, dass das Format nicht architekturabhängig ist.

Bestimmte Begriffe, die in dieser Spezifikation vorkommen, werden in der folgenden Tabelle beschrieben:

Name Beschreibung
attribut-Zertifikat
Ein Zertifikat, das dazu dient, überprüfbare Aussagen mit einem Image zu verknüpfen. Einer Datei kann eine Reihe verschiedener überprüfbarer Aussagen zugeordnet werden; eine der nützlichsten ist die Aussage eines Softwareherstellers, die angibt, wie der Message Digest des Images voraussichtlich aussehen wird. Ein Message Digest ist ähnlich wie eine Prüfsumme, nur dass er extrem schwer zu fälschen ist. Daher ist es sehr schwierig, eine Datei so zu verändern, dass sie denselben Message Digest wie die Originaldatei aufweist. Die Aussage kann mit Hilfe von Kryptographieverfahren mit öffentlichem oder privatem Schlüssel als vom Hersteller stammend überprüft werden. Dieses Dokument beschreibt Details zu Attributzertifikaten, die nicht das Einfügen in Imagedateien ermöglichen.
Datums-/Zeitstempel
Ein Stempel, der an mehreren Stellen in einer PE- oder COFF-Datei für unterschiedliche Zwecke verwendet wird. In den meisten Fällen ist das Format jedes Stempels dasselbe, das von den Zeitfunktionen in der C-Laufzeitbibliothek verwendet wird. Für Ausnahmen siehe die Beschreibung von IMAGE_DEBUG_TYPE_REPRO in Debug Type. Wenn der Stempelwert 0 oder 0xFFFFFFFF ist, handelt es sich nicht um einen echten oder sinnvollen Datums-/Zeitstempel.
Dateizeiger
Der Ort, an dem sich ein Element in der Datei selbst befindet, bevor es vom Linker (im Falle von Objektdateien) oder vom Lader (im Falle von Imagedateien) verarbeitet wird. Mit anderen Worten, dies ist eine Position innerhalb der Datei, wie sie auf der Festplatte gespeichert ist.
linker
Ein Verweis auf den Linker, der mit Microsoft Visual Studio geliefert wird.
Objektdatei
Eine Datei, die als Eingabe für den Linker dient. Der Linker erzeugt eine Imagedatei, die wiederum als Eingabe für den Lader dient. Der Begriff „Object File“ (Objektdatei) impliziert nicht unbedingt eine Verbindung zur objektorientierten Programmierung.
reserviert, muss 0 sein
Eine Beschreibung eines Feldes, die angibt, dass der Wert des Feldes für Erzeuger Null sein muss und Verbraucher das Feld ignorieren müssen.
Relative virtuelle Adresse (RVA)
In einer Imagedatei ist dies die Adresse eines Elements, nachdem es in den Speicher geladen wurde, wobei die Basisadresse der Imagedatei davon abgezogen wird. Der RVA eines Elements unterscheidet sich fast immer von seiner Position innerhalb der Datei auf der Festplatte (Dateizeiger).
In einer Objektdatei ist ein RVA weniger aussagekräftig, da Speicherplätze nicht zugewiesen werden. In diesem Fall wäre ein RVA eine Adresse innerhalb eines Abschnitts (wie später in dieser Tabelle beschrieben), auf die später bei der Verknüpfung eine Verschiebung angewendet wird. Der Einfachheit halber sollte ein Compiler einfach den ersten RVA in jedem Abschnitt auf Null setzen.
abschnitt
Die Grundeinheit von Code oder Daten innerhalb einer PE- oder COFF-Datei. So kann z. B. der gesamte Code einer Objektdatei in einem einzigen Abschnitt zusammengefasst werden, oder (je nach Compilerverhalten) jede Funktion kann einen eigenen Abschnitt belegen. Je mehr Abschnitte, desto mehr Datei-Overhead, aber der Linker kann den Code selektiver einbinden. Ein Abschnitt ist vergleichbar mit einem Segment in der Intel 8086-Architektur. Alle Rohdaten in einem Abschnitt müssen zusammenhängend geladen werden. Darüber hinaus kann eine Imagedatei eine Reihe von Abschnitten enthalten, z. B. .tls oder .reloc , die einen besonderen Zweck erfüllen.
Virtuelle Adresse (VA)
Wie RVA, nur dass die Basisadresse der Imagedatei nicht subtrahiert wird. Die Adresse wird als VA bezeichnet, weil Windows für jeden Prozess einen eigenen VA-Speicherbereich erstellt, der unabhängig vom physischen Speicher ist. Für fast alle Zwecke sollte ein VA nur als Adresse betrachtet werden. Ein VA ist nicht so vorhersehbar wie ein RVA, da der Lader das Image möglicherweise nicht an der gewünschten Stelle lädt.

Übersicht

Die folgende Liste beschreibt das Format der ausführbaren Microsoft PE-Dateien, wobei die Basis des Image-Headers oben steht. Der Abschnitt vom MS-DOS 2.0-kompatiblen EXE-Header bis zum unbenutzten Abschnitt kurz vor dem PE-Header ist der MS-DOS 2.0-Abschnitt und wird nur für die MS-DOS-Kompatibilität verwendet.

  • MS-DOS 2.0 kompatibler EXE-Header

  • unbenutzt

  • OEM-Bezeichner

    Informationen zum Gerätehersteller

    Offset zum PE-Kopf

  • MS-DOS 2.0 Stub-Programm und Verschiebungstabelle

  • unbenutzt

  • PE-Header (an 8-Byte-Grenze ausgerichtet)

  • Abschnittsüberschriften

  • Bildseiten:

    Importinfo

    Exportinfo

    Standortverlagerungen

    Ressourceninfo

Die folgende Liste beschreibt das Microsoft COFF-Objektmodulformat:

  • Microsoft COFF-Kopfzeile

  • Abschnittsüberschriften

  • Rohdaten:

    Code

    Daten

    Debug-Information

    Verschiebungen

Dateiheaderzeilen

Der PE-Dateiheader besteht aus einem Microsoft MS-DOS-Stub, der PE-Signatur, dem COFF-Dateiheader und einem optionalen Kopf. Der Header einer COFF-Objektdatei besteht aus einem COFF-Dateiheader und einem optionalen Header. In beiden Fällen folgen auf die Dateiköpfe unmittelbar die Abschnittsüberschriften.

MS-DOS Stub (nur Image)

Der MS-DOS-Stub ist eine gültige Anwendung, die unter MS-DOS läuft. Sie wird dem EXE-Image vorangestellt. Der Linker setzt hier einen Standard-Stub, der die Meldung „Dieses Programm kann nicht im DOS-Modus ausgeführt werden“ ausgibt, wenn das Image unter MS-DOS ausgeführt wird. Der Benutzer kann mit der Linkeroption /STUB einen anderen Stub angeben.

An der Stelle 0x3c enthält der Stub den Dateioffset zur PE-Signatur. Diese Informationen ermöglichen es Windows, die Imagedatei korrekt auszuführen, auch wenn sie einen MS-DOS-Stub hat. Dieser Dateioffset wird während der Verknüpfung an der Position 0x3c platziert.

Unterschrift (nur Image)

Nach dem MS-DOS-Stub befindet sich an dem in Offset 0x3c angegebenen Datei-Offset eine 4-Byte-Signatur, die die Datei als Imagedatei im PE-Format identifiziert. Diese Signatur lautet „PE\0\0“ (die Buchstaben „P“ und „E“ gefolgt von zwei Nullbytes).

COFF-Dateiheader (Objekt und Image)

Am Anfang einer Objektdatei oder unmittelbar nach der Signatur einer Imagedatei befindet sich ein Standard-COFF-Dateiheader in folgendem Format. Beachten Sie, dass der Windows-Loader die Anzahl der Abschnitte auf 96 begrenzt.

Abstand Größe Feld Beschreibung
0
2
Maschine
Die Nummer, die den Typ des Zielrechners identifiziert. Weitere Informationen finden Sie unter Maschinentypen.
2
2
NumberOfSections
Die Anzahl der Abschnitte. Dies gibt die Größe der Abschnittstabelle an, die unmittelbar auf die Header folgt.
4
4
TimeDateStamp
Die unteren 32 Bits der Anzahl der Sekunden seit 00:00 1. Januar 1970 (ein time_t-Wert der C-Laufzeit), der angibt, wann die Datei erstellt wurde.
8
4
PointerToSymbolTable
Der Dateioffset der COFF-Symboltabelle oder Null, wenn keine COFF-Symboltabelle vorhanden ist. Dieser Wert sollte für ein Image Null sein, da die COFF-Debugging-Informationen veraltet sind.
12
4
NumberOfSymbols
Die Anzahl der Einträge in der Symboltabelle. Diese Daten können verwendet werden, um die Zeichenfolgentabelle zu suchen, die unmittelbar auf die Symboltabelle folgt. Dieser Wert sollte für ein Image Null sein, da die COFF-Debugging-Informationen veraltet sind.
16
2
SizeOfOptionalHeader
Die Größe des optionalen Headers, der für ausführbare Dateien erforderlich ist, nicht aber für Objektdateien. Dieser Wert sollte für eine Objektdatei NULL sein. Eine Beschreibung des Kopfzeilenformats finden Sie unter Optionale Kopfzeile (nur Image).
18
2
Merkmale
Die Flags, die die Attribute der Datei angeben. Spezifische Flagwerte finden Sie unter Merkmale.

Maschinentypen

Das Feld Maschine hat einen der folgenden Werte, die den CPU-Typ angeben. Eine Image-Datei kann nur auf dem angegebenen Rechner oder auf einem System, das den angegebenen Rechner emuliert, ausgeführt werden.

Konstante Wert Beschreibung
IMAGE_FILE_MACHINE_UNKNOWN
0x0
Es wird davon ausgegangen, dass der Inhalt dieses Feldes auf jeden Maschinentyp anwendbar ist
IMAGE_FILE_MACHINE_ALPHA
0x184
Alpha AXP, 32-Bit-Adressraum
IMAGE_FILE_MACHINE_ALPHA64
0x284
Alpha 64, 64-Bit-Adressraum
IMAGE_FILE_MACHINE_AM33
0x1d3
Matsushita AM33
IMAGE_FILE_MACHINE_AMD64
0x8664
x64
IMAGE_FILE_MACHINE_ARM
0x1c0
ARM Little-Endian
IMAGE_FILE_MACHINE_ARM64
0xaa64
ARM64 Little-Endian
IMAGE_FILE_MACHINE_ARMNT
0x1c4
ARM Thumb-2 Little-Endian
IMAGE_FILE_MACHINE_AXP64
0x284
AXP 64 (Gleich wie Alpha 64)
IMAGE_FILE_MACHINE_EBC
0xebc
EFI-Byte-Code
IMAGE_FILE_MACHINE_I386
0x14c
Intel 386-Prozessoren oder höher und kompatible Prozessoren
IMAGE_FILE_MACHINE_IA64
0x200
Intel Itanium-Prozessorfamilie
IMAGE_FILE_MACHINE_LOONGARCH32
0x6232
LoongArch 32-Bit-Prozessorfamilie
IMAGE_FILE_MACHINE_LOONGARCH64
0x6264
LoongArch 64-Bit-Prozessorfamilie
IMAGE_FILE_MACHINE_M32R
0x9041
Mitsubishi M32R Little-Endian
IMAGE_FILE_MACHINE_MIPS16
0x266
MIPS16
IMAGE_FILE_MACHINE_MIPSFPU
0x366
MIPS mit FPU
IMAGE_FILE_MACHINE_MIPSFPU16
0x466
MIPS16 mit FPU
IMAGE_FILE_MACHINE_POWERPC
0x1f0
Power PC Little-Endian
IMAGE_FILE_MACHINE_POWERPCFP
0x1f1
Power PC mit Gleitkomma-Unterstützung
IMAGE_FILE_MACHINE_R4000
0x166
MIPS Little-Endian
IMAGE_FILE_MACHINE_RISCV32
0x5032
RISC-V 32-Bit-Adressraum
IMAGE_FILE_MACHINE_RISCV64
0x5064
RISC-V 64-Bit-Adressraum
IMAGE_FILE_MACHINE_RISCV128
0x5128
RISC-V 128-Bit-Adressraum
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 Little-Endian WCE v2

Merkmale

Das Feld Merkmale enthält Kennzeichnungen, die Attribute des Objekts oder der Imagedatei angeben. Die folgenden Flags sind derzeit definiert:

Flag Wert Beschreibung
IMAGE_FILE_RELOCS_STRIPPED
0x0001
Nur Image, Windows CE und Microsoft Windows NT und höher. Dies bedeutet, dass die Datei keine Basisverschiebungen enthält und daher an ihrer bevorzugten Basisadresse geladen werden muss. Wenn die Basisadresse nicht verfügbar ist, meldet der Lader einen Fehler. Das Standardverhalten des Linkers ist es, Basisverschiebungen aus ausführbaren (EXE) Dateien zu entfernen.
IMAGE_FILE_EXECUTABLE_IMAGE
0x0002
Nur Image. Dies zeigt an, dass die Imagedatei gültig ist und ausgeführt werden kann. Wenn dieses Flag nicht gesetzt ist, liegt ein Linkerfehler vor.
IMAGE_FILE_LINE_NUMS_STRIPPED
0x0004
Die COFF-Zeilennummern wurden entfernt. Dieses Flag ist veraltet und sollte Null sein.
IMAGE_FILE_LOCAL_SYMS_STRIPPED
0x0008
COFF-Symboltabelleneinträge für lokale Symbole wurden entfernt. Dieses Flag ist veraltet und sollte Null sein.
IMAGE_FILE_AGGRESSIVE_WS_TRIM
0x0010
Veraltet. Aggressiv geschnittener Arbeitssatz. Dieses Flag ist für Windows 2000 und später veraltet und muss Null sein.
IMAGE_FILE_LARGE_ADDRESS_ AWARE
0x0020
Die Anwendung kann > 2-GB-Adressen verarbeiten.
0x0040
Dieses Flag ist für die zukünftige Verwendung reserviert.
IMAGE_FILE_BYTES_REVERSED_LO
0x0080
Little-Endian: Das niedrigstwertige Bit (LSB) steht vor dem höchstwertigen Bit (MSB) im Speicher. Dieses Flag ist veraltet und sollte Null sein.
IMAGE_FILE_32BIT_MACHINE
0x0100
Die Maschine basiert auf einer 32-Bit-Wort-Architektur.
IMAGE_FILE_DEBUG_STRIPPED
0x0200
Die Debugging-Informationen werden aus der Imagedatei entfernt.
IMAGE_FILE_REMOVABLE_RUN_ FROM_SWAP
0x0400
Wenn sich das Abbild auf einem Wechselmedium befindet, laden Sie es vollständig und kopieren Sie es in die Auslagerungsdatei.
IMAGE_FILE_NET_RUN_FROM_SWAP
0x0800
Wenn sich das Abbild auf einem Netzwerkmedium befindet, laden Sie es vollständig und kopieren Sie es in die Auslagerungsdatei.
IMAGE_FILE_SYSTEM
0x1000
Die Abbilddatei ist eine Systemdatei, kein Benutzerprogramm.
IMAGE_FILE_DLL
0x2000
Die Image-Datei ist eine Dynamic-Link-Library (DLL). Solche Dateien werden für fast alle Zwecke als ausführbare Dateien betrachtet, obwohl sie nicht direkt ausgeführt werden können.
IMAGE_FILE_UP_SYSTEM_ONLY
0x4000
Die Datei sollte nur auf einem Uniprozessor-Rechner ausgeführt werden.
IMAGE_FILE_BYTES_REVERSED_HI
0x8000
Big-Endian: Das MSB steht vor dem LSB im Speicher. Dieses Flag ist veraltet und sollte Null sein.

Optionaler Header (nur Image)

Jede Imagedatei hat einen optionalen Header, der Informationen für den Lader enthält. Diese Kopfzeile ist insofern optional, als einige Dateien (insbesondere Objektdateien) sie nicht enthalten. Für Imagedateien ist dieser Header erforderlich. Eine Objektdatei kann einen optionalen Header haben, aber im Allgemeinen hat dieser Header keine Funktion in einer Objektdatei, außer dass er ihre Größe erhöht.

Beachten Sie, dass die Größe der optionalen Kopfzeile nicht festgelegt ist. Das Feld SizeOfOptionalHeader im COFF-Header muss verwendet werden, um zu überprüfen, dass eine Abfrage in der Datei für ein bestimmtes Datenverzeichnis nicht über SizeOfOptionalHeader hinausgeht. Weitere Informationen finden Sie unter COFF File Header (Object and Image).

Das Feld NumberOfRvaAndSizes der optionalen Kopfzeile sollte auch verwendet werden, um sicherzustellen, dass keine Sonde für einen bestimmten Datenverzeichniseintrag über die optionale Kopfzeile hinausgeht. Darüber hinaus ist es wichtig, die optionale magische Kopfnummer für die Formatkompatibilität zu validieren.

Die optionale magische Zahl im Header bestimmt, ob es sich bei einem Image um ein PE32- oder PE32+-Abbild handelt.

Magische Zahl PE-Format
0x10b
PE32
0x20b
PE32+

PE32+-Images ermöglichen einen 64-Bit-Adressraum und begrenzen die Imagegröße auf 2 Gigabyte. Andere PE32+-Änderungen werden in den entsprechenden Abschnitten behandelt.

Die optionale Kopfzeile selbst besteht aus drei Hauptteilen.

Offset (PE32/PE32+) Größe (PE32/PE32+) Teil der Kopfzeile Beschreibung
0
28/24
Standardfelder
Felder, die für alle Implementierungen von COFF, einschließlich UNIX, definiert sind.
28/24
68/88
Windows-spezifische Felder
Zusätzliche Felder zur Unterstützung spezifischer Funktionen von Windows (z. B. Subsysteme).
96/112
Variable:
Datenverzeichnisse
Adress-/Größenpaare für spezielle Tabellen, die sich in der Abbilddatei befinden und vom Betriebssystem verwendet werden (z. B. die Import- und Exporttabelle).

Optionaler Header Standardfelder (nur Image)

Die ersten acht Felder des optionalen Headers sind Standardfelder, die für jede Implementierung von COFF definiert sind. Diese Felder enthalten allgemeine Informationen, die für das Laden und Ausführen einer ausführbaren Datei nützlich sind. Sie sind für das PE32+-Format unverändert.

Abstand Größe Feld Beschreibung
0
2
Magie
Die ganze Zahl ohne Vorzeichen, die den Zustand der Imagedatei angibt. Die häufigste Nummer ist 0x10B, was sie als normale ausführbare Datei kennzeichnet. 0x107 kennzeichnet es als ROM-Image, und 0x20B kennzeichnet es als ausführbare PE32+-Datei.
2
1
MajorLinkerVersion
Die Hauptversionsnummer des Linker.
3
1
MinorLinkerVersion
Die Nebenversionsnummer des Linker.
4
4
SizeOfCode
Die Größe des Codeabschnitts (Text) oder die Summe aller Codeabschnitte, wenn es mehrere Abschnitte gibt.
8
4
SizeOfInitializedData
Die Größe des initialisierten Datenbereichs oder die Summe aller dieser Bereiche, wenn es mehrere Datenbereiche gibt.
12
4
SizeOfUninitializedData
Die Größe des nicht initialisierten Datenbereichs (BSS) oder die Summe aller solcher Bereiche, wenn es mehrere BSS-Bereiche gibt.
16
4
AddressOfEntryPoint
Die Adresse des Einstiegspunkts relativ zur Bildbasis, wenn die ausführbare Datei in den Speicher geladen wird. Bei Programmbildern ist dies die Startadresse. Bei Gerätetreibern ist dies die Adresse der Initialisierungsfunktion. Ein Einstiegspunkt ist für DLLs optional. Wenn kein Eintragspunkt vorhanden ist, muss dieses Feld Null sein.
20
4
BaseOfCode
Die Adresse, die relativ zur Bildbasis des Codeanfangsabschnitts ist, wenn er in den Speicher geladen wird.

PE32 enthält dieses zusätzliche Feld, das in PE32+ fehlt, nach BaseOfCode.

Abstand Größe Feld Beschreibung
24
4
BaseOfData
Die Adresse, die sich auf die Bildbasis des Datenanfangsabschnitts bezieht, wenn dieser in den Speicher geladen wird.

Optionaler Header Spezifische Felder (nur Image)

Die nächsten 21 Felder sind eine Erweiterung des optionalen COFF-Header-Formats. Sie enthalten zusätzliche Informationen, die vom Linker und Loader in Windows benötigt werden.

Offset (PE32/ PE32+) Größe (PE32/ PE32+) Feld Beschreibung
28/24
4/8
ImageBase
Die bevorzugte Adresse des ersten Bytes des Images, wenn es in den Speicher geladen wird; muss ein Vielfaches von 64 K sein. Der Standardwert für DLLs ist 0x10000000. Der Standardwert für Windows CE EXEs ist 0x00010000. Der Standardwert für Windows NT, Windows 2000, Windows XP, Windows 95, Windows 98 und Windows Me ist 0x00400000.
32/32
4
SectionAlignment
Die Ausrichtung (in Bytes) von Abschnitten beim Laden in den Arbeitsspeicher. Sie muss größer oder gleich FileAlignment sein. Der Standard für die Architektur ist die Seitengröße.
36/36
4
FileAlignment
Der Ausrichtungsfaktor (in Byte), der verwendet wird, um die Rohdaten von Abschnitten in der Imagedatei auszurichten. Der Wert sollte eine Zweierpotenz zwischen 512 und 64 K einschließlich sein. Der Standardwert liegt bei 512. Ist SectionAlignment kleiner als die Seitengröße der Architektur, muss FileAlignment mit SectionAlignment übereinstimmen.
40/40
2
MajorOperatingSystemVersion
Die Hauptversionsnummer des erforderlichen Betriebssystems.
42/42
2
MinorOperatingSystemVersion
Die Nebenversionsnummer des erforderlichen Betriebssystems.
44/44
2
MajorImageVersion
Die Hauptversionsnummer des Images.
46/46
2
MinorImageVersion
Die Nebenversionsnummer des Images.
48/48
2
MajorSubsystemVersion
Die Hauptversionsnummer des Subsystems.
50/50
2
MinorSubsystemVersion
Die Nebenversionsnummer des Subsystems.
52/52
4
Win32VersionValue
Reserviert, muss Null sein.
56/56
4
SizeOfImage
Die Größe (in Bytes) des Images, einschließlich aller Header, wenn das Image in den Speicher geladen wird. Sie muss ein Vielfaches von SectionAlignment sein.
60/60
4
SizeOfHeaders
Die kombinierte Größe von MS-DOS-Stub, PE-Header und Sektionsheader, aufgerundet auf ein Vielfaches von FileAlignment.
64/64
4
Prüfsumme
Die Prüfsumme der Imagedatei. Der Algorithmus zur Berechnung der Prüfsumme ist in der IMAGHELP.DLL enthalten. Beim Laden werden alle Treiber, alle DLLs, die beim Booten geladen werden, und alle DLLs, die in einen kritischen Windows-Prozess geladen werden, auf ihre Gültigkeit überprüft.
68/68
2
Subsystem
Das Subsystem, das zum Ausführen dieses Images erforderlich ist. Weitere Informationen finden Sie unter Windows Subsystem.
70/70
2
DllCharacteristics
Weitere Informationen finden Sie unter DLL-Merkmale weiter unten in dieser Spezifikation.
72/72
4/8
SizeOfStackReserve
Die Größe des Stapels, der reserviert werden soll. Nur SizeOfStackCommit wird übertragen; der Rest wird seitenweise zur Verfügung gestellt, bis die Reservegröße erreicht ist.
76/80
4/8
SizeOfStackCommit
Dier Größe des Stapels, für den ein Commit ausgeführt wird.
80/88
4/8
SizeOfHeapReserve
Die Größe des Speicherplatzes für den lokalen Heap, der reserviert werden soll. Nur SizeOfHeapCommit wird übertragen; der Rest wird seitenweise zur Verfügung gestellt, bis die Reservegröße erreicht ist.
84/96
4/8
SizeOfHeapCommit
Die Größe des Speicherplatzes für den lokalen Heap, für den ein Commit ausgeführt werden soll.
88/104
4
LoaderFlags
Reserviert, muss Null sein.
92/108
4
NumberOfRvaAndSizes
Die Anzahl der Datenverzeichniseinträge im restlichen Teil der optionalen Kopfzeile. Jeder beschreibt einen Speicherort und eine Größe.
Windows-Teilsystem

Die folgenden für das Feld Subsystem des optionalen Headers definierten Werte bestimmen, welches Windows-Subsystem (falls vorhanden) für die Ausführung des Abbilds erforderlich ist.

Konstante Wert Beschreibung
IMAGE_SUBSYSTEM_UNKNOWN
0
Ein unbekanntes Teilsystem
IMAGE_SUBSYSTEM_NATIVE
1
Gerätetreiber und native Windows-Prozesse
IMAGE_SUBSYSTEM_WINDOWS_GUI
2
Das Windows-Subsystem für die grafische Benutzeroberfläche (GUI)
IMAGE_SUBSYSTEM_WINDOWS_CUI
3
Das Windows-Zeichensubsystem
IMAGE_SUBSYSTEM_OS2_CUI
5
Das OS/2-Zeichensubsystem
IMAGE_SUBSYSTEM_POSIX_CUI
7
Das Posix-Zeichensubsystem
IMAGE_SUBSYSTEM_NATIVE_WINDOWS
8
Native Win9x-Treiber
IMAGE_SUBSYSTEM_WINDOWS_CE_GUI
9
Windows CE
IMAGE_SUBSYSTEM_EFI_APPLICATION
10
Eine EFI-Anwendung (Extensible Firmware Interface)
IMAGE_SUBSYSTEM_EFI_BOOT_ SERVICE_DRIVER
11
Ein EFI-Treiber mit Bootdiensten
IMAGE_SUBSYSTEM_EFI_RUNTIME_ DRIVER
12
Ein EFI-Treiber mit Laufzeitdiensten
IMAGE_SUBSYSTEM_EFI_ROM
13
Ein EFI-ROM-Abbild
IMAGE_SUBSYSTEM_XBOX
14
XBOX
IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION
16
Windows-Boot-Anwendung.
DLL-Merkmale

Die folgenden Werte sind für das Feld DllCharacteristics des optionalen Headers definiert.

Konstante Wert Beschreibung
0x0001
Reserviert, muss Null sein.
0x0002
Reserviert, muss Null sein.
0x0004
Reserviert, muss Null sein.
0x0008
Reserviert, muss Null sein.
IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA
0x0020
Image kann mit einem virtuellen 64-Bit-Adressraum mit hoher Entropie umgehen.
IMAGE_DLLCHARACTERISTICS_
DYNAMIC_BASE
0x0040
DLL kann zum Zeitpunkt des Ladens verschoben werden.
IMAGE_DLLCHARACTERISTICS_
FORCE_INTEGRITY
0x0080
Code-Integritätsprüfungen werden durchgesetzt.
IMAGE_DLLCHARACTERISTICS_
NX_COMPAT
0x0100
Das Image ist NX-kompatibel.
IMAGE_DLLCHARACTERISTICS_ NO_ISOLATION
0x0200
Isolation bewusst, aber nicht das Image isolieren.
IMAGE_DLLCHARACTERISTICS_ NO_SEH
0x0400
Verwendet keine strukturierte Ausnahmebehandlung (SE). In diesem Image darf kein SE-Handler aufgerufen werden.
IMAGE_DLLCHARACTERISTICS_ NO_BIND
0x0800
Das Image darf nicht gebunden werden.
IMAGE_DLLCHARACTERISTICS_APPCONTAINER
0x1000
Image muss in einem AppContainer ausgeführt werden.
IMAGE_DLLCHARACTERISTICS_ WDM_DRIVER
0x2000
Ein WDM-Treiber.
IMAGE_DLLCHARACTERISTICS_GUARD_CF
0x4000
Image unterstützt Control Flow Guard.
IMAGE_DLLCHARACTERISTICS_ TERMINAL_SERVER_AWARE
0x8000
Terminal-Server-kompatibel.

Optionaler Header Datenverzeichnisse (nur Image)

Jedes Datenverzeichnis enthält die Adresse und Größe einer Tabelle oder Zeichenfolge, die von Windows verwendet wird. Diese Datenverzeichniseinträge werden alle in den Speicher geladen, damit das System sie zur Laufzeit verwenden kann. Ein Datenverzeichnis ist ein 8-Byte-Feld mit der folgenden Erklärung:

typedef struct _IMAGE_DATA_DIRECTORY {
    DWORD   VirtualAddress;
    DWORD   Size;
} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

Das erste Feld, VirtualAddress, ist eigentlich das RVA der Tabelle. Die RVA ist die Adresse der Tabelle relativ zur Basisadresse des Images, wenn die Tabelle geladen wird. Das zweite Feld gibt die Größe in Bytes an. Die Datenverzeichnisse, die den letzten Teil der optionalen Kopfzeile bilden, sind in der folgenden Tabelle aufgeführt.

Beachten Sie, dass die Anzahl der Verzeichnisse nicht festgelegt ist. Bevor Sie nach einem bestimmten Verzeichnis suchen, überprüfen Sie das Feld NumberOfRvaAndSizes in der optionalen Kopfzeile.

Gehen Sie auch nicht davon aus, dass die RVAs in dieser Tabelle auf den Anfang eines Abschnitts verweisen oder dass die Abschnitte, die bestimmte Tabellen enthalten, bestimmte Namen haben.

Offset (PE/PE32+) Größe Feld Beschreibung
96/112
8
Tabelle exportieren
Die Adresse und Größe der Exporttabelle. Weitere Informationen finden Sie unter . edata-Abschnitt (nur Image).
104/120
8
Tabelle importieren
Die Adresse und Größe der Importtabelle. Weitere Informationen finden Sie unter Der .idata-Abschnitt.
112/128
8
Ressourcentabelle
Die Adresse und Größe der Ressourcentabelle. Weitere Informationen finden Sie unter Der .rsrc-Abschnitt.
120/136
8
Tabelle der Ausnahmen
Die Adresse und Größe der Ausnahmetabelle. Weitere Informationen finden Sie unter Der .pdata-Abschnitt.
128/144
8
Zertifikattabelle
Die Adresse und Größe der Attribut-Zertifikatstabelle. Weitere Informationen finden Sie unter Die Tabelle der Attributzertifikate (nur Image).
136/152
8
Base-Relocation-Tabelle
Die Adresse und Größe der Base-Relocation-Tabelle. Weitere Informationen finden Sie unter The .reloc Section (Image Only).
144/160
8
Debug
Die Anfangsadresse und Größe der Debug-Daten. Weitere Informationen finden Sie im Abschnitt .debug.
152/168
8
Architektur
Reserviert, muss 0 sein
160/176
8
Global Ptr
Der RVA des Wertes, der im globalen Zeigerregister gespeichert werden soll. Das Größenelement dieser Struktur muss auf Null gesetzt werden.
168/184
8
TLS-Tabelle
Die Adresse und Größe der Tabelle für den lokalen Thread-Speicher (TLS). Weitere Informationen finden Sie im Abschnitt .tls.
176/192
8
Konfig-Tabelle laden
Die Adresse und Größe der Lastkonfigurationstabelle. Weitere Informationen finden Sie unter The Load Configuration Structure (Image Only).
184/200
8
Bound-Import
Die Adresse und Größe der gebundenen Importtabelle.
192/208
8
IAT
Die Adresse und Größe der Importadresstabelle. Weitere Informationen finden Sie unter Import der Adresstabelle.
200/216
8
Verzögerungs-Importdeskriptor
Die Adresse und Größe des Delay-Import-Deskriptors. Weitere Informationen finden Sie unter Delay-Load Import Tables (Image Only).
208/224
8
CLR-Laufzeit-Header
Die Adresse und Größe des CLR-Laufzeit-Headers. Weitere Informationen finden Sie unter The .cormeta Section (Object Only).
216/232
8
Reserviert, muss Null sein

Der Eintrag Zertifikatstabelle verweist auf eine Tabelle mit Attributzertifikaten. Diese Zertifikate werden nicht als Teil des Images in den Speicher geladen. Daher ist das erste Feld dieses Eintrags, das normalerweise ein RVA ist, stattdessen ein Dateizeiger.

Abschnittstabelle (Abschnittsüberschriften)

Jede Zeile der Abschnittstabelle ist im Grunde genommen eine Abschnittsüberschrift. Diese Tabelle folgt unmittelbar auf die optionale Kopfzeile, falls vorhanden. Diese Positionierung ist erforderlich, weil der Dateiheader keinen direkten Zeiger auf die Sektionstabelle enthält. Stattdessen wird die Position der Abschnittstabelle bestimmt, indem die Position des ersten Bytes nach den Kopfzeilen berechnet wird. Stellen Sie sicher, dass Sie die Größe der optionalen Kopfzeile verwenden, die in der Kopfzeile der Datei angegeben ist.

Die Anzahl der Einträge in der Sektionstabelle wird durch das Feld NumberOfSections im Dateiheader angegeben. Die Einträge in der Abschnittstabelle sind von eins (1) an durchnummeriert. Die Einträge im Code- und Datenspeicherbereich sind in der vom Linker gewählten Reihenfolge.

In einer Imagedatei müssen die VAs für Abschnitte vom Linker so zugewiesen werden, dass sie in aufsteigender Reihenfolge und nebeneinander liegen, und sie müssen ein Vielfaches des SectionAlignment-Wertes im optionalen Header sein.

Jeder Sektionskopf (Sektionstabelleneintrag) hat das folgende Format, insgesamt 40 Bytes pro Eintrag.

Abstand Größe Feld Beschreibung
0
8
Name
Ein 8-Byte-String in UTF-8-Kodierung mit Null-Padding. Wenn der String genau 8 Zeichen lang ist, gibt es keine abschließende Null. Bei längeren Namen enthält dieses Feld einen Schrägstrich (/), gefolgt von einer ASCII-Darstellung einer Dezimalzahl, die einen Offset in der Stringtabelle darstellt. Ausführbare Bilder verwenden keine Stringtabelle und unterstützen keine Abschnittsnamen, die länger als 8 Zeichen sind. Lange Namen in Objektdateien werden abgeschnitten, wenn sie in eine ausführbare Datei ausgegeben werden.
8
4
VirtualSize
Die Gesamtgröße des Abschnitts beim Laden in den Speicher. Ist dieser Wert größer als SizeOfRawData, wird der Abschnitt mit Nullen aufgefüllt. Dieses Feld ist nur für ausführbare Images gültig und sollte für Objektdateien auf Null gesetzt werden.
12
4
VirtualAddress
Bei ausführbaren Bildern die Adresse des ersten Byte des Abschnitts relativ zur Bildbasis, wenn der Abschnitt in den Speicher geladen wird. Bei Objektdateien ist dieses Feld die Adresse des ersten Bytes vor der Verschiebung; der Einfachheit halber sollten die Compiler dieses Feld auf Null setzen. Andernfalls handelt es sich um einen willkürlichen Wert, der bei der Verschiebung von den Offsets abgezogen wird.
16
4
SizeOfRawData
Die Größe des Abschnitts (bei Objektdateien) oder die Größe der initialisierten Daten auf der Festplatte (bei Imagedateien). Bei ausführbaren Bildern muss dies ein Vielfaches von FileAlignment aus dem optionalen Header sein. Ist dieser Wert kleiner als VirtualSize, wird der Rest des Abschnitts mit Null ausgefüllt. Da das Feld SizeOfRawData gerundet ist, das Feld VirtualSize jedoch nicht, ist es möglich, dass SizeOfRawData auch größer ist als VirtualSize. Wenn ein Abschnitt nur uninitialisierte Daten enthält, sollte dieses Feld Null sein.
20
4
PointerToRawData
Der Dateizeiger auf die erste Seite des Abschnitts innerhalb der COFF-Datei. Bei ausführbaren Bildern muss dies ein Vielfaches von FileAlignment aus dem optionalen Header sein. Bei Objektdateien sollte der Wert an einer 4-Byte-Grenze ausgerichtet werden, um die beste Leistung zu erzielen. Wenn ein Abschnitt nur uninitialisierte Daten enthält, sollte dieses Feld Null sein.
24
4
PointerToRelocations
Der Dateizeiger auf den Beginn der Umzugseinträge für den Abschnitt. Bei ausführbaren Images oder wenn es keine Verschiebungen gibt, wird dieser Wert auf Null gesetzt.
28
4
PointerToLinenumbers
Der Dateizeiger auf den Beginn der Zeilennummerneinträge für den Abschnitt. Sie wird auf Null gesetzt, wenn es keine COFF-Zeilennummern gibt. Dieser Wert sollte für ein Image Null sein, da die COFF-Debugging-Informationen veraltet sind.
32
2
NumberOfRelocations
Die Anzahl der Verschiebungseinträge für den Abschnitt. Bei ausführbaren Images ist dieser Wert auf Null gesetzt.
34
2
NumberOfLinenumbers
Die Anzahl der Zeilennummerneinträge für den Abschnitt. Dieser Wert sollte für ein Image Null sein, da die COFF-Debugging-Informationen veraltet sind.
36
4
Merkmale
Die Flags, die die Merkmale des Abschnitts beschreiben. Weitere Informationen finden Sie im Abschnitt Flags.

 

Sektionsflaggen

Die Abschnittsflags im Feld Merkmale des Abschnittskopfes geben die Merkmale des Abschnitts an.

Flag Wert Beschreibung
0x00000000
Für die zukünftige Verwendung reserviert.
0x00000001
Für die zukünftige Verwendung reserviert.
0x00000002
Für die zukünftige Verwendung reserviert.
0x00000004
Für die zukünftige Verwendung reserviert.
IMAGE_SCN_TYPE_NO_PAD
0x00000008
Der Abschnitt sollte nicht bis zur nächsten Begrenzung aufgefüllt werden. Dieses Flag ist veraltet und wird durch IMAGE_SCN_ALIGN_1BYTES ersetzt. Dies gilt nur für Objektdateien.
0x00000010
Für die zukünftige Verwendung reserviert.
IMAGE_SCN_CNT_CODE
0x00000020
Der Abschnitt enthält ausführbaren Code.
IMAGE_SCN_CNT_INITIALIZED_DATA
0x00000040
Der Abschnitt enthält initialisierte Daten.
IMAGE_SCN_CNT_UNINITIALIZED_ DATA
0x00000080
Der Abschnitt enthält uninitialisierte Daten.
IMAGE_SCN_LNK_OTHER
0x00000100
Für die zukünftige Verwendung reserviert.
IMAGE_SCN_LNK_INFO
0x00000200
Der Abschnitt enthält Kommentare oder andere Informationen. Der Abschnitt .drectve hat diesen Typ. Dies gilt nur für Objektdateien.
0x00000400
Für die zukünftige Verwendung reserviert.
IMAGE_SCN_LNK_REMOVE
0x00000800
Der Ausschnitt wird nicht Teil des Images. Dies gilt nur für Objektdateien.
IMAGE_SCN_LNK_COMDAT
0x00001000
Der Abschnitt enthält COMDAT-Daten. Weitere Informationen finden Sie im Abschnitt COMDAT (nur Objekt). Dies gilt nur für Objektdateien.
IMAGE_SCN_GPREL
0x00008000
Der Abschnitt enthält Daten, auf die über den globalen Zeiger (GP) verwiesen wird.
IMAGE_SCN_MEM_PURGEABLE
0x00020000
Für die zukünftige Verwendung reserviert.
IMAGE_SCN_MEM_16BIT
0x00020000
Für die zukünftige Verwendung reserviert.
IMAGE_SCN_MEM_LOCKED
0x00040000
Für die zukünftige Verwendung reserviert.
IMAGE_SCN_MEM_PRELOAD
0x00080000
Für die zukünftige Verwendung reserviert.
IMAGE_SCN_ALIGN_1BYTES
0x00100000
Ausrichten von Daten an einer 1-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_2BYTES
0x00200000
Ausrichten von Daten an einer 2-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_4BYTES
0x00300000
Ausrichten von Daten an einer 4-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_8BYTES
0x00400000
Ausrichten von Daten an einer 8-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_16BYTES
0x00500000
Ausrichten von Daten an einer 16-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_32BYTES
0x00600000
Ausrichten von Daten an einer 32-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_64BYTES
0x00700000
Ausrichten von Daten an einer 64-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_128BYTES
0x00800000
Ausrichten von Daten an einer 128-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_256BYTES
0x00900000
Ausrichten von Daten an einer 256-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_512BYTES
0x00A00000
Ausrichten von Daten an einer 512-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_1024BYTES
0x00B00000
Ausrichten von Daten an einer 1024-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_2048BYTES
0x00C00000
Ausrichten von Daten an einer 2048-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_4096BYTES
0x00D00000
Ausrichten von Daten an einer 4096-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_ALIGN_8192BYTES
0x00E00000
Ausrichten von Daten an einer 8192-Byte-Grenze. Gilt nur für Objektdateien.
IMAGE_SCN_LNK_NRELOC_OVFL
0x01000000
Der Abschnitt enthält erweiterte Verschiebungen.
IMAGE_SCN_MEM_DISCARDABLE
0x02000000
Der Abschnitt kann bei Bedarf entsorgt werden.
IMAGE_SCN_MEM_NOT_CACHED
0x04000000
Der Abschnitt kann nicht zwischengespeichert werden.
IMAGE_SCN_MEM_NOT_PAGED
0x08000000
Der Abschnitt ist nicht auslagerbar.
IMAGE_SCN_MEM_SHARED
0x10000000
Der Abschnitt kann im Speicher gemeinsam genutzt werden.
IMAGE_SCN_MEM_EXECUTE
0x20000000
Der Abschnitt kann als Code ausgeführt werden.
IMAGE_SCN_MEM_READ
0x40000000
Der Abschnitt kann gelesen werden.
IMAGE_SCN_MEM_WRITE
0x80000000
Der Abschnitt kann angeschrieben werden.

 

IMAGE_SCN_LNK_NRELOC_OVFL zeigt an, dass die Anzahl der Verschiebungen für den Abschnitt die 16 Bits überschreitet, die dafür im Abschnittskopf reserviert sind. Wenn das Bit gesetzt ist und das Feld NumberOfRelocations im Abschnittskopf 0xffff lautet, wird die tatsächliche Anzahl der Verschiebungen im 32-Bit-Feld VirtualAddress der ersten Verschiebung gespeichert. Es ist ein Fehler, wenn IMAGE_SCN_LNK_NRELOC_OVFL gesetzt ist und es weniger als 0xffff Verschiebungen in dem Abschnitt gibt.

Gruppierte Abschnitte (nur Objekt)

Das „$“-Zeichen (Dollarzeichen) hat eine besondere Bedeutung in Abschnittsnamen in Objektdateien.

Bei der Bestimmung des Bildabschnitts, der den Inhalt eines Objektabschnitts enthält, verwirft der Linker das „$“ und alle darauf folgenden Zeichen. So trägt ein Objektabschnitt mit dem Namen .text$X tatsächlich zu dem Abschnitt .text im Image bei.

Die auf das „$“ folgenden Zeichen bestimmen jedoch die Reihenfolge der Beiträge zum Bildteil. Alle Beiträge mit demselben Objektteilnamen werden zusammenhängend im Image angeordnet, und die Beitragsblöcke werden in lexikalischer Reihenfolge nach Objektteilnamen sortiert. Daher landet alles in Objektdateien mit dem Abschnittsnamen .text$X zusammen, nach den Beiträgen .text$W und vor den Beiträgen .text$Y.

Der Abschnittsname in einer Imagedatei enthält niemals ein „$“-Zeichen.

Andere Inhalte der Datei

Die bisher beschriebenen Datenstrukturen, bis hin zum optionalen Header, befinden sich alle an einem festen Offset vom Anfang der Datei (oder vom PE-Header, wenn die Datei ein Image ist, das einen MS-DOS-Stub enthält).

Der Rest eines COFF-Objekts oder einer Imagedatei enthält Datenblöcke, die sich nicht unbedingt an einem bestimmten Dateioffset befinden. Stattdessen werden die Orte durch Zeiger in der optionalen Kopfzeile oder einer Abschnittsüberschrift definiert.

Eine Ausnahme bilden Bilder mit einem SectionAlignment-Wert, der kleiner ist als die Seitengröße der Architektur (4 K für Intel x86 und für MIPS und 8 K für Itanium). Eine Beschreibung von SectionAlignment finden Sie unter Optional Header (Nur Image). In diesem Fall gibt es Beschränkungen für den Dateioffset der Abschnittsdaten, wie in Abschnitt 5.1, „Abschnittsdaten“, beschrieben Eine weitere Ausnahme ist, dass die Attributzertifikat- und Debug-Informationen ganz am Ende einer Imagedatei platziert werden müssen, wobei die Attributzertifikat-Tabelle unmittelbar vor dem Debug-Abschnitt stehen muss, da der Lader diese nicht im Speicher abbildet. Die Regel über Attribut-Zertifikate und Debug-Informationen gilt jedoch nicht für Objektdateien.

Abschnitt Daten

Initialisierte Daten für einen Abschnitt bestehen aus einfachen Byte-Blöcken. Für Abschnitte, die ausschließlich Nullen enthalten, müssen die Abschnittsdaten jedoch nicht angegeben werden.

Die Daten für jeden Abschnitt befinden sich an dem Datei-Offset, der durch das Feld PointerToRawData im Abschnittskopf angegeben wurde. Die Größe dieser Daten in der Datei wird durch das Feld SizeOfRawData angegeben. Wenn SizeOfRawData kleiner ist als VirtualSize, wird der Rest mit Nullen aufgefüllt.

In einer Imagedatei müssen die Abschnittsdaten an einer Grenze ausgerichtet sein, die durch das Feld FileAlignment im optionalen Header angegeben ist. Die Abschnittsdaten müssen in der Reihenfolge der RVA-Werte für die entsprechenden Abschnitte erscheinen (wie auch die einzelnen Abschnittsüberschriften in der Abschnittstabelle).

Es gibt zusätzliche Einschränkungen für Imagedateien, wenn der Wert für SectionAlignment in der optionalen Kopfzeile kleiner ist als die Seitengröße der Architektur. Bei solchen Dateien muss die Position der Abschnittsdaten in der Datei mit ihrer Position im Speicher übereinstimmen, wenn das Image geladen wird, sodass der physische Offset für die Abschnittsdaten mit dem RVA übereinstimmt.

COFF-Verschiebungen (nur Objekt)

Objektdateien enthalten COFF-Verschiebungen, die angeben, wie die Abschnittsdaten geändert werden sollen, wenn sie in der Imagedatei platziert und anschließend in den Speicher geladen werden.

Imagedateien enthalten keine COFF-Verschiebungen, da alle referenzierten Symbole bereits Adressen in einem flachen Adressraum zugewiesen bekommen haben. Ein Image enthält Verschiebungsinformationen in Form von Basisverschiebungen im Abschnitt .reloc (sofern das Image nicht das Attribut IMAGE_FILE_RELOCS_STRIPPED hat). Weitere Informationen finden Sie unter The .reloc Section (Image Only).

Für jeden Abschnitt in einer Objektdatei enthält ein Array von Datensätzen fester Länge die COFF-Verschiebungen des Abschnitts. Die Position und die Länge des Arrays sind in der Abschnittsüberschrift angegeben. Jedes Element des Arrays hat das folgende Format.

Abstand Größe Feld Beschreibung
0
4
VirtualAddress
Die Adresse der Position, auf die die Verschiebung angewendet wird. Dies ist der Versatz vom Beginn des Abschnitts plus dem Wert des Feldes RVA/Offset des Abschnitts. Siehe Abschnittstabelle (Abschnittsüberschriften). Wenn beispielsweise das erste Byte des Abschnitts eine Adresse von 0x10 hat, hat das dritte Byte eine Adresse von 0x12.
4
4
SymbolTableIndex
Ein Null-basierter Index in der Symboltabelle. Dieses Symbol gibt die Adresse an, die für die Verschiebung verwendet werden soll. Wenn das angegebene Symbol eine Abschnittsspeicherklasse hat, dann ist die Adresse des Symbols die Adresse des ersten Abschnitts mit demselben Namen.
8
2
Typ
Ein Wert, der die Art der Verschiebung angibt, die durchgeführt werden soll. Gültige Verschiebungsarten hängen vom Maschinentyp ab. Siehe Typenkennzeichen.

 

Wenn das Symbol, auf das das Feld SymbolTableIndex verweist, die Speicherklasse IMAGE_SYM_CLASS_SECTION hat, ist die Adresse des Symbols der Anfang des Abschnitts. Der Abschnitt befindet sich in der Regel in derselben Datei, außer wenn die Objektdatei Teil eines Archivs (Bibliothek) ist. In diesem Fall kann der Abschnitt in jeder anderen Objektdatei im Archiv gefunden werden, die denselben Archivelementsnamen wie die aktuelle Objektdatei hat. (Die Beziehung mit dem Namen des Archivelements wird bei der Verknüpfung von Importtabellen, d.h. dem .idata-Abschnitt, verwendet)

Typindikatoren

Das Feld Typ des Verschiebungsdatensatzes gibt an, welche Art von Verschiebung durchgeführt werden soll. Für jede Art von Maschine werden unterschiedliche Verschiebungsarten definiert.

x64 Prozessoren

Für x64- und kompatible Prozessoren sind die folgenden Umzugsindikatoren definiert.

Konstante Wert Beschreibung
IMAGE_REL_AMD64_ABSOLUTE
0x0000
Die Verschiebung wird ignoriert.
IMAGE_REL_AMD64_ADDR64
0x0001
Die 64-Bit-VA des Verschiebungsziels.
IMAGE_REL_AMD64_ADDR32
0x0002
Die 32-Bit-VA des Verschiebungsziels.
IMAGE_REL_AMD64_ADDR32NB
0x0003
Die 32-Bit-Adresse ohne Bildbasis (RVA).
IMAGE_REL_AMD64_REL32
0x0004
Die relative 32-Bit-Adresse ab dem auf die Verschiebung folgenden Byte.
IMAGE_REL_AMD64_REL32_1
0x0005
Die 32-Bit-Adresse relativ zum Byteabstand 1 von der Verschiebung.
IMAGE_REL_AMD64_REL32_2
0x0006
Die 32-Bit-Adresse relativ zum Byteabstand 2 von der Verschiebung.
IMAGE_REL_AMD64_REL32_3
0x0007
Die 32-Bit-Adresse relativ zum Byteabstand 3 von der Verschiebung.
IMAGE_REL_AMD64_REL32_4
0x0008
Die 32-Bit-Adresse relativ zum Byteabstand 4 von der Verschiebung.
IMAGE_REL_AMD64_REL32_5
0x0009
Die 32-Bit-Adresse relativ zum Byteabstand 5 von der Verschiebung.
IMAGE_REL_AMD64_SECTION
0x000A
Der 16-Bit-Abschnittsindex des Abschnitts, der das Ziel enthält. Dies wird zur Unterstützung von Debugging-Informationen verwendet.
IMAGE_REL_AMD64_SECREL
0x000B
Der 32-Bit-Offset des Ziels vom Beginn seines Abschnitts. Dies dient der Unterstützung von Debugging-Informationen und der lokalen Speicherung statischer Threads.
IMAGE_REL_AMD64_SECREL7
0x000C
Ein 7-Bit-Offset ohne Vorzeichen von der Basis des Abschnitts, der das Ziel enthält.
IMAGE_REL_AMD64_TOKEN
0x000D
CLR-Tokens.
IMAGE_REL_AMD64_SREL32
0x000E
Ein vorzeichenbehafteter 32-Bit-Spannungswert, der in das Objekt ausgegeben wird.
IMAGE_REL_AMD64_PAIR
0x000F
Ein Paar, das unmittelbar auf jeden span-abhängigen Wert folgen muss.
IMAGE_REL_AMD64_SSPAN32
0x0010
Ein vorzeichenbehafteter 32-Bit-Spannenwert, der zum Zeitpunkt der Verknüpfung angewendet wird.

 

ARM-Prozessoren

Für ARM-Prozessoren sind die folgenden Verschiebungsindikatoren definiert.

Konstante Wert Beschreibung
IMAGE_REL_ARM_ABSOLUTE
0x0000
Die Verschiebung wird ignoriert.
IMAGE_REL_ARM_ADDR32
0x0001
Die 32-Bit-VA des Ziels.
IMAGE_REL_ARM_ADDR32NB
0x0002
Die 32-Bit-RVA des Ziels.
IMAGE_REL_ARM_BRANCH24
0x0003
Die 24-Bit-Relativverschiebung zum Ziel.
IMAGE_REL_ARM_BRANCH11
0x0004
Der Verweis auf einen Unterprogrammaufruf. Die Referenz besteht aus zwei 16-Bit-Anweisungen mit 11-Bit-Offsets.
IMAGE_REL_ARM_REL32
0x000A
Die relative 32-Bit-Adresse ab dem auf die Verschiebung folgenden Byte.
IMAGE_REL_ARM_SECTION
0x000E
Der 16-Bit-Abschnittsindex des Abschnitts, der das Ziel enthält. Dies wird zur Unterstützung von Debugging-Informationen verwendet.
IMAGE_REL_ARM_SECREL
0x000F
Der 32-Bit-Offset des Ziels vom Beginn seines Abschnitts. Dies dient der Unterstützung von Debugging-Informationen und der lokalen Speicherung statischer Threads.
IMAGE_REL_ARM_MOV32
0x0010
Die 32-Bit-VA des Ziels. Diese Verschiebung erfolgt durch einen MOVW-Befehl für die niedrigen 16 Bits, gefolgt von einem MOVT für die hohen 16 Bits.
IMAGE_REL_THUMB_MOV32
0x0011
Die 32-Bit-VA des Ziels. Diese Verschiebung erfolgt durch einen MOVW-Befehl für die niedrigen 16 Bits, gefolgt von einem MOVT für die hohen 16 Bits.
IMAGE_REL_THUMB_BRANCH20
0x0012
Der Befehl wird mit der 21-Bit-Relativverschiebung zum 2-Byte-ausgerichteten Ziel fixiert. Das niederwertige Bit der Verschiebung ist immer Null und wird nicht gespeichert. Diese Verschiebung entspricht einer Thumb-2 32-Bit bedingten B-Anweisung.
Unbenutzt
0x0013
IMAGE_REL_THUMB_BRANCH24
0x0014
Der Befehl wird mit der 25-Bit-Relativverschiebung zum 2-Byte-ausgerichteten Ziel fixiert. Das niederwertigste Bit der Verschiebung ist Null und wird nicht gespeichert; diese Verschiebung entspricht einem Thumb-2 B-Befehl.
IMAGE_REL_THUMB_BLX23
0x0015
Der Befehl wird mit der 25-Bit-Relativverschiebung zum 4-Byte-ausgerichteten Ziel fixiert. Die unteren 2 Bits der Verschiebung sind Null und werden nicht gespeichert.
Diese Verschiebung entspricht einem Thumb-2-BLX-Befehl.
IMAGE_REL_ARM_PAIR
0x0016
Die Verschiebung ist nur gültig, wenn sie unmittelbar auf ein ARM_REFHI oder THUMB_REFHI folgt. Sein SymbolTableIndex enthält eine Verschiebung und nicht einen Index in der Symboltabelle.

 

ARM64-Prozessoren

Für ARM64-Prozessoren sind die folgenden Verschiebungsindikatoren definiert.

Konstante Wert Beschreibung
IMAGE_REL_ARM64_ABSOLUTE
0x0000
Die Verschiebung wird ignoriert.
IMAGE_REL_ARM64_ADDR32
0x0001
Die 32-Bit-VA des Ziels.
IMAGE_REL_ARM64_ADDR32NB
0x0002
Die 32-Bit-RVA des Ziels.
IMAGE_REL_ARM64_BRANCH26
0x0003
Die 26-Bit-Relativverschiebung zum Ziel, für B- und BL-Befehle.
IMAGE_REL_ARM64_PAGEBASE_REL21
0x0004
Die Seitenbasis des Ziels, für ADRP-Befehl.
IMAGE_REL_ARM64_REL21
0x0005
Die 12-Bit-Relativverschiebung zum Ziel, für die Anweisung ADR
IMAGE_REL_ARM64_PAGEOFFSET_12A
0x0006
Der 12-Bit-Seiten-Offset des Ziels, für die Befehle ADD/ADDS (immediate) mit Nullverschiebung.
IMAGE_REL_ARM64_PAGEOFFSET_12L
0x0007
Der 12-Bit-Seiten-Offset des Ziels für den Befehl LDR (indiziert, vorzeichenlos unmittelbar).
IMAGE_REL_ARM64_SECREL
0x0008
Der 32-Bit-Offset des Ziels vom Beginn seines Abschnitts. Dies dient der Unterstützung von Debugging-Informationen und der lokalen Speicherung statischer Threads.
IMAGE_REL_ARM64_SECREL_LOW12A
0x0009
Bit 0:11 des Abschnittsoffsets des Ziels, für die Befehle ADD/ADDS (immediate) mit Nullverschiebung.
IMAGE_REL_ARM64_SECREL_HIGH12A
0x000A
Bit 12:23 des Abschnittsoffsets des Ziels, für die Befehle ADD/ADDS (immediate) mit Nullverschiebung.
IMAGE_REL_ARM64_SECREL_LOW12L
0x000B
Bit 0:11 des Abschnittsoffsets des Ziels für den Befehl LDR (indiziert, vorzeichenlos, unmittelbar).
IMAGE_REL_ARM64_TOKEN
0x000C
CLR-Token.
IMAGE_REL_ARM64_SECTION
0x000D
Der 16-Bit-Abschnittsindex des Abschnitts, der das Ziel enthält. Dies wird zur Unterstützung von Debugging-Informationen verwendet.
IMAGE_REL_ARM64_ADDR64
0x000E
Die 64-Bit-VA des Verschiebungsziels.
IMAGE_REL_ARM64_BRANCH19
0x000F
Der 19-Bit-Offset zum Verschiebungsziel für die bedingte Anweisung B.
IMAGE_REL_ARM64_BRANCH14
0x0010
Der 14-Bit-Offset zum Verschiebungsziel, für die Befehle TBZ und TBNZ.
IMAGE_REL_ARM64_REL32
0x0011
Die relative 32-Bit-Adresse ab dem auf die Verschiebung folgenden Byte.
Hitachi SuperH Prozessoren

Für SH3- und SH4-Prozessoren sind die folgenden Kennzeichen für die Verschiebungsart definiert. SH5-spezifische Verschiebungen werden als SHM (SH Media) bezeichnet.

Konstante Wert Beschreibung
IMAGE_REL_SH3_ABSOLUTE
0x0000
Die Verschiebung wird ignoriert.
IMAGE_REL_SH3_DIRECT16
0x0001
Ein Verweis auf die 16-Bit-Stelle, die den VA des Zielsymbols enthält.
IMAGE_REL_SH3_DIRECT32
0x0002
Die 32-Bit-VA des Zielsymbols.
IMAGE_REL_SH3_DIRECT8
0x0003
Ein Verweis auf die 8-Bit-Stelle, die den VA des Zielsymbols enthält.
IMAGE_REL_SH3_DIRECT8_WORD
0x0004
Ein Verweis auf die 8-Bit-Anweisung, die die effektive 16-Bit-VA des Zielsymbols enthält.
IMAGE_REL_SH3_DIRECT8_LONG
0x0005
Ein Verweis auf die 8-Bit-Anweisung, die die effektive 32-Bit-VA des Zielsymbols enthält.
IMAGE_REL_SH3_DIRECT4
0x0006
Ein Verweis auf den 8-Bit-Speicherplatz, dessen niedrige 4 Bits den VA des Zielsymbols enthalten.
IMAGE_REL_SH3_DIRECT4_WORD
0x0007
Ein Verweis auf den 8-Bit-Befehl, dessen niedrige 4 Bits die effektive 16-Bit-VA des Zielsymbols enthalten.
IMAGE_REL_SH3_DIRECT4_LONG
0x0008
Ein Verweis auf den 8-Bit-Befehl, dessen niedrige 4 Bits die effektive 32-Bit-VA des Zielsymbols enthalten.
IMAGE_REL_SH3_PCREL8_WORD
0x0009
Ein Verweis auf die 8-Bit-Anweisung, die den effektiven relativen 16-Bit-Offset des Zielsymbols enthält.
IMAGE_REL_SH3_PCREL8_LONG
0x000A
Ein Verweis auf die 8-Bit-Anweisung, die den effektiven relativen 32-Bit-Offset des Zielsymbols enthält.
IMAGE_REL_SH3_PCREL12_WORD
0x000B
Ein Verweis auf den 16-Bit-Befehl, dessen niedrige 12 Bits den effektiven relativen 16-Bit-Offset des Zielsymbols enthalten.
IMAGE_REL_SH3_STARTOF_SECTION
0x000C
Ein Verweis auf eine 32-Bit-Stelle, die der VA des Abschnitts ist, der das Zielsymbol enthält.
IMAGE_REL_SH3_SIZEOF_SECTION
0x000D
Ein Verweis auf den 32-Bit-Speicherplatz, der die Größe des Abschnitts angibt, der das Zielsymbol enthält.
IMAGE_REL_SH3_SECTION
0x000E
Der 16-Bit-Abschnittsindex des Abschnitts, der das Ziel enthält. Dies wird zur Unterstützung von Debugging-Informationen verwendet.
IMAGE_REL_SH3_SECREL
0x000F
Der 32-Bit-Offset des Ziels vom Beginn seines Abschnitts. Dies dient der Unterstützung von Debugging-Informationen und der lokalen Speicherung statischer Threads.
IMAGE_REL_SH3_DIRECT32_NB
0x0010
Die 32-Bit-RVA des Zielsymbols.
IMAGE_REL_SH3_GPREL4_LONG
0x0011
GP-Relative.
IMAGE_REL_SH3_TOKEN
0x0012
CLR-Token.
IMAGE_REL_SHM_PCRELPT
0x0013
Der Offset der aktuellen Anweisung in Langwörtern. Wenn das NOMODE-Bit nicht gesetzt ist, fügen Sie die Umkehrung des Low-Bits an Bit 32 ein, um PTA oder PTB auszuwählen.
IMAGE_REL_SHM_REFLO
0x0014
Die niedrigen 16 Bits der 32-Bit-Adresse.
IMAGE_REL_SHM_REFHALF
0x0015
Die hohen 16 Bits der 32-Bit-Adresse.
IMAGE_REL_SHM_RELLO
0x0016
Die niedrigen 16 Bits der relativen Adresse.
IMAGE_REL_SHM_RELHALF
0x0017
Die hohen 16 Bits der relativen Adresse.
IMAGE_REL_SHM_PAIR
0x0018
Die Verschiebung ist nur gültig, wenn sie unmittelbar auf eine REFHALF-, RELHALF- oder RELLO-Verschiebung folgt. Das Feld SymbolTableIndex der Verschiebung enthält eine Verschiebung und nicht einen Index in der Symboltabelle.
IMAGE_REL_SHM_NOMODE
0x8000
Die Verschiebung ignoriert den Abschnittsmodus.

 

IBM PowerPC-Prozessoren

Für PowerPC-Prozessoren sind die folgenden Verschiebungsindikatoren definiert.

Konstante Wert Beschreibung
IMAGE_REL_PPC_ABSOLUTE
0x0000
Die Verschiebung wird ignoriert.
IMAGE_REL_PPC_ADDR64
0x0001
Die 64-Bit-VA des Ziels.
IMAGE_REL_PPC_ADDR32
0x0002
Die 32-Bit-VA des Ziels.
IMAGE_REL_PPC_ADDR24
0x0003
Die niedrigen 24 Bits der VA des Ziels. Dies gilt nur, wenn das Zielsymbol absolut ist und das Vorzeichen auf seinen ursprünglichen Wert erweitert werden kann.
IMAGE_REL_PPC_ADDR16
0x0004
Die niedrigen 16 Bits der VA des Ziels.
IMAGE_REL_PPC_ADDR14
0x0005
Die niedrigen 14 Bits der VA des Ziels. Dies gilt nur, wenn das Zielsymbol absolut ist und das Vorzeichen auf seinen ursprünglichen Wert erweitert werden kann.
IMAGE_REL_PPC_REL24
0x0006
Ein 24-Bit PC-relativer Offset zur Position des Symbols.
IMAGE_REL_PPC_REL14
0x0007
Ein 14-Bit PC-relativer Offset zur Position des Symbols.
IMAGE_REL_PPC_ADDR32NB
0x000A
Die 32-Bit-RVA des Ziels.
IMAGE_REL_PPC_SECREL
0x000B
Der 32-Bit-Offset des Ziels vom Beginn seines Abschnitts. Dies dient der Unterstützung von Debugging-Informationen und der lokalen Speicherung statischer Threads.
IMAGE_REL_PPC_SECTION
0x000C
Der 16-Bit-Abschnittsindex des Abschnitts, der das Ziel enthält. Dies wird zur Unterstützung von Debugging-Informationen verwendet.
IMAGE_REL_PPC_SECREL16
0x000F
Der 16-Bit-Offset des Ziels vom Beginn seines Abschnitts. Dies dient der Unterstützung von Debugging-Informationen und der lokalen Speicherung statischer Threads.
IMAGE_REL_PPC_REFHI
0x0010
Die hohen 16 Bits der 32-Bit-VA des Ziels. Dies wird für den ersten Befehl in einer Zwei-Befehls-Sequenz verwendet, die eine vollständige Adresse lädt. Auf diese Verschiebung muss unmittelbar eine PAIR-Verschiebung folgen, deren SymbolTableIndex eine vorzeichenbehaftete 16-Bit-Verschiebung enthält, die zu den oberen 16 Bits hinzugefügt wird, die von der zu verschiebenden Stelle genommen wurden.
IMAGE_REL_PPC_REFLO
0x0011
Die niedrigen 16 Bits der VA des Ziels.
IMAGE_REL_PPC_PAIR
0x0012
Eine Verschiebung, die nur gültig ist, wenn sie unmittelbar auf eine REFHI- oder SECRELHI-Verschiebung folgt. Sein SymbolTableIndex enthält eine Verschiebung und nicht einen Index in der Symboltabelle.
IMAGE_REL_PPC_SECRELLO
0x0013
Die unteren 16 Bits des 32-Bit-Offsets des Ziels vom Beginn seines Abschnitts.
IMAGE_REL_PPC_GPREL
0x0015
Die vorzeichenbehaftete 16-Bit-Verschiebung des Ziels relativ zum GP-Register.
IMAGE_REL_PPC_TOKEN
0x0016
Das CLR-Token.

 

Intel 386er Prozessoren

Für Intel 386 und kompatible Prozessoren sind die folgenden Umzugsindikatoren definiert.

Konstante Wert Beschreibung
IMAGE_REL_I386_ABSOLUTE
0x0000
Die Verschiebung wird ignoriert.
IMAGE_REL_I386_DIR16
0x0001
Wird nicht unterstützt.
IMAGE_REL_I386_REL16
0x0002
Wird nicht unterstützt.
IMAGE_REL_I386_DIR32
0x0006
Die 32-Bit-VA des Ziels.
IMAGE_REL_I386_DIR32NB
0x0007
Die 32-Bit-RVA des Ziels.
IMAGE_REL_I386_SEG12
0x0009
Wird nicht unterstützt.
IMAGE_REL_I386_SECTION
0x000A
Der 16-Bit-Abschnittsindex des Abschnitts, der das Ziel enthält. Dies wird zur Unterstützung von Debugging-Informationen verwendet.
IMAGE_REL_I386_SECREL
0x000B
Der 32-Bit-Offset des Ziels vom Beginn seines Abschnitts. Dies dient der Unterstützung von Debugging-Informationen und der lokalen Speicherung statischer Threads.
IMAGE_REL_I386_TOKEN
0x000C
Das CLR-Token.
IMAGE_REL_I386_SECREL7
0x000D
Ein 7-Bit-Offset von der Basis des Abschnitts, der das Ziel enthält.
IMAGE_REL_I386_REL32
0x0014
Die 32-Bit-Relativverschiebung zum Ziel. Dies unterstützt die relativen x86-Verzweigungs- und Aufrufbefehle.

 

Intel Itanium-Prozessorfamilie (IPF)

Für die Intel Itanium-Prozessorfamilie und kompatible Prozessoren sind die folgenden Verschiebungsindikatoren definiert. Beachten Sie, dass Relocations auf Anweisungen den Offset und die Slotnummer des Bundles für den Relocation Offset verwenden.

Konstante Wert Beschreibung
IMAGE_REL_IA64_ABSOLUTE
0x0000
Die Verschiebung wird ignoriert.
IMAGE_REL_IA64_IMM14
0x0001
Auf die Befehlsverschiebung kann eine ADDEND-Verschiebung folgen, deren Wert zur Zieladresse hinzugefügt wird, bevor sie in den angegebenen Steckplatz im IMM14-Bündel eingefügt wird. Das Verschiebungsziel muss absolut sein oder das Image muss fixiert sein.
IMAGE_REL_IA64_IMM22
0x0002
Auf die Befehlsverschiebung kann eine ADDEND-Verschiebung folgen, deren Wert zur Zieladresse hinzugefügt wird, bevor sie in den angegebenen Steckplatz im IMM22-Bündel eingefügt wird. Das Verschiebungsziel muss absolut sein oder das Image muss fixiert sein.
IMAGE_REL_IA64_IMM64
0x0003
Die Slotnummer dieser Verschiebung muss eins (1) sein. Auf die Verschiebung kann eine ADDEND-Verschiebung folgen, deren Wert zur Zieladresse addiert wird, bevor sie in allen drei Steckplätzen des IMM64-Bündels gespeichert wird.
IMAGE_REL_IA64_DIR32
0x0004
Die 32-Bit-VA des Ziels. Dies wird nur für /LARGEADDRESSAWARE:NO-Bilder unterstützt.
IMAGE_REL_IA64_DIR64
0x0005
Die 64-Bit-VA des Ziels.
IMAGE_REL_IA64_PCREL21B
0x0006
Die Anweisung wird mit der 25-Bit-Relativverschiebung zum 16-Bit-ausgerichteten Ziel fixiert. Die unteren 4 Bits der Verschiebung sind Null und werden nicht gespeichert.
IMAGE_REL_IA64_PCREL21M
0x0007
Die Anweisung wird mit der 25-Bit-Relativverschiebung zum 16-Bit-ausgerichteten Ziel fixiert. Die niedrigen 4 Bits der Verschiebung, die Null sind, werden nicht gespeichert.
IMAGE_REL_IA64_PCREL21F
0x0008
Die LSBs des Offsets dieser Verschiebung müssen die Slotnummer enthalten, während der Rest die Bündeladresse ist. Das Bündel wird mit der 25-Bit-Relativverschiebung zum 16-Bit-ausgerichteten Ziel fixiert. Die unteren 4 Bits der Verschiebung sind Null und werden nicht gespeichert.
IMAGE_REL_IA64_GPREL22
0x0009
Auf die Befehlsverschiebung kann eine ADDEND-Verschiebung folgen, deren Wert zur Zieladresse addiert wird, und dann ein 22-Bit-GP-relativer Offset, der berechnet und auf das GPREL22-Bündel angewendet wird.
IMAGE_REL_IA64_LTOFF22
0x000A
Die Anweisung wird mit dem 22-Bit-GP-relativen Offset zum Literal-Table-Eintrag des Zielsymbols fixiert. Der Linker erstellt diesen literalen Tabelleneintrag auf der Grundlage dieser Verschiebung und der ADDEND-Verschiebung, die möglicherweise folgt.
IMAGE_REL_IA64_SECTION
0x000B
Der 16-Bit-Abschnittsindex des Abschnitts enthält das Ziel. Dies wird zur Unterstützung von Debugging-Informationen verwendet.
IMAGE_REL_IA64_SECREL22
0x000C
Die Anweisung wird mit dem 22-Bit-Offset des Ziels vom Beginn ihres Abschnitts an festgelegt. Auf diese Verschiebung kann unmittelbar eine ADDEND-Verschiebung folgen, deren Feld Value den vorzeichenlosen 32-Bit-Offset des Ziels vom Beginn des Abschnitts enthält.
IMAGE_REL_IA64_SECREL64I
0x000D
Die Slotnummer für diese Verschiebung muss eins (1) sein. Die Anweisung wird mit dem 64-Bit-Offset des Ziels vom Beginn ihres Abschnitts an festgelegt. Auf diese Verschiebung kann unmittelbar eine ADDEND-Verschiebung folgen, deren Wertfeld den vorzeichenlosen 32-Bit-Offset des Ziels vom Beginn des Abschnitts enthält.
IMAGE_REL_IA64_SECREL32
0x000E
Die Adresse der Daten, die mit dem 32-Bit-Offset des Ziels ab dem Beginn seines Abschnitts zu fixieren sind.
IMAGE_REL_IA64_DIR32NB
0x0010
Die 32-Bit-RVA des Ziels.
IMAGE_REL_IA64_SREL14
0x0011
Dies wird auf einen vorzeichenbehafteten 14-Bit-Immediate angewendet, der die Differenz zwischen zwei verschiebbaren Zielen enthält. Dies ist ein deklaratives Feld für den Linker, das anzeigt, dass der Compiler diesen Wert bereits ausgegeben hat.
IMAGE_REL_IA64_SREL22
0x0012
Dies wird auf einen vorzeichenbehafteten 22-Bit-Immediate angewendet, der die Differenz zwischen zwei verschiebbaren Zielen enthält. Dies ist ein deklaratives Feld für den Linker, das anzeigt, dass der Compiler diesen Wert bereits ausgegeben hat.
IMAGE_REL_IA64_SREL32
0x0013
Dies wird auf einen vorzeichenbehafteten 32-Bit-Immediate angewendet, der die Differenz zwischen zwei verschiebbaren Werten enthält. Dies ist ein deklaratives Feld für den Linker, das anzeigt, dass der Compiler diesen Wert bereits ausgegeben hat.
IMAGE_REL_IA64_UREL32
0x0014
Dies wird auf einen vorzeichenlosen 32-Bit-Immediate angewendet, der die Differenz zwischen zwei verschiebbaren Werten enthält. Dies ist ein deklaratives Feld für den Linker, das anzeigt, dass der Compiler diesen Wert bereits ausgegeben hat.
IMAGE_REL_IA64_PCREL60X
0x0015
Eine 60-Bit PC-relative Korrektur, die immer als BRL-Anweisung eines MLX-Bündels bleibt.
IMAGE_REL_IA64_PCREL60B
0x0016
Eine 60-Bit PC-relative Korrektur. Wenn die Zielverschiebung in ein vorzeichenbehaftetes 25-Bit-Feld passt, konvertieren Sie das gesamte Bündel in ein MBB-Bündel mit NOP.B in Slot 1 und einem 25-Bit-BR-Befehl (mit den 4 niedrigsten Bits, die alle null sind und weggelassen werden) in Slot 2.
IMAGE_REL_IA64_PCREL60F
0x0017
Eine 60-Bit PC-relative Korrektur. Wenn die Zielverschiebung in ein vorzeichenbehaftetes 25-Bit-Feld passt, konvertieren Sie das gesamte Bündel in ein MFB-Bündel mit NOP.F in Slot 1 und einem 25-Bit-BR-Befehl (die 4 niedrigsten Bits sind alle null und werden gelöscht) in Slot 2.
IMAGE_REL_IA64_PCREL60I
0x0018
Eine 60-Bit PC-relative Korrektur. Wenn die Zielverschiebung in ein vorzeichenbehaftetes 25-Bit-Feld passt, konvertieren Sie das gesamte Bündel in ein MIB-Bündel mit NOP.I in Slot 1 und einem 25-Bit-BR-Befehl (die 4 niedrigsten Bits sind alle null und werden gelöscht) in Slot 2.
IMAGE_REL_IA64_PCREL60M
0x0019
Eine 60-Bit PC-relative Korrektur. Wenn die Zielverschiebung in ein vorzeichenbehaftetes 25-Bit-Feld passt, konvertieren Sie das gesamte Bündel in ein MMB-Bündel mit NOP.M in Slot 1 und einem 25-Bit-BR-Befehl (die 4 niedrigsten Bits sind alle null und werden gelöscht) in Slot 2.
IMAGE_REL_IA64_IMMGPREL64
0x001a
Eine 64-Bit GP-relative Korrektur.
IMAGE_REL_IA64_TOKEN
0x001b
Ein CLR-Token.
IMAGE_REL_IA64_GPREL32
0x001c
Eine 32-Bit GP-relative Korrektur.
IMAGE_REL_IA64_ADDEND
0x001F
Die Verschiebung ist nur gültig, wenn sie unmittelbar auf eine der folgenden Verschiebungen folgt: IMM14, IMM22, IMM64, GPREL22, LTOFF22, LTOFF64, SECREL22, SECREL64I oder SECREL32. Sein Wert enthält den Zusatz, der für Anweisungen innerhalb eines Bundles gilt, nicht für Daten.

 

MIPS-Prozessoren

Für MIPS-Prozessoren sind die folgenden Verschiebungsindikatoren definiert.

Konstante Wert Beschreibung
IMAGE_REL_MIPS_ABSOLUTE
0x0000
Die Verschiebung wird ignoriert.
IMAGE_REL_MIPS_REFHALF
0x0001
Die hohen 16 Bits der 32-Bit-VA des Ziels.
IMAGE_REL_MIPS_REFWORD
0x0002
Die 32-Bit-VA des Ziels.
IMAGE_REL_MIPS_JMPADDR
0x0003
Die niedrigen 26 Bits der VA des Ziels. Dies unterstützt die MIPS-Befehle J und JAL.
IMAGE_REL_MIPS_REFHI
0x0004
Die hohen 16 Bits der 32-Bit-VA des Ziels. Dies wird für den ersten Befehl in einer Zwei-Befehls-Sequenz verwendet, die eine vollständige Adresse lädt. Auf diese Verschiebung muss unmittelbar eine PAIR-Verschiebung folgen, deren SymbolTableIndex eine vorzeichenbehaftete 16-Bit-Verschiebung enthält, die zu den oberen 16 Bits addiert wird, die von der zu verschiebenden Stelle genommen werden.
IMAGE_REL_MIPS_REFLO
0x0005
Die niedrigen 16 Bits der VA des Ziels.
IMAGE_REL_MIPS_GPREL
0x0006
Eine vorzeichenbehaftete 16-Bit-Verschiebung des Ziels relativ zum GP-Register.
IMAGE_REL_MIPS_LITERAL
0x0007
Dasselbe wie IMAGE_REL_MIPS_GPREL.
IMAGE_REL_MIPS_SECTION
0x000A
Der 16-Bit-Abschnittsindex des Abschnitts enthält das Ziel. Dies wird zur Unterstützung von Debugging-Informationen verwendet.
IMAGE_REL_MIPS_SECREL
0x000B
Der 32-Bit-Offset des Ziels vom Beginn seines Abschnitts. Dies dient der Unterstützung von Debugging-Informationen und der lokalen Speicherung statischer Threads.
IMAGE_REL_MIPS_SECRELLO
0x000C
Die unteren 16 Bits des 32-Bit-Offsets des Ziels vom Beginn seines Abschnitts.
IMAGE_REL_MIPS_SECRELHI
0x000D
Die hohen 16 Bits des 32-Bit-Offsets des Ziels vom Beginn seines Abschnitts. Eine IMAGE_REL_MIPS_PAIR-Verschiebung muss unmittelbar auf diese folgen. Der SymbolTableIndex der PAIR-Verschiebung enthält eine vorzeichenbehaftete 16-Bit-Verschiebung, die zu den oberen 16 Bits addiert wird, die von der zu verschiebenden Stelle genommen werden.
IMAGE_REL_MIPS_JMPADDR16
0x0010
Die niedrigen 26 Bits der VA des Ziels. Dies unterstützt den MIPS16 JAL-Befehl.
IMAGE_REL_MIPS_REFWORDNB
0x0022
Die 32-Bit-RVA des Ziels.
IMAGE_REL_MIPS_PAIR
0x0025
Die Verschiebung ist nur gültig, wenn sie unmittelbar auf eine REFHI- oder SECRELHI-Verschiebung folgt. Sein SymbolTableIndex enthält eine Verschiebung und nicht einen Index in der Symboltabelle.

 

Mitsubishi M32R

Für die Mitsubishi M32R-Prozessoren sind die folgenden Verschiebungsindikatoren definiert.

Konstante Wert Beschreibung
IMAGE_REL_M32R_ABSOLUTE
0x0000
Die Verschiebung wird ignoriert.
IMAGE_REL_M32R_ADDR32
0x0001
Die 32-Bit-VA des Ziels.
IMAGE_REL_M32R_ADDR32NB
0x0002
Die 32-Bit-RVA des Ziels.
IMAGE_REL_M32R_ADDR24
0x0003
Die 24-Bit-VA des Ziels.
IMAGE_REL_M32R_GPREL16
0x0004
Der 16-Bit-Offset des Ziels aus dem GP-Register.
IMAGE_REL_M32R_PCREL24
0x0005
Der 24-Bit-Offset des Ziels vom Programmzähler (PC), um 2 Bits nach links verschoben und vorzeichenerweitert
IMAGE_REL_M32R_PCREL16
0x0006
Der 16-Bit-Offset des Ziels gegenüber dem PC, um 2 Bits nach links verschoben und vorzeichenerweitert
IMAGE_REL_M32R_PCREL8
0x0007
Der 8-Bit-Offset des Ziels gegenüber dem PC, um 2 Bits nach links verschoben und vorzeichenerweitert
IMAGE_REL_M32R_REFHALF
0x0008
Die 16 MSBs der Ziel-VA.
IMAGE_REL_M32R_REFHI
0x0009
Die 16 MSBs der Ziel-VA, angepasst an die LSB-Vorzeichenerweiterung. Dies wird für den ersten Befehl in einer Zwei-Befehls-Sequenz verwendet, die eine volle 32-Bit-Adresse lädt. Auf diese Verschiebung muss unmittelbar eine PAIR-Verschiebung folgen, deren SymbolTableIndex eine vorzeichenbehaftete 16-Bit-Verschiebung enthält, die zu den oberen 16 Bits addiert wird, die von der zu verschiebenden Stelle genommen werden.
IMAGE_REL_M32R_REFLO
0x000A
Die 16 LSBs der Ziel-VA.
IMAGE_REL_M32R_PAIR
0x000B
Die Verschiebung muss nach der REFHI-Verschiebung erfolgen. Sein SymbolTableIndex enthält eine Verschiebung und nicht einen Index in der Symboltabelle.
IMAGE_REL_M32R_SECTION
0x000C
Der 16-Bit-Abschnittsindex des Abschnitts, der das Ziel enthält. Dies wird zur Unterstützung von Debugging-Informationen verwendet.
IMAGE_REL_M32R_SECREL
0x000D
Der 32-Bit-Offset des Ziels vom Beginn seines Abschnitts. Dies dient der Unterstützung von Debugging-Informationen und der lokalen Speicherung statischer Threads.
IMAGE_REL_M32R_TOKEN
0x000E
Das CLR-Token.

 

COFF-Zeilennummern (veraltet)

COFF-Zeilennummern werden nicht mehr hergestellt und in Zukunft auch nicht mehr verbraucht.

COFF-Zeilennummern geben die Beziehung zwischen Code und Zeilennummern in Quelldateien an. Das Microsoft-Format für COFF-Zeilennummern ähnelt dem Standard-COFF-Format, wurde aber erweitert, damit sich ein einzelner Abschnitt auf Zeilennummern in mehreren Quelldateien beziehen kann.

COFF-Zeilennummern bestehen aus einer Reihe von Datensätzen fester Länge. Der Speicherort (Datei-Offset) und die Größe des Arrays werden in der Kopfzeile des Abschnitts angegeben. Jeder Zeilennummernsatz hat das folgende Format.

Abstand Größe Feld Beschreibung
0
4
Typ (*)
Dies ist eine Vereinigung von zwei Feldern: SymbolTableIndex und VirtualAddress. Ob SymbolTableIndex oder RVA verwendet wird, hängt von dem Wert von Linenumber ab.
4
2
Leinennummer
Wenn dieses Feld ungleich Null ist, gibt es eine einseitige Zeilennummer an. Wenn das Feld Typ Null ist, wird es als Symboltabellenindex für eine Funktion interpretiert.

 

Das Feld „Typ“ ist eine Vereinigung zweier 4-Byte-Felder: SymbolTableIndex und VirtualAddress.

Abstand Größe Feld Beschreibung
0
4
SymbolTableIndex
Wird verwendet, wenn Linenumber gleich Null ist: Index zum Symboltabelleneintrag für eine Funktion. Dieses Format wird verwendet, um die Funktion anzugeben, auf die sich eine Gruppe von Zeilennummerneinträgen bezieht.
0
4
VirtualAddress
Wird verwendet, wenn Linenumber ungleich Null ist: der RVA des ausführbaren Codes, der der angegebenen Quellzeile entspricht. In einer Objektdatei enthält dies die VA innerhalb des Abschnitts.

 

Ein Zeilennummern-Datensatz kann entweder das Feld Zeilennummer auf Null setzen und auf eine Funktionsdefinition in der Symboltabelle verweisen, oder er kann als Standard-Zeilennummern-Eintrag funktionieren, indem er eine positive Ganzzahl (Zeilennummer) und die entsprechende Adresse im Objektcode angibt.

Eine Gruppe von Zeilennummerneinträgen beginnt immer mit dem ersten Format: dem Index eines Funktionssymbols. Wenn dies der erste Zeilennummernsatz im Abschnitt ist, dann ist dies auch der COMDAT-Symbolname für die Funktion, wenn das COMDAT-Flag des Abschnitts gesetzt ist. Siehe COMDAT-Abschnitte (nur Objekt). Der Hilfssatz der Funktion in der Symboltabelle hat einen Zeiger auf das Feld Zeilennummer, der auf denselben Zeilennummernsatz verweist.

Auf einen Datensatz, der eine Funktion identifiziert, folgt eine beliebige Anzahl von Zeilennummerneinträgen, die tatsächliche Zeilennummerninformationen enthalten (d. h. Einträge mit Linenumber größer als Null). Diese Einträge sind einzeilig, relativ zum Anfang der Funktion, und repräsentieren jede Quellzeile in der Funktion mit Ausnahme der ersten Zeile.

Der erste Zeilennummern-Datensatz des folgenden Beispiels würde beispielsweise die Funktion ReverseSign (SymbolTableIndex von ReverseSign und Linenumber auf Null gesetzt) angeben. Dann würden Datensätze mit den Zeilennummern 1, 2 und 3 folgen, die den gezeigten Quellzeilen entsprechen:

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

COFF-Symboltabelle

Die Symboltabelle in diesem Abschnitt wurde vom traditionellen COFF-Format übernommen. Sie unterscheidet sich von den Debug-Informationen von Microsoft Visual C++. Eine Datei kann sowohl eine COFF-Symboltabelle als auch Visual C++-Debug-Informationen enthalten, und beide werden getrennt gehalten. Einige Microsoft-Tools verwenden die Symboltabelle für begrenzte, aber wichtige Zwecke, z. B. zur Übermittlung von COMDAT-Informationen an den Linker. Abschnittsnamen und Dateinamen sowie Code- und Datensymbole sind in der Symboltabelle aufgeführt.

Der Ort der Symboltabelle ist im COFF-Header angegeben.

Die Symboltabelle ist ein Array von Datensätzen, die jeweils 18 Bytes lang sind. Jeder Datensatz ist entweder ein Standard- oder ein Hilfssymboltabellendatensatz. Ein Standardsatz definiert ein Symbol oder einen Namen und hat das folgende Format.

Abstand Größe Feld Beschreibung
0
8
Name (*)
Der Name des Symbols, dargestellt durch eine Vereinigung von drei Strukturen. Ein Array von 8 Bytes wird verwendet, wenn der Name nicht mehr als 8 Bytes lang ist. Weitere Informationen finden Sie unter Darstellung von Symbolnamen.
8
4
Wert
Der Wert, der mit dem Symbol verbunden ist. Die Interpretation dieses Feldes hängt von SectionNumber und StorageClass ab. Eine typische Bedeutung ist die verschiebbare Adresse.
12
2
AbschnittNummer
Die vorzeichenbehaftete Ganzzahl, die den Abschnitt identifiziert, wobei ein einseitiger Index in der Abschnittstabelle verwendet wird. Einige Werte haben eine besondere Bedeutung, wie in Abschnitt 5.4.2, „Abschnittsnummernwerte“, definiert
14
2
Typ
Eine Zahl, die den Typ darstellt. Microsoft-Tools setzen dieses Feld auf 0x20 (Funktion) oder 0x0 (keine Funktion). Weitere Informationen finden Sie unter Typendarstellung.
16
1
StorageClass
Ein Aufzählungswert, der die Speicherklasse darstellt. Weitere Informationen finden Sie unter Storage Class.
17
1
NumberOfAuxSymbols
Die Anzahl der Hilfssymboltabelleneinträge, die auf diesen Datensatz folgen.

 

Jedem Standardsymboltabellendatensatz folgen unmittelbar null oder mehr Hilfssymboltabellendatensätze. Normalerweise folgt jedoch nicht mehr als ein Hilfssymboltabellendatensatz auf einen Standardsymboltabellendatensatz (außer bei .file-Datensätzen mit langen Dateinamen). Jeder Hilfssatz hat die gleiche Größe wie ein Standard-Symboltabellendatensatz (18 Byte), aber anstatt ein neues Symbol zu definieren, enthält der Hilfssatz zusätzliche Informationen über das zuletzt definierte Symbol. Welches von mehreren Formaten zu verwenden ist, hängt vom Feld StorageClass ab. Die derzeit definierten Formate für Hilfssymboltabellensätze sind in Abschnitt 5.5, „Hilfssymbolsätze“, dargestellt

Werkzeuge, die COFF-Symboltabellen lesen, müssen Hilfssymbolsätze, deren Interpretation unbekannt ist, ignorieren. Dadurch kann das Symboltabellenformat erweitert werden, um neue Hilfssätze hinzuzufügen, ohne dass bestehende Werkzeuge zerstört werden.

Symbol Name Darstellung

Das Feld Kurzname in einer Symboltabelle besteht aus 8 Bytes, die den Namen selbst enthalten, wenn er nicht länger als 8 Bytes ist, oder das Feld Kurzname gibt einen Offset in der Stringtabelle an. Um festzustellen, ob der Name selbst oder ein Offset angegeben ist, testen Sie die ersten 4 Bytes auf Gleichheit mit Null.

Konventionell werden die Namen als nullterminierte UTF-8-kodierte Strings behandelt.

Abstand Größe Feld Beschreibung
0
8
Kurzname
Ein Array von 8 Bytes. Dieses Array wird auf der rechten Seite mit Nullen aufgefüllt, wenn der Name weniger als 8 Byte lang ist.
0
4
Nullen
Ein Feld, das auf alle Nullen gesetzt wird, wenn der Name länger als 8 Byte ist.
4
4
Abstand
Ein Offset in der Stringtabelle.

 

Abschnitt Nummer Werte

Normalerweise ist das Feld Abschnittswert in einem Symboltabelleneintrag ein einseitiger Index in der Abschnittstabelle. Dieses Feld ist jedoch eine Ganzzahl mit Vorzeichen und kann negative Werte annehmen. Die folgenden Werte, die kleiner als eins sind, haben eine besondere Bedeutung.

Konstante Wert Beschreibung
IMAGE_SYM_UNDEFINED
0
Dem Symbolsatz ist noch kein Abschnitt zugeordnet. Ein Wert von Null bedeutet, dass ein Verweis auf ein externes Symbol an anderer Stelle definiert ist. Ein Wert ungleich Null ist ein gemeinsames Symbol mit einer Größe, die durch den Wert angegeben wird.
IMAGE_SYM_ABSOLUTE
-1
Das Symbol hat einen absoluten (nicht verschiebbaren) Wert und ist keine Adresse.
IMAGE_SYM_DEBUG
-2
Das Symbol liefert allgemeine Typ- oder Debugging-Informationen, entspricht aber keinem Abschnitt. Microsoft-Tools verwenden diese Einstellung zusammen mit .file-Datensätzen (Speicherklasse FILE).

 

Typendarstellung

Das Feld Typ eines Symboltabelleneintrags enthält 2 Bytes, wobei jedes Byte eine Typinformation darstellt. Das LSB steht für den einfachen (Basis-)Datentyp und das MSB für den komplexen Typ, falls vorhanden:

MSB LSB
Komplexer Typ: keine, Zeiger, Funktion, Array.
Basistyp: Ganzzahl, Fließkomma, usw.

 

Die folgenden Werte sind für den Basistyp definiert, obwohl Microsoft-Tools dieses Feld im Allgemeinen nicht verwenden und das LSB auf 0 setzen. Stattdessen werden Visual C++-Debug-Informationen verwendet, um Typen anzuzeigen. Die möglichen COFF-Werte werden hier jedoch der Vollständigkeit halber aufgeführt.

Konstante Wert Beschreibung
IMAGE_SYM_TYPE_NULL
0
Keine Typinformationen oder unbekannter Basistyp. Microsoft-Tools verwenden diese Einstellung
IMAGE_SYM_TYPE_VOID
1
Kein gültiger Typ; wird mit void-Zeigern und Funktionen verwendet
IMAGE_SYM_TYPE_CHAR
2
Ein Zeichen (Byte mit Vorzeichen)
IMAGE_SYM_TYPE_SHORT
3
Eine 2-Byte-Ganzzahl mit Vorzeichen
IMAGE_SYM_TYPE_INT
4
Ein natürlicher Integer-Typ (normalerweise 4 Bytes in Windows)
IMAGE_SYM_TYPE_LONG
5
Eine 4-Byte-Ganzzahl mit Vorzeichen
IMAGE_SYM_TYPE_FLOAT
6
Eine 4-Byte-Gleitkommazahl
IMAGE_SYM_TYPE_DOUBLE
7
Eine 8-Byte-Gleitkommazahl
IMAGE_SYM_TYPE_STRUCT
8
Eine Struktur
IMAGE_SYM_TYPE_UNION
9
Eine Gewerkschaft
IMAGE_SYM_TYPE_ENUM
10
Ein Aufzählungstyp
IMAGE_SYM_TYPE_MOE
11
Ein Element einer Aufzählung (ein bestimmter Wert)
IMAGE_SYM_TYPE_BYTE
12
A Byte; vorzeichenlose 1-Byte-Ganzzahl
IMAGE_SYM_TYPE_WORD
13
Ein Wort; 2-Byte-Ganzzahl ohne Vorzeichen
IMAGE_SYM_TYPE_UINT
14
Eine Ganzzahl ohne Vorzeichen mit natürlicher Größe (normalerweise 4 Byte)
IMAGE_SYM_TYPE_DWORD
15
Eine 4-Byte-Ganzzahl ohne Vorzeichen

 

Das höchstwertige Byte gibt an, ob das Symbol ein Zeiger auf, eine Funktion, die zurückkehrt, oder ein Array des Basistyps ist, der im LSB angegeben ist. Microsoft-Tools verwenden dieses Feld nur, um anzugeben, ob das Symbol eine Funktion ist, sodass die einzigen beiden resultierenden Werte 0x0 und 0x20 für das Feld Typ sind. Andere Tools können dieses Feld jedoch nutzen, um weitere Informationen zu übermitteln.

Es ist sehr wichtig, dass das Funktionsattribut korrekt angegeben wird. Diese Informationen sind erforderlich, damit die inkrementelle Verknüpfung korrekt funktioniert. Bei einigen Architekturen können die Informationen für andere Zwecke erforderlich sein.

Konstante Wert Beschreibung
IMAGE_SYM_DTYPE_NULL
0
Kein abgeleiteter Typ; das Symbol ist eine einfache skalare Variable.
IMAGE_SYM_DTYPE_POINTER
1
Das Symbol ist ein Zeiger auf den Basistyp.
IMAGE_SYM_DTYPE_FUNCTION
2
Das Symbol ist eine Funktion, die einen Basistyp zurückgibt.
IMAGE_SYM_DTYPE_ARRAY
3
Das Symbol ist ein Array vom Basistyp.

 

Speicherklasse

Das Feld StorageClass der Symboltabelle gibt an, für welche Art von Definition ein Symbol steht. Die folgende Tabelle zeigt die möglichen Werte. Beachten Sie, dass das Feld StorageClass eine vorzeichenlose 1-Byte-Ganzzahl ist. Der spezielle Wert -1 sollte daher als sein vorzeichenloses Äquivalent, 0xFF, verstanden werden.

Obwohl das traditionelle COFF-Format viele Speicherklassenwerte verwendet, verlassen sich Microsoft-Tools für die meisten symbolischen Informationen auf das Visual C++-Debug-Format und verwenden im Allgemeinen nur vier Speicherklassenwerte: EXTERN (2), STATIC (3), FUNCTION (101) und FILE (103). Außer in der zweiten Spaltenüberschrift unten ist mit „Wert“ das Feld „Wert“ des Symbolsatzes gemeint (dessen Interpretation von der als Speicherklasse gefundenen Zahl abhängt).

Konstante Wert Beschreibung/Interpretation des Feldes Wert
IMAGE_SYM_CLASS_END_OF_FUNCTION
-1 (0xFF)
Ein spezielles Symbol, das zu Debugging-Zwecken das Ende einer Funktion darstellt.
IMAGE_SYM_CLASS_NULL
0
Keine zugeordnete Speicherklasse.
IMAGE_SYM_CLASS_AUTOMATIC
1
Die automatische (Stapel-)Variable. Das Feld Wert gibt den Stack-Frame-Offset an.
IMAGE_SYM_CLASS_EXTERNAL
2
Ein Wert, den Microsoft-Tools für externe Symbole verwenden. Das Feld Wert gibt die Größe an, wenn die Abschnittsnummer IMAGE_SYM_UNDEFINED (0) lautet. Ist die Abschnittsnummer ungleich Null, so gibt das Feld Wert den Offset innerhalb des Abschnitts an.
IMAGE_SYM_CLASS_STATIC
3
Der Offset des Symbols innerhalb des Abschnitts. Ist das Feld Wert gleich Null, so steht das Symbol für einen Abschnittsnamen.
IMAGE_SYM_CLASS_REGISTER
4
Eine Registervariable. Das Feld Wert gibt die Registernummer an.
IMAGE_SYM_CLASS_EXTERNAL_DEF
5
Ein Symbol, das von außen definiert wird.
IMAGE_SYM_CLASS_LABEL
6
Eine Codebezeichnung, die innerhalb des Moduls definiert wird. Das Feld Wert gibt den Offset des Symbols innerhalb des Abschnitts an.
IMAGE_SYM_CLASS_UNDEFINED_LABEL
7
Ein Verweis auf ein nicht definiertes Codelabel.
IMAGE_SYM_CLASS_MEMBER_OF_STRUCT
8
Das Strukturelement. Das Feld Wert gibt das n-te Element an.
IMAGE_SYM_CLASS_ARGUMENT
9
Ein formales Argument (Parameter) einer Funktion. Das Feld Wert gibt das n-te Argument an.
IMAGE_SYM_CLASS_STRUCT_TAG
10
Die Struktur tag-name entry.
IMAGE_SYM_CLASS_MEMBER_OF_UNION
11
Ein Gewerkschaftselement. Das Feld Wert gibt das n-te Element an.
IMAGE_SYM_CLASS_UNION_TAG
12
Der Eintrag Union tag-name.
IMAGE_SYM_CLASS_TYPE_DEFINITION
13
Ein Typedef-Eintrag.
IMAGE_SYM_CLASS_UNDEFINED_STATIC
14
Eine statische Datendeklaration.
IMAGE_SYM_CLASS_ENUM_TAG
15
Ein Aufzählungstyp tagname-Eintrag.
IMAGE_SYM_CLASS_MEMBER_OF_ENUM
16
Ein Element einer Aufzählung. Das Feld Wert gibt das n-te Element an.
IMAGE_SYM_CLASS_REGISTER_PARAM
17
Ein Registerparameter.
IMAGE_SYM_CLASS_BIT_FIELD
18
Eine Bit-Feld-Referenz. Das Feld Wert gibt das n-te Bit im Bitfeld an.
IMAGE_SYM_CLASS_BLOCK
100
Ein .bb (Anfang des Blocks) oder .eb (Ende des Blocks) Datensatz. Das Feld Wert ist die verschiebbare Adresse der Codestelle.
IMAGE_SYM_CLASS_FUNCTION
101
Ein Wert, den Microsoft-Tools für Symbolsätze verwenden, die den Umfang einer Funktion definieren: Funktionsbeginn (.bf ), Funktionsende ( .ef ) und Zeilen in der Funktion ( .lf ). Bei .lf-Datensätzen gibt das Feld Wert die Anzahl der Quellzeilen in der Funktion an. Bei .ef-Datensätzen gibt das Feld Wert die Größe des Funktionscodes an.
IMAGE_SYM_CLASS_END_OF_STRUCT
102
Ein Eintrag am Ende der Struktur.
IMAGE_SYM_CLASS_FILE
103
Ein Wert, den Microsoft-Tools sowie das traditionelle COFF-Format für den Symbolsatz der Quelldatei verwenden. Auf das Symbol folgen Hilfssätze, die die Datei benennen.
IMAGE_SYM_CLASS_SECTION
104
Eine Definition eines Abschnitts (Microsoft-Tools verwenden stattdessen die Speicherklasse STATIC).
IMAGE_SYM_CLASS_WEAK_EXTERNAL
105
Ein schwaches Äußeres. Weitere Informationen finden Sie unter Auxiliary Format 3: Schwache Externe.
IMAGE_SYM_CLASS_CLR_TOKEN
107
Ein CLR-Token-Symbol. Der Name ist ein ASCII-String, der aus dem hexadezimalen Wert des Tokens besteht. Weitere Informationen finden Sie unter CLR Token Definition (Object Only).

 

Datensätze für Hilfssymbole

Hilfssymboltabellensätze folgen immer auf einen Standardsymboltabellensatz und beziehen sich auf diesen. Ein Hilfsdatensatz kann ein beliebiges Format haben, das von den Werkzeugen erkannt werden kann, aber es müssen 18 Bytes für sie reserviert werden, damit die Symboltabelle als Array mit regulärer Größe gepflegt wird. Derzeit erkennen die Microsoft-Tools Hilfsformate für die folgenden Arten von Datensätzen: Funktionsdefinitionen, Funktionsanfangs- und -endsymbole (.bf und .ef), schwache Externals, Dateinamen und Abschnittsdefinitionen.

Das traditionelle COFF-Design umfasst auch Hilfsdatensatzformate für Arrays und Strukturen. Microsoft-Tools verwenden diese nicht, sondern platzieren diese symbolischen Informationen im Visual C++-Debug-Format in den Debug-Abschnitten.

Zusätzliches Format 1: Funktionsdefinitionen

Ein Symboltabellendatensatz markiert den Beginn einer Funktionsdefinition, wenn er alle folgenden Merkmale aufweist: eine Speicherklasse von EXTERNAL (2), einen Typwert, der anzeigt, dass es sich um eine Funktion handelt (0x20), und eine Abschnittsnummer, die größer als Null ist. Beachten Sie, daß ein Symboltabellendatensatz mit einer Abschnittsnummer von UNDEFINED (0) die Funktion nicht definiert und keinen Hilfssatz hat. Auf die Funktionsdefinitionssymbole folgt ein Hilfsdatensatz in dem unten beschriebenen Format:

Abstand Größe Feld Beschreibung
0
4
TagIndex
Der Symboltabellenindex des entsprechenden .bf (begin function)-Symboldatensatzes.
4
4
TotalSize
Die Größe des ausführbaren Codes für die Funktion selbst. Befindet sich die Funktion in einem eigenen Abschnitt, ist die SizeOfRawData in der Abschnittsüberschrift größer oder gleich diesem Feld, je nach Ausrichtungsüberlegungen.
8
4
PointerToLinenumber
Der Datei-Offset des ersten COFF-Zeilennummerneintrags für die Funktion oder Null, wenn kein Eintrag existiert. Weitere Informationen finden Sie unter COFF-Zeilennummern (veraltet).
12
4
PointerToNextFunction
Der Symboltabellenindex des Datensatzes für die nächste Funktion. Wenn die Funktion die letzte in der Symboltabelle ist, wird dieses Feld auf Null gesetzt.
16
2
Unbenutzt

 

Zusätzliches Format 2: .bf- und .ef-Symbole

Für jede Funktionsdefinition in der Symboltabelle beschreiben drei Elemente den Anfang, das Ende und die Anzahl der Zeilen. Jedes dieser Symbole hat die Speicherklasse FUNCTION (101):

Ein Symbolsatz mit dem Namen .bf (begin function). Das Feld Wert ist unbenutzt.

Ein Symbolsatz mit dem Namen .lf (lines in function). Das Feld Wert gibt die Anzahl der Zeilen in der Funktion an.

Ein Symbolsatz mit dem Namen .ef (end of function). Das Feld Wert hat die gleiche Nummer wie das Feld Gesamtgröße im Funktionsdefinitionssymboldatensatz.

Den .bf- und .ef-Symboldatensätzen (nicht aber den .lf-Datensätzen) folgt ein Hilfssatz mit folgendem Format:

Abstand Größe Feld Beschreibung
0
4
Unbenutzt
4
2
Leinennummer
Die tatsächliche ordinale Zeilennummer (1, 2, 3 usw.) innerhalb der Quelldatei, die dem .bf- oder .ef-Datensatz entspricht.
6
6
Unbenutzt
12
4
PointerToNextFunction (nur .bf)
Der Symboltabellenindex des nächsten .bf-Symboldatensatzes. Wenn die Funktion die letzte in der Symboltabelle ist, wird dieses Feld auf Null gesetzt. Sie wird nicht für .ef-Einträge verwendet.
16
2
Unbenutzt

 

Zusätzliches Format 3: Schwache Äußerlichkeiten

„Weak Externals“ sind ein Mechanismus für Objektdateien, der Flexibilität zur Link-Zeit ermöglicht. Ein Modul kann ein nicht aufgelöstes externes Symbol (sym1) enthalten, es kann aber auch einen Hilfssatz enthalten, der angibt, dass, wenn sym1 zum Zeitpunkt der Verknüpfung nicht vorhanden ist, stattdessen ein anderes externes Symbol (sym2) zur Auflösung von Referenzen verwendet wird.

Wenn eine Definition von sym1 verknüpft ist, wird ein externer Verweis auf das Symbol normal aufgelöst. Wenn eine Definition von sym1 nicht verknüpft ist, beziehen sich alle Verweise auf das schwache Externe von sym1 stattdessen auf sym2. Das externe Symbol sym2 muss immer verlinkt werden; normalerweise wird es in dem Modul definiert, das den schwachen Verweis auf sym1 enthält.

Schwache Externe werden durch einen Symboltabellensatz mit der Speicherklasse EXTERNAL, der Abschnittsnummer UNDEF und einem Wert von Null dargestellt. Auf den Satz mit dem schwachen externen Symbol folgt ein Hilfssatz mit folgendem Format:

Abstand Größe Feld Beschreibung
0
4
TagIndex
Der Symboltabellenindex von sym2, dem zu verknüpfenden Symbol, wenn sym1 nicht gefunden wird.
4
4
Merkmale
Ein Wert von IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY bedeutet, dass keine Bibliothekssuche für sym1 durchgeführt werden soll.
Ein Wert von IMAGE_WEAK_EXTERN_SEARCH_LIBRARY bedeutet, dass eine Bibliothekssuche für sym1 durchgeführt werden soll.
Ein Wert von IMAGE_WEAK_EXTERN_SEARCH_ALIAS bedeutet, dass sym1 ein Alias für sym2 ist.
8
10
Unbenutzt

 

Beachten Sie, daß das Feld Merkmale in WINNT.H nicht definiert ist; statt dessen wird das Feld Gesamtgröße verwendet.

Zusätzliches Format 4: Dateien

Dieses Format folgt einem Symboltabellensatz mit der Speicherklasse FILE (103). Der Symbolname selbst sollte .file lauten, und der darauf folgende Hilfssatz gibt den Namen einer Quellcodedatei an.

Abstand Größe Feld Beschreibung
0
18
Datei Name
Ein ANSI-String, der den Namen der Quelldatei angibt. Diese wird mit Nullen aufgefüllt, wenn sie kleiner als die maximale Länge ist.

 

Zusätzliches Format 5: Abschnitt Definitionen

Dieses Format folgt einem Symboltabellendatensatz, der einen Abschnitt definiert. Ein solcher Datensatz hat einen Symbolnamen, der der Name eines Abschnitts ist (z. B. .text oder .drectve), und die Speicherklasse STATIC (3). Der Hilfsdatensatz enthält Informationen über den Abschnitt, auf den er sich bezieht. Dadurch werden einige der Informationen in der Abschnittsüberschrift dupliziert.

Abstand Größe Feld Beschreibung
0
4
Länge
Die Größe der Abschnittsdaten; entspricht SizeOfRawData in der Abschnittsüberschrift.
4
2
NumberOfRelocations
Die Anzahl der Verschiebungseinträge für den Abschnitt.
6
2
NumberOfLinenumbers
Die Anzahl der Zeilennummerneinträge für den Abschnitt.
8
4
Prüfsumme
Die Prüfsumme für kommunale Daten. Sie ist anwendbar, wenn das Flag IMAGE_SCN_LNK_COMDAT im Abschnittskopf gesetzt ist. Weitere Informationen finden Sie im Abschnitt COMDAT (nur Objekt).
12
2
Nummer
Einseitiger Index in der Abschnittstabelle für den zugehörigen Abschnitt. Dies wird verwendet, wenn die COMDAT-Auswahl auf 5 eingestellt ist.
14
1
Auswahl
Die COMDAT-Auswahlnummer. Dies gilt, wenn der Abschnitt ein COMDAT-Abschnitt ist.
15
3
Unbenutzt

 

COMDAT-Abschnitte (nur Objekt)

Das Feld Auswahl des Hilfsformats für die Abschnittsdefinition ist anwendbar, wenn der Abschnitt ein COMDAT-Abschnitt ist. Ein COMDAT-Abschnitt ist ein Abschnitt, der von mehr als einer Objektdatei definiert werden kann. (Das Flag IMAGE_SCN_LNK_COMDAT ist im Feld „Section Flags“ des Abschnittskopfes gesetzt) Das Feld Auswahl bestimmt die Art und Weise, wie der Linker die Mehrfachdefinitionen von COMDAT-Abschnitten auflöst.

Das erste Symbol, das den Abschnittswert des COMDAT-Abschnitts hat, muss das Abschnittssymbol sein. Dieses Symbol enthält den Namen des Abschnitts, das Feld Wert gleich Null, die Abschnittsnummer des betreffenden COMDAT-Abschnitts, das Feld Typ gleich IMAGE_SYM_TYPE_NULL, das Feld Klasse gleich IMAGE_SYM_CLASS_STATIC und einen Hilfssatz. Das zweite Symbol wird als „COMDAT-Symbol“ bezeichnet und wird vom Linker in Verbindung mit dem Auswahlfeld verwendet.

Die Werte für das Feld Auswahl sind unten aufgeführt.

Konstante Wert Beschreibung
IMAGE_COMDAT_SELECT_NODUPLICATES
1
Wenn dieses Symbol bereits definiert ist, gibt der Linker einen „multiply defined symbol“-Fehler aus.
IMAGE_COMDAT_SELECT_ANY
2
Jeder Abschnitt, der das gleiche COMDAT-Symbol definiert, kann verknüpft werden; die übrigen werden entfernt.
IMAGE_COMDAT_SELECT_SAME_SIZE
3
Der Linker wählt eine beliebige Sektion aus den Definitionen für dieses Symbol aus. Wenn nicht alle Definitionen die gleiche Größe haben, wird der Fehler „multiply defined symbol“ ausgegeben.
IMAGE_COMDAT_SELECT_EXACT_MATCH
4
Der Linker wählt eine beliebige Sektion aus den Definitionen für dieses Symbol aus. Wenn nicht alle Definitionen genau übereinstimmen, wird ein Fehler „mehrfach definiertes Symbol“ ausgegeben.
IMAGE_COMDAT_SELECT_ASSOCIATIVE
5
Der Abschnitt wird verknüpft, wenn ein bestimmter anderer COMDAT-Abschnitt verknüpft ist. Dieser andere Abschnitt wird durch das Feld Nummer des Hilfssymbolsatzes für die Abschnittsdefinition angegeben. Diese Einstellung ist nützlich für Definitionen, die Komponenten in mehreren Abschnitten haben (z. B. Code in einem und Daten in einem anderen), die aber alle miteinander verknüpft oder als Gruppe verworfen werden müssen. Der andere Abschnitt, mit dem dieser Abschnitt verbunden ist, muss ein COMDAT-Abschnitt sein, der ein anderer assoziativer COMDAT-Abschnitt sein kann. Die Abschnittsassoziationskette eines assoziativen COMDAT-Abschnitts kann keine Schleife bilden. Die Kette der Abschnittszuordnung muss schließlich zu einem COMDAT-Abschnitt führen, für den nicht IMAGE_COMDAT_SELECT_ASSOCIATIVE gesetzt ist.
IMAGE_COMDAT_SELECT_LARGEST
6
Der Linker wählt die größte Definition aus allen Definitionen für dieses Symbol aus. Wenn mehrere Definitionen diese Größe haben, ist die Wahl zwischen ihnen willkürlich.

 

CLR-Token-Definition (nur Objekt)

Dieses Hilfssymbol folgt im Allgemeinen auf das Symbol IMAGE_SYM_CLASS_CLR_TOKEN. Es wird verwendet, um ein Token mit dem Namensraum der COFF-Symboltabelle zu verknüpfen.

Abstand Größe Feld Beschreibung
0
1
bAuxType
Muss IMAGE_AUX_SYMBOL_TYPE_TOKEN_DEF (1) sein.
1
1
bReserved
Reserviert, muss Null sein.
2
4
SymbolTableIndex
Der Symbolindex des COFF-Symbols, auf das sich diese CLR-Token-Definition bezieht.
6
12
Reserviert, muss Null sein.

 

COFF-Zeichenfolgentabelle

Unmittelbar nach der COFF-Symboltabelle folgt die COFF-Stringtabelle. Die Position dieser Tabelle wird ermittelt, indem man die Adresse der Symboltabelle im COFF-Header nimmt und die Anzahl der Symbole multipliziert mit der Größe eines Symbols addiert.

Am Anfang der COFF-Stringtabelle stehen 4 Bytes, die die Gesamtgröße (in Bytes) der restlichen Stringtabelle enthalten. Diese Größe schließt das Größenfeld selbst ein, sodass der Wert an dieser Stelle 4 wäre, wenn keine Strings vorhanden wären.

Nach der Größe folgen nullterminierte Strings, auf die Symbole in der COFF-Symboltabelle verweisen.

Die Attribut-Zertifikat-Tabelle (nur Image)

Attributzertifikate können mit einem Image verknüpft werden, indem eine Attributzertifikatstabelle hinzugefügt wird. Die Attributzertifikatstabelle besteht aus einer Reihe von zusammenhängenden, vierfach ausgerichteten Attributzertifikatseinträgen. Um diese Ausrichtung zu erreichen, wird zwischen dem ursprünglichen Ende der Datei und dem Beginn der Tabelle der Attributzertifikate ein Null-Padding eingefügt. Jeder Eintrag für ein Attribut-Zertifikat enthält die folgenden Felder.

Abstand Größe Feld Beschreibung
0
4
dwLength
Gibt die Länge des Eintrags für das Attributzertifikat an.
4
2
wRevision
Enthält die Versionsnummer des Zertifikats. Weitere Informationen finden Sie im folgenden Text.
6
2
wCertificateType
Gibt den Typ des Inhalts in bCertificate an. Weitere Informationen finden Sie im folgenden Text.
8
Finden Sie hier
bCertificate
Enthält ein Zertifikat, z. B. eine Authenticode-Signatur. Weitere Informationen finden Sie im folgenden Text.

 

Der Wert der virtuellen Adresse aus dem Eintrag in der Zertifikatstabelle im Verzeichnis der optionalen Kopfdaten ist ein Dateioffset zum ersten Attributzertifikatseintrag. Auf nachfolgende Einträge wird zugegriffen, indem die dwLength-Bytes des jeweiligen Eintrags, aufgerundet auf ein 8-Byte-Vielfaches, vom Beginn des aktuellen Attributzertifikatseintrags an weitergeschaltet werden. Dies wird so lange fortgesetzt, bis die Summe der gerundeten dwLength-Werte dem Size-Wert aus dem Eintrag in der Zertifikattabelle im Verzeichnis der optionalen Kopfdaten entspricht. Wenn die Summe der gerundeten dwLength-Werte nicht dem Size-Wert entspricht, dann ist entweder die Attribut-Zertifikatstabelle oder das Size-Feld beschädigt.

Wenn z. B. der Zertifikatstabelleneintrag des Verzeichnisses der optionalen Kopfdaten Folgendes enthält:

virtual address = 0x5000
size = 0x1000

Das erste Zertifikat beginnt am Offset 0x5000 vom Anfang der Datei auf der Festplatte. Um alle Einträge für Attribut-Zertifikate zu durchlaufen:

  1. Addieren Sie den dwLength-Wert des ersten Attributzertifikats zum Startoffset.
  2. Runden Sie den Wert aus Schritt 1 auf das nächstgelegene 8-Byte-Vielfache auf, um den Offset des zweiten Attributzertifikatseintrags zu ermitteln.
  3. Addieren Sie den Offset-Wert aus Schritt 2 zum dwLength-Wert des zweiten Attributzertifikatseintrags und runden Sie auf das nächste 8-Byte-Vielfache auf, um den Offset des dritten Attributzertifikatseintrags zu ermitteln.
  4. Wiederholen Sie Schritt 3 für jedes weitere Zertifikat, bis der berechnete Offset 0x6000 (0x5000 Start + 0x1000 Gesamtgröße) beträgt, was bedeutet, dass Sie die gesamte Tabelle durchlaufen haben.

Alternativ können Sie die Zertifikatseinträge aufzählen, indem Sie die Funktion Win32 ImageEnumerateCertificates in einer Schleife aufrufen. Einen Link zur Referenzseite der Funktion finden Sie unter Referenzen.

Attribut-Zertifikatstabelleneinträge können jeden Zertifikatstyp enthalten, solange der Eintrag den richtigen dwLength-Wert, einen eindeutigen wRevision-Wert und einen eindeutigen wCertificateType-Wert hat. Der gebräuchlichste Typ eines Zertifikatstabelleneintrags ist eine WIN_CERTIFICATE-Struktur, die in Wintrust.h dokumentiert ist und im weiteren Verlauf dieses Abschnitts behandelt wird.

Die Optionen für das Element WIN_CERTIFICATE wRevision umfassen (sind aber nicht auf) folgende.

Wert Name Notizen
0x0100
WIN_CERT_REVISION_1_0
Version 1, ältere Version der Win_Certificate-Struktur. Sie wird nur für die Überprüfung von Authenticode-Signaturen unterstützt
0x0200
WIN_CERT_REVISION_2_0
Version 2 ist die aktuelle Version der Win_Certificate-Struktur.

 

Die Optionen für das Element WIN_CERTIFICATE wCertificateType umfassen (sind aber nicht beschränkt auf) die in der folgenden Tabelle aufgeführten Elemente. Beachten Sie, dass einige Werte derzeit nicht unterstützt werden.

Wert Name Notizen
0x0001
WIN_CERT_TYPE_X509
bCertificate enthält ein X.509-Zertifikat
Nicht unterstützt
0x0002
WIN_CERT_TYPE_PKCS_SIGNED_DATA
bCertificate enthält eine PKCS#7 SignedData-Struktur
0x0003
WIN_CERT_TYPE_RESERVED_1
Reserviert
0x0004
WIN_CERT_TYPE_TS_STACK_SIGNED
Terminal Server Protocol Stack Zertifikatssignierung
Nicht unterstützt

 

Das Element bCertificate der Struktur WIN_CERTIFICATE enthält ein Byte-Array variabler Länge mit dem durch wCertificateType angegebenen Inhaltstyp. Der von Authenticode unterstützte Typ ist WIN_CERT_TYPE_PKCS_SIGNED_DATA, eine PKCS#7 SignedData-Struktur. Einzelheiten zum digitalen Authenticode-Signaturformat finden Sie unter Windows Authenticode Portable Executable Signature Format.

Wenn der Inhalt von bCertificate nicht auf einer Quadword-Grenze endet, wird der Eintrag für das Attribut „Zertifikat“ vom Ende von bCertificate bis zur nächsten Quadword-Grenze mit Nullen aufgefüllt.

Der Wert dwLength ist die Länge der fertiggestellten WIN_CERTIFICATE-Struktur und wird wie folgt berechnet:

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

Diese Länge sollte die Größe aller Auffüllungen einschließen, die verwendet werden, um die Anforderung zu erfüllen, dass jede WIN_CERTIFICATE-Struktur quadword-aligned ist:

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

Die Größe der Zertifikatstabelle – angegeben im Eintrag Zertifikatstabelle in den Optionalen Kopfdatenverzeichnissen (nur Image) – schließt die Füllung ein.

Weitere Informationen zur Verwendung der ImageHlp-API zum Aufzählen, Hinzufügen und Entfernen von Zertifikaten aus PE-Dateien finden Sie unter ImageHlp-Funktionen.

Zertifikat Daten

Wie im vorangegangenen Abschnitt erwähnt, können die Zertifikate in der Attribut-Zertifikatstabelle jeden Zertifikatstyp enthalten. Zertifikate, die die Integrität einer PE-Datei gewährleisten, können einen PE-Image-Hash enthalten.

Ein PE-Image-Hash (oder Datei-Hash) ähnelt einer Dateiprüfsumme, da der Hash-Algorithmus einen Message Digest erzeugt, der sich auf die Integrität einer Datei bezieht. Eine Prüfsumme wird jedoch durch einen einfachen Algorithmus erzeugt und dient in erster Linie dazu, festzustellen, ob ein Speicherblock auf der Festplatte fehlerhaft ist und die dort gespeicherten Werte korrumpiert wurden. Ein Datei-Hash ähnelt einer Prüfsumme, da er auch die Beschädigung von Dateien erkennt. Im Gegensatz zu den meisten Prüfsummenalgorithmen ist es jedoch sehr schwierig, eine Datei zu verändern, ohne dass der Hashwert der Datei von seinem ursprünglichen, unveränderten Wert abweicht. Ein Datei-Hash kann daher verwendet werden, um absichtliche und sogar subtile Änderungen an einer Datei zu erkennen, wie z. B. solche, die von Viren, Hackern oder Trojaner-Programmen vorgenommen wurden.

Wenn der Image Digest in ein Zertifikat aufgenommen wird, muss er bestimmte Felder im PE-Image ausschließen, z. B. die Prüfsumme und den Eintrag für die Zertifikatstabelle in den optionalen Kopfdatenverzeichnissen. Dies liegt daran, dass sich diese Felder durch das Hinzufügen eines Zertifikats ändern und ein anderer Hash-Wert berechnet wird.

Die Funktion Win32 ImageGetDigestStream liefert einen Datenstrom aus einer PE-Zieldatei, mit dem Hash-Funktionen ausgeführt werden können. Dieser Datenstrom bleibt konsistent, wenn Zertifikate zu einer PE-Datei hinzugefügt oder aus ihr entfernt werden. Basierend auf den Parametern, die an ImageGetDigestStream übergeben werden, können andere Daten aus dem PE-Image bei der Hash-Berechnung ausgelassen werden. Einen Link zur Referenzseite der Funktion finden Sie unter Referenzen.

Delay-Load-Importtabellen (nur Image)

Diese Tabellen wurden dem Image hinzugefügt, um einen einheitlichen Mechanismus für Anwendungen zu unterstützen, der das Laden einer DLL bis zum ersten Aufruf dieser DLL verzögert. Das Layout der Tabellen entspricht dem der traditionellen Importtabellen, die in Abschnitt 6.4 beschrieben werden, The .idata Section. Hier wird nur auf einige wenige Details eingegangen.

Die Delay-Load-Verzeichnis-Tabelle

Die Delay-Load-Verzeichnistabelle ist das Gegenstück zur Import-Verzeichnistabelle. Er kann über den Eintrag „Delay Import Descriptor“ in der Liste der optionalen Kopfdatenverzeichnisse (Offset 200) abgerufen werden. Die Tabelle ist wie folgt aufgebaut:

Abstand Größe Feld Beschreibung
0
4
Attribute
Muss Null sein.
4
4
Name
Die RVA des Namens der zu ladenden DLL. Der Name befindet sich im schreibgeschützten Datenbereich des Images.
8
4
Modul-Griff
Die RVA des Modulhandles (im Datenteil des Images) der DLL, die verzögert geladen werden soll. Es wird von der Routine, die für die Verwaltung des Delay-Loading vorgesehen ist, zur Speicherung verwendet.
12
4
Verzögerung Import Adresstabelle
Die RVA der Delay-Load-Import-Adresstabelle. Weitere Informationen finden Sie unter Delay Import Address Table (IAT).
16
4
Delay Import Name Table
Die RVA der Delay-Load-Namenstabelle, die die Namen der Importe enthält, die möglicherweise geladen werden müssen. Dies entspricht dem Layout der Tabelle der Importnamen. Weitere Informationen finden Sie unter Hint/Name Table.
20
4
Bound-Delay-Importtabelle
Die RVA der Tabelle der gebundenen Verzögerungslastadressen, falls vorhanden.
24
4
Unload-Delay-Importtabelle
Die RVA der Tabelle der Entladeverzögerungsadressen, falls vorhanden. Es handelt sich um eine exakte Kopie der Adressentabelle für den Delay-Import. Wenn der Aufrufer die DLL entlädt, sollte diese Tabelle über die Delay-Import-Adresstabelle zurückkopiert werden, damit nachfolgende Aufrufe der DLL den Thunking-Mechanismus weiterhin korrekt verwenden.
28
4
Zeitstempel
Der Zeitstempel der DLL, an die dieses Image gebunden wurde.

 

Die Tabellen, auf die in dieser Datenstruktur verwiesen wird, sind genauso organisiert und sortiert wie ihre Gegenstücke bei traditionellen Importen. Einzelheiten finden Sie im Abschnitt .idata.

Attribute

Bisher sind noch keine Attributflags definiert. Der Linker setzt dieses Feld im Image auf Null. Dieses Feld kann verwendet werden, um den Datensatz zu erweitern, indem das Vorhandensein neuer Felder angegeben wird, oder es kann verwendet werden, um Verhaltensweisen für die Hilfsfunktionen zum Verzögern oder Entladen anzugeben.

Name

Der Name der DLL, die mit Verzögerung geladen werden soll, befindet sich im schreibgeschützten Datenbereich des Images. Es wird über das Feld szName referenziert.

Modul-Griff

Das Handle der DLL, die mit Verzögerung geladen werden soll, befindet sich im Datenteil des Images. Das Feld phmod zeigt auf das Handle. Der mitgelieferte Delay-Load-Helfer verwendet diesen Ort, um das Handle zur geladenen DLL zu speichern.

Verzögerung Import Adresstabelle

Die Delay-Import-Adresstabelle (IAT) wird vom Delay-Import-Deskriptor über das Feld pIAT referenziert. Der Delay-Load-Helfer aktualisiert diese Zeiger mit den tatsächlichen Einstiegspunkten, sodass sich die Thunks nicht mehr in der Aufrufschleife befinden. Auf die Funktionszeiger wird mit dem Ausdruck pINT->u1.Function zugegriffen.

Delay Import Name Table

Die Delay Import Name Table (INT) enthält die Namen der Importe, die möglicherweise geladen werden müssen. Sie sind in der gleichen Weise angeordnet wie die Funktionszeiger im IAT. Sie bestehen aus denselben Strukturen wie das Standard-INT und werden mit dem Ausdruck pINT->u1.AddressOfData->Name[0] angesprochen.

Verzögerungsgebundener Import von Adresstabelle und Zeitstempel

Die Delay-Bound-Import-Adresstabelle (BIAT) ist eine optionale Tabelle mit IMAGE_THUNK_DATA-Elementen, die zusammen mit dem Zeitstempelfeld der Delay-Load-Verzeichnistabelle in einer Post-Process-Bindungsphase verwendet wird.

Entladen verzögern Adresstabelle importieren

Die Delay-Unload-Import-Adresstabelle (UIAT) ist eine optionale Tabelle mit IMAGE_THUNK_DATA-Elementen, die der Entladecode zur Bearbeitung einer expliziten Entladeanforderung verwendet. Sie besteht aus initialisierten Daten im schreibgeschützten Bereich, die eine exakte Kopie der ursprünglichen IAT sind, die den Code auf die Delay-Load Thunks verwiesen hat. Bei der Entladeanforderung kann die Bibliothek freigegeben, die *phmod gelöscht und die UIAT über die IAT geschrieben werden, um alles in den Zustand vor dem Laden zurückzusetzen.

Besondere Abschnitte

Typische COFF-Abschnitte enthalten Code oder Daten, die Linker und Microsoft Win32-Lader ohne besondere Kenntnisse des Abschnittsinhalts verarbeiten. Der Inhalt ist nur für die Anwendung relevant, die verknüpft oder ausgeführt wird.

Einige COFF-Abschnitte haben jedoch besondere Bedeutungen, wenn sie in Objekt- oder Imagedateien vorkommen. Tools und Lader erkennen diese Abschnitte, weil sie spezielle Flags im Abschnittskopf gesetzt haben, weil spezielle Stellen im optionalen Header des Images auf sie verweisen oder weil der Abschnittsname selbst auf eine spezielle Funktion des Abschnitts hinweist. (Auch wenn der Abschnittsname selbst nicht auf eine besondere Funktion des Abschnitts hinweist, ist der Abschnittsname durch Konvention vorgegeben, sodass sich die Autoren dieser Spezifikation in jedem Fall auf einen Abschnittsnamen beziehen können)

Die reservierten Abschnitte und ihre Attribute werden in der folgenden Tabelle beschrieben, gefolgt von detaillierten Beschreibungen für die Abschnittstypen, die in ausführbaren Dateien persistiert werden, und die Abschnittstypen, die Metadaten für Erweiterungen enthalten.

Abschnittsname Inhalt Merkmale
.bss
Uninitialisierte Daten (freies Format)
IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
.cormeta
CLR-Metadaten, die anzeigen, dass die Objektdatei verwalteten Code enthält
IMAGE_SCN_LNK_INFO
.daten
Initialisierte Daten (freies Format)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
.debug$F
Generierte FPO-Debug-Informationen (nur Objekt, nur x86-Architektur, und jetzt veraltet)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
.debug$P
Vorkompilierte Debug-Typen (nur Objekt)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
.debug$S
Debugsymbole (nur Objekt)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
.debug$T
Debug-Typen (nur Objekt)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
.drective
Linker-Optionen
IMAGE_SCN_LNK_INFO
.edata
Tabellen exportieren
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
.idata
Tabellen importieren
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
.idlsym
Enthält registrierte SEH (nur Image) zur Unterstützung von IDL-Attributen. Weitere Informationen finden Sie unter „IDL-Attribute“ in Referenzen am Ende dieses Themas.
IMAGE_SCN_LNK_INFO
.pdata
Informationen zu Ausnahmen
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
.rdata
Nur lesbare initialisierte Daten
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
.reloc
Bildverschiebungen
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE
.rsrc
Ressourcenverzeichnis
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
.sbss
GP-relative uninitialisierte Daten (freies Format)
IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE _SCN_GPREL Das Flag IMAGE_SCN_GPREL sollte nur für IA64-Architekturen gesetzt werden; für andere Architekturen ist dieses Flag nicht gültig. Das Flag IMAGE_SCN_GPREL gilt nur für Objektdateien; wenn dieser Abschnittstyp in einer Imagedatei erscheint, darf das Flag IMAGE_SCN_GPREL nicht gesetzt werden.
.sdata
GP-relative initialisierte Daten (freies Format)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE _SCN_GPREL Das Flag IMAGE_SCN_GPREL sollte nur für IA64-Architekturen gesetzt werden; dieses Flag ist für andere Architekturen nicht gültig. Das Flag IMAGE_SCN_GPREL gilt nur für Objektdateien; wenn dieser Abschnittstyp in einer Imagedatei erscheint, darf das Flag IMAGE_SCN_GPREL nicht gesetzt werden.
.srdata
GP-relative Nur-Lese-Daten (freies Format)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE _SCN_GPREL Das Flag IMAGE_SCN_GPREL sollte nur für IA64-Architekturen gesetzt werden; für andere Architekturen ist dieses Flag nicht gültig. Das Flag IMAGE_SCN_GPREL gilt nur für Objektdateien; wenn dieser Abschnittstyp in einer Imagedatei erscheint, darf das Flag IMAGE_SCN_GPREL nicht gesetzt werden.
.sxdata
Registrierte Exception-Handler-Daten (freies Format und nur x86/Objekt)
IMAGE_SCN_LNK_INFO Enthält den Symbolindex jedes der Ausnahmebehandlungsprogramme, auf die der Code in dieser Objektdatei verweist. Das Symbol kann für ein UNDEF-Symbol oder ein Symbol stehen, das in diesem Modul definiert ist.
.text
Ausführbarer Code (freies Format)
IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IIMAGE_SCN_MEM_READ
.tls
Thread-lokale Speicherung (nur Objekt)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
.tls$
Thread-lokale Speicherung (nur Objekt)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
.vsdata
GP-relative initialisierte Daten (freies Format und nur für ARM-, SH4- und Thumb-Architekturen)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
.xdata
Informationen zu Ausnahmen (freies Format)
IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ

 

Einige der hier aufgeführten Abschnitte sind mit „nur Objekt“ oder „nur Image“ gekennzeichnet, um anzuzeigen, dass ihre spezielle Semantik nur für Objektdateien bzw. Imagedateien relevant ist. Ein Abschnitt, der mit „image only“ gekennzeichnet ist, kann in einer Objektdatei immer noch erscheinen, um in die Imagedatei zu gelangen, aber der Abschnitt hat keine besondere Bedeutung für den Linker, sondern nur für den Lader der Imagedatei.

Der Abschnitt .debug

Der Abschnitt .debug wird in Objektdateien verwendet, um vom Compiler erzeugte Debug-Informationen zu enthalten, und in Imagedateien, um alle erzeugten Debug-Informationen zu enthalten. Dieser Abschnitt beschreibt die Verpackung von Debug-Informationen in Objekt- und Image-Dateien.

Der nächste Abschnitt beschreibt das Format des Debug-Verzeichnisses, das an einer beliebigen Stelle im Image liegen kann. In den folgenden Abschnitten werden die „Gruppen“ in Objektdateien beschrieben, die Debug-Informationen enthalten.

Die Voreinstellung für den Linker ist, dass Debug-Informationen nicht in den Adressraum des Images eingeblendet werden. Ein .debug-Abschnitt existiert nur, wenn Debug-Informationen im Adressraum abgebildet werden.

Debug-Verzeichnis (nur Image)

Image-Dateien enthalten ein optionales Debug-Verzeichnis, das angibt, welche Form von Debug-Informationen vorhanden ist und wo sie sich befinden. Dieses Verzeichnis besteht aus einem Array von Debug-Verzeichniseinträgen, deren Position und Größe im optionalen Header des Images angegeben sind.

Das Debug-Verzeichnis kann sich in einem zu verwerfenden .debug-Abschnitt befinden (falls vorhanden), oder es kann in einem beliebigen anderen Abschnitt der Imagedatei enthalten sein, oder es kann sich überhaupt nicht in einem Abschnitt befinden.

Jeder Eintrag im Debug-Verzeichnis identifiziert den Ort und die Größe eines Blocks von Debug-Informationen. Der angegebene RVA kann Null sein, wenn die Debug-Informationen nicht durch einen Sektions-Header abgedeckt sind (d.h. sie befinden sich in der Image-Datei und sind nicht im Laufzeit-Adressraum abgebildet). Wenn sie zugeordnet ist, ist die RVA ihre Adresse.

Ein Eintrag im Debug-Verzeichnis hat das folgende Format:

Abstand Größe Feld Beschreibung
0
4
Merkmale
Reserviert, muss Null sein.
4
4
TimeDateStamp
Die Uhrzeit und das Datum, zu dem die Debug-Daten erstellt wurden.
8
2
MajorVersion
Die Hauptversionsnummer des Debug-Datenformats.
10
2
MinorVersion
Die Minor-Versionsnummer des Debug-Datenformats.
12
4
Typ
Das Format der Debugging-Informationen. Dieses Feld ermöglicht die Unterstützung von mehreren Debuggern. Weitere Informationen finden Sie unter Debug-Typ.
16
4
SizeOfData
Die Größe der Debug-Daten (ohne das Debug-Verzeichnis selbst).
20
4
AddressOfRawData
Die Adresse der Debug-Daten, wenn sie geladen werden, bezogen auf die Bildbasis.
24
4
PointerToRawData
Der Dateizeiger auf die Debug-Daten.

 

Debug-Typ

Die folgenden Werte sind für das Feld Typ des Debug-Verzeichniseintrags definiert:

Konstante Wert Beschreibung
IMAGE_DEBUG_TYPE_UNKNOWN
0
Ein unbekannter Wert, der von allen Tools ignoriert wird.
IMAGE_DEBUG_TYPE_COFF
1
Die COFF-Debuginformationen (Zeilennummern, Symboltabelle und Zeichenfolgentabelle). Auf diese Art von Debuginformationen wird auch von Feldern in Dateiheadern verwiesen.
IMAGE_DEBUG_TYPE_CODEVIEW
2
Die Debug-Informationen von Visual C++.
IMAGE_DEBUG_TYPE_FPO
3
Die Frame Pointer Omission (FPO)-Informationen. Diese Informationen teilen dem Debugger mit, wie er nicht standardmäßige Stack-Frames interpretieren soll, die das EBP-Register für einen anderen Zweck als einen Frame-Pointer verwenden.
IMAGE_DEBUG_TYPE_MISC
4
Der Speicherort der DBG-Datei.
IMAGE_DEBUG_TYPE_EXCEPTION
5
Eine Kopie des .pdata-Abschnitts.
IMAGE_DEBUG_TYPE_FIXUP
6
Reserviert.
IMAGE_DEBUG_TYPE_OMAP_TO_SRC
7
Die Zuordnung von einem RVA im Image zu einem RVA im Quellbild.
IMAGE_DEBUG_TYPE_OMAP_FROM_SRC
8
Die Zuordnung von einer RVA im Quellbild zu einer RVA im Image.
IMAGE_DEBUG_TYPE_BORLAND
9
Reserviert für Borland.
IMAGE_DEBUG_TYPE_RESERVED10
10
Reserviert.
IMAGE_DEBUG_TYPE_CLSID
11
Reserviert.
IMAGE_DEBUG_TYPE_REPRO
16
PE-Determinismus oder Reproduzierbarkeit.
Nicht definiert
17
Die Debugging-Informationen werden in die PE-Datei an der durch PointerToRawData angegebenen Stelle eingebettet.
Nicht definiert
19
Speichert den Krypto-Hash für den Inhalt der Symboldatei, die zur Erstellung der PE/COFF-Datei verwendet wird.
IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS 20 Bits der erweiterten DLL-Eigenschaften.

 

Wenn das Feld Typ auf IMAGE_DEBUG_TYPE_FPO gesetzt ist, sind die Debug-Rohdaten ein Array, in dem jedes Element den Stack-Frame einer Funktion beschreibt. Nicht für jede Funktion in der Imagedatei müssen FPO-Informationen definiert sein, auch wenn der Debug-Typ FPO ist. Bei Funktionen, die keine FPO-Informationen haben, wird davon ausgegangen, dass sie normale Stackframes haben. Das Format für die Postfachinformationen ist wie folgt:

#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;

Das Vorhandensein eines Eintrags des Typs IMAGE_DEBUG_TYPE_REPRO zeigt an, dass die PE-Datei so aufgebaut ist, dass Determinismus oder Reproduzierbarkeit erreicht wird. Wenn sich die Eingabe nicht ändert, ist die PE-Ausgabedatei garantiert Bit für Bit identisch, unabhängig davon, wann und wo die PE-Datei erstellt wird. Verschiedene Datums-/Zeitstempelfelder in der PE-Datei werden mit einem Teil oder allen Bits eines berechneten Hash-Wertes gefüllt, der den Inhalt der PE-Datei als Eingabe verwendet, und stellen daher nicht mehr das tatsächliche Datum und die tatsächliche Uhrzeit dar, zu der eine PE-Datei oder damit verbundene spezifische Daten innerhalb der PE-Datei erzeugt werden. Die Rohdaten dieses Debug-Eintrags können leer sein oder einen berechneten Hash-Wert enthalten, dem ein Vier-Byte-Wert vorangestellt ist, der die Hash-Wert-Länge angibt.

Wenn das Feld Type auf IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS gesetzt ist, enthalten die Debug-Rohdaten erweiterte DLL-Charakteristik-Bits, zusätzlich zu denen, die im optionalen Header des Images gesetzt werden können. Siehe DLL-Merkmale im Abschnitt Optionale Kopfzeilen Windows-spezifische Felder (nur Image).

Erweiterte DLL-Merkmale

Die folgenden Werte sind für die Bits der erweiterten DLL-Eigenschaften definiert.

Konstante Wert Beschreibung
IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT 0x0001 Das Image ist mit der Control-flow Enforcement Technology (CET) Shadow Stack kompatibel.
IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT 0x0040 Alle Verzweigungsziele in allen Abschnitten des Bildcodes sind mit Anweisungen zur Sicherung der Kontrollflussintegrität versehen, wie z. B. x86 CET-Indirect Branch Tracking (IBT) oder ARM Branch Target Identification (BTI) Anweisungen. Dieses Bit wird von Windows nicht verwendet.

.debug$F (nur Objekt)

Die Daten in diesem Abschnitt wurden in Visual C++ Version 7.0 und später durch einen umfangreicheren Satz von Daten ersetzt, die in einem .debug$S-Unterabschnitt ausgegeben werden.

Objektdateien können .debug$F-Abschnitte enthalten, deren Inhalt ein oder mehrere FPO_DATA-Datensätze (Frame Pointer Omission Information) sind. Siehe „IMAGE_DEBUG_TYPE_FPO“ in Debug-Typ.

Der Linker erkennt diese .debug$F-Datensätze. Wenn Debug-Informationen erzeugt werden, sortiert der Linker die FPO_DATA-Datensätze nach der Prozedur RVA und erzeugt einen Debug-Verzeichniseintrag für sie.

Der Compiler sollte keine FPO-Datensätze für Prozeduren erzeugen, die ein Standard-Frame-Format haben.

.debug$S (nur Objekt)

Dieser Abschnitt enthält Visual C++-Debug-Informationen (symbolische Informationen).

.debug$P (nur Objekt)

Dieser Abschnitt enthält Visual C++-Debug-Informationen (vorkompilierte Informationen). Diese Typen werden von allen Objekten gemeinsam genutzt, die mit Hilfe des vorkompilierten Headers kompiliert wurden, der mit diesem Objekt erzeugt wurde.

.debug$T (nur Objekt)

Dieser Abschnitt enthält Visual C++-Debug-Informationen (Typinformationen).

Linker-Unterstützung für Microsoft-Debug-Informationen

Um Debug-Informationen zu unterstützen, muss der Linker:

  • Sammelt alle relevanten Debug-Daten aus den Abschnitten .debug$F, debug$S, .debug$P und .debug$T.

  • Verarbeitet diese Daten zusammen mit den vom Linker generierten Debugging-Informationen in der PDB-Datei und erstellt einen Debug-Verzeichniseintrag, um darauf zu verweisen.

Der Abschnitt .drectve (nur Objekt)

Ein Abschnitt ist ein Richtlinienabschnitt, wenn das Flag IMAGE_SCN_LNK_INFO im Abschnittskopf gesetzt ist und der Abschnittsname .drectve lautet. Der Linker entfernt einen .drectve-Abschnitt nach der Verarbeitung der Informationen, sodass der Abschnitt nicht in der Imagedatei erscheint, die verlinkt wird.

Ein .drectve-Abschnitt besteht aus einer Textkette, die als ANSI oder UTF-8 kodiert sein kann. Wenn die UTF-8-Byte-Order-Markierung (BOM, ein Drei-Byte-Präfix, das aus 0xEF, 0xBB und 0xBF besteht) nicht vorhanden ist, wird die Richtlinienzeichenfolge als ANSI interpretiert. Der Direktiven-String ist eine Reihe von Linker-Optionen, die durch Leerzeichen getrennt sind. Jede Option enthält einen Bindestrich, den Optionsnamen und ein entsprechendes Attribut. Wenn eine Option Leerzeichen enthält, muss die Option in Anführungszeichen gesetzt werden. Der Abschnitt .drectve darf keine Versetzungen oder Zeilennummern enthalten.

Der .edata-Abschnitt (nur Image)

Der Abschnitt mit den Exportdaten, genannt .edata, enthält Informationen über Symbole, auf die andere Bilder durch dynamische Verknüpfung zugreifen können. Exportierte Symbole befinden sich im Allgemeinen in DLLs, aber auch DLLs können Symbole importieren.

Im Folgenden wird ein Überblick über die allgemeine Struktur des Exportbereichs gegeben. Die beschriebenen Tabellen sind in der Regel in der angegebenen Reihenfolge in der Datei enthalten (dies ist jedoch nicht erforderlich). Für den Export von Symbolen als Ordnungszahlen sind nur die Export-Verzeichnistabelle und die Export-Adresstabelle erforderlich. (Eine Ordnungszahl ist ein Export, auf den direkt über den Index seiner Exportadresstabelle zugegriffen wird) Die Namenszeigertabelle, die Ordinaltabelle und die Exportnamens-Tabelle sind alle vorhanden, um die Verwendung von Exportnamen zu unterstützen.

Tabellenname Beschreibung
Verzeichnis-Tabelle exportieren
Eine Tabelle mit nur einer Zeile (im Gegensatz zum Debug-Verzeichnis). In dieser Tabelle sind die Positionen und Größen der anderen Exporttabellen angegeben.
Adresstabelle exportieren
Ein Array von RVAs der exportierten Symbole. Dies sind die tatsächlichen Adressen der exportierten Funktionen und Daten innerhalb des ausführbaren Codes und der Datenabschnitte. Andere Imagedateien können ein Symbol importieren, indem sie einen Index dieser Tabelle (eine Ordnungszahl) verwenden oder optional den öffentlichen Namen verwenden, der der Ordnungszahl entspricht, wenn ein öffentlicher Name definiert ist.
Namenszeiger-Tabelle
Ein Array von Zeigern auf die öffentlichen Exportnamen, in aufsteigender Reihenfolge sortiert.
Ordinaltabelle
Ein Array mit den Ordnungszahlen, die den Elementen der Namenszeigertabelle entsprechen. Die Entsprechung erfolgt nach Position; daher müssen die Namenszeigertabelle und die Ordinaltabelle die gleiche Anzahl von Elementen haben. Jede Ordnungszahl ist ein Index in der Exportadresstabelle.
Namenstabelle exportieren
Eine Reihe von ASCII-Strings mit Nullen als Abschluss. Die Elemente der Namenszeigertabelle zeigen auf diesen Bereich. Diese Namen sind die öffentlichen Namen, über die die Symbole importiert und exportiert werden; sie sind nicht unbedingt identisch mit den privaten Namen, die in der Imagedatei verwendet werden.

 

Wenn eine andere Imagedatei ein Symbol nach Namen importiert, sucht der Win32-Lader in der Namenszeigertabelle nach einem passenden String. Wird ein übereinstimmender String gefunden, wird die zugehörige Ordnungszahl durch Nachschlagen des entsprechenden Elements in der Ordinaltabelle ermittelt (d. h. das Element der Ordinaltabelle mit demselben Index wie der in der Namenszeigertabelle gefundene Stringszeiger). Die sich daraus ergebende Ordnungszahl ist ein Index in der Exportadresstabelle, der die tatsächliche Position des gewünschten Symbols angibt. Jedes Exportsymbol kann über eine Ordnungszahl erreicht werden.

Wenn eine andere Imagedatei ein Symbol nach der Ordnungszahl importiert, ist es nicht notwendig, die Namenszeigertabelle nach einem passenden String zu durchsuchen. Die direkte Verwendung einer Ordnungszahl ist daher effizienter. Ein Exportname ist jedoch leichter zu merken und erfordert nicht, dass der Benutzer den Tabellenindex für das Symbol kennt.

Verzeichnis-Tabelle exportieren

Die Exportsymbolinformationen beginnen mit der Exportverzeichnistabelle, die den Rest der Exportsymbolinformationen beschreibt. Die Exportverzeichnistabelle enthält Adressinformationen, die verwendet werden, um Importe zu den Einstiegspunkten innerhalb dieses Images aufzulösen.

Abstand Größe Feld Beschreibung
0
4
Flags exportieren
Reserviert, muss 0 sein.
4
4
Zeit-/Datumsstempel
Die Uhrzeit und das Datum, zu dem die Exportdaten erstellt wurden.
8
2
Hauptversion
Die Hauptversionsnummer. Die Haupt- und Nebenversionsnummern können vom Benutzer festgelegt werden.
10
2
Nebenversion
Die Nebenversionsnummer.
12
4
Name RVA
Die Adresse des ASCII-Strings, der den Namen der DLL enthält. Diese Adresse ist relativ zur Bildbasis.
16
4
Ordinale Basis
Die Anfangsordnungsnummer für die Exporte in diesem Image. Dieses Feld gibt die erste Ordnungszahl für die Exportadresstabelle an. Normalerweise ist er auf 1 eingestellt.
20
4
Einträge in der Adresstabelle
Die Anzahl der Einträge in der Exportadresstabelle.
24
4
Anzahl von Namenszeigern
Die Anzahl der Einträge in der Namenszeigertabelle. Dies ist auch die Anzahl der Einträge in der Ordinaltabelle.
28
4
Adresstabelle RVA exportieren
Die Adresse der Exportadresstabelle, bezogen auf die Bildbasis.
32
4
Name Zeiger RVA
Die Adresse der Exportname-Zeigertabelle, bezogen auf die Bildbasis. Die Tabellengröße wird durch das Feld Number of Name Pointers angegeben.
36
4
Ordinaltabelle RVA
Die Adresse der Ordinaltabelle, bezogen auf die Bildbasis.

 

Adresstabelle exportieren

Die Exportadresstabelle enthält die Adressen der exportierten Einstiegspunkte und der exportierten Daten und Absolutwerte. Eine Ordnungszahl wird als Index für die Exportadresstabelle verwendet.

Jeder Eintrag in der Exportadresstabelle ist ein Feld, das eines der beiden Formate in der folgenden Tabelle verwendet. Liegt die angegebene Adresse nicht innerhalb des Exportabschnitts (wie durch die im optionalen Header angegebene Adresse und Länge definiert), handelt es sich bei dem Feld um ein Export-RVA, also eine tatsächliche Adresse in Code oder Daten. Andernfalls ist das Feld ein Forwarder-RVA, das ein Symbol in einer anderen DLL benennt.

Abstand Größe Feld Beschreibung
0
4
Export RVA
Die Adresse des exportierten Symbols, wenn es in den Speicher geladen wird, bezogen auf die Bildbasis. Zum Beispiel die Adresse einer exportierten Funktion.
0
4
Forwarder-RVA
Der Zeiger zu einem nullterminierten ASCII-String im Exportbereich. Diese String muss innerhalb des Bereichs liegen, der durch den Eintrag im Datenverzeichnis der Exporttabelle vorgegeben ist. Siehe Optionale Kopfdatenverzeichnisse (nur Image). Dieser String enthält den DLL-Namen und den Namen des Exports (z. B. „MYDLL.expfunc“) oder den DLL-Namen und die Ordnungsnummer des Exports (z. B. „MYDLL.#27“).

 

Ein Forwarder-RVA exportiert eine Definition aus einem anderen Image, sodass es so aussieht, als würde sie vom aktuellen Image exportiert werden. Das Symbol wird also gleichzeitig importiert und exportiert.

Beispielsweise wird in Kernel32.dll unter Windows XP der Export namens „HeapAlloc“ an die String „NTDLL.RtlAllocateHeap“ weitergeleitet Dies ermöglicht es Anwendungen, das Windows XP-spezifische Modul Ntdll.dll zu verwenden, ohne tatsächlich Importverweise darauf zu enthalten. Die Importtabelle der Anwendung verweist nur auf die Datei Kernel32.dll. Daher ist die Anwendung nicht spezifisch für Windows XP und kann auf jedem Win32-System ausgeführt werden.

Exportname Zeigertabelle

Die Exportnamen-Zeigertabelle ist ein Array von Adressen (RVAs) in der Exportnamen-Tabelle. Die Zeiger haben jeweils 32 Bit und sind relativ zur Bildbasis. Die Zeiger sind lexikalisch geordnet, um eine binäre Suche zu ermöglichen.

Ein Exportname ist nur dann definiert, wenn die Tabelle der Exportnamenzeiger einen Zeiger darauf enthält.

Ordinaltabelle exportieren

Die Export-Ordinaltabelle ist ein Array von 16-Bit-unbiased-Indizes in der Export-Adresstabelle. Die Ordnungszahlen werden durch das Feld Ordnungszahl-Basis der Exportverzeichnis-Tabelle beeinflusst. Mit anderen Worten, die Ordinalbasis muss von den Ordinalzahlen subtrahiert werden, um echte Indizes in der Exportadresstabelle zu erhalten.

Die Zeigertabelle für den Exportnamen und die Ordinaltabelle für den Export bilden zwei parallele Felder, die getrennt sind, um eine natürliche Ausrichtung der Felder zu ermöglichen. Diese beiden Tabellen funktionieren als eine Tabelle, in der die Spalte Export Name Pointer auf einen öffentlichen (exportierten) Namen verweist und die Spalte Export Ordinal die entsprechende Ordnungszahl für diesen öffentlichen Namen angibt. Ein Element der Export-Namenszeigertabelle und ein Element der Export-Ordinaltabelle sind dadurch verbunden, dass sie dieselbe Position (Index) in ihren jeweiligen Arrays haben.

Wenn also die Zeigertabelle für Exportnamen durchsucht wird und an der Position i ein übereinstimmender String gefunden wird, lautet der Algorithmus zur Ermittlung der RVA und der verzerrten Ordnungszahl des Symbols:

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

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

Bei der Suche nach einem Symbol nach (voreingenommener) Ordnungszahl lautet der Algorithmus zum Auffinden des RVA und des Namens des Symbols:

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

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

Namenstabelle exportieren

Die Exportnamens-Tabelle enthält die tatsächlichen String-Daten, auf die die Exportnamens-Zeigertabelle verweist. Die Strings in dieser Tabelle sind öffentliche Namen, die andere Bilder zum Importieren der Symbole verwenden können. Diese öffentlichen Exportnamen müssen nicht unbedingt mit den privaten Symbolnamen übereinstimmen, die die Symbole in ihrer eigenen Imagedatei und ihrem Quellcode haben, obwohl sie es sein können.

Jedes exportierte Symbol hat einen Ordinalwert, der lediglich den Index in der Exportadresstabelle darstellt. Die Verwendung von Exportnamen ist jedoch fakultativ. Einige, alle oder keine der exportierten Symbole können Exportnamen haben. Für exportierte Symbole, die Exportnamen haben, arbeiten die entsprechenden Einträge in der Exportnamenszeigertabelle und der Exportordinaltabelle zusammen, um jeden Namen mit einer Ordnungszahl zu verknüpfen.

Die Struktur der Exportnamens-Tabelle besteht aus einer Reihe von ASCII-Strings variabler Länge mit Null-Endung.

Der Abschnitt .idata

Alle Imagedateien, die Symbole importieren, einschließlich praktisch aller ausführbaren Dateien (EXE), haben einen .idata-Abschnitt. Es folgt ein typisches Dateilayout für die Importinformationen:

  • Verzeichnis Tabelle

    Null-Verzeichniseintrag

  • DLL1 Import Lookup Table

    Null

  • DLL2 Import Lookup Table

    Null

  • DLL3 Import Lookup Table

    Null

  • Hint-Name-Tabelle

Verzeichnis-Tabelle importieren

Die Importinformationen beginnen mit der Tabelle des Importverzeichnisses, in der der Rest der Importinformationen beschrieben wird. Die Importverzeichnistabelle enthält Adressinformationen, die zur Auflösung von Fixup-Referenzen auf die Einstiegspunkte innerhalb eines DLL-Images verwendet werden. Die Importverzeichnis-Tabelle besteht aus einem Array von Importverzeichnis-Einträgen, einem Eintrag für jede DLL, auf die das Image verweist. Der letzte Verzeichniseintrag ist leer (mit Nullwerten gefüllt), was das Ende der Verzeichnistabelle anzeigt.

Jeder Eintrag im Importverzeichnis hat das folgende Format:

Abstand Größe Feld Beschreibung
0
4
Import Lookup-Tabelle RVA (Merkmale)
Der RVA der Import-Lookup-Tabelle. Diese Tabelle enthält einen Namen oder eine Ordnungszahl für jeden Import. (Der Name „Characteristics“ wird in Winnt.h verwendet, beschreibt dieses Feld aber nicht mehr)
4
4
Zeit-/Datumsstempel
Der Stempel, der auf Null gesetzt wird, bis das Image gebunden ist. Nachdem das Image gebunden wurde, wird dieses Feld auf den Zeit-/Datenstempel der DLL gesetzt.
8
4
Forwarder-Chain
Der Index der ersten Forwarder-Referenz.
12
4
Name RVA
Die Adresse eine ASCII-Strings, der den Namen der DLL enthält. Diese Adresse ist relativ zur Bildbasis.
16
4
Adresstabelle RVA importieren (Thunk-Tabelle)
Die RVA der Importadresstabelle. Der Inhalt dieser Tabelle ist identisch mit dem Inhalt der Import-Lookup-Tabelle, bis das Image gebunden ist.

 

Lookup-Tabelle importieren

Eine Import-Lookup-Tabelle ist ein Array von 32-Bit-Zahlen für PE32 oder ein Array von 64-Bit-Zahlen für PE32+. Jeder Eintrag verwendet das in der folgenden Tabelle beschriebene Bitfeldformat. In diesem Format ist Bit 31 das höchstwertige Bit für PE32 und Bit 63 ist das höchstwertige Bit für PE32+. Die Sammlung dieser Einträge beschreibt alle Importe aus einer bestimmten DLL. Der letzte Eintrag wird auf Null (NULL) gesetzt, um das Ende der Tabelle anzuzeigen.

Bit(s) Größe Bitfeld Beschreibung
31/63
1
Ordnungszahl/Name-Flag
Wenn dieses Bit gesetzt ist, wird nach Ordnungszahl importiert. Andernfalls importieren Sie nach Namen. Bit ist maskiert als 0x80000000 für PE32, 0x8000000000000000 für PE32+.
15-0
16
Ordnungszahl
Eine 16-Bit-Ordnungszahl. Dieses Feld wird nur verwendet, wenn das Bitfeld Ordinal/Name Flag 1 ist (Import nach Ordinal). Die Bits 30-15 oder 62-15 müssen 0 sein.
30-0
31
Hinweis/Name Tabelle RVA
Ein 31-Bit-RVA eines Hinweis/Namen-Tabelleneintrags. Dieses Feld wird nur verwendet, wenn das Bitfeld Ordinal/Name Flag 0 ist (Import nach Name). Bei PE32+ müssen die Bits 62-31 Null sein.

 

Hinweis/Namenstabelle

Eine Hinweis-/Namenstabelle reicht für den gesamten Importbereich aus. Jeder Eintrag in der Hinweis/Namen-Tabelle hat das folgende Format:

Abstand Größe Feld Beschreibung
0
2
Hinweis
Ein Index in der Exportnamen-Zeigertabelle. Bei diesem Wert wird zuerst versucht, einen Treffer zu erzielen. Schlägt dies fehl, wird eine binäre Suche in der Exportname-Zeigertabelle der DLL durchgeführt.
2
variabel
Name
Ein ASCII-String, der den zu importierenden Namen enthält. Dies ist der String, der mit dem öffentlichen Namen in der DLL übereinstimmen muss. Bei diesem String wird zwischen Groß- und Kleinschreibung unterschieden und sie wird mit einem Null-Byte abgeschlossen.
*
0 oder 1
Pad
Ein abschließendes Null-Byte, das nach dem abschließenden Null-Byte erscheint, falls erforderlich, um den nächsten Eintrag an einer geraden Grenze auszurichten.

 

Adresstabelle importieren

Struktur und Inhalt der Import-Adresstabelle sind identisch mit denen der Import-Lookup-Tabelle, bis die Datei gebunden wird. Beim Binden werden die Einträge in der Importadresstabelle mit den 32-Bit (für PE32) oder 64-Bit (für PE32+) Adressen der zu importierenden Symbole überschrieben. Diese Adressen sind die tatsächlichen Speicheradressen der Symbole, obwohl sie technisch gesehen immer noch als „virtuelle Adressen“ bezeichnet werden Der Lader verarbeitet in der Regel die Bindung.

Der Abschnitt .pdata

Der Abschnitt .pdata enthält ein Array von Funktionstabelleneinträgen, die für die Ausnahmebehandlung verwendet werden. Darauf verweist der Eintrag in der Ausnahmetabelle im Bilddatenverzeichnis. Die Einträge müssen nach den Funktionsadressen (das erste Feld in jeder Struktur) sortiert werden, bevor sie in das endgültige Image übertragen werden. Die Zielplattform bestimmt, welche der drei unten beschriebenen Varianten des Formats für Funktionstabelleneinträge verwendet wird.

Bei 32-Bit-MIPS-Images haben die Funktionstabelleneinträge das folgende Format:

Abstand Größe Feld Beschreibung
0
4
Beginn der Adresse
Die VA der entsprechenden Funktion.
4
4
Endadresse
Die VA des Endes der Funktion.
8
4
Ausnahme-Handler
Der Zeiger auf den auszuführenden Exception-Handler.
12
4
Handler-Daten
Der Zeiger auf zusätzliche Informationen, die an den Handler zu übergeben sind.
16
4
Prolog-Endadresse
Die VA des Endes des Prologs der Funktion.

 

Für die ARM-, PowerPC-, SH3- und SH4-Windows-CE-Plattformen haben die Funktionstabelleneinträge das folgende Format:

Abstand Größe Feld Beschreibung
0
4
Beginn der Adresse
Die VA der entsprechenden Funktion.
4
8 Bit
Prolog Länge
Die Anzahl der Anweisungen im Prolog der Funktion.
4
22 Bit
Funktion Länge
Die Anzahl der Anweisungen in der Funktion.
4
1 Bit
32-Bit-Flag
Falls gesetzt, besteht die Funktion aus 32-Bit-Anweisungen. Ist diese Option deaktiviert, besteht die Funktion aus 16-Bit-Befehlen.
4
1 Bit
Ausnahme-Flag
Wenn gesetzt, existiert ein Exception-Handler für die Funktion. Andernfalls ist kein Exception-Handler vorhanden.

 

Für x64- und Itanium-Plattformen haben die Funktionstabelleneinträge das folgende Format:

Abstand Größe Feld Beschreibung
0
4
Beginn der Adresse
Die RVA der entsprechenden Funktion.
4
4
Endadresse
Die RVA des Endes der Funktion.
8
4
Informationen zum Entspannen
Der RVA der Abwicklungsinformationen.

 

Der .reloc-Bereich (nur Image)

Die Basisverschiebungstabelle enthält Einträge für alle Basisverschiebungen im Image. Das Feld Base Relocation Table in den optionalen Kopfdatenverzeichnissen gibt die Anzahl der Bytes in der Base Relocation Table an. Weitere Informationen finden Sie unter Optionale Kopfdatenverzeichnisse (nur Image). Die Basis-Umzugstabelle ist in Blöcke unterteilt. Jeder Block stellt die Basisverschiebungen für eine 4K-Seite dar. Jeder Block muss an einer 32-Bit-Grenze beginnen.

Der Lader muss keine vom Linker aufgelösten Basisverschiebungen verarbeiten, es sei denn, das Ladebild kann nicht mit der im PE-Header angegebenen Bildbasis geladen werden.

Basisverlagerungsblock

Jeder Base-Relocation-Block beginnt mit der folgenden Struktur:

Abstand Größe Feld Beschreibung
0
4
Seiten-RVA
Die Bildbasis plus die Seiten-RVA wird zu jedem Offset addiert, um den VA zu erstellen, auf den die Basisverschiebung angewendet werden muss.
4
4
Blockgröße
Die Gesamtzahl der Bytes im Base-Relocation-Block, einschließlich der Felder Page RVA und Block Size sowie der nachfolgenden Felder Type/Offset.

 

Auf das Feld Blockgröße folgt eine beliebige Anzahl von Einträgen im Feld Typ oder Offset. Jeder Eintrag ist ein WORD (2 Bytes) und hat die folgende Struktur:

Abstand Größe Feld Beschreibung
0
4 Bit
Typ
Ein in den oberen 4 Bits des WORD gespeicherter Wert, der die Art der Basisverschiebung angibt, die angewendet werden soll. Weitere Informationen finden Sie unter Basisverlagerungsarten.
0
12 Bit
Abstand
In den verbleibenden 12 Bits des WORDs wird ein Offset von der Startadresse gespeichert, die im Feld Page RVA für den Block angegeben wurde. Dieser Offset gibt an, wo die Basisverschiebung durchgeführt werden soll.

 

Um eine Basisverschiebung vorzunehmen, wird die Differenz zwischen der bevorzugten Basisadresse und der Basis, an der das Image tatsächlich geladen ist, berechnet. Wenn das Image mit seiner bevorzugten Basis geladen wird, ist die Differenz gleich Null und die Basisverschiebungen müssen nicht durchgeführt werden.

Basisverlagerungsarten

Konstante Wert Beschreibung
IMAGE_REL_BASED_ABSOLUTE
0
Die Basisverlagerung wird übersprungen. Dieser Typ kann verwendet werden, um einen Block aufzufüllen.
IMAGE_REL_BASED_HIGH
1
Die Basisverschiebung addiert die hohen 16 Bits der Differenz zu dem 16-Bit-Feld am Offset. Das 16-Bit-Feld stellt den Höchstwert eines 32-Bit-Wortes dar.
IMAGE_REL_BASED_LOW
2
Die Basisverschiebung addiert die niedrigen 16 Bits der Differenz zu dem 16-Bit-Feld am Offset. Das 16-Bit-Feld stellt die untere Hälfte eines 32-Bit-Wortes dar.
IMAGE_REL_BASED_HIGHLOW
3
Die Basisverschiebung wendet alle 32 Bits der Differenz auf das 32-Bit-Feld am Offset an.
IMAGE_REL_BASED_HIGHADJ
4
Die Basisverschiebung addiert die hohen 16 Bits der Differenz zu dem 16-Bit-Feld am Offset. Das 16-Bit-Feld stellt den Höchstwert eines 32-Bit-Wortes dar. Die unteren 16 Bits des 32-Bit-Wertes werden in dem 16-Bit-Wort gespeichert, das auf diese Basisverschiebung folgt. Das bedeutet, dass diese Basisverlagerung zwei Steckplätze belegt.
IMAGE_REL_BASED_MIPS_JMPADDR
5
Die Interpretation der Verschiebung ist abhängig vom Maschinentyp.
Wenn der Maschinentyp MIPS ist, gilt die Basisverschiebung für eine MIPS-Sprunganweisung.
IMAGE_REL_BASED_ARM_MOV32
5
Diese Verschiebung ist nur sinnvoll, wenn der Maschinentyp ARM oder Thumb ist. Die Basisverschiebung wendet die 32-Bit-Adresse eines Symbols auf ein aufeinanderfolgendes MOVW/MOVT-Befehlspaar an.
IMAGE_REL_BASED_RISCV_HIGH20
5
Diese Verschiebung ist nur sinnvoll, wenn der Maschinentyp RISC-V ist. Die Basisverschiebung gilt für die oberen 20 Bits einer 32-Bit-Absolutadresse.
6
Reserviert, muss Null sein.
IMAGE_REL_BASED_THUMB_MOV32
7
Diese Verschiebung ist nur sinnvoll, wenn der Maschinentyp Thumb ist. Die Basisverschiebung wendet die 32-Bit-Adresse eines Symbols auf ein aufeinanderfolgendes MOVW/MOVT-Befehlspaar an.
IMAGE_REL_BASED_RISCV_LOW12I
7
Diese Verschiebung ist nur sinnvoll, wenn der Maschinentyp RISC-V ist. Die Basisverschiebung gilt für die niedrigen 12 Bits einer 32-Bit-Absolutadresse, die im RISC-V-Befehlsformat vom Typ I gebildet wird.
IMAGE_REL_BASED_RISCV_LOW12S
8
Diese Verschiebung ist nur sinnvoll, wenn der Maschinentyp RISC-V ist. Die Basisverschiebung gilt für die niedrigen 12 Bits einer 32-Bit-Absolutadresse, die im RISC-V-S-Befehlsformat gebildet wird.
IMAGE_REL_BASED_LOONGARCH32_MARK_LA
8
Diese Verschiebung ist nur sinnvoll, wenn der Maschinentyp LoongArch 32-bit ist. Die Basisverschiebung gilt für eine 32-Bit-Absolutadresse, die in zwei aufeinanderfolgenden Befehlen gebildet wird.
IMAGE_REL_BASED_LOONGARCH64_MARK_LA
8
Diese Verschiebung ist nur sinnvoll, wenn der Maschinentyp LoongArch 64-bit ist. Die Basisverschiebung gilt für eine 64-Bit-Absolutadresse, die in vier aufeinanderfolgenden Anweisungen gebildet wird.
IMAGE_REL_BASED_MIPS_JMPADDR16
9
Die Verschiebung ist nur sinnvoll, wenn der Maschinentyp MIPS ist. Die Basisverschiebung gilt für einen MIPS16-Sprungbefehl.
IMAGE_REL_BASED_DIR64
10
Die Basisverschiebung wendet die Differenz auf das 64-Bit-Feld am Offset an.

 

Der .tls-Abschnitt

Der Abschnitt .tls bietet direkte PE- und COFF-Unterstützung für statischen lokalen Thread-Speicher (TLS). TLS ist eine spezielle von Windows unterstützte Speicherklasse, bei der ein Datenobjekt keine automatische (Stack-)Variable ist, sondern für jeden einzelnen Thread, der den Code ausführt, lokal ist. So kann jeder Thread einen anderen Wert für eine mit TLS deklarierte Variable erhalten.

Beachten Sie, dass mit den API-Aufrufen TlsAlloc, TlsFree, TlsSetValue und TlsGetValue jede beliebige Menge an TLS-Daten unterstützt werden kann. Die PE- oder COFF-Implementierung ist ein alternativer Ansatz zur Verwendung der API und hat den Vorteil, dass sie aus Sicht des Programmierers einer Hochsprache einfacher ist. Diese Implementierung ermöglicht die Definition und Initialisierung von TLS-Daten ähnlich wie bei gewöhnlichen statischen Variablen in einem Programm. In Visual C++ kann zum Beispiel eine statische TLS-Variable wie folgt definiert werden, ohne die Windows-API zu verwenden:

__declspec (thread) int tlsFlag = 1;

Um dieses Programmierkonstrukt zu unterstützen, spezifiziert der PE- und COFF-.tls-Abschnitt die folgenden Informationen: Initialisierungsdaten, Callback-Routinen für die Initialisierung und Beendigung pro Thread und den TLS-Index, die im Folgenden erläutert werden.

Hinweis

Vor Windows Vista können statisch deklarierte TLS-Datenobjekte nur in statisch geladenen Imagedateien verwendet werden. Diese Tatsache macht es unzuverlässig, statische TLS-Daten in einer DLL zu verwenden, es sei denn, Sie wissen, dass die DLL oder alles, was statisch mit ihr verknüpft ist, niemals dynamisch mit der LoadLibrary-API-Funktion geladen wird. Ab Windows Vista wurden jedoch Verbesserungen am Windows-Lader vorgenommen, um das dynamische Laden von DLLs mit statischem TLS besser zu unterstützen. Diese Änderung bedeutet, dass DLLs mit statisch deklarierten TLS-Datenobjekten nun zuverlässiger verwendet werden können, auch wenn sie dynamisch mit LoadLibrary geladen werden. Der Lader ist in der Lage, TLS-Slots für solche DLLs zum Zeitpunkt des Ladens zuzuweisen, wodurch die Einschränkungen in früheren Windows-Versionen gemildert werden.

 

Hinweis

Verweise auf 32-Bit-Offsets und Indexmultiplikatoren von 4 gelten für Systeme mit 32-Bit-Architekturen. In einem System, das auf 64-Bit-Architekturen basiert, passen Sie sie nach Bedarf an.

Ausführbarer Code greift über die folgenden Schritte auf ein statisches TLS-Datenobjekt zu:

  1. Zur Linkzeit setzt der Linker das Feld Address of Index des TLS-Verzeichnisses. Dieses Feld verweist auf einen Ort, an dem das Programm den TLS-Index erwartet.

    Die Microsoft-Laufzeitbibliothek erleichtert diesen Prozess, indem sie ein Speicherabbild des TLS-Verzeichnisses definiert und ihm den speziellen Namen „__tls_used“ (Intel x86-Plattformen) oder „_tls_used“ (andere Plattformen) gibt. Der Linker sucht nach diesem Speicherabbild und verwendet die dortigen Daten, um das TLS-Verzeichnis zu erstellen. Andere Compiler, die TLS unterstützen und mit dem Microsoft Linker arbeiten, müssen diese Technik ebenfalls anwenden.

  2. Wenn ein Thread erstellt wird, teilt der Lader die Adresse des TLS-Arrays des Threads mit, indem er die Adresse des Thread Environment Blocks (TEB) in das FS-Register einträgt. Ein Zeiger auf das TLS-Array befindet sich am Offset 0x2C vom Anfang von TEB. Dieses Verhalten ist Intel x86-spezifisch.

  3. Der Lader weist den Wert des TLS-Indexes der Stelle zu, die durch das Feld Adresse des Indexes angegeben wurde.

  4. Der ausführbare Code ruft den TLS-Index und auch den Ort des TLS-Arrays ab.

  5. Der Code verwendet den TLS-Index und die Position des TLS-Arrays (indem er den Index mit 4 multipliziert und als Offset zum Array verwendet), um die Adresse des TLS-Datenbereichs für das jeweilige Programm und Modul zu ermitteln. Jeder Thread hat seinen eigenen TLS-Datenbereich, aber dies ist für das Programm transparent, das nicht wissen muss, wie die Daten für die einzelnen Threads zugewiesen werden.

  6. Der Zugriff auf ein einzelnes TLS-Datenobjekt erfolgt über einen festen Offset im TLS-Datenbereich.

Das TLS-Array ist ein Array von Adressen, das das System für jeden Thread verwaltet. Jede Adresse in diesem Array gibt die Position der TLS-Daten für ein bestimmtes Modul (EXE oder DLL) innerhalb des Programms an. Der TLS-Index gibt an, welches Element des Arrays zu verwenden ist. Der Index ist eine (nur für das System aussagekräftige) Nummer, die das Modul identifiziert.

Das TLS-Verzeichnis

Das TLS-Verzeichnis hat das folgende Format:

Offset (PE32/ PE32+) Größe (PE32/ PE32+) Feld Beschreibung
0
4/8
Rohdaten Start VA
Die Startadresse der TLS-Vorlage. Die Vorlage ist ein Datenblock, der zur Initialisierung von TLS-Daten verwendet wird. Das System kopiert alle diese Daten jedes Mal, wenn ein Thread erstellt wird, sodass sie nicht beschädigt werden dürfen. Beachten Sie, dass es sich bei dieser Adresse nicht um eine RVA handelt, sondern um eine Adresse, für die eine Basisverschiebung im Abschnitt .reloc vorgesehen ist.
4/8
4/8
Rohdaten Ende VA
Die Adresse des letzten Bytes des TLS, mit Ausnahme der Nullfüllung. Wie beim Feld Rohdaten Start VA handelt es sich um einen VA, nicht um einen RVA.
8/16
4/8
Adresse des Index
Der Ort, an dem der TLS-Index empfangen wird, den der Loader zuweist. Dieser Speicherort befindet sich in einem gewöhnlichen Datenbereich und kann daher mit einem symbolischen Namen versehen werden, der dem Programm zugänglich ist.
12/24
4/8
Adresse der Rückrufe
Der Zeiger auf ein Array von TLS-Callback-Funktionen. Das Array ist nullterminiert, wenn also keine Callback-Funktion unterstützt wird, zeigt dieses Feld auf 4 auf Null gesetzte Bytes. Informationen über den Prototyp für diese Funktionen finden Sie unter TLS Callback Functions.
16/32
4
Größe der Nullfüllung
Die Größe der Vorlage in Bytes, die über die initialisierten Daten hinausgeht, die durch die Felder Raw Data Start VA und Raw Data End VA begrenzt sind. Die Gesamtgröße der Vorlage sollte mit der Gesamtgröße der TLS-Daten in der Imagedatei übereinstimmen. Die Nullfüllung ist die Datenmenge, die nach den initialisierten Nicht-Null-Daten kommt.
20/36
4
Merkmale
Die vier Bits [23:20] beschreiben die Ausrichtungsinformationen. Mögliche Werte sind die als IMAGE_SCN_ALIGN_* definierten, die auch zur Beschreibung der Ausrichtung von Abschnitten in Objektdateien verwendet werden. Die übrigen 28 Bits sind für die zukünftige Verwendung reserviert.

 

TLS-Rückruf-Funktionen

Das Programm kann eine oder mehrere TLS-Callback-Funktionen bereitstellen, um zusätzliche Initialisierung und Beendigung für TLS-Datenobjekte zu unterstützen. Eine typische Verwendung für eine solche Callback-Funktion wäre der Aufruf von Konstruktoren und Destruktoren für Objekte.

Obwohl es in der Regel nicht mehr als eine Callback-Funktion gibt, wird ein Callback als Array implementiert, um bei Bedarf weitere Callback-Funktionen hinzufügen zu können. Wenn es mehr als eine Callback-Funktion gibt, wird jede Funktion in der Reihenfolge aufgerufen, in der ihre Adresse im Array erscheint. Ein Null-Zeiger beendet das Array. Es ist durchaus möglich, eine leere Liste zu haben (kein Rückruf unterstützt), in diesem Fall hat das Rückruf-Array genau ein Element - einen Null-Zeiger.

Der Prototyp für eine Callback-Funktion (auf den ein Zeiger vom Typ PIMAGE_TLS_CALLBACK zeigt) hat die gleichen Parameter wie eine DLL-Einstiegsfunktion:

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

Der Parameter Reserviert sollte auf Null gesetzt werden. Der Parameter Reason kann die folgenden Werte annehmen:

Einstellung Wert Beschreibung
DLL_PROCESS_ATTACH
1
Ein neuer Prozess hat begonnen, einschließlich des ersten Threads.
DLL_THREAD_ATTACH
2
Es wurde ein neues Thema erstellt. Diese Meldung wurde für alle Themen außer dem ersten gesendet.
DLL_THREAD_DETACH
3
Ein Thema steht kurz vor der Beendigung. Diese Meldung wurde für alle Themen außer dem ersten gesendet.
DLL_PROCESS_DETACH
0
Ein Prozess steht kurz vor der Beendigung, einschließlich des ursprünglichen Threads.

 

Die Struktur der Ladekonfiguration (nur Image)

Die Ladekonfigurationsstruktur (IMAGE_LOAD_CONFIG_DIRECTORY) wurde früher in sehr begrenzten Fällen im Windows NT-Betriebssystem selbst verwendet, um verschiedene Merkmale zu beschreiben, die zu schwierig oder zu umfangreich waren, um sie im Dateiheader oder im optionalen Kopf des Images zu beschreiben. Aktuelle Versionen des Microsoft Linkers und Windows XP und spätere Versionen von Windows verwenden eine neue Version dieser Struktur für 32-Bit-x86-basierte Systeme, die die reservierte SEH-Technologie enthalten. Hier finden Sie eine Liste der sicheren strukturierten Ausnahmebehandlungsprogramme, die das Betriebssystem bei der Verteilung von Ausnahmen verwendet. Wenn die Adresse des Handlers im VA-Bereich eines Images liegt und als reserviert und SEH-fähig gekennzeichnet ist (d.h. IMAGE_DLLCHARACTERISTICS_NO_SEH ist im Feld DllCharacteristics des optionalen Headers leer, wie zuvor beschrieben), dann muss der Handler in der Liste der bekannten sicheren Handler für dieses Image enthalten sein. Andernfalls bricht das Betriebssystem die Anwendung ab. Dies hilft, den Exploit „x86 exception handler hijacking“ zu verhindern, der in der Vergangenheit verwendet wurde, um die Kontrolle über das Betriebssystem zu übernehmen.

Der Microsoft Linker stellt automatisch eine Standard-Ladekonfigurationsstruktur bereit, die die reservierten SEH-Daten enthält. Wenn der Anwendercode bereits eine Ladekonfigurationsstruktur bereitstellt, muss er die neuen reservierten SEH-Felder enthalten. Andernfalls kann der Linker die reservierten SEH-Daten nicht einbinden und das Image wird nicht als reservierte SEH-Daten enthaltend gekennzeichnet.

Konfigurationsverzeichnis laden

Der Datenverzeichniseintrag für eine vorreservierte SEH-Ladekonfigurationsstruktur muss eine bestimmte Größe der Ladekonfigurationsstruktur angeben, da der Betriebssystemlader immer einen bestimmten Wert erwartet. In dieser Hinsicht ist die Größe wirklich nur eine Versionskontrolle. Um die Kompatibilität mit Windows XP und früheren Versionen von Windows zu gewährleisten, muss die Größe bei x86-Images 64 betragen.

Konfiguration laden Layout

Die Struktur der Ladekonfiguration ist für 32-Bit- und 64-Bit-PE-Dateien wie folgt aufgebaut:

Abstand Größe Feld Beschreibung
0
4
Merkmale
Flags, die Attribute der Datei angeben, derzeit unbenutzt.
4
4
TimeDateStamp
Wert des Datums- und Zeitstempels. Der Wert wird in der Anzahl der Sekunden angegeben, die seit Mitternacht (00:00:00), 1. Januar 1970, koordinierte Weltzeit, gemäß der Systemuhr verstrichen sind. Der Zeitstempel kann mit der Zeitfunktion der C-Laufzeit (CRT) ausgedruckt werden.
8
2
MajorVersion
Nummer der Hauptversion.
10
2
MinorVersion
MinorVersion-Nummer.
12
4
GlobalFlagsClear
Die globalen Loader-Flags, die für diesen Prozess zu löschen sind, wenn der Loader den Prozess startet.
16
4
GlobalFlagsSet
Die globalen Loader-Flags, die für diesen Prozess gesetzt werden sollen, wenn der Loader den Prozess startet.
20
4
CriticalSectionDefaultTimeout
Der Standard-Timeout-Wert, der für die kritischen Abschnitte dieses Prozesses, die abgebrochen werden, verwendet werden soll.
24
4/8
DeCommitFreeBlockThreshold
Speicher, der freigegeben werden muss, bevor er an das System zurückgegeben wird, in Bytes.
28/32
4/8
DeCommitTotalFreeThreshold
Gesamtmenge des freien Speichers in Bytes.
32/40
4/8
LockPrefixTable
[nur x86] Die VA einer Liste von Adressen, bei denen das LOCK-Präfix verwendet wird, sodass sie auf Einzelprozessormaschinen durch NOP ersetzt werden können.
36/48
4/8
MaximumAllocationSize
Maximale Zuweisungsgröße in Bytes.
40/56
4/8
VirtualMemoryThreshold
Maximale Größe des virtuellen Speichers, in Bytes.
44/64
4/8
ProcessAffinityMask
Das Setzen dieses Feldes auf einen Wert ungleich Null ist gleichbedeutend mit dem Aufruf von SetProcessAffinityMask mit diesem Wert während des Prozessstarts (.exe only)
48/72
4
ProcessHeapFlags
Prozess-Heap-Flags, die dem ersten Argument der Funktion HeapCreate entsprechen. Diese Flags gelten für den Prozess-Heap, der während des Prozessstarts angelegt wird.
52/76
2
CSDVersion
Die Kennung der Service Pack-Version.
54/78
2
Reserviert
Muss Null sein.
56/80
4/8
EditList
Reserviert für die Verwendung durch das System.
60/88
4/8
SecurityCookie
Ein Zeiger auf einen Cookie, der von Visual C++ oder der GS-Implementierung verwendet wird.
64/96
4/8
SEHandlerTable
[nur x86] Die VA der sortierten Tabelle der RVAs jedes gültigen, eindeutigen SE-Handlers im Image.
68/104
4/8
SEHandlerCount
[nur x86] Die Anzahl der eindeutigen Handler in der Tabelle.
72/112
4/8
GuardCFCheckFunctionPointer
Die VA, in der der Zeiger der Kontrollflusswächter-Prüffunktion gespeichert ist.
76/120
4/8
GuardCFDispatchFunctionPointer
Die VA, in der der Control Flow Guard Dispatch-Funktionszeiger gespeichert ist.
80/128
4/8
GuardCFFunctionTable
Die VA der sortierten Tabelle der RVAs jeder Control Flow Guard-Funktion im Image.
84/136
4/8
GuardCFFunctionCount
Die Anzahl der eindeutigen RVAs in der obigen Tabelle.
88/144
4
GuardFlags
Control Flow Guard-bezogene Flags.
92/148
12
CodeIntegrity
Informationen zur Code-Integrität.
104/160
4/8
GuardAddressTakenIatEntryTable
Die VA, in der die vom Control Flow Guard übernommene Adresse der IAT-Tabelle gespeichert ist.
108/168
4/8
GuardAddressTakenIatEntryCount
Die Anzahl der eindeutigen RVAs in der obigen Tabelle.
112/176
4/8
GuardLongJumpTargetTable
Die VA, in der die Control Flow Guard-Weitsprungzieltabelle gespeichert ist.
116/184
4/8
GuardLongJumpTargetCount
Die Anzahl der eindeutigen RVAs in der obigen Tabelle.

 

Das Feld GuardFlags enthält eine Kombination aus einem oder mehreren der folgenden Flags und Unterfelder:

  • Das Modul führt Kontrollflussintegritätsprüfungen mit Hilfe der vom System bereitgestellten Unterstützung durch.

    #define IMAGE_GUARD_CF_INSTRUMENTED 0x00000100

  • Das Modul führt Kontrollfluss- und Schreibintegritätsprüfungen durch.

    #define IMAGE_GUARD_CFW_INSTRUMENTED 0x00000200

  • Modul enthält gültige Kontrollflussziel-Metadaten.

    #define IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT 0x00000400

  • Das Modul verwendet das /GS-Sicherheits-Cookie nicht.

    #define IMAGE_GUARD_SECURITY_COOKIE_UNUSED 0x00000800

  • Das Modul unterstützt nur das Lesen der Verzögerungslast IAT.

    #define IMAGE_GUARD_PROTECT_DELAYLOAD_IAT 0x00001000

  • Delayload-Importtabelle in einem eigenen .didat-Abschnitt (mit nichts anderem darin), der frei wiedergeschützt werden kann.

    #define IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION 0x00002000

  • Das Modul enthält unterdrückte Exportinformationen. Daraus ergibt sich auch, dass die adressierte IAT-Tabelle auch in der Lastkonfiguration vorhanden ist.

    #define IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT 0x00004000

  • Das Modul ermöglicht die Unterdrückung von Exporten.

    #define IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION 0x00008000

  • Das Modul enthält longjmp-Zielinformationen.

    #define IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT 0x00010000

  • Maske für das Unterfeld, das die Schrittweite der Tabelleneinträge der Control Flow Guard-Funktion enthält (d. h. die zusätzliche Anzahl von Bytes pro Tabelleneintrag).

    #define IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK 0xF0000000

Zusätzlich definiert der Windows SDK winnt.h Header dieses Makro für die Anzahl der Bits, um den GuardFlags Wert nach rechts zu verschieben, um die Control Flow Guard Funktionstabelle rechtsbündig zu machen:

#define IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT 28

Der .rsrc-Abschnitt

Die Ressourcen werden durch eine mehrstufige, binär sortierte Baumstruktur indiziert. Der allgemeine Entwurf kann 2**31 Ebenen umfassen. Konventionell verwendet Windows jedoch drei Ebenen:

Typ Name Sprache

Eine Reihe von Tabellen mit Ressourcenverzeichnissen verbindet alle Ebenen auf folgende Weise miteinander: Auf jede Verzeichnistabelle folgt eine Reihe von Verzeichniseinträgen, die den Namen oder die Kennung (ID) für diese Ebene (Typ-, Namens- oder Sprachebene) und eine Adresse entweder einer Datenbeschreibung oder einer anderen Verzeichnistabelle enthalten. Zeigt die Adresse auf eine Datenbeschreibung, so sind die Daten ein Blatt in der Baumstruktur. Wenn die Adresse auf eine andere Verzeichnistabelle verweist, listet diese Tabelle Verzeichniseinträge auf der nächsttieferen Ebene auf.

Die IDs Typ, Name und Sprache eines Blattes werden durch den Pfad bestimmt, der durch die Verzeichnistabellen führt, um das Blatt zu erreichen. Die erste Tabelle bestimmt die Typ-ID, die zweite Tabelle (auf die der Verzeichniseintrag in der ersten Tabelle verweist) die Namens-ID und die dritte Tabelle die Sprach-ID.

Die allgemeine Struktur des .rsrc-Abschnitts ist wie folgt:

Daten Beschreibung
Ressourcenverzeichnis-Tabellen (und Ressourcenverzeichnis-Einträge)
Eine Reihe von Tabellen, eine für jede Gruppe von Knoten in der Baumstruktur. Alle Knoten der obersten Ebene (Typ) sind in der ersten Tabelle aufgeführt. Die Einträge in dieser Tabelle verweisen auf Tabellen der zweiten Ebene. Jeder Baum der zweiten Ebene hat die gleiche Typ-ID, aber unterschiedliche Namens-IDs. Bäume der dritten Ebene haben die gleichen Typ- und Namens-IDs, aber unterschiedliche Sprach-IDs.
Auf jede einzelne Tabelle folgen unmittelbar Verzeichniseinträge, in denen jeder Eintrag einen Namen oder eine numerische Kennung und einen Verweis auf eine Datenbeschreibung oder eine Tabelle auf der nächsttieferen Ebene hat.
Ressourcenverzeichnis Strings
Zwei-Byte-ausgerichtete Unicode-Strings, die als String-Daten dienen, auf die Verzeichniseinträge verweisen.
Ressourcendaten Beschreibung
Ein Array von Datensätzen, auf die Tabellen verweisen, die die tatsächliche Größe und den Speicherort der Ressourcendaten beschreiben. Diese Datensätze sind die Blätter des Ressourcenbeschreibungsbaums.
Ressourcen-Daten
Rohdaten des Ressourcenbereichs. Die Größen- und Ortsangaben im Feld Ressourcendatenbeschreibungen grenzen die einzelnen Regionen der Ressourcendaten ab.

 

Tabelle Ressourcenverzeichnis

Jede Ressourcenverzeichnis-Tabelle hat das folgende Format. Diese Datenstruktur sollte als Überschrift einer Tabelle betrachtet werden, da die Tabelle eigentlich aus Verzeichniseinträgen (beschrieben in Abschnitt 6.9.2, „Ressourcenverzeichniseinträge“) und dieser Struktur besteht:

Abstand Größe Feld Beschreibung
0
4
Merkmale
Ressourcenflags. Dieses Feld ist für die zukünftige Verwendung reserviert. Sie ist derzeit auf Null gesetzt.
4
4
Zeit-/Datumsstempel
Der Zeitpunkt, zu dem die Ressourcendaten vom Ressourcen-Compiler erstellt wurden.
8
2
Hauptversion
Die Hauptversionsnummer, die vom Benutzer festgelegt wird.
10
2
Nebenversion
Die Nummer der Nebenversion, die vom Benutzer festgelegt wird.
12
2
Anzahl der Namenseinträge
Die Anzahl der unmittelbar auf die Tabelle folgenden Verzeichniseinträge, die Strings zur Identifizierung von Typ-, Namens- oder Spracheinträgen verwenden (je nach Ebene der Tabelle).
14
2
Anzahl der ID-Einträge
Die Anzahl der Verzeichniseinträge, die unmittelbar auf die Namenseinträge folgen und numerische IDs für Typ-, Namens- oder Spracheinträge verwenden.

 

Einträge im Ressourcenverzeichnis

Die Verzeichniseinträge bilden die Zeilen einer Tabelle. Jeder Eintrag im Ressourcenverzeichnis hat das folgende Format. Ob es sich bei dem Eintrag um einen Namens- oder einen ID-Eintrag handelt, geht aus der Tabelle des Ressourcenverzeichnisses hervor, die angibt, wie viele Namens- und ID-Einträge ihm folgen (denken Sie daran, dass alle Namenseinträge vor allen ID-Einträgen der Tabelle stehen). Alle Einträge der Tabelle werden in aufsteigender Reihenfolge sortiert: die Namenseinträge nach der Groß- und Kleinschreibung und die ID-Einträge nach dem numerischen Wert. Offsets sind relativ zur Adresse im IMAGE_DIRECTORY_ENTRY_RESOURCE DataDirectory. Siehe Peering innerhalb der PE: A Tour of the Win32 Portable Executable File Format für weitere Informationen.

Abstand Größe Feld Beschreibung
0
4
Name-Offset
Der Offset eines Strings, der den Eintrag Typ, Name oder Sprach-ID angibt, je nach Tabellenebene.
0
4
Ganzzahlige ID
Eine 32-Bit-Ganzzahl, die den Typ-, Namens- oder Sprach-ID-Eintrag identifiziert.
4
4
Data-Entry-Offset
High Bit 0. Adresse eines Ressourcendateneintrags (ein Blatt).
4
4
Unterverzeichnis-Offset
High Bit 1. Die unteren 31 Bits sind die Adresse einer anderen Ressourcenverzeichnistabelle (der nächst tieferen Ebene).

 

Ressourcenverzeichnis-String

Der String-Bereich des Ressourcenverzeichnisses besteht aus Unicode-Strings, die wortorientiert sind. Diese Strings werden zusammen nach dem letzten Eintrag im Ressourcenverzeichnis und vor dem ersten Eintrag in den Ressourcendaten gespeichert. Dadurch werden die Auswirkungen dieser Strings mit variabler Länge auf die Ausrichtung der Verzeichniseinträge mit fester Größe minimiert. Jeder String des Ressourcenverzeichnisses hat das folgende Format:

Abstand Größe Feld Beschreibung
0
2
Länge
Die Größe des Strings, ohne das Längenfeld selbst.
2
variabel
Unicode String
Der Unicode-String variabler Länge, wortorientiert.

 

Ressource Dateneingabe

Jeder Ressourcendateneintrag beschreibt eine tatsächliche Einheit von Rohdaten im Bereich Ressourcendaten. Ein Ressourcendateneintrag hat das folgende Format:

Abstand Größe Feld Beschreibung
0
4
Daten-RVA
Die Adresse einer Einheit von Ressourcendaten im Ressourcendatenbereich.
4
4
Größe
Die Größe der Ressourcendaten, auf die das Feld Data RVA verweist, in Bytes.
8
4
Codepage
Die Codepage, die zur Dekodierung von Codepoint-Werten innerhalb der Ressourcendaten verwendet wird. Normalerweise ist die Codepage die Unicode-Codepage.
12
4
Reserviert, muss 0 sein.

 

Der Abschnitt .cormeta (nur Objekt)

CLR-Metadaten werden in diesem Abschnitt gespeichert. Es wird verwendet, um anzuzeigen, dass die Objektdatei verwalteten Code enthält. Das Format der Metadaten ist nicht dokumentiert, kann aber den CLR-Schnittstellen für die Verarbeitung von Metadaten übergeben werden.

Der Abschnitt .sxdata

Die gültigen Ausnahmebehandler eines Objekts sind im Abschnitt .sxdata dieses Objekts aufgeführt. Der Abschnitt ist mit IMAGE_SCN_LNK_INFO gekennzeichnet. Es enthält den COFF-Symbolindex jedes gültigen Handlers, wobei 4 Bytes pro Index verwendet werden.

Zusätzlich markiert der Compiler ein COFF-Objekt als registriertes SEH, indem er das absolute Symbol „@feat.00“ ausgibt, wobei das LSB des Wertefeldes auf 1 gesetzt wird. Ein COFF-Objekt ohne registrierte SEH-Handler hätte zwar das Symbol „@feat.00“, aber keinen .sxdata-Abschnitt.

Archiv (Bibliothek) Dateiformat

Das COFF-Archivformat bietet einen Standardmechanismus zur Speicherung von Sammlungen von Objektdateien. Diese Sammlungen werden in der Programmierdokumentation gemeinhin als Bibliotheken bezeichnet.

Die ersten 8 Bytes eines Archivs bestehen aus der Dateisignatur. Der Rest des Archivs besteht aus einer Reihe von Archivelementen, wie folgt:

  • Das erste und das zweite Element sind „Linker-Elemente“ Jedes dieser Elemente hat sein eigenes Format, wie im Abschnitt Import Name Type beschrieben. Normalerweise legt ein Linker Informationen in diesen Archivelementen ab. Die Linker-Elemente enthalten das Verzeichnis des Archivs.

  • Das dritte Element ist das Element „longnames“. Dieses optionale Element besteht aus einer Reihe von ASCII-Strings mit Null als Endung, wobei jeder String der Name eines anderen Archivelements ist.

  • Der Rest des Archivs besteht aus Standardelementen (Objektdateien). Jedes dieser Elemente enthält den Inhalt einer Objektdatei in ihrer Gesamtheit.

Jedem Element ist ein Archivelementheader vorangestellt. Die folgende Liste zeigt die allgemeine Struktur eines Archivs:

Signatur: „!<arch>\n“
Header
1. Linker Element
Header
2. Linker Element
Header
Longnames Element
Header
Inhalt der OBJ-Datei 1
(COFF-Format)
Header
Inhalt der OBJ-Datei 2
(COFF-Format)

...

Header
Inhalt der OBJ-Datei N
(COFF-Format)

Archivdatei-Signatur

Die Signatur der Archivdatei identifiziert den Dateityp. Jedes Dienstprogramm (z. B. ein Linker), das eine Archivdatei als Eingabe akzeptiert, kann den Dateityp durch Lesen dieser Signatur überprüfen. Die Signatur besteht aus den folgenden ASCII-Zeichen, wobei jedes der nachstehenden Zeichen wörtlich wiedergegeben wird, mit Ausnahme des Zeilenumbruchs (\n):

!<arch>\n

Der Windows SDK winnt.h Header definiert die folgenden Makros:

#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>/   "

Archivieren von Elementekopfzeilen

Jedem Member (Linker, Longnames oder Object-File Member) wird ein Header vorangestellt. Die Kopfzeile eines Archivelements hat das folgende Format, wobei jedes Feld eine ASCII-Textzeichenfolge ist, die linksbündig ausgerichtet ist und bis zum Ende des Feldes mit Leerzeichen aufgefüllt wird. In keinem dieser Felder gibt es ein abschließendes Nullzeichen.

Jeder Elementskopf beginnt an der ersten geraden Adresse nach dem Ende des vorherigen Archivelements, ein Byte '\n' (IMAGE_ARCHIVE_PAD) kann nach einem Archivelement eingefügt werden, damit das folgende Element an einer geraden Adresse beginnt.

Abstand Größe Feld Beschreibung
0
16
Name
Der Name des Archivelements, an den ein Schrägstrich (/) angehängt ist, um den Namen zu beenden. Wenn das erste Zeichen ein Schrägstrich ist, hat der Name eine besondere Interpretation, wie in der folgenden Tabelle beschrieben.
16
12
Datum
Das Datum und die Uhrzeit, zu der das Archivelement erstellt wurde: Dies ist die ASCII-Dezimaldarstellung der Anzahl der Sekunden seit dem 1.1.1970 UCT.
28
6
Benutzer-ID
Eine ASCII-Dezimaldarstellung der Benutzer-ID. Dieses Feld enthält auf Windows-Plattformen keinen aussagekräftigen Wert, da Microsoft-Tools ausschließlich Leerzeichen ausgeben.
34
6
Gruppen-ID
Eine ASCII-Dezimaldarstellung der Gruppen-ID. Dieses Feld enthält auf Windows-Plattformen keinen aussagekräftigen Wert, da Microsoft-Tools ausschließlich Leerzeichen ausgeben.
40
8
Modus
Eine oktale ASCII-Darstellung des Dateimodus des Elements. Dies ist der ST_MODE-Wert aus der C-Laufzeitfunktion _wstat.
48
10
Größe
Eine ASCII-Dezimaldarstellung der Gesamtgröße des Archivelements, ohne die Größe des Headers.
58
2
Ende der Überschrift
Die beiden Bytes (0x60 0x0A) im C-String „`\n“ (IMAGE_ARCHIVE_END).

Das Feld Name hat eines der in der folgenden Tabelle aufgeführten Formate. Wie bereits erwähnt, wird jeder dieser Strings linksbündig ausgerichtet und mit Leerzeichen am Ende innerhalb eines Feldes von 16 Bytes aufgefüllt:

Inhalt des Feldes Name Beschreibung
name/
Der Name des Archivelements.
/
Das Archiv-Element ist eines der beiden Linker-Elemente. Die beiden Linker haben diesen Namen.
//
Das Archivelement ist das Longnames-Element, das aus einer Reihe von ASCII-Strings mit Null-Ende besteht. Das Element longnames ist das dritte Archivelement und ist optional.
/n
Der Name des Archivelements befindet sich am Offset n innerhalb des longnames-Elements. Die Zahl n ist die dezimale Darstellung des Offsets. Beispiel: „/26“ bedeutet, dass sich der Name des Archivelements 26 Bytes hinter dem Anfang des Inhalts des Longnames-Elements befindet.

 

Erster Linker Element

Der Name des ersten Linker-Elements ist „/“ (IMAGE_ARCHIVE_LINKER_MEMBER). Das erste Linker-Element ist aus Gründen der Abwärtskompatibilität enthalten. Sie wird von den aktuellen Linkern nicht verwendet, aber ihr Format muss korrekt sein. Dieses Linkerelement liefert ein Verzeichnis von Symbolnamen, ebenso wie das zweite Linkerelement. Für jedes Symbol geben die Informationen an, wo das Archivelement zu finden ist, das das Symbol enthält.

Das erste Linkerelement hat das folgende Format. Diese Information erscheint nach der Kopfzeile:

Abstand Größe Feld Beschreibung
0
4
Anzahl von Symbolen
Long-Wert ohne Vorzeichen, der die Anzahl der indizierten Symbole enthält. Diese Zahl wird im Big-Endian-Format gespeichert. Jedes Objektdateielement definiert normalerweise ein oder mehrere externe Symbole.
4
4 * n
Offsets
Ein Array von Datei-Offsets für die Kopfzeilen von Archivelementen, wobei n gleich dem Feld Anzahl der Symbole ist. Jede Zahl in dem Array ist ein vorzeichenloser Long-Wert, der im Big-Endian-Format gespeichert wird. Für jedes Symbol, das in der Stringtabelle genannt wird, gibt das entsprechende Element im Array offsets die Position des Archivelements an, das das Symbol enthält.
*
*
String-Tabelle
Eine Reihe von nullterminierten Strings, die alle Symbole im Verzeichnis benennen. Jeder String beginnt unmittelbar nach dem Null-Zeichen der vorherigen String. Die Anzahl der Strings muss dem Wert im Feld Anzahl der Symbole entsprechen.

 

Die Elemente im Array Offsets müssen in aufsteigender Reihenfolge angeordnet sein. Dies bedeutet, dass die Symbole in der Stringtabelle in der Reihenfolge der Archivelemente angeordnet werden müssen. So müssten beispielsweise alle Symbole in der ersten Objektdatei vor den Symbolen in der zweiten Objektdatei aufgeführt werden.

Zweiter Linker Element

Wie das erste Linker-Element hat auch das zweite Linker-Element den Namen „/“ (IMAGE_ARCHIVE_LINKER_MEMBER). Obwohl beide Linkerelemente ein Verzeichnis von Symbolen und Archivelementen, die diese enthalten, bereitstellen, wird das zweite Linkerelement von allen aktuellen Linkern dem ersten vorgezogen. Das zweite Linkerelement enthält Symbolnamen in lexikalischer Reihenfolge, was eine schnellere Suche nach Namen ermöglicht.

Das zweite Element hat das folgende Format. Diese Information erscheint nach der Kopfzeile:

Abstand Größe Feld Beschreibung
0
4
Anzahl der Elemente
Ein Long-Wert ohne Vorzeichen, der die Anzahl der Archivelemente enthält.
4
4 * m
Offsets
Ein Array von Datei-Offsets zu den Kopfzeilen der Archivelemente, in aufsteigender Reihenfolge angeordnet. Jeder Offset ist ein unsigned long . Die Zahl m ist gleich dem Wert des Feldes Anzahl der Elemente.
*
4
Anzahl von Symbolen
Ein Long-Wert ohne Vorzeichen, der die Anzahl der indizierten Symbole enthält. Jedes Objektdateielement definiert normalerweise ein oder mehrere externe Symbole.
*
2 * n
Indizes
Ein Array von 1-basierten Indizes (unsigned short ), die Symbolnamen auf Archivelemente-Offsets abbilden. Die Zahl n ist gleich dem Feld Anzahl der Symbole. Für jedes Symbol, das in der Stringtabelle genannt wird, gibt das entsprechende Element im Array Indices einen Index im Array Offsets an. Das Array Offsets wiederum gibt die Position des Archivelements an, das das Symbol enthält.
*
*
String-Tabelle
Eine Reihe von nullterminierten Strings, die alle Symbole im Verzeichnis benennen. Jeder String beginnt unmittelbar nach dem Null-Byte der vorangegangenen String. Die Anzahl der Strings muss dem Wert im Feld Anzahl der Symbole entsprechen. In dieser Tabelle sind alle Symbolnamen in aufsteigender lexikalischer Reihenfolge aufgeführt.

 

Longnames Element

Der Name des Longnames-Members ist „//“ (IMAGE_ARCHIVE_LONGNAMES_MEMBER). Das Element „longnames“ ist eine Reihe von Strings mit den Namen von Archivelementen. Ein Name erscheint hier nur, wenn der Platz im Feld Name (16 Bytes) nicht ausreicht. Das Element longnames ist optional. Sie kann leer sein und nur eine Überschrift enthalten, oder sie kann ganz ohne Überschrift auskommen.

Die Strings sind nullterminiert. Jeder String beginnt unmittelbar nach dem Null-Byte der vorangegangenen String.

Bibliotheksformat importieren

Traditionelle Importbibliotheken, d. h. Bibliotheken, die die Exporte eines Images zur Verwendung durch ein anderes beschreiben, folgen in der Regel dem in Abschnitt 7 beschriebenen Layout, Archive (Library) File Format. Der Hauptunterschied besteht darin, dass die Elemente der Importbibliothek Pseudo-Objektdateien anstelle von echten Dateien enthalten, wobei jedes Element die Sektionsbeiträge enthält, die für die Erstellung der Importtabellen erforderlich sind, die in Abschnitt 6.4 beschrieben werden, . Die .idata-Sektion Der Linker erzeugt dieses Archiv während der Erstellung der exportierenden Anwendung.

Die Abschnittsbeiträge für einen Import können aus einer kleinen Anzahl von Informationen abgeleitet werden. Der Linker kann entweder die vollständigen, ausführlichen Informationen für jedes Element zum Zeitpunkt der Erstellung der Bibliothek in die Importbibliothek generieren oder nur die kanonischen Informationen in die Bibliothek schreiben und es der Anwendung, die sie später verwendet, überlassen, die erforderlichen Daten im laufenden Betrieb zu generieren.

In einer Importbibliothek mit dem Langformat enthält ein einzelnes Element die folgenden Informationen:

  • Kopfzeile des Archivelements
  • Datei-Header
  • Abschnittsüberschriften
  • Daten, die den einzelnen Abschnittsüberschriften entsprechen
  • COFF-Symboltabelle
  • Strings

Im Gegensatz dazu wird eine kurze Importbibliothek wie folgt geschrieben:

  • Kopfzeile des Archivelements
  • Kopfzeile importieren
  • Null-terminierter Importnamen-String
  • DLL-Namensstring mit Null-Terminierung

Diese Informationen reichen aus, um den gesamten Inhalt des Elements zum Zeitpunkt seiner Nutzung genau zu rekonstruieren.

Kopfzeile importieren

Der Importkopf enthält die folgenden Felder und Offsets:

Abstand Größe Feld Beschreibung
0
2
Sig1
Muss IMAGE_FILE_MACHINE_UNKNOWN sein. Weitere Informationen finden Sie unter Maschinentypen.
2
2
Sig2
Muss 0xFFFF sein.
4
2
Version
Die Strukturversion.
6
2
Maschine
Die Nummer, die den Typ des Zielrechners identifiziert. Weitere Informationen finden Sie unter Maschinentypen.
8
4
Zeit-Datum-Stempel
Uhrzeit und Datum der Erstellung der Datei.
12
4
Größe der Daten
Die Größe der Strings, die auf die Kopfzeile folgen.
16
2
Ordinal/Hinweis
Entweder die Ordnungszahl oder der Hinweis für den Import, bestimmt durch den Wert im Feld Namenstyp.
18
2 Bit
Typ
Der Importtyp. Spezifische Werte und Beschreibungen finden Sie unter Importtyp.
3 Bit
Name Typ
Der Typ des Importnamens. Weitere Informationen finden Sie unter Import Name Type.
11 Bit
Reserviert
Reserviert, muss 0 sein.

 

Auf diese Struktur folgen zwei nullterminierte Strings, die den Namen des importierten Symbols und die DLL, aus der es stammt, beschreiben.

Importtyp

Die folgenden Werte sind für das Feld Typ im Importkopf definiert:

Konstante Wert Beschreibung
IMPORT_OBJEKT_CODE
0
Ausführbarer Code.
IMPORT_OBJECT_DATA
1
Daten.
IMPORT_OBJECT_CONST
2
In der .def-Datei als CONST angegeben.

Diese Werte werden verwendet, um zu bestimmen, welche Abschnittsbeiträge von dem Werkzeug, das die Bibliothek verwendet, erzeugt werden müssen, wenn es auf diese Daten zugreifen muss.

Import Name Typ

Der mit Null beendete Name des Importsymbols folgt unmittelbar auf den zugehörigen Importkopf. Die folgenden Werte sind für das Feld Name Type in der Importkopfzeile definiert. Sie geben an, wie der Name zu verwenden ist, um die korrekten Symbole zu erzeugen, die den Import darstellen:

Konstante Wert Beschreibung
IMPORT_OBJECT_ORDINAL 0 Der Import erfolgt nach der Ordnungszahl. Dies bedeutet, dass der Wert im Feld Ordinal/Hint des Import-Headers die Ordnungszahl des Imports ist. Wird diese Konstante nicht angegeben, so ist das Feld Ordinal/Hint immer als Hinweis für den Import zu interpretieren.
IMPORT_OBJECT_NAME 1 Der Importname ist identisch mit dem Namen des öffentlichen Symbols.
IMPORT_OBJECT_NAME_NOPREFIX 2 Der Importname ist der Name des öffentlichen Symbols, wobei das führende ?, @ oder optional _ weggelassen wird.
IMPORT_OBJECT_NAME_UNDECORATE 3 Der Importname ist der Name des öffentlichen Symbols, wobei jedoch das führende ?, @ oder optional _ übersprungen und das erste @ abgeschnitten wird.

Anhang A: Berechnung des Authenticode PE Image Hash

Es wird erwartet, dass mehrere Attributzertifikate verwendet werden, um die Integrität der Bilder zu überprüfen. Am häufigsten wird jedoch die Authenticode-Signatur verwendet. Eine Authenticode-Signatur kann verwendet werden, um zu überprüfen, dass die relevanten Abschnitte einer PE-Image-Datei nicht in irgendeiner Weise gegenüber der ursprünglichen Form der Datei verändert worden sind. Um diese Aufgabe zu erfüllen, enthalten Authenticode-Signaturen einen so genannten PE-Image-Hash

Was ist ein Authenticode PE Image Hash?

Der Authenticode PE Image Hash, oder kurz File Hash, ähnelt einer Datei-Prüfsumme, indem er einen kleinen Wert erzeugt, der sich auf die Integrität einer Datei bezieht. Eine Prüfsumme wird durch einen einfachen Algorithmus erstellt und dient in erster Linie der Erkennung von Speicherfehlern. Das heißt, sie wird verwendet, um festzustellen, ob ein Speicherblock auf der Festplatte defekt ist und die dort gespeicherten Werte verfälscht wurden. Ein Datei-Hash ähnelt einer Prüfsumme, da er auch die Beschädigung von Dateien erkennt. Im Gegensatz zu den meisten Prüfsummenalgorithmen ist es jedoch sehr schwierig, eine Datei so zu verändern, dass sie denselben Datei-Hash aufweist wie ihre ursprüngliche (unveränderte) Form. Eine Prüfsumme ist dazu gedacht, einfache Speicherfehler zu erkennen, die zu einer Beschädigung führen, aber ein Datei-Hash kann verwendet werden, um absichtliche und sogar subtile Änderungen an einer Datei zu erkennen, wie z. B. solche, die durch Viren, Hacker oder Trojanerprogramme eingeführt wurden.

Bei einer Authenticode-Signatur wird der Datei-Hash mit einem privaten Schlüssel digital signiert, den nur der Unterzeichner der Datei kennt. Ein Software-Nutzer kann die Integrität der Datei überprüfen, indem er den Hash-Wert der Datei berechnet und ihn mit dem Wert des signierten Hashs vergleicht, der in der digitalen Authenticode-Signatur enthalten ist. Stimmen die Datei-Hashes nicht überein, wurde ein Teil der Datei, die vom PE-Image-Hash abgedeckt wird, verändert.

Was beinhaltet ein Authenticode PE Image Hash?

Es ist weder möglich noch wünschenswert, alle Imagedateidaten in die Berechnung des PE-Image-Hashes einzubeziehen. Manchmal hat es einfach unerwünschte Eigenschaften (z. B. können Debugging-Informationen nicht aus öffentlich freigegebenen Dateien entfernt werden); manchmal ist es einfach unmöglich. Es ist beispielsweise nicht möglich, alle Informationen in einer Imagedatei in eine Authenticode-Signatur einzubeziehen, dann die Authenticode-Signatur, die diesen PE-Image-Hash enthält, in das PE-Image einzufügen und später einen identischen PE-Image-Hash zu erzeugen, indem alle Daten der Imagedatei erneut in die Berechnung einbezogen werden, da die Datei nun die Authenticode-Signatur enthält, die ursprünglich nicht vorhanden war.

Verfahren zur Generierung des Authenticode PE Image Hashes

In diesem Abschnitt wird beschrieben, wie ein PE-Image-Hash berechnet wird und welche Teile des PE-Images verändert werden können, ohne dass die Authenticode-Signatur ungültig wird.

Hinweis

Der PE-Image-Hash für eine bestimmte Datei kann in eine separate Katalogdatei aufgenommen werden, ohne dass ein Attributzertifikat in die Hash-Datei aufgenommen wird. Dies ist wichtig, da es möglich ist, den PE-Image-Hash in einer Authenticode-signierten Katalogdatei ungültig zu machen, indem ein PE-Image verändert wird, das keine Authenticode-Signatur enthält.

Alle Daten in Abschnitten des PE-Abbilds, die in der Abschnittstabelle angegeben sind, werden mit Ausnahme der folgenden Ausschlussbereiche vollständig gehasht:

  • Das Datei-CheckSum-Feld der Windows-spezifischen Felder des optionalen Headers. Diese Prüfsumme umfasst die gesamte Datei (einschließlich aller Attributzertifikate in der Datei). Es ist sehr wahrscheinlich, dass sich die Prüfsumme nach dem Einfügen der Authenticode-Signatur vom Originalwert unterscheidet.

  • Informationen zu den Attributzertifikaten. Die Bereiche des PE-Images, die sich auf die Authenticode-Signatur beziehen, werden nicht in die Berechnung des PE-Image-Hashes einbezogen, da Authenticode-Signaturen zu einem Image hinzugefügt oder daraus entfernt werden können, ohne die Gesamtintegrität des Images zu beeinträchtigen. Das ist kein Problem, denn es gibt Benutzerszenarien, die auf das Nachsignieren von PE-Bildern oder das Hinzufügen eines Zeitstempels angewiesen sind. Authenticode schließt die folgenden Informationen von der Hash-Berechnung aus:

    • Das Feld Zertifikatstabelle der optionalen Kopfdatenverzeichnisse.

    • Die Zertifikatstabelle und die entsprechenden Zertifikate, auf die das unmittelbar oben aufgeführte Feld Zertifikatstabelle verweist.

    Zur Berechnung des PE-Image-Hashes ordnet Authenticode die in der Sektionstabelle angegebenen Abschnitte nach Adressbereichen und hasst dann die sich ergebende Folge von Bytes, wobei die Ausschlussbereiche übersprungen werden.

  • Informationen über das Ende des letzten Abschnitts hinaus. Der Bereich nach dem letzten Abschnitt (definiert durch den höchsten Offset) wird nicht gehasht. Dieser Bereich enthält in der Regel Debug-Informationen. Debug-Informationen können im Allgemeinen als Hinweise für Debugger betrachtet werden; sie beeinträchtigen nicht die eigentliche Integrität des ausführbaren Programms. Es ist im wahrsten Sinne des Wortes möglich, Debug-Informationen aus einem Image zu entfernen, nachdem ein Produkt ausgeliefert wurde, ohne die Funktionalität des Programms zu beeinträchtigen. Tatsächlich wird dies manchmal getan, um Speicherplatz zu sparen. Es ist zu beachten, dass Debug-Informationen, die in den angegebenen Abschnitten des PE-Images enthalten sind, nicht entfernt werden können, ohne die Authenticode-Signatur ungültig zu machen.

Sie können die im Windows Platform SDK enthaltenen Tools makecert und signtool verwenden, um mit der Erstellung und Überprüfung von Authenticode-Signaturen zu experimentieren. Weitere Informationen finden Sie unter Referenz, unten.

Referenzen

Downloads und Tools für Windows (einschließlich des Windows-SDK)

Erstellen, Anzeigen und Verwalten von Zertifikaten

Kernel-Mode Code Signing Walkthrough (.doc)

SignTool

Windows Authenticode Portable Executable Signature Format (.docx)

ImageHlp-Funktionen