2008-09-24 15 views
45

Me he dado cuenta de que Windbg es un depurador muy potente para la plataforma de Windows &. Aprendo algo nuevo al respecto de vez en cuando. ¿Pueden los usuarios de Windbg compartir algunas de sus locas habilidades?¿Cuál es su consejo/truco favorito de Windbg?

ps: No estoy buscando un comando ingenioso, esos se pueden encontrar en la documentación. ¿Qué tal si compartimos consejos sobre cómo hacer algo que de otro modo no podríamos imaginar con windbg? p.ej. Una forma de generar estadísticas sobre las asignaciones de memoria cuando un proceso se ejecuta bajo windbg.

Respuesta

27

Mi favorito es el comando .cmdtree <file> (no documentado, pero al que se hace referencia en notas de la versión anterior). Esto puede ayudar a mostrar otra ventana (que se puede acoplar) para mostrar los comandos útiles o de uso común. Esto puede ayudar a que el usuario sea mucho más productivo al usar la herramienta.

Inicialmente habló de aquí, con un ejemplo para el <file> parámetro: http://blogs.msdn.com/debuggingtoolbox/archive/2008/09/17/special-command-execute-commands-from-a-customized-user-interface-with-cmdtree.aspx

Ejemplo: alt text http://blogs.msdn.com/photos/debuggingtoolbox/images/8954736/original.aspx

+4

donnot sabe por qué, pero parece que no está disponible en WinDbg: 6.12.0002.633, cuando entró .cmdtree el archivo emergente de ayuda emergente. –

+4

¿Se incluyó el parámetro de archivo? Utilicé la misma versión de WinDbg con ese comando con éxito. –

+0

tienes razón, me perdí el parámetro del archivo. –

18

El siguiente comando es muy práctico cuando se mira en la pila de objetos de C++ con vtables, especialmente cuando trabajando con compilaciones de lanzamiento cuando se optimizan bastantes cosas.

DPP esp Rango


Ser capaz de cargar un archivo PE arbitrario como vertedero es limpio:

windbg -z mylib.dll


de consulta GetLastError() con:

GLE


Esto ayuda a descifrar los códigos de error comunes:!

error_number error
+1

DPP - bueno, gracias. – user15071

+0

dpp - ¡un salvavidas! , ¡¡¡muchas gracias!!! – Tal

+0

muchas gracias por los consejos –

15

Casi el 60% de los comandos que uso todos los días ..

dv /i /t 
?? this 
kM (kinda undocumented) generates links to frames 
.frame x 
!analyze -v 
!lmi 
~ 
+2

Wow. ¡kM es bastante fabuloso! – Aaron

1

hacer no comando uso de WinDBG .heap -stat. A veces le dará salida incorrecta. En su lugar, use informes de memoria DebugDiags.

Con los números correctos, puede usar el comando .heap -flt ... de WinDbg.

2

Me gusta usar comandos avanzados de punto de interrupción, como el uso de puntos de interrupción para crear nuevos puntos de interrupción de un solo disparo.

10

la "punta" que utilizo con más frecuencia es la que te salvará de tener que tocar ese ratón molestos con tanta frecuencia: Alt +

Alt + colocará enfoque en la ventana de comandos para que pueda escribir un comando y para que la flecha hacia arriba realmente se desplace por el historial de comandos. Sin embargo, no funciona si su enfoque ya está en el historial de comandos desplazables.

Peeve: ¿por qué las teclas son ignoradas mientras el foco está en una ventana de fuente? No es como si pudieras editar el código fuente desde dentro de WinDbg. Alt + al rescate.

+1

'alt + 2, alt + 1, alt + 2, ctrl + F4' Lame hack ... Funcionará incluso si el cursor está en la ventana de comandos. : P – anishsane

25

Para investigar una pérdida de memoria en un volcado de memoria (ya que prefiero con diferencia UMDH para procesos en vivo). La estrategia es que todos los objetos del mismo tipo están asignados con el mismo tamaño.

  • Alimentar el comando !heap -h 0 a cdb.exe línea de comando versión de WinDbg (para mayor velocidad) para obtener todas las asignaciones del montón:
"C:\Program Files\Debugging Tools for Windows\cdb.exe" -c "!heap -h 0;q" -z [DumpPath] > DumpHeapEntries.log 
  • Uso Cygwin a grep la lista de asignaciones, agrupándolas por tamaño:
grep "busy ([[:alnum:]]\+)" DumpHeapEntries.log \ 
| gawk '{ str = $8; gsub(/\(|\)/, "", str); print "0x" str " 0x" $4 }' \ 
| sort \ 
| uniq -c \ 
| gawk '{ printf "%10.2f %10d %10d (%s = %d)\n", $1*strtonum($3)/1024, $1, strtonum($3), $2, strtonum($2) }' \ 
| sort > DumpHeapEntriesStats.log 
  • que conseguir una mesa que tiene este aspecto, por ejemplo, nos dice que 25529270 asignaciones de 0x24 bytes toman cerca de 1,2   GB de memoria.
8489.52  707  12296 (0x3000 = 12288) 
    11894.28  5924  2056 (0x800 = 2048) 
    13222.66  846250   16 (0x2 = 2) 
    14120.41  602471   24 (0x2 = 2) 
    31539.30 2018515   16 (0x1 = 1) 
    38902.01 1659819   24 (0x1 = 1) 
    40856.38  817  51208 (0xc800 = 51200) 
1196684.53 25529270   48 (0x24 = 36) 
  • Entonces si los objetos tienen vtables, sólo tiene que utilizar el comando dps a buscar algunas de las asignaciones del montón 0x24 bytes en DumpHeapEntries.log a conocer el tipo de los objetos que se están llevando toda la memoria.
0:075> dps 3be7f7e8 
3be7f7e8 00020006 
3be7f7ec 090c01e7 
3be7f7f0 0b40fe94 SomeDll!SomeType::`vftable' 
3be7f7f4 00000000 
3be7f7f8 00000000 

Es cursi, pero funciona :)

+0

Este es un hombre épico, gracias muchísimo por publicarlo. – pj4533

+0

He estado tratando de implementar esto por mí mismo, pero estoy confundido. ¿Cómo se obtiene la dirección '3be7f7e8' para dar dds? ¿Es solo la primera columna en la salida de! Heap? Lo que significa que busca su registro original para la asignación de ese tamaño, obtener la dirección, luego hacer un dds en él? – pj4533

+0

Exactamente, en el registro se obtiene una línea que se ve así para cada asignación de memoria: "3be7f7e8: 00038. 00040 [107] - busy (24)". 24 es el valor que buscamos aquí, obtenido de la tabla anterior que nos dice que la mayor parte de la memoria es utilizada por asignaciones de 0x24 bytes. Luego uso de cygwin menos para buscar DumpHeapEntriesStats.log para estas líneas utilizando el comando "/ (24)", recoger algunas de las direcciones coincidentes y los DDS CDB/WinDBG. – jturcotte

7

Una palabra (bueno, vale, tres): LMD, es decir depurador de lenguaje de marcado de.

Esta es una adición bastante reciente a WinDbg, y no está documentada en el archivo de ayuda. Sin embargo, hay documentación en "dml.doc" en el directorio de instalación de las herramientas de depuración para Windows.

Básicamente, esta es una sintaxis similar a HTML que puede agregar a sus scripts de depuración para formatear y, lo que es más importante, vincular. Puede usar enlaces para llamar a otros scripts, o incluso al mismo script.

Mi trabajo diario implica el mantenimiento de un metamodelador que proporciona objetos genéricos y la relación entre objetos para una gran parte del software C++. Al principio, para facilitar la depuración, había escrito un simple script de volcado que extraía información relevante de estos objetos.

Ahora, con DML, he podido agregar enlaces a la salida, permitiendo que se vuelva a llamar a la misma secuencia de comandos en objetos relacionados. Esto permite una exploración mucho más rápida de un modelo.

Aquí hay un ejemplo simplificado. Supongamos que el objeto bajo introspección tiene una relación llamada "referencia" a otro objeto. r @ $ t0 = $ $$ arg1 arg1 es la dirección de un objeto a examinar

Obviamente, este es un ejemplo bastante lata, pero esto es realmente muy valiosa para mí. En lugar de buscar objetos muy complejos para los miembros de datos correctos (que generalmente demoraban un minuto y varios trucos de fundición y desreferenciación), ¡todo se automatiza con un solo clic!

4

Otra respuesta mencionado la ventana de comandos y Alt + para centrarse en la ventana de entrada de comandos. ¿Alguien tiene dificultades para desplazarse por la ventana de salida del comando sin usar el mouse?

Bueno, recientemente he usado AutoHotkey para desplazar la ventana de salida del comando usando el teclado y sin salir de la ventana de entrada del comando.

; WM_VSCROLL = 0x115 (277) 
ScrollUp(control="") 
{ 
    SendMessage, 277, 0, 0, %control%, A 
} 

ScrollDown(control="") 
{ 
    SendMessage, 277, 1, 0, %control%, A 
} 

ScrollPageUp(control="") 
{ 
    SendMessage, 277, 2, 0, %control%, A 
} 

ScrollPageDown(control="") 
{ 
    SendMessage, 277, 3, 0, %control%, A 
} 

ScrollToTop(control="") 
{ 
    SendMessage, 277, 6, 0, %control%, A 
} 

ScrollToBottom(control="") 
{ 
    SendMessage, 277, 7, 0, %control%, A 
} 

#IfWinActive, ahk_class WinDbgFrameClass 
    ; For WinDbg, when the child window is attached to the main window 
    !UP::ScrollUp("RichEdit50W1") 
    ^k::ScrollUp("RichEdit50W1") 
    !DOWN::ScrollDown("RichEdit50W1") 
    ^j::ScrollDown("RichEdit50W1") 
    !PGDN::ScrollPageDown("RichEdit50W1") 
    !PGUP::ScrollPageUp("RichEdit50W1") 
    !HOME::ScrollToTop("RichEdit50W1") 
    !END::ScrollToBottom("RichEdit50W1") 
#IfWinActive, ahk_class WinBaseClass 
    ; Also for WinDbg, when the child window is a separate window 
    !UP::ScrollUp("RichEdit50W1") 
    !DOWN::ScrollDown("RichEdit50W1") 
    !PGDN::ScrollPageDown("RichEdit50W1") 
    !PGUP::ScrollPageUp("RichEdit50W1") 
    !HOME::ScrollToTop("RichEdit50W1") 
    !END::ScrollToBottom("RichEdit50W1") 

Después de ejecutar esta secuencia de comandos, puede utilizar Alt + hasta/abajo para desplazarse una línea de la ventana de salida de comandos, Alt + AvPág/Re Pág para desplazarse una pantalla

Nota: parece que las diferentes versiones de WinDbg tendrán diferentes nombres de clase para la ventana y los controles, por lo que es posible que desee utilizar la herramienta de ventana de espionaje proporcionada por AutoHotkey para encontrar primero los nombres de clase reales.

6
  • .prefer_dml 1

    Esto modifica muchos de los comandos integrados (por ejemplo, lm) para mostrar la salida LMD, que permite hacer clic en enlaces en lugar de la ejecución de comandos. Bastante práctico ...

  • .reload /f /o file.dll (el /o se sobreponen a la copia actual del símbolo que tiene)

  • .enable_unicode 1 // Cambia el depurador por defecto a Unicode para las cadenas ya que todos los componentes de Windows utilizan Unicode internamente , esto es bastante útil.

  • .ignore_missing_pages 1 // Si realiza una gran cantidad de análisis de volcado de kernel, verá una gran cantidad de errores con respecto a la paginación de la memoria. Este comando le indicará al depurador que deje de lanzar esta advertencia.

alias alias alias ...

ganar un tiempo en el depurador. Estas son algunas de las minas:

aS !p !process; 
aS !t !thread; 
aS .f .frame; 
aS .p .process /p /r 
aS .t .thread /p /r 
aS dv dv /V /i /t //make dv do your favorite options by default 
aS f !process 0 0 //f for find, e.g. f explorer.exe 
1

Para el comando & rutinas sencillas (estáticas o automatizables) donde se utiliza el depurador, que es muy bueno para ser capaz de poner todo el depurador comandos para ejecutar a través de un archivo de comandos de texto y ejecute eso como entrada a través de kd.exe o cdb.exe, que se puede llamar a través de un script por lotes, etc.

Ejecute eso siempre que necesite hacer la misma rutina anterior, sin tener que iniciar WinDbg y hacer cosas manualmente. Lástima que esto no funciona cuando no está seguro de lo que está buscando, o algunos parámetros de comando necesitan un análisis manual para encontrar/obtener.

4

script para cargar SOS basado en la versión del marco .NET (v2.0/v4.0):

!for_each_module .if(($sicmp("@#ModuleName" , "mscorwks") = 0)) 
{.loadby sos mscorwks} .elsif ($sicmp("@#ModuleName" , "clr") = 0) 
{.loadby sos clr} 
1

cadena volcado independiente de la plataforma de código administrado que trabajará para x86/x64:

j $ptrsize = 8 'aS !ds .printf "%mu \n", c+';'aS !ds .printf "%mu \n", 10+' 

Aquí es un ejemplos de uso:

0:000> !ds 00000000023620b8 

MaxConcurrentInstances 
Cuestiones relacionadas