Depuración con símbolos

En este artículo se proporciona información general de alto nivel sobre cómo usar mejor los símbolos en el proceso de depuración. Se explica cómo usar el servidor de símbolos de Microsoft y también cómo configurar y usar su propio servidor de símbolos privado. Estos procedimientos recomendados pueden ayudar a aumentar la eficacia y la capacidad de depurar problemas, incluso en casos en los que todos los símbolos y archivos ejecutables relacionados con un problema no se encuentran en el equipo.

Símbolos

Hay disponibles varios tipos diferentes de símbolos para la depuración. Incluyen símbolos de CodeView, COFF, DBG, SYM, PDB e incluso símbolos de exportación generados a partir de una tabla de exportación de archivos binarios. En este documento técnico solo se describen VS.NET y los símbolos de formato PDB, ya que son el formato preferido más reciente. Se generan de forma predeterminada para los proyectos compilados mediante Visual Studio.

La generación de archivos PDB para archivos ejecutables de versión no afecta a ninguna optimización ni modifica significativamente el tamaño de los archivos generados. Normalmente, la única diferencia es la ruta de acceso y el nombre de archivo del archivo PDB se inserta en el archivo ejecutable. Por este motivo, siempre debe generar archivos PDB, incluso si no desea enviarlos con el ejecutable.

Los archivos PDB se generan si se compila un proyecto mediante el modificador del compilador /Zi o /ZI (Generar información de PDB), junto con el modificador del enlazador /DEBUG (Generar información de depuración). Los archivos PDB generados por el compilador se combinan y escriben en un único archivo PDB que se coloca en el mismo directorio que el ejecutable.

De forma predeterminada, los archivos PDB contienen la siguiente información:

  • Símbolos públicos (normalmente todas las funciones, variables estáticas y globales)
  • Lista de archivos de objeto responsables de secciones de código en el ejecutable
  • Información de optimización del puntero de marco (FPO)
  • Información de nombre y tipo para variables locales y estructuras de datos
  • Información de número de línea y archivo de origen

Si le preocupa a los usuarios que usan la información del archivo PDB para ayudarles a diseñar inverso el archivo ejecutable, también puede generar archivos PDB eliminados mediante la opción del enlazador /PDBSTRIPPED:filename. Si tiene archivos PDB existentes de los que desea quitar información privada, puede usar una herramienta denominada pdbcopy, que forma parte de las herramientas de depuración para Windows.

De forma predeterminada, los archivos PDB eliminados contienen la siguiente información:

  • Símbolos públicos (normalmente solo funciones no estáticas y variables globales)
  • Lista de archivos de objeto responsables de secciones de código en el ejecutable
  • Información de optimización del puntero de marco (FPO)

Esta es la información mínima necesaria para permitir la depuración confiable. La información mínima también dificulta la obtención de información adicional sobre el código fuente original. Dado que se genera un archivo PDB quitado y un archivo PDB normal, puede proporcionar la versión eliminada a los usuarios que pueden necesitar capacidades de depuración limitadas, pero mantener confidenciales los PDB completos. Tenga en cuenta que /PDBSTRIPPED genera un segundo archivo PDB más pequeño, por lo que debe asegurarse de usar el archivo PDB correcto al generar compilaciones para distribuir de forma amplia. Para un proyecto típico, una PDB normal puede tener un tamaño de unos pocos megabytes, pero una versión despojada de la PDB puede ser solo unos pocos cientos de kilobytes.

Usar símbolos para la depuración

Al depurar una aplicación que se ha bloqueado, el depurador intenta mostrar las funciones de la pila que provocaron el bloqueo. Sin un archivo PDB, el depurador no puede resolver los nombres de función, sus parámetros ni las variables locales almacenadas en la pila. Si depura ejecutables de 32 bits, hay situaciones en las que ni siquiera puede obtener seguimientos de pila confiables sin símbolos. A veces es posible examinar los valores sin procesar de la pila y averiguar qué valores pueden devolver direcciones, pero estos pueden confundirse fácilmente con las referencias de función o los datos.

Si las funciones de la pila actual se compilaron mediante la optimización Omitir punteros de marco (/Oy) y, si los símbolos no están presentes, el depurador no puede determinar de forma confiable qué función llamó a la función actual. Esto se debe a que sin la información de optimización de puntero de marco (FPO) que contienen los archivos PDB, el depurador no puede confiar en el registro de puntero de marco (EBP) para apuntar al puntero de marco anterior guardado y en la dirección de retorno de la función primaria. En su lugar, trata de adivinar. A veces acierta. Sin embargo, con frecuencia se equivoca, lo que puede ser engañoso. Si ve una advertencia sobre los símbolos que faltan o ningún símbolo cargado, como en el ejemplo siguiente, no confíe en la pila desde ese punto hacia abajo.

SWPerfTest.exe!TextFunction(... ...)    Line 59    C++
d3dx9d.dll!008829b5()
[Frames below may be incorrect and/or missing, no symbols loaded for d3dx9d.dll]
SWPerfTest.exe!main(int argc=, const char * * argv=)  Line 328 + 0x12 bytes     C++
SWPerfTest.exe!__mainCRTStartup() Line 716 + 0x17 bytes    C
kernel32.dll!@BaseThreadInitThunk@12() + 0x12 bytes
ntdll.dll!__RtlUserThreadStart@8() + 0x27 bytes

En muchos casos, es posible seguir depurando sin símbolos, ya que el problema está en una ubicación que tiene símbolos precisos y no es necesario examinar las funciones más abajo de la pila de llamadas. Incluso si una biblioteca que se encuentra en la pila de llamadas no tiene archivos PDB disponibles, siempre y cuando se compilaran con punteros de marco, el depurador debería poder adivinar correctamente en las funciones primarias. A partir de Windows XP Service Pack 2, todos los archivos DLL de Windows y ejecutables se compilan con FPO deshabilitado, ya que hace que la depuración sea más precisa. Deshabilitar FPO también permite a los generadores de perfiles de muestreo recorrer la pila durante el tiempo de ejecución, con un impacto mínimo en el rendimiento. En las versiones de Windows anteriores a Windows XP SP2, todos los archivos binarios del sistema operativo requieren archivos de símbolos coincidentes que contienen información de FPO, para permitir una depuración y generación de perfiles precisas.

Si depura ejecutables nativos de 64 bits, no necesita archivos de símbolos para generar seguimientos de pila válidos, ya que los sistemas operativos y compiladores x64 están diseñados para no requerirlos. Sin embargo, todavía necesita archivos de símbolos para recuperar los nombres de función, llamar a parámetros y variables locales.

Sin embargo, algunos casos son especialmente difíciles de depurar sin símbolos. Por ejemplo, si depura un programa para el que creó un archivo PDB y si se bloquea en una devolución de llamada de una función de un archivo DLL para el que no tiene símbolos, no podrá ver qué función provocó la devolución de llamada, ya que no podrá descodificar la pila. Esto sucede con frecuencia en bibliotecas de terceros, si no se proporcionan archivos PDB o en componentes antiguos del sistema operativo, si los archivos PDB no están disponibles. A menudo, las devoluciones de llamada se producen durante el paso de mensajes, la enumeración, la asignación de memoria o el control de excepciones. La depuración de estas funciones sin una pila precisa puede ser frustrante.

Para depurar de forma confiable minivolcados que se generan en un equipo diferente o que se bloquean en el código que no posee, es importante poder acceder a todos los símbolos y archivos binarios de los ejecutables a los que se hace referencia en el minivolcado. Si los símbolos y archivos binarios están disponibles en un servidor de símbolos, el depurador los obtiene automáticamente. Para obtener más información sobre minivolcados, consulte las notas del producto Análisis de volcado de memoria.

Obtención de los símbolos que necesita

Visual Studio y otros depuradores de Microsoft, como WinDbg, normalmente se configuran para que funcionen solo si va a compilar una aplicación y depurarla en su propio equipo. Si necesita proporcionar el archivo ejecutable a otra persona, si tiene varias versiones de un archivo DLL o un archivo .exe en el equipo, o si desea depurar con precisión una aplicación que use Windows u otras bibliotecas, como DirectX, debe comprender cómo los depuradores buscan y cargan símbolos. El depurador usa la ruta de acceso de búsqueda de símbolos especificada por el usuario, que se encuentra en Options\Debugging\Symbols en Visual Studio, o la variable de entorno _NT_SYMBOL_PATH. Normalmente, el depurador busca archivos PDB coincidentes en las siguientes ubicaciones:

  • La ubicación que se especifica dentro del archivo DLL o el archivo ejecutable.

    Si ha creado un archivo DLL o un archivo ejecutable en el equipo, el enlazador coloca de forma predeterminada la ruta de acceso completa y el nombre de archivo del archivo PDB asociado dentro del archivo DLL o el archivo ejecutable. Al depurar, el depurador comprueba primero si el archivo de símbolos existe en la ubicación especificada dentro del archivo DLL o el archivo ejecutable. Esto resulta útil, ya que siempre tiene símbolos disponibles para el código que ha compilado en el equipo.

  • Archivos PDB que pueden estar presentes en la misma carpeta que el archivo DLL o ejecutable.

  • Cualquier carpeta de caché de símbolos local.

  • Cualquier servidor de símbolos de recurso compartido de archivos de red local.

  • Cualquier servidor de símbolos de Internet, como el servidor de símbolos de Microsoft.

Para asegurarse de que tiene todos los archivos PDB que necesita para la depuración precisa, instale las herramientas de depuración para Windows. Las versiones de 32 y 64 bits se pueden encontrar en Herramientas de depuración para Windows.

Una herramienta útil que se instala con este paquete es symchk.exe. Puede ayudar a identificar símbolos que faltan o son incorrectos. Esta herramienta tiene un gran número de posibles opciones de línea de comandos. Estas son dos de las más útiles y más usadas.

Compruebe si un archivo DLL o .exe determinado y PDB en la misma carpeta coinciden

"c:\Program Files\Debugging Tools for Windows\symchk" testing.dll /s .

SYMCHK: FAILED files = 0
SYMCHK: PASSED + IGNORED files = 1

La opción /s indica a symchk que busque símbolos solo en la carpeta actual y no busque ningún servidor de símbolos.

Compruebe si todos los archivos DLL y ejecutables de un conjunto de carpetas tienen archivos PDB coincidentes

"c:\Program Files\Debugging Tools for Windows\symchk" *.* /r

La opción /r establece symchk para recorrer de forma recursiva las carpetas para comprobar que todos los archivos ejecutables tienen archivos PDB coincidentes. Sin la opción /s, symchk usa el _NT_SYMBOL_PATH actual para buscar símbolos en cualquier servidor privado o local, o en los servidores de símbolos de Microsoft. La herramienta symchk solo busca símbolos para archivos ejecutables (.exe, .dll y similares). No puede usar la búsqueda de caracteres comodín para los archivos no ejecutables.

Funcionamiento de symchk

Cuando el enlazador genera archivos .dll, ejecutable y PDB, almacena GUID idénticos en cada archivo. Las herramientas usan el GUID para determinar si un archivo PDB determinado coincide con un archivo DLL o un archivo ejecutable. Si modifica un archivo DLL o un archivo ejecutable, mediante un editor de recursos o una codificación de protección de copia, o modificando su información de versión, el GUID se actualiza y el depurador no puede cargar el archivo PDB. Por este motivo, es muy importante evitar manipular el archivo DLL o ejecutable después de crearlo el enlazador.

También puede usar la utilidad DUMPBIN que viene con VS.NET para mostrar las rutas de acceso de símbolos que se buscan y para ver si se encuentran archivos de símbolos que coinciden con un archivo DLL o ejecutable determinado. Por ejemplo:

DUMPBIN /PDBPATH:VERBOSE filename.exe

Servidores de símbolos

Un servidor de símbolos es un repositorio para varias versiones de archivos ejecutables y de símbolos. Contiene los propios archivos de símbolos o punteros a los archivos de símbolos asociados. Los depuradores reconocen cómo usar servidores de símbolos y pueden usarlos para buscar símbolos que faltan o desconocidos.

Los archivos DLL y ejecutables también están disponibles en el servidor de símbolos de Microsoft. Esto permite depurar bloqueos y examinar el código de los archivos del sistema operativo que pueden no existir en la máquina. Si un depurador encuentra un archivo ejecutable o un archivo DLL que no existe en el sistema que está usando para la depuración, solicita automáticamente los símbolos y una copia del archivo binario de los servidores de símbolos de Microsoft. Esto resulta útil si está depurando un componente que tiene muchas versiones (por ejemplo, msvcrt.dll) y debe examinar el código de una versión que no existe en el equipo. Esto también ayuda a depurar minivolcados que se generan en un sistema operativo diferente del sistema que se usa para la depuración.

Microsoft publica todos los archivos PDB para todos los sistemas operativos y otros componentes redistribuidos, como el SDK de DirectX, en su servidor de símbolos accesible externamente. Esto facilita la depuración de una aplicación que usa estos archivos DLL o ejecutables. Puede usar el servidor de símbolos de Microsoft para resolver símbolos, junto con los símbolos locales de los componentes creados en el equipo.

Puede configurar el equipo para que use el servidor de símbolos de Microsoft, que proporciona acceso a todos los archivos de símbolos de Microsoft. También puede configurar un servidor de símbolos privado para su empresa, equipo o red, que se puede usar para almacenar varias versiones anteriores de un proyecto en el que está trabajando o para proporcionar una caché local para los símbolos que usa desde el servidor de símbolos de Microsoft.

Para usar un servidor de símbolos, especifique la ruta de acceso de búsqueda en una variable de entorno denominada _NT_SYMBOL_PATH. Los depuradores y las herramientas modernas, como WinDbg, NTSD o Visual Studio, usan automáticamente esta ruta de acceso para buscar símbolos.

Cuando un depurador busca símbolos, primero busca localmente. A continuación, se ve en los servidores de símbolos. Cuando encuentra un símbolo coincidente, transfiere el archivo de símbolos a la memoria caché local. Los símbolos de un archivo DLL o ejecutable típico oscilan entre 1 y 100 MB de tamaño. Por lo tanto, si está depurando un proceso que incluye muchos archivos DLL, puede tardar algún tiempo en resolver todos los símbolos y transferirlos a una caché local.

Uso del servidor de símbolos de Microsoft

El servidor de símbolos de Microsoft permite obtener todos los símbolos más recientes, incluidos los símbolos de los archivos revisados o actualizados. El servidor de símbolos de Microsoft está disponible en https://msdl.microsoft.com/download/symbols.

Puede acceder al servidor de símbolos de una de las maneras siguientes:

  • Escriba la dirección del servidor directamente. En Visual Studio, en el menú Herramientas, elija Opciones, luego Depuración, y a continuación Símbolos.

  • Use la variable de entorno _NT_SYMBOL_PATH. Se recomienda este método.

    Esto lo usan todas las herramientas de depuración. Visual Studio también lo usa y se lee y descodifica cuando Se abre Visual Studio. Por lo tanto, si lo cambia, debe reiniciar Visual Studio.

    Esta variable de entorno permite especificar varios servidores de símbolos, por ejemplo, un servidor de símbolos privado interno. También permite especificar un directorio de caché local para almacenar archivos PDB para todos los símbolos que busque desde servidores de símbolos, tanto internamente como a través de Internet.

La sintaxis de la variable _NT_SYMBOL_PATH es:

srv*[local cache]*[private symbol server]*https://msdl.microsoft.com/download/symbols

Reemplace [caché local] por el nombre de un directorio en el equipo donde desea almacenar una memoria caché de los símbolos usados, por ejemplo, %SYSTEMROOT%\Symbols o c:\symbols.

El [servidor de símbolos privados] es opcional. Puede apuntar a un servidor de símbolos que se encuentra en la red, o bien puede apuntar a un servidor de símbolos compartido por su equipo, grupo de productos o empresa.

Para usar solo el servidor de símbolos de Microsoft junto con una caché local de símbolos, para acelerar el acceso a través de Internet, use la siguiente configuración para _NT_SYMBOL_PATH:

srv*c:\symbols*https://msdl.microsoft.com/download/symbols

Puede encontrar otras opciones para el _NT_SYMBOL_PATH en el archivo de ayuda que se instala con el paquete Herramientas de depuración de Microsoft para Windows.

Los ejecutables sin símbolos pueden aumentar el tiempo necesario para iniciar un depurador si usa un servidor de símbolos. Esto se debe a que el depurador consulta el servidor de símbolos cada vez que intenta cargar el ejecutable. Por este motivo, es mejor solicitar siempre símbolos para todos los componentes.

Es posible que no sea posible solicitar símbolos para cada componente; por ejemplo, los controladores de vídeo pueden tener archivos DLL en el espacio de proceso y los archivos PDB necesarios están disponibles en el servidor de símbolos de Microsoft. En este caso, hay un pequeño retraso al iniciar una sesión de depuración.

Para evitar incluso este pequeño retraso, puede ejecutar el depurador una vez para almacenar en caché todos los símbolos localmente desde el servidor de símbolos de Microsoft. A continuación, modifique el _NT_SYMBOL_PATH para quitar el servidor de símbolos de Microsoft. A menos que cambien los archivos ejecutables, compruebe si hay archivos ejecutables que no tienen símbolos no requerirá una consulta a través de Internet, ya que tiene copias almacenadas en caché local de todos los símbolos que necesita del servidor de símbolos de Microsoft.

Obtener símbolos manualmente

Si ha configurado el depurador correctamente, carga automáticamente los símbolos que requiere de la memoria caché local o desde un servidor de símbolos. Si desea obtener los símbolos de solo un archivo ejecutable o para una carpeta de ejecutables, puede usar symchk. Por ejemplo, si desea descargar los símbolos del archivo d3dx9_30.dll en la carpeta Sistema de Windows en el directorio actual, puede usar el siguiente comando:

"c:\Program Files\Debugging Tools for Windows\symchk" c:\Windows\System32\d3dx9_30.dll /oc \.

La herramienta symchk tiene muchos otros usos. Para obtener más información, consulte symchk /?, o busque en la documentación de Herramientas de depuración de Microsoft para Windows.

Configurar un servidor de símbolos

Configurar un servidor de símbolos es muy sencillo. Es útil por los siguientes motivos:

  • Para ahorrar ancho de banda o acelerar la resolución de símbolos para su empresa, equipo o producto. Un servidor de símbolos interno en un recurso compartido de archivos local de la red almacena en caché las referencias a servidores de símbolos externos, como el servidor de símbolos de Microsoft. Muchas personas pueden acceder rápidamente a un servidor de símbolos local o interno al mismo tiempo. Por lo tanto, ahorra ancho de banda y la latencia que pueden crear las solicitudes de símbolos duplicados.
  • Para almacenar símbolos para compilaciones, versiones o versiones externas antiguas de la aplicación. Al almacenar los símbolos de estas compilaciones en un servidor de símbolos al que puede acceder fácilmente, puede depurar bloqueos y problemas en estas compilaciones en cualquier equipo que tenga un depurador y una conexión con el servidor de símbolos local. Esto es especialmente útil si depura minivolcados generados por ejecutables que no se compilaron usted mismo, es decir, compilaciones generadas por otro programador o por una máquina de compilación. Si los símbolos de estas compilaciones se almacenan en el servidor de símbolos, tendrá una depuración confiable y precisa.
  • Para mantener actualizados los símbolos. Cuando se actualizan los componentes, como los componentes del sistema operativo modificados por Windows Update o por el SDK de DirectX, todavía puede depurar con todos los símbolos más recientes.

Configurar un servidor de símbolos en su propia red local es tan sencillo como crear un recurso compartido de archivos en un servidor y conceder a los usuarios permisos completos para acceder al recurso compartido, para crear archivos y carpetas. Este recurso compartido debe crearse en un sistema operativo de servidor, como Windows Server 2003, para que el número de personas que puedan acceder al recurso compartido simultáneamente no esté limitada.

Por ejemplo, si configura un recurso compartido de archivos en \\mainserver\symbols, los miembros del equipo establecen el _NT_SYMBOL_PATH en lo siguiente:

Srv*c:\symbols*\\mainserver\symbols*https://msdl.microsoft.com/download/symbols

A medida que se recuperan símbolos, los archivos y las carpetas aparecen en el directorio compartido \\mainserver\symbols, así como en cachés individuales, en el directorio c:\symbols.

Esto suele ser todo lo que implica configurar y usar su propio servidor de símbolos o el servidor de símbolos de Microsoft.

Cómo agregar símbolos en un servidor de símbolos

Para agregar, eliminar o editar archivos en un recurso compartido de servidor de símbolos, use la herramienta symstore.exe. Esta herramienta forma parte del paquete Herramientas de depuración de Microsoft para Windows. La documentación completa sobre los servidores de símbolos, la herramienta symstore y los símbolos de indexación se incluyen en el paquete Herramientas de depuración para Windows.

Puede que quiera agregar símbolos directamente a su propio servidor de símbolos, como parte de un proceso de compilación, o para que los símbolos estén disponibles para todo el equipo para bibliotecas o herramientas de terceros. El proceso de agregar un símbolo a un recurso compartido de archivos del servidor de símbolos se denomina símbolos de indexación. Hay dos maneras comunes de indexar símbolos. Se puede copiar un archivo de símbolos en el servidor de símbolos. O bien, se puede copiar un puntero a la ubicación del símbolo en el servidor de símbolos. Si tiene una carpeta de archivo que contiene las compilaciones antiguas, puede que desee indexar punteros a los archivos PDB que ya están en el recurso compartido, en lugar de duplicar símbolos. Dado que los símbolos a veces pueden ser decenas de megabytes de tamaño, es una buena idea planear con antelación cuánto espacio puede requerir para archivar todas las compilaciones del proyecto en todo el desarrollo. Si solo indexa punteros a símbolos, es posible que tenga problemas si quita compilaciones antiguas o cambia el nombre de un recurso compartido de archivos.

Por ejemplo, para indexar de forma recursiva todos los símbolos de c:\dxsym\Extras\Symbols obtenidos del SDK de DirectX de octubre de 2006 en un recurso compartido de archivos de servidor de símbolos denominado \\mainserver\symbols, puede usar el siguiente comando:

"c:\Program Files\Debugging Tools for Windows\symstore" add /f "C:\dxsym\Extras\Symbols\*.pdb"
/s \\mainserver\symbols /t "October 2006 DirectX SDK " /r

El parámetro /t "comment" se usa para agregar una descripción a la transacción que agregó los símbolos. Esto puede ser útil al realizar tareas administrativas en los símbolos.

Procedimientos recomendados

  • Configure su propio recurso compartido de archivos del servidor de símbolos para su equipo, empresa o producto.
  • Configure _NT_SYMBOL_PATH para que apunte a una memoria caché local, a un servidor de símbolos privado y al servidor de símbolos de Microsoft.
  • Si un depurador no puede cargar símbolos para un componente que está depurando, póngase en contacto con el propietario del componente para solicitar símbolos, al menos una PDB eliminada.
  • Configure un sistema de compilación automatizado para indexar símbolos en el servidor de símbolos privados para cada compilación que se genere. Asegúrese de que las compilaciones que distribuya son las compilaciones generadas por este proceso. Esto garantiza que los símbolos estén siempre disponibles para depurar problemas.
  • Configure un servidor de símbolos para permitir que los depuradores accedan al código fuente de un módulo específico directamente desde un sistema de control de código fuente basado en Visual Source Safe o Perforce. Si la información del archivo de origen y los símbolos de una versión publicada de un juego se indexan, los desarrolladores que tienen acceso al servidor de símbolos pueden tener depuración de nivel de origen completo de problemas notificados, sin mantener entornos de compilación ni versiones antiguas de archivos de origen en sus equipos de desarrollo. Para configurar el servidor de símbolos para permitir la indexación de la información del archivo de origen, consulte la documentación del servidor de origen.