Programmdatenbank

Die PDB ist eine einzelne Datei, die logisch aus mehreren Unterdateien, sogenannten Streams, zusammengesetzt ist. Sie wurde entwickelt, um den Prozess der Änderungen an der PDB zu optimieren, wie sie durch Kompilieren und inkrementelle Links durchgeführt werden. Ströme können entfernt, hinzugefügt oder ersetzt werden, ohne andere Ströme neu zu schreiben, und die Änderungen an den Metadaten, die die Ströme beschreiben, werden ebenfalls minimiert.

Die PDB ist in Seiten fester Größe organisiert, typischerweise 1K, 2K oder 4K, die beginnend mit 0 fortlaufend nummeriert sind.

Anmerkung: Es wird davon ausgegangen, dass alle numerischen Informationen (z.B., Stream- und Seitennummern) im Little-Endian-Format gespeichert sind, der nativen Form für Intel x86-basierte Prozessoren. Der Python-Code von pdbparse geht von dieser Annahme aus.

StreamEdit

Jeder Stream in der PDB nimmt mehrere Seiten ein, die nicht unbedingt fortlaufend nummeriert sind. Der Stream hat eine Nummer und eine Länge. Der Inhalt des Datenstroms ist die Verkettung seiner Seiten, die auf die Länge des Datenstroms gekürzt werden.

MetadatenformatBearbeiten

Die Funktion der PDB-Metadaten besteht darin, alle Komponenten des Datenstroms zu identifizieren, wobei die Länge und die Reihenfolge der Seiten für jeden Datenstrom angegeben werden. Es gibt auch einen nicht nummerierten Root-Stream, der einige der Metadaten enthält.

HeaderEdit

Die PDB beginnt mit einem Header, bestehend aus:

  • Signatur, die zur Identifizierung und Validierung des spezifischen Formats dient. Die Länge der Signatur variiert mit dem spezifischen Format.
  • Der Rest des Headers variiert mit dem Format, das durch die Signatur identifiziert wird.

Der Header kann länger als eine Seite sein.

Microsoft-Tools verwenden zwei PDB-Formate:

Version 7Edit

Die Signatur ist "Microsoft C/C++ MSF 7.00\r\n\x1ADS"(32 Bytes).

Rest des Headers besteht aus:

  • Seitengröße, 4 Bytes.
  • Zuweisungstabellenzeiger, 4 Bytes. Die Bedeutung dieser Angabe ist unbekannt. Es scheint eine Zuordnungstabelle zu geben, ein Array von 65.536 Bits (8.192 Bytes), das sich am Ende der PDB befindet, und ein 1-Bit bedeutet eine Seite, die nicht verwendet wird.
  • Anzahl der Dateiseiten, 4 Bytes.
  • Seitengröße des Root-Streams, 4 Bytes.
  • Reserviert, 4 Bytes.
  • Seitennummer der Seitenzahlenliste des Root-Streams. Sie gibt nicht den Ort des Root-Streams selbst an, sondern nur die Seite, die die Struktur enthält, die auf seine Seiten verweist. Auf dieser Seite gibt die Seitennummernliste des Root-Streams die Seiten an, auf denen der Root-Stream gespeichert ist. Sie enthält 4 Bytes pro Seite, genug, um die obige Größe des Root-Streams abzudecken.

Root-StreamEdit

Der Root-Stream beschreibt alle PDB-Streams, beginnend mit Stream 0. Sein Inhalt variiert je nach PDB-Formatversion.

Version 2Bearbeiten

Der Root Stream besteht aus:

  • Anzahl der Streams, 2 Bytes.
  • Reserviert, 2 Bytes.
  • Für jeden Stream:
    • Streamgröße, 4 Bytes.
    • Reserviert, 4 Bytes.
  • Für jeden Stream:
    • Seitennummernliste des Streams, 2 Byte pro Seite, genug, um die obige Streamgröße abzudecken.

Version 7Edit

Der Root Stream besteht aus:

  • Anzahl der Streams, 4 Bytes.
  • Für jeden Stream:
    • Streamgröße, 4 Bytes.
  • Für jeden Stream:
    • Seitennummernliste des Streams, 4 Bytes pro Seite, genug, um die obige Stream-Größe abzudecken.

Stream-InhaltBearbeiten

Microsoft-Tools speichern verschiedene Arten von Informationen in verschieden nummerierten Streams. Einigen Stream-Nummern ist ein fester Informationstyp zugeordnet, und andere Streams werden in den oben genannten Streams mit festem Typ identifiziert.

Stream 1 wird verwendet, um zu überprüfen, ob es sich bei der PDB um dieselbe Datei handelt, auf die in einem Stream einer ausführbaren Datei oder einer Objektdatei verwiesen wird.

  • Version, 4 Byte.
  • Datumsstempel, 4 Byte.
  • Alter, 4 Byte. Dies ist die Anzahl, wie oft diese PDB seit ihrer Erstellung geändert wurde.
  • GUID, 16 Bytes.
  • Gesamtlänge der folgenden Namen, 4 Bytes. Gefolgt von null-terminierten Zeichenketten.

Stream 2 und Stream 4 enthalten Typinformationen. Die eigentlichen Typsätze definieren die im Programm verwendeten Typen. Die Struktur dieser Datensätze ist in der von Microsoft bereitgestellten Datei cvinfo.h zu finden. Es gibt zwei Arten von Datensätzen, jeder mit einem eigenen Satz von Indexnummern: Typ-IDs und Typen; nur Typen werden in Stream 2 gespeichert, und nur Typ-IDs werden in Stream 4 gespeichert. Die Indizes werden verwendet, um innerhalb von Symbol-Datensätzen und anderen Typ-Datensätzen auf diese Datensätze zu verweisen.

  • Ein Header:
    • Version, 4 Bytes.
    • Header-Größe, 4 Bytes.
    • Minimaler und maximaler (letzter + 1) Index für Typ-Datensätze (jeweils 4 Bytes).
    • Größe der folgenden Daten, 4 Bytes, bis zum Ende des Stroms.
  • Hash-Informationen:
    • Stream-Nummer, 2 Bytes mit 2 Bytes Padding.
    • Hash-Schlüssel, 4 Bytes.
    • Buckets, 4 Bytes.
    • HashVals, TiOff und HashAdj, jeweils bestehend aus einem Offset und einer Länge, jeweils 4 Bytes.
  • Typ-Datensätze, variable Länge, Anzahl = (Maximum – Minimum) aus obigem Header.

Stream 3 ist ein Verzeichnis für andere Streams. Es ist weder in Version 2 noch in einer von einem Compiler erstellten PDB vorhanden. Der Stream beginnt mit einem Header, der auf insgesamt 64 Bytes aufgefüllt wird

PDB Stream 3 Header (struct NewDBIHdr)
Offset Size Name Description
0 4 Signature Header identifier, == 0xFFFFFFFF
4 4 HeaderVersion Version des Headers
8 4 Alter
12 2 snGSSyms
14 2 usVerAll
 union { struct { USHORT usVerPdbDllMin : 8; // minor version and USHORT usVerPdbDllMaj : 7; // major version and USHORT fNewVerFmt : 1; // flag telling us we have rbld stored elsewhere (high bit of original major version) } vernew; // that built this pdb last. struct { USHORT usVerPdbDllRbld: 4; USHORT usVerPdbDllMin : 7; USHORT usVerPdbDllMaj : 5; } verold; USHORT usVerAll; };
16 2 snPSSyms
18 2 usVerPdbDllBuild Build-Version der pdb dll, die diese pdb zuletzt erstellt hat
20 2 snSymRecs
22 2 VerPdbDllRBld rbld Version der pdb dll, die diese pdb zuletzt erstellt hat
24 4 cbGpModi Größe des rgmodi-Substroms
28 4 cbSC Größe des Section Contribution-Substroms
32 4 cbSecMap Größe der Section Map
36 4 cbFileInfo Größe des File Info Stream
40 4 cbTSMap Größe des Type Server Map Substreams
44 4 iMFC MFC Index
48 4 cbDbgHdr Größe der optionalen DbgHdr-Info, die am Ende des Streams angehängt wird
52 4 cbECInfo Anzahl der Bytes im EC-Substream, oder 0, wenn kein EC aktiviert Mods
56 2 flags
 struct _flags { USHORT fIncLink:1; // true if linked incrmentally (really just if ilink thunks are present) USHORT fStripped:1; // true if PDB::CopyTo stripped the private data out USHORT fCTypes:1; // true if this PDB is using CTypes. USHORT unused:13; // reserved, must be 0. } flags;
58 2 wMachine Maschinenkennung, wie im COFF-Objektformat verwendet, z. B.g., hex 8664 für Intel x86 64-bit
60 4 RESERVED zukünftige Erweiterung, auf 64 Bytes auffüllen
  • Modulinformationen, variable Länge. Gesamtgröße im obigen Header. Es gibt eine davon für jedes vom Linker verwendete Objektmodul
    • Opened, 4 Bytes.
    • Symbol info.
      • Section number, 2 Bytes + 2 Bytes padding.
      • Offset und Größe, je 4 Bytes.
      • Flags, 4 Bytes.
      • Modulnummer, 2 Bytes + 2 Bytes Auffüllung.
      • CRCs für Abschnittsdaten und Verschiebungsdaten, je 4 Bytes.
    • Flags, 2 Bytes.
    • Streamnummer, 2 Bytes.
    • Symbolgröße, 4 Bytes.
    • Alte und neue Zeilennummer Info-Größen, je 4 Bytes.
    • Anzahl der Quelldateien, 2 Bytes + 2 Bytes Auffüllung.
    • Offsets, 4 Bytes.
    • niSource und niCompiler, je 4 Bytes.
    • Modulname, nullterminierter Byte-String.
    • Objektname, nullterminierter Byte-String.
    • Padding auf ein Vielfaches von 4 Bytes.
  • Abschnittsbeiträge, Abschnittskopfzeilen, Dateiinfo, ts-Map und EC-Info. Ihre Größen sind im obigen Header zu finden.
  • Debug-Header,
    • Stream-Nummern für Old Frame Pointer Omission, Exceptions, Fixups, Object Maps to and from Source, Section Headers, Token Ring IDs, Xdata, Pdata, New Frame Pointer Omission, und Section Header Origin. Jeweils 2 Bytes.