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
- MS-DOS Stub (nur Image)
- Unterschrift (nur Image)
- COFF-Dateiheader (Objekt und Image)
- Optionaler Header (nur Image)
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.
Abweichung | Size | 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.
Abweichung | Size | 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.
Abweichung | Size | 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+) | Size | 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.
Abweichung | Size | 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
- Abschnitt Daten
- COFF-Verschiebungen (nur Objekt)
- COFF-Zeilennummern (veraltet)
- COFF-Symboltabelle
- Datensätze für Hilfssymbole
- COFF-Zeichenfolgentabelle
- Die Attribut-Zertifikat-Tabelle (nur Image)
- Delay-Load-Importtabellen (nur Image)
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.
Abweichung | Size | 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 |
Nicht unterstützt. |
IMAGE_REL_I386_REL16 |
0x0002 |
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 |
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.
Abweichung | Size | 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.
Abweichung | Size | 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.
Abweichung | Size | 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.
Abweichung | Size | 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:
Abweichung | Size | 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:
Abweichung | Size | 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:
Abweichung | Size | 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.
Abweichung | Size | 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.
Abweichung | Size | 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.
Abweichung | Size | 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.
Abweichung | Size | 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:
- Addieren Sie den dwLength-Wert des ersten Attributzertifikats zum Startoffset.
- Runden Sie den Wert aus Schritt 1 auf das nächstgelegene 8-Byte-Vielfache auf, um den Offset des zweiten Attributzertifikatseintrags zu ermitteln.
- 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.
- 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 | Hinweise |
---|---|---|
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 | Hinweise |
---|---|---|
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:
Abweichung | Size | 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
- Der Abschnitt .debug
- Der Abschnitt .drectve (nur Objekt)
- Der .edata-Abschnitt (nur Image)
- Der Abschnitt .idata
- Der Abschnitt .pdata
- Der .reloc-Bereich (nur Image)
- Der .tls-Abschnitt
- Die Struktur der Ladekonfiguration (nur Image)
- Der .rsrc-Abschnitt
- Der Abschnitt .cormeta (nur Objekt)
- Der Abschnitt .sxdata
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:
Abweichung | Size | 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.
Abweichung | Size | 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.
Abweichung | Size | 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:
Abweichung | Size | 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) | Size | 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:
Abweichung | Size | 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:
Abweichung | Size | 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:
Abweichung | Size | 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:
Abweichung | Size | 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:
Abweichung | Size | 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:
Abweichung | Size | 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:
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.
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.
Der Lader weist den Wert des TLS-Indexes der Stelle zu, die durch das Feld Adresse des Indexes angegeben wurde.
Der ausführbare Code ruft den TLS-Index und auch den Ort des TLS-Arrays ab.
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.
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:
Abweichung | Size | 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 |
DependentLoadFlags |
Die Standardladekennzeichnungen, die verwendet werden, wenn das Betriebssystem die statisch verknüpften Importe eines Moduls aufgelöst. |
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:
Abweichung | Size | 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.
Abweichung | Size | 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:
Abweichung | Size | 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:
Abweichung | Size | 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
- Archivdatei-Signatur
- Archivieren von Elementekopfzeilen
- Erster Linker Element
- Zweiter Linker Element
- Longnames Element
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.
Abweichung | Size | 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:
Abweichung | Size | 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:
Abweichung | Size | 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:
Abweichung | Size | 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)
Windows Authenticode Portable Executable Signature Format (.docx)