PDB jest pojedynczym plikiem, który logicznie składa się z kilku pod-plików, zwanych strumieniami. Został on zaprojektowany w celu optymalizacji procesu wprowadzania zmian do PDB, wykonywanego przez kompilacje i łącza przyrostowe. Strumienie mogą być usuwane, dodawane lub zastępowane bez przepisywania innych strumieni, a zmiany metadanych opisujących strumienie są również minimalizowane.
PDB jest zorganizowany w strony o stałym rozmiarze, zwykle 1K, 2K lub 4K, numerowane kolejno począwszy od 0.
Uwaga: Zakłada się, że wszystkie informacje numeryczne (np, strumień i numery stron) są przechowywane w formacie little-endian, natywnym dla procesorów Intel x86. Kod pdbparse Pythona przyjmuje to założenie.
StreamEdit
Każdy strumień w PDB zajmuje kilka stron, które niekoniecznie są kolejno numerowane. Strumień ma swój numer i długość. Zawartość strumienia jest konkatenacją jego stron, obciętych do długości strumienia.
Format metadanychEdit
Funkcją metadanych PDB jest identyfikacja wszystkich strumieni składowych, podanie długości i kolejności stron dla każdego strumienia. Strumienie są numerowane kolejno, począwszy od 0. Istnieje również strumień główny, nienumerowany, który zawiera niektóre metadane.
NagłówekEdit
PDB rozpoczyna się od nagłówka, składającego się z:
- Podpisu, używanego do identyfikacji i walidacji określonego formatu. Długość podpisu zmienia się w zależności od konkretnego formatu.
- Pozostała część nagłówka zmienia się w zależności od formatu identyfikowanego przez podpis.
Nagłówek może być dłuższy niż pojedyncza strona.
Narzędzia Microsoftu używają dwóch formatów PDB:
Wersja 7Edit
Podpis to "Microsoft C/C++ MSF 7.00\r\n\x1ADS"
(32 bajty).
Remainder nagłówka składa się z:
- Rozmiar strony, 4 bajty.
- Wskaźnik tablicy alokacji, 4 bajty. Znaczenie tego nie jest znane. Wydaje się, że istnieje tablica alokacji, tablica 65 536 bitów (8 192 bajtów), znajdująca się na końcu PDB, a 1 bit oznacza stronę, która nie jest używana.
- Liczba stron pliku, 4 bajty.
- Rozmiar strumienia głównego, 4 bajty.
- Zarezerwowane, 4 bajty.
- Numer strony listy numerów stron strumienia głównego. Nie wskazuje lokalizacji samego strumienia Root, tylko strony zawierającej strukturę, która wskazuje na jego strony. Na tej stronie lista numerów stron strumienia Root wskazuje strony, na których jest przechowywany strumień Root. Zawiera ona 4 bajty na stronę, co wystarcza na pokrycie powyższego rozmiaru strumienia Root.
Strumień RootEdit
Strumień Root opisuje wszystkie strumienie PDB począwszy od strumienia 0. Jego zawartość zmienia się w zależności od wersji formatu PDB.
Wersja 2Edit
Strumień główny składa się z:
- Liczba strumieni, 2 bajty.
- Zarezerwowane, 2 bajty.
- Dla każdego strumienia:
- Rozmiar strumienia, 4 bajty.
- Zarezerwowane, 4 bajty.
- Dla każdego strumienia:
- Lista numerów stron strumienia, 2 bajty na stronę, wystarczająca do pokrycia powyższego rozmiaru strumienia.
Wersja 7Edit
Strumień główny składa się z:
- Liczba strumieni, 4 bajty.
- Dla każdego strumienia:
- Rozmiar strumienia, 4 bajty.
- Dla każdego strumienia:
- Lista numerów stron strumienia, 4 bajty na stronę, wystarczająca do pokrycia powyższego rozmiaru strumienia.
Zawartość strumieniaEdit
Narzędzia Microsoftu przechowują różne rodzaje informacji w strumieniach o różnych numerach. Niektóre numery strumieni mają przypisany stały typ informacji, a inne strumienie są identyfikowane we wspomnianych strumieniach o stałym typie.
Strumień 1 jest używany do sprawdzania, czy PDB jest tym samym plikiem, o którym mowa w strumieniu plików wykonywalnych lub obiektowych.
- Wersja, 4 bajty.
- Datownik czasowy, 4 bajty.
- Wiek, 4 bajty. Jest to liczba modyfikacji tego pliku PDB od momentu jego utworzenia.
- GUID, 16 bajtów.
- Łączna długość następujących nazw, 4 bajty. Po nich następują ciągi znaków zakończone zerem.
Strumień 2 i strumień 4 zawierają informacje o typach. Rekordy typów rzeczywistych definiują typy używane w programie. Strukturę tych rekordów można znaleźć w pliku cvinfo.h dostarczonym przez Microsoft. Istnieją dwa rodzaje rekordów, każdy z własnym zestawem numerów indeksów: identyfikatory typów i typy; tylko typy są przechowywane w strumieniu 2, a tylko identyfikatory typów są przechowywane w strumieniu 4. Indeksy są używane do odwoływania się do tych rekordów wewnątrz rekordów symboli i innych rekordów typów.
- Nagłówek:
- Wersja, 4 bajty.
- Rozmiar nagłówka, 4 bajty.
- Minimalny i maksymalny (ostatni + 1) indeks dla rekordów typów (po 4 bajty).
- Rozmiar następujących danych, 4 bajty, do końca strumienia.
- Informacje o haszu:
- Numer strumienia, 2 bajty z 2 bajtowym wypełnieniem.
- Klucz haszu, 4 bajty.
- Bufory, 4 bajty.
- HashVals, TiOff, i HashAdj, każdy złożony z offsetu i długości, po 4 bajty.
- Rejestry typów, zmienna długość, count = (maximum – minimum) z powyższego nagłówka.
Strumień 3 jest katalogiem dla innych strumieni. Uwaga, nie ma go w wersji 2, ani w PDB produkowanym przez kompilator. Strumień zaczyna się od nagłówka, który jest wyściełany tak, aby w sumie miał 64 bajty
Offset | Size | Name | Description | |
---|---|---|---|---|
0 | 4 | Signature | Identyfikator nagłówka, == 0xFFFFFFFF | |
4 | 4 | HeaderVersion | Wersja nagłówka | |
8 | 4 | Age | ||
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 | 2 | snPSSyms | |
18 | 2 | usVerPdbDllBuild | wersja dll, która ostatnio zbudowała to pdb | |
20 | 2 | snSymRecs | ||
22 | 2 | VerPdbDllRBld | rbld wersja pdb dll, która zbudowała to pdb ostatnio | |
24 | 4 | cbGpModi | rozmiar strumienia podrzędnego rgmodi | |
28 | 4 | cbSC | rozmiar strumienia podrzędnego Section Contribution | |
32 | 4 | cbSecMap | rozmiar mapy sekcji | |
36 | 4 | cbFileInfo | rozmiar strumienia informacji o pliku | |
40 | 4 | cbTSMap | rozmiar strumienia podrzędnej mapy serwera typów | |
44 | 4 | iMFC | indeks MFC | |
48 | 4 | cbDbgHdr | rozmiar opcjonalnej informacji DbgHdr dołączonej na końcu strumienia | |
52 | 4 | cbECInfo | liczba bajtów w podstrumieniu EC, lub 0, jeśli brak włączonego EC 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 | identyfikator maszyny, taki sam jak używany w formacie obiektu COFF, np.g., hex 8664 w przypadku Intel x86 64-bit | |
60 | 4 | RESERVED | przyszłe rozszerzenie, pad do 64 bajtów |
- Informacje o module, zmienna długość. Całkowity rozmiar w powyższym nagłówku. Jest jedna taka informacja dla każdego modułu obiektu używanego przez linker
- Opened, 4 bajty.
- Informacja o symbolu.
- Numer sekcji, 2 bajty + 2 bajty wypełnienia.
- Offset i rozmiar, po 4 bajty.
- Flagi, 4 bajty.
- Numer modułu, 2 bajty + 2 bajty padding.
- CRC dla danych sekcji i danych relokacji, po 4 bajty każdy.
- Flagi, 2 bajty.
- Numer strumienia, 2 bajty.
- Rozmiar symboli, 4 bajty.
- Rozmiary informacji o starym i nowym numerze linii, po 4 bajty.
- Liczba plików źródłowych, 2 bajty + 2 bajty wypełnienia.
- Offsets, 4 bajty.
- niSource i niCompiler, po 4 bajty.
- Nazwa modułu, łańcuch bajtów zakończony zerem.
- Nazwa obiektu, łańcuch bajtów zakończony zerem.
- Podawanie wielokrotności 4 bajtów.
- Wkłady sekcji, nagłówki sekcji, informacja o pliku, mapa ts i informacja o EC. Ich rozmiary znajdują się w powyższym nagłówku.
- Nagłówek debug,
- Numery strumieni dla Old Frame Pointer Omission, Exceptions, Fixups, Object Maps to and from Source, Section Headers, Token Ring IDs, Xdata, Pdata, New Frame Pointer Omission i Section Header Origin. 2 bajty każdy.