Símbolos públicos y privados

Cuando un enlazador crea un archivo de símbolos .pdb o .dbg de tamaño completo, contiene dos colecciones distintas de información: los datos de símbolos privados y una tabla de símbolos públicos. Estas colecciones difieren en la lista de elementos que contienen y la información que almacenan sobre cada elemento.

Los datos de símbolos privados incluyen los siguientes elementos:

  • Functions

  • Variables globales

  • Variables locales

  • Información sobre estructuras, clases y tipos de datos definidos por el usuario

  • El nombre del archivo de origen y el número de línea de ese archivo correspondiente a cada instrucción binaria

La tabla de símbolos públicos contiene menos elementos:

  • Funciones (excepto las funciones declaradas estáticas)

  • Variables globales especificadas como extern (y cualquier otra variable global visible en varios archivos de objetos)

Como regla general, la tabla de símbolos públicos contiene exactamente los elementos a los que se puede acceder desde un archivo de origen a otro. Los elementos visibles en un solo archivo de objeto, como funciones estáticas , variables que solo son globales dentro de un único archivo de origen y variables locales, no se incluyen en la tabla de símbolos públicos.

Estas dos colecciones de datos también difieren en la información que incluyen para cada elemento. La siguiente información se incluye normalmente para cada elemento contenido en los datos de símbolos privados :

  • Nombre del elemento

  • Dirección del elemento en memoria virtual

  • Tipo de datos de cada variable, estructura y función

  • Tipos y nombres de los parámetros de cada función

  • Ámbito de cada variable local

  • Símbolos asociados a cada línea de cada archivo de origen

  • Registros de omisión del puntero de marco (FPO) para cada función usada para acceder a la pila

Por otro lado, la tabla de símbolos públicos almacena solo la siguiente información sobre cada elemento incluido en ella:

  • Nombre del elemento.

  • Dirección del elemento en el espacio de memoria virtual de su módulo. Para una función, esta es la dirección de su punto de entrada.

  • Registros de omisión del puntero de marco (FPO) para cada función.

  • Puede incluir prefijos o sufijos de símbolos a los que se hace referencia como decoraciones.

Los datos de símbolos públicos se pueden considerar como un subconjunto de los datos de símbolos privados de dos maneras: contiene una lista más corta de elementos y también contiene menos información sobre cada elemento. Por ejemplo, los datos de símbolos públicos no incluyen variables locales.

Cada variable local solo se incluye en los datos del símbolo privado, con su dirección, tipo de datos y ámbito. Por otro lado, las funciones se incluyen tanto en los datos de símbolos privados como en la tabla de símbolos públicos, pero mientras que los datos del símbolo privado incluyen el nombre de la función, la dirección, los registros FPO, los tipos y los tipos de parámetros de entrada, y el tipo de salida, la tabla de símbolos públicos incluye solo el nombre de la función, la dirección y el registro FPO.

Hay otra diferencia entre los datos de símbolos privados y la tabla de símbolos públicos. Muchos de los elementos de la tabla de símbolos públicos tienen nombres que están decorados con un prefijo, un sufijo o ambos. El compilador de C, el compilador de C y el ensamblador de MASM agregan estas decoraciones. Los prefijos típicos incluyen una serie de caracteres de subrayado o la cadena __imp_ (designando una función importada). Los sufijos típicos incluyen uno o varios signos ( @ ) seguidos de direcciones u otras cadenas de identificación. El enlazador usa estas decoraciones para eliminar la ambigüedad del símbolo, ya que es posible que los nombres de función o los nombres de variables globales se puedan repetir en distintos módulos. Estas decoraciones son una excepción a la regla general de que la tabla de símbolos públicos es un subconjunto de los datos de símbolos privados.

Archivos de símbolos completos y archivos de símbolos eliminados

Un archivo de símbolos completo contiene los datos de símbolos privados y la tabla de símbolos públicos. Este tipo de archivo se conoce a veces como un archivo de símbolos privado, pero este nombre es engañoso, para este tipo de archivo contiene símbolos privados y públicos.

Un archivo de símbolos quitado es un archivo más pequeño que contiene solo la tabla de símbolos públicos, o, en algunos casos, solo un subconjunto de la tabla de símbolos públicos. Este archivo se conoce a veces como un archivo de símbolos público.

Crear archivos de símbolos completos y eliminados

Si compila los archivos binarios con Visual Studio, puede crear archivos de símbolos completos o eliminados. Para obtener información sobre cómo crear símbolos quitados, vea /PDBSTRIPPED (Quitar símbolos privados).

Con la herramienta BinPlace, puede crear un archivo de símbolos quitado de un archivo de símbolos completo. Cuando se usan las opciones de BinPlace más comunes (-a -x -s -n), los archivos de símbolos quitados se colocan en el directorio que aparece después del modificador -s y los archivos de símbolos completos se colocan en el directorio que aparece después del modificador -n . Cuando BinPlace quita un archivo de símbolos, las versiones quitadas y completas del archivo reciben firmas idénticas y otra información de identificación. Esto le permite usar cualquiera de las versiones para la depuración. Para obtener más información sobre BinPlace, vea BinPlace.

Con la herramienta PDBCopy, puede crear un archivo de símbolos quitado de un archivo de símbolos completo quitando los datos del símbolo privado. PDBCopy también puede quitar un subconjunto especificado de la tabla de símbolos públicos. Para más información, consulte PDBCopy.

Con la herramienta SymChk, puede determinar si un archivo de símbolos contiene símbolos privados. Para obtener más información, consulte SymChk.

Visualización de símbolos públicos y privados en el depurador

Puede usar WinDbg, KD o CDB para ver símbolos. Cuando uno de estos depuradores tiene acceso a un archivo de símbolos completo, tiene la información que se muestra en los datos de símbolos privados y la información que aparece en la tabla de símbolos públicos. Los datos de símbolos públicos contienen decoraciones de símbolos.

Al acceder a símbolos privados, siempre se usan datos de símbolos privados porque estos símbolos no se incluyen en la tabla de símbolos públicos. Estos símbolos nunca están decorados.

El comando .symopt (Establecer opciones de símbolos) se puede usar para controlar las opciones de símbolos que determinan cómo usan el depurador los símbolos públicos y privados. Por ejemplo, este comando activa la información de depuración de símbolos.

 .symopt+ 0x80000000

Las siguientes opciones cambian cómo se usan los símbolos públicos y privados en el depurador.

  • Cuando la opción SYMOPT_UNDNAME está activada, las decoraciones no se incluyen cuando se muestra el nombre de un símbolo público. Además, al buscar símbolos, se omiten las decoraciones. Cuando esta opción está desactivada, las decoraciones se muestran al mostrar símbolos públicos y las decoraciones se usan en búsquedas. Los símbolos privados nunca están decorados en ninguna circunstancia. Esta opción está activada de forma predeterminada en todos los depuradores.

  • Cuando la opción SYMOPT_PUBLICS_ONLY está activada, se omiten los datos de símbolos privados y solo se usa la tabla de símbolos públicos. Esta opción está desactivada de forma predeterminada en todos los depuradores.

  • Cuando la opción SYMOPT_NO_PUBLICS está activada, se omite la tabla de símbolos públicas y se busca y la información de símbolos usa solo los datos de símbolos privados. Esta opción está desactivada de forma predeterminada en todos los depuradores.

  • Cuando la opción SYMOPT_AUTO_PUBLICS está activada (y SYMOPT_PUBLICS_ONLY y SYMOPT_NO_PUBLICS están desactivadas), la primera búsqueda de símbolos se realiza en los datos de símbolos privados. Si el símbolo deseado se encuentra allí, la búsqueda finaliza. Si no es así, se busca en la tabla de símbolos públicos. Puesto que la tabla de símbolos públicos contiene un subconjunto de los símbolos de los datos privados, normalmente esto provoca que se omita la tabla de símbolos públicos.

  • Cuando las opciones SYMOPT_PUBLICS_ONLY, SYMOPT_NO_PUBLICS y SYMOPT_AUTO_PUBLICS están desactivadas, se buscan los datos de símbolos privados y la tabla de símbolos públicos cada vez que se necesita un símbolo. Sin embargo, cuando se encuentran coincidencias en ambos lugares, se usa la coincidencia en los datos de símbolos privados. Por lo tanto, el comportamiento de esta instancia es el mismo que cuando SYMOPT_AUTO_PUBLICS está activado, salvo que el uso de SYMOPT_AUTO_PUBLICS puede hacer que las búsquedas de símbolos se produzcan un poco más rápido.

Este es un ejemplo en el que el comando x (Examinar símbolos) se usa tres veces. La primera vez que se usan las opciones de símbolos predeterminadas, por lo que la información se toma de los datos del símbolo privado. Tenga en cuenta que esto incluye información sobre la dirección, el tamaño y el tipo de datos de la matriz typingString. A continuación, se usa el comando .symopt+ 4000, lo que hace que el depurador omita los datos del símbolo privado. Cuando se vuelve a ejecutar el comando x , se usa la tabla de símbolos públicos; esta vez no hay información de tamaño ni de tipo de datos para typingString. Por último, se usa el comando .symopt- 2, lo que hace que el depurador incluya decoraciones. Cuando el comando x se ejecuta esta última vez, se muestra la versión decorada del nombre de la función, _typingString.

0:000> x /t /d *!*typingstring* 
00434420 char [128] TimeTest!typingString = char [128] ""

0:000> .symopt+ 4000

0:000> x /t /d *!*typingstring* 
00434420 <NoType> TimeTest!typingString = <no type information>

0:000> .symopt- 2

0:000> x /t /d *!*typingstring* 
00434420 <NoType> TimeTest!_typingString = <no type information> 

Visualización de símbolos públicos y privados con la herramienta DBH

Otra manera de ver símbolos es mediante la herramienta DBH . Muestra las opciones de ayuda con la /? opción .

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>dbh /?
dbh dbghelp shell
usage: dbh [-n] [-c] [-d] [-?] [-??] [-p] [targetmodule] [command]
       [-n]             display noisy symbol spew
       [-d]             use decorated publics
       [-p:XXXX]        attaches to process ID XXXX
       [-s:SSSS]        set symbol path to SSSS
       [-c]             callbacks return false
       [targetmodule]   load symbols for specified module
       [command]        execute command and exit
       [-?]             display these usage instructions
       [-??]            display detailed usage instructions

Use una herramienta como Tlist para enumerar los identificadores de proceso y la opción -p para asociar a un proceso existente.

C:\Program Files (x86)\Windows Kits\10\Debuggers\x64>dbh -p:4308

DBH usa las mismas opciones de símbolo que el depurador. Al igual que el depurador, DBH deja SYMOPT_PUBLICS_ONLY y SYMOPT_NO_PUBLICS desactivado de forma predeterminada, y activa SYMOPT_UNDNAME y SYMOPT_AUTO_PUBLICS de forma predeterminada. Estos valores predeterminados se pueden invalidar mediante una opción de línea de comandos o un comando DBH.

Este es un ejemplo en el que se usa el agregador de comandos de DBH 414fe0 tres veces. La primera vez que se usan las opciones de símbolo predeterminadas, por lo que la información se toma de los datos del símbolo privado. Tenga en cuenta que esto incluye información sobre la dirección, el tamaño y el tipo de datos de la función fgets. A continuación, se usa el comando symopt +4000, lo que hace que DBH ignore los datos del símbolo privado. Cuando se vuelve a ejecutar el addr 414fe0 , se usa la tabla de símbolos públicos; esta vez no hay información de tamaño y tipo de datos para los fgets de la función. Por último, se usa el comando symopt -2, lo que hace que DBH incluya decoraciones. Cuando el agregador 414fe0 se ejecuta esta última vez, se muestra la versión decorada del nombre de la función, _fgets.

pid:4308 mod:TimeTest[400000]: addr 414fe0

fgets
   name : fgets
   addr :   414fe0
   size : 113
  flags : 0
   type : 7e
modbase :   400000
  value :        0
    reg : 0
  scope : SymTagNull (0)
    tag : SymTagFunction (5)
  index : 7d

pid:4308 mod:TimeTest[400000]: symopt +4000

Symbol Options: 0x10c13
Symbol Options: 0x14c13

pid:4308 mod:TimeTest[400000]: addr 414fe0

fgets
   name : fgets
   addr :   414fe0
   size : 0
  flags : 0
   type : 0
modbase :   400000
  value :        0
    reg : 0
  scope : SymTagNull (0)
    tag : SymTagPublicSymbol (a)
  index : 7f

pid:4308 mod:TimeTest[400000]: symopt -2

Symbol Options: 0x14c13
Symbol Options: 0x14c11

pid:4308 mod:TimeTest[400000]: addr 414fe0

_fgets
   name : _fgets
   addr :   414fe0
   size : 0
  flags : 0
   type : 0
modbase :   400000
  value :        0
    reg : 0
  scope : SymTagNull (0)
    tag : SymTagPublicSymbol (a)
  index : 7f 

Información adicional

Para obtener más información sobre los símbolos, vea Sintaxis de símbolos y Coincidencia de símbolos, Opciones de símbolos, Abreviaturas de estado de símbolos y Carga diferida de símbolos.