La PDB est un fichier unique qui est logiquement composé de plusieurs sous-fichiers, appelés flux. Il est conçu pour optimiser le processus de modification de la PDB, tel qu’il est effectué par les compilations et les liens incrémentaux. Les flux peuvent être supprimés, ajoutés ou remplacés sans réécrire d’autres flux, et les modifications des métadonnées qui décrivent les flux sont également minimisées.
La PDB est organisée en pages de taille fixe, typiquement 1K, 2K ou 4K, numérotées consécutivement à partir de 0.
Note : Il est présumé que toutes les informations numériques (par ex, les numéros de flux et de pages) sont stockées sous la forme little-endian, la forme native des processeurs basés sur Intel x86. Le code Python de pdbparse fait cette supposition.
StreamEdit
Chaque flux dans la PDB occupe plusieurs pages, qui ne sont pas nécessairement numérotées consécutivement. Le flux a un numéro et une longueur. Le contenu du flux est la concaténation de ses pages, tronquée à la longueur du flux.
Format des métadonnéesEdit
La fonction des métadonnées de la PDB est d’identifier tous les flux composants, en donnant la longueur, et la séquence des pages pour chaque flux. Les flux sont numérotés consécutivement en commençant par 0. Il existe également un flux racine, non numéroté, qui contient certaines des métadonnées.
En-têteEdit
La PDB commence par un en-tête, composé de :
- Signature, utilisée pour identifier et valider le format spécifique. La longueur de la signature varie selon le format spécifique.
- Le reste de l’en-tête varie selon le format identifié par la signature.
L’en-tête peut être plus long qu’une seule page.
Les outils Microsoft utilisent deux formats PDB :
Version 7Edit
La signature est "Microsoft C/C++ MSF 7.00\r\n\x1ADS"
(32 octets).
Le reste de l’en-tête consiste en:
- Taille de la page, 4 octets.
- Pointeur de table d’allocation, 4 octets. La signification de ceci est inconnue. Il semble y avoir une table d’allocation, un tableau de 65 536 bits (8 192 octets), situé à la fin de la PDB, et un bit 1 signifie une page qui n’est pas utilisée.
- Nombre de pages de fichier, 4 octets.
- Taille du flux racine, 4 octets.
- Réservé, 4 octets.
- Numéro de page de la liste des numéros de page du flux racine. Il n’indique pas l’emplacement du Root stream lui-même, seulement de la page contenant la structure qui pointe vers ses pages. À cette page, la liste des numéros de pages du flux racine indique les pages où le flux racine est stocké. Elle contient 4 octets par page, suffisamment pour couvrir la taille du Root stream ci-dessus.
Root streamEdit
Le Root stream décrit tous les streams PDB en commençant par le stream 0. Son contenu varie selon la version du format PDB.
Version 2Edit
Le flux racine se compose de :
- Nombre de flux, 2 octets.
- Réservé, 2 octets.
- Pour chaque flux :
- Taille du flux, 4 octets.
- Réservé, 4 octets.
- Pour chaque flux:
- La liste des numéros de page du flux, 2 octets par page, assez pour couvrir la taille du flux ci-dessus.
Version 7Edit
Le flux racine se compose de :
- Nombre de flux, 4 octets.
- Pour chaque flux :
- Taille du flux, 4 octets.
- Pour chaque flux:
- La liste des numéros de page du flux, 4 octets par page, assez pour couvrir la taille du flux ci-dessus.
Contenu du fluxEdit
Les outils Microsoft stockent différentes sortes d’informations dans différents flux numérotés. Certains numéros de flux sont associés à un type d’information fixe, et d’autres flux sont identifiés dans les flux de type fixe susmentionnés.
Le flux 1 est utilisé pour vérifier que la PDB est le même fichier auquel il est fait référence dans un flux de fichier exécutable ou objet.
- Version, 4 octets.
- Horloge de date et d’heure, 4 octets.
- Age, 4 octets. Il s’agit du nombre de fois où cette PDB a été modifiée depuis sa création.
- GUID, 16 octets.
- Longueur totale des noms suivants, 4 octets. Suivi de chaînes de caractères à terminaison nulle.
Les flux 2 et 4 contiennent des informations sur les types. Les enregistrements de types réels définissent les types utilisés dans le programme. La structure de ces enregistrements se trouve dans le fichier cvinfo.h fourni par Microsoft. Il existe deux types d’enregistrements, chacun avec son propre jeu de numéros d’index : les ID de type et les types ; seuls les types sont stockés dans le flux 2 et seuls les ID de type sont stockés dans le flux 4. Les indices sont utilisés pour se référer à ces enregistrements à partir des enregistrements de symboles et d’autres enregistrements de types.
- Un en-tête:
- Version, 4 octets.
- Taille de l’en-tête, 4 octets.
- Indice minimum et maximum (dernier + 1) pour les enregistrements de types (4 octets chacun).
- Taille des données suivantes, 4 octets, jusqu’à la fin du flux.
- Informations sur le hachage :
- Numéro du flux, 2 octets avec un remplissage de 2 octets.
- Clé du hachage, 4 octets.
- Buckets, 4 octets.
- HashVals, TiOff et HashAdj, composés chacun d’un décalage et d’une longueur, 4 octets chacun.
- Enregistrements de type, longueur variable, compte = (maximum – minimum) de l’en-tête ci-dessus.
Le flux 3 est un répertoire pour les autres flux. Attention, il n’est pas présent dans la version 2, ni dans une PDB produite par un compilateur. Le flux commence par un en-tête qui est paddé pour avoir 64 octets au total
Offset | Size | Nom | Description |
---|---|---|---|
0 | 4 | Signature | Identifiant d’en-tête, == 0xFFFFFF |
4 | 4 | HeaderVersion | Version de l’en-tête |
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 | snPSSyms | |
18 | 2 | usVerPdbDllBuild | version de la dll du pdb qui a construit ce pdb en dernier |
20 | 2 | snSymRecs | |
22 | 2 | VerPdbDllRBld | rbld version du pdb dll qui a construit ce pdb en dernier |
24 | 4 | cbGpModi | taille du sous-flux rgmodi |
28 | 4 | cbSC | taille du sous-flux Section Contribution |
32 | 4 | cbSecMap | taille de la carte des sections |
36 | 4 | cbFileInfo | taille du flux d’informations sur les fichiers |
40 | 4 | cbTSMap | taille du sous-flux de la carte du serveur de types |
44 | 4 | iMFC | Index MFC |
48 | 4 | cbDbgHdr | taille des infos DbgHdr optionnelles ajoutées à la fin du flux |
52 | 4 | cbECInfo | nombre d’octets dans le sous-flux EC, ou 0 si aucun EC n’est activé 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 | Identifiant de la machine, identique à celui utilisé dans le format d’objet COFF, par ex.g., hex 8664 pour Intel x86 64-bit |
60 | 4 | RESERVED | future expansion, pad à 64 octets |
- Information sur le module, longueur variable. Taille totale dans l’en-tête ci-dessus. Il y en a un pour chaque module objet utilisé par le linker
- Opened, 4 octets.
- Info sur le symbole.
- Numéro de section, 2 octets + 2 octets de remplissage.
- Offset et taille, 4 octets chacun.
- Flags, 4 octets.
- Numéro de module, 2 octets + 2 octets de remplissage.
- CRC pour les données de section et les données de relocalisation, 4 octets chacun.
- Flags, 2 octets.
- Numéro de flux, 2 octets.
- Symboles taille, 4 octets.
- Taille des infos de l’ancien et du nouveau numéro de ligne, 4 octets chacun.
- Nombre de fichiers sources, 2 octets + 2 octets de remplissage.
- Offsets, 4 octets.
- niSource et niCompiler, 4 octets chacun.
- Nom du module, chaîne d’octets à terminaison nulle.
- Nom de l’objet, chaîne d’octets à terminaison nulle.
- Padding à un multiple de 4 octets.
- Contributions de section, en-têtes de section, info de fichier, ts map et info EC. Leurs tailles se trouvent dans l’en-tête ci-dessus.
- En-tête de débogage,
- Numéros de flux pour Old Frame Pointer Omission, Exceptions, Fixups, Object Maps to and from Source, Section Headers, Token Ring IDs, Xdata, Pdata, New Frame Pointer Omission, et Section Header Origin. 2 octets chacun.