Base de datos de programas

La PDB es un archivo único que se compone lógicamente de varios subarchivos, llamados flujos. Está diseñado para optimizar el proceso de realizar cambios en la PDB, tal y como se realiza mediante compilaciones y enlaces incrementales. Los flujos pueden ser eliminados, añadidos o reemplazados sin reescribir ningún otro flujo, y los cambios en los metadatos que describen los flujos se minimizan también.

El PDB está organizado en páginas de tamaño fijo, típicamente 1K, 2K o 4K, numeradas consecutivamente comenzando por 0.

Nota: Se supone que toda la información numérica (por ejemplo, números de flujo y de página) se almacena en forma little-endian, la forma nativa de los procesadores basados en Intel x86. El código pdbparse Python hace esta suposición.

StreamEdit

Cada flujo en la PDB ocupa varias páginas, que no están necesariamente numeradas consecutivamente. El flujo tiene un número y una longitud. El contenido del flujo es la concatenación de sus páginas, truncadas a la longitud del flujo.

Formato de los metadatosEditar

La función de los metadatos de la PDB es identificar todos los flujos componentes, dando la longitud, y la secuencia de páginas para cada flujo. Los flujos se numeran consecutivamente empezando por el 0. También hay un flujo raíz, sin numerar, que contiene algunos de los metadatos.

HeaderEdit

El PDB comienza con un encabezado, que consiste en:

  • Signature, utilizado para identificar y validar el formato específico. La longitud de la firma varía según el formato específico.
  • El resto de la cabecera varía según el formato identificado por la firma.

La cabecera puede ser más larga que una sola página.

Las herramientas de Microsoft utilizan dos formatos PDB:

Versión 7Edit

La firma es "Microsoft C/C++ MSF 7.00\r\n\x1ADS"(32 bytes).

El resto de la cabecera consta de:

  • Tamaño de página, 4 bytes.
  • Puntero de tabla de asignación, 4 bytes. El significado de esto es desconocido. Parece que hay una tabla de asignación, una matriz de 65.536 bits (8.192 bytes), situada al final de la PDB, y un 1 bit significa una página que no se está utilizando.
  • Número de páginas del archivo, 4 bytes.
  • Tamaño del flujo raíz, 4 bytes.
  • Reservado, 4 bytes.
  • Número de página de la lista de números de página del flujo raíz. No indica la ubicación del flujo raíz en sí mismo, sólo de la página que contiene la estructura que apunta a sus páginas. En esa página, la lista de números de página del flujo raíz indica las páginas donde se almacena el flujo raíz. Contiene 4 bytes por página, suficientes para cubrir el tamaño del Root stream anterior.

Root streamEdit

El Root stream describe todos los streams de la PDB empezando por el stream 0. Su contenido varía con la versión del formato de la PDB.

Versión 2Editar

El flujo raíz consta de:

  • Número de flujos, 2 bytes.
  • Reservado, 2 bytes.
  • Para cada flujo:
    • Tamaño del flujo, 4 bytes.
    • Reservado, 4 bytes.
  • Para cada flujo:
    • Lista de números de página del flujo, 2 bytes por página, suficiente para cubrir el tamaño del flujo anterior.

Versión 7Edit

El flujo raíz consiste en:

  • Número de flujos, 4 bytes.
  • Para cada flujo:
    • Tamaño del flujo, 4 bytes.
  • Para cada flujo:
    • Lista de números de página del flujo, 4 bytes por página, suficiente para cubrir el tamaño del flujo anterior.

Contenido del flujoEditar

Las herramientas de Microsoft almacenan diferentes tipos de información en diferentes flujos numerados. Algunos números de flujo tienen un tipo de información fija asociada a ellos, y otros flujos se identifican en los mencionados flujos de tipo fijo.

El flujo 1 se utiliza para verificar que el PDB es el mismo archivo al que se hace referencia en un flujo de archivo ejecutable u objeto.

  • Versión, 4 bytes.
  • Fecha de caducidad, 4 bytes.
  • Edad, 4 bytes. Es el número de veces que se ha modificado este PDB desde su creación.
  • GUID, 16 bytes.
  • Longitud total de los nombres siguientes, 4 bytes. Seguido de cadenas de caracteres terminadas en cero.

El flujo 2 y el flujo 4 contienen información sobre los tipos. Los registros de tipos reales definen los tipos utilizados en el programa. La estructura de estos registros se puede encontrar en el archivo cvinfo.h proporcionado por Microsoft. Hay dos tipos de registros, cada uno con su propio conjunto de números de índice: IDs de tipo y tipos; sólo los tipos se almacenan en el flujo 2 y sólo los IDs de tipo se almacenan en el flujo 4. Los índices se utilizan para referirse a estos registros desde dentro de los registros de símbolos y otros registros de tipos.

  • Una cabecera:
    • Versión, 4 bytes.
    • Tamaño de la cabecera, 4 bytes.
    • Índice mínimo y máximo (último + 1) para los registros de tipos (4 bytes cada uno).
    • Tamaño de los datos siguientes, 4 bytes, hasta el final del flujo.
  • Información del Hash:
    • Número de flujo, 2 bytes con 2 bytes de relleno.
    • Clave del Hash, 4 bytes.
    • Buckets, 4 bytes.
    • HashVals, TiOff, y HashAdj, cada uno compuesto por un offset y una longitud, cada uno de 4 bytes.
  • Registros de tipo, longitud variable, cuenta = (máximo – mínimo) de la cabecera anterior.

El flujo 3 es un directorio para otros flujos. Tenga en cuenta que no está presente en la versión 2, ni en un PDB producido por un compilador. El flujo comienza con una cabecera que se rellena para tener 64 bytes en total

Cabecera del flujo 3 de la PDB (struct NewDBIHdr)
Offset Size Name Description
0 4 Signature Header identifier, == 0xFFFFFF
4 4 HeaderVersion Versión del encabezado
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 versión del pdb dll que construyó este pdb por última vez
20 2 snSymRecs
22 2 VerPdbDllRBld versión rbld de la dll pdb que construyó este pdb por última vez
24 4 cbGpModi tamaño del subflujo rgmodi
28 4 cbSC tamaño del subflujo Section Contribution
32 4 cbSecMap tamaño del mapa de sección
36 4 cbFileInfo tamaño del flujo de información del archivo
40 4 cbTSMap tamaño del subflujo Type Server Map
44 4 iMFC MFC Index
48 4 cbDbgHdr tamaño de la información DbgHdr opcional añadida al final del flujo
52 4 cbECInfo número de bytes en el subflujo EC, o 0 si no hay EC habilitado 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 Identificador de máquina, el mismo que se utiliza en el formato de objeto COFF, por ejemplog., hex 8664 para Intel x86 64-bit
60 4 RESERVED expansión futura, relleno de 64 bytes
  • Información del módulo, longitud variable. Tamaño total en la cabecera anterior. Hay uno de estos para cada módulo de objeto utilizado por el enlazador
    • Apertura, 4 bytes.
    • Información de símbolos.
      • Número de sección, 2 bytes + 2 bytes de relleno.
      • Desplazamiento y tamaño, 4 bytes cada uno.
      • Banderas, 4 bytes.
      • Número de módulo, 2 bytes + 2 bytes de relleno.
      • CRCs para datos de sección y datos de reubicación, 4 bytes cada uno.
    • Flags, 2 bytes.
    • Número de flujo, 2 bytes.
    • Tamaño de los símbolos, 4 bytes.
    • Tamaño de la información del número de línea antiguo y nuevo, 4 bytes cada uno.
    • Número de archivos fuente, 2 bytes + 2 bytes de relleno.
    • Offsets, 4 bytes.
    • niSource y niCompiler, 4 bytes cada uno.
    • Nombre del módulo, cadena de bytes con terminación nula.
    • Nombre del objeto, cadena de bytes con terminación nula.
    • Relleno a múltiplo de 4 bytes.
  • Contribuciones de sección, cabeceras de sección, información de archivo, mapa ts e información EC. Sus tamaños se encuentran en la cabecera anterior.
  • Cabecera de depuración,
    • Números de flujo para omisión de puntero de trama antigua, excepciones, arreglos, mapas de objetos hacia y desde el origen, cabeceras de sección, ID de anillo de tokens, Xdata, Pdata, omisión de puntero de trama nueva y origen de cabecera de sección. 2 bytes cada uno.