Introducción a WinDbg (modo de usuario)
WinDbg es un depurador en modo kernel y en modo usuario que se incluye en Herramientas de depuración para Windows. Los siguientes ejercicios prácticos pueden ayudarle a empezar a usar WinDbg como depurador en modo de usuario.
Para obtener información sobre cómo obtener las Herramientas de depuración para Windows, consulte Descarga e instalación del depurador de Windows de WinDbg.
Después de instalar las herramientas de depuración, busque los directorios de instalación de las versiones de 64 bits (x64) y de 32 bits (x86) de las herramientas. Por ejemplo:
- C:\Archivos de programa (x86)\Windows Kits\10\Debuggers\x64
- C:\Archivos de programa (x86)\Windows Kits\10\Debuggers\x86
Abra Bloc de notas y adjunte WinDbg
Vaya al directorio de instalación y abra WinDbg.exe.
En el menú Archivo, seleccione Iniciar ejecutable. En el cuadro de diálogo Iniciar ejecutable, vaya a la carpeta que contiene notepad.exe. (El archivo notepad.exe normalmente está en C:\Windows\System32). En Nombre de archivo, escriba notepad.exe. Seleccione Open (Abrir).
En la línea de comandos cerca de la parte inferior de la ventana winDbg, escriba este comando:
El resultado es similar a este ejemplo:
Symbol search path is: srv* Expanded Symbol search path is: cache*;SRV
La ruta de búsqueda de símbolos indica a WinDbg dónde buscar archivos de símbolos (PDB). El depurador necesita archivos de símbolos para obtener información sobre los módulos de código, como nombres de función y nombres de variable.
A continuación, escriba este comando:
El comando
.reload
indica a WinDbg que realice la búsqueda inicial para buscar y cargar archivos de símbolos.Para ver los símbolos del módulo notepad.exe, escriba este comando:
Nota:
Si no aparece ninguna salida, escriba
.reload /f
para intentar forzar la carga de símbolos. Use !sym noisy para mostrar información adicional de carga de símbolos.Para ver los símbolos del módulo notepad.exe que contienen
main
, use el comando examinar símbolos para enumerar los módulos que coinciden con la máscara:x notepad!wWin*
El resultado es similar a este ejemplo:
00007ff6`6e76b0a0 notepad!wWinMain (wWinMain) 00007ff6`6e783db0 notepad!wWinMainCRTStartup (wWinMainCRTStartup)
Para colocar un punto de interrupción en
notepad!wWinMain
, escriba este comando:Para comprobar que se ha establecido el punto de interrupción, escriba este comando:
El resultado es similar a este ejemplo:
0 e Disable Clear 00007ff6`6e76b0a0 0001 (0001) 0:**** notepad!wWinMain
Para iniciar el proceso de Bloc de notas, escriba este comando:
Bloc de notas se ejecuta hasta que llega a la función
WinMain
y, a continuación, interrumpe el depurador.Breakpoint 0 hit notepad!wWinMain: 00007ff6`6e76b0a0 488bc4 mov rax,rsp
Para ver una lista de módulos de código que se cargan actualmente en el proceso de Bloc de notas, escriba este comando:
El resultado es similar a este ejemplo:
0:000> lm start end module name 00007ff6`6e760000 00007ff6`6e798000 notepad (pdb symbols) C:\ProgramData\Dbg\sym\notepad.pdb\BC04D9A431EDE299D4625AD6201C8A4A1\notepad.pdb 00007ff8`066a0000 00007ff8`067ab000 gdi32full (deferred) 00007ff8`067b0000 00007ff8`068b0000 ucrtbase (deferred) 00007ff8`06a10000 00007ff8`06aad000 msvcp_win (deferred) 00007ff8`06ab0000 00007ff8`06ad2000 win32u (deferred) 00007ff8`06b40000 00007ff8`06e08000 KERNELBASE (deferred) 00007ff8`07220000 00007ff8`072dd000 KERNEL32 (deferred) 00007ff8`07420000 00007ff8`07775000 combase (deferred) 00007ff8`07820000 00007ff8`079c0000 USER32 (deferred) 00007ff8`079c0000 00007ff8`079f0000 IMM32 (deferred) 00007ff8`07c00000 00007ff8`07c2a000 GDI32 (deferred) 00007ff8`08480000 00007ff8`085ab000 RPCRT4 (deferred) 00007ff8`085b0000 00007ff8`0864e000 msvcrt (deferred) 00007ff8`08c40000 00007ff8`08cee000 shcore (deferred) 00007ff8`08db0000 00007ff8`08fa5000 ntdll (pdb symbols) C:\ProgramData\Dbg\sym\ntdll.pdb\53F12BFE149A2F50205C8D5D66290B481\ntdll.pdb 00007fff`f8580000 00007fff`f881a000 COMCTL32 (deferred)
Para ver un seguimiento de pila, escriba este comando:
El resultado es similar a este ejemplo:
0:000> k 00 000000c8`2647f708 00007ff6`6e783d36 notepad!wWinMain 01 000000c8`2647f710 00007ff8`07237034 notepad!__scrt_common_main_seh+0x106 02 000000c8`2647f750 00007ff8`08e02651 KERNEL32!BaseThreadInitThunk+0x14 03 000000c8`2647f780 00000000`00000000 ntdll!RtlUserThreadStart+0x21
Para volver a ejecutar el Bloc de notas, escriba este comando:
Para interrumpir el Bloc de notas, en el menú Archivo, seleccione Interrumpir.
Para establecer y comprobar un punto de interrupción en
ZwWriteFile
, escriba estos comandos:Para volver a iniciar el Bloc de notas, escriba g. En la ventana Bloc de notas, escriba algún texto. En el menú Archivo, seleccione Guardar. El código en ejecución se interrumpe cuando se trata de
ZwCreateFile
. Escriba el comando k para ver el seguimiento de la pila.En la ventana WinDbg, a la izquierda de la línea de comandos, se muestran los números de procesador y subproceso. En este ejemplo, el número de procesador actual es 0 y el número de subproceso actual es 11 (
0:011>
). La ventana muestra el seguimiento de la pila para el subproceso 11 que se ejecuta en el procesador 0.Para ver una lista de todos los subprocesos del proceso de Bloc de notas, escriba este comando (la virgulilla):
El resultado es similar a este ejemplo:
0:011> ~ 0 Id: 5500.34d8 Suspend: 1 Teb: 000000c8`262c4000 Unfrozen 1 Id: 5500.3960 Suspend: 1 Teb: 000000c8`262c6000 Unfrozen 2 Id: 5500.5d68 Suspend: 1 Teb: 000000c8`262c8000 Unfrozen 3 Id: 5500.4c90 Suspend: 1 Teb: 000000c8`262ca000 Unfrozen 4 Id: 5500.4ac4 Suspend: 1 Teb: 000000c8`262cc000 Unfrozen 5 Id: 5500.293c Suspend: 1 Teb: 000000c8`262ce000 Unfrozen 6 Id: 5500.53a0 Suspend: 1 Teb: 000000c8`262d0000 Unfrozen 7 Id: 5500.3ca4 Suspend: 1 Teb: 000000c8`262d4000 Unfrozen 8 Id: 5500.808 Suspend: 1 Teb: 000000c8`262da000 Unfrozen 10 Id: 5500.3940 Suspend: 1 Teb: 000000c8`262dc000 Unfrozen . 11 Id: 5500.28b0 Suspend: 1 Teb: 000000c8`262de000 Unfrozen 12 Id: 5500.12bc Suspend: 1 Teb: 000000c8`262e0000 Unfrozen 13 Id: 5500.4c34 Suspend: 1 Teb: 000000c8`262e2000 Unfrozen
En este ejemplo, 14 subprocesos tienen índices de 0 a 13.
Para examinar el seguimiento de la pila del subproceso 0, escriba estos comandos:
El resultado es similar a este ejemplo:
0:011> ~0s 0:011> ~0s win32u!NtUserGetProp+0x14: 00007ff8`06ab1204 c3 ret 0:000> k # Child-SP RetAddr Call Site 00 000000c8`2647bd08 00007ff8`07829fe1 win32u!NtUserGetProp+0x14 01 000000c8`2647bd10 00007fff`f86099be USER32!GetPropW+0xd1 02 000000c8`2647bd40 00007ff8`07d12f4d COMCTL32!DefSubclassProc+0x4e 03 000000c8`2647bd90 00007fff`f8609aba SHELL32!CAutoComplete::_EditWndProc+0xb1 04 000000c8`2647bde0 00007fff`f86098b7 COMCTL32!CallNextSubclassProc+0x9a 05 000000c8`2647be60 00007ff8`0782e858 COMCTL32!MasterSubclassProc+0xa7 06 000000c8`2647bf00 00007ff8`0782de1b USER32!UserCallWinProcCheckWow+0x2f8 07 000000c8`2647c090 00007ff8`0782d68a USER32!SendMessageWorker+0x70b 08 000000c8`2647c130 00007ff8`07afa4db USER32!SendMessageW+0xda
Para salir de la depuración y desasociar del proceso de Bloc de notas, escriba este comando:
Abra su propia aplicación y adjunte WinDbg
Por ejemplo, supongamos que ha escrito y creado esta aplicación de consola pequeña:
...
void MyFunction(long p1, long p2, long p3)
{
long x = p1 + p2 + p3;
long y = 0;
y = x / p2;
}
void main ()
{
long a = 2;
long b = 0;
MyFunction(a, b, 5);
}
En este ejercicio, supongamos que la aplicación creada (MyApp.exe) y el archivo de símbolos (MyApp.pdb) están en C:\MyApp\x64\Debug. Supongamos también que el código fuente de la aplicación está en C:\MyApp\MyApp y que la máquina de destino ha creado MyApp.exe.
Abra WinDbg.
En el menú Archivo, seleccione Iniciar ejecutable. En el cuadro de diálogo Iniciar ejecutable, vaya a C:\MyApp\x64\Debug. En Nombre de archivo, escriba MyApp.exe. Seleccione Open (Abrir).
Escriba estos comandos:
.sympath+ C:\MyApp\x64\Debug
Los comandos indican a WinDbg dónde buscar símbolos y código fuente para la aplicación. En este caso, no es necesario establecer la ubicación del código fuente mediante .srcpath porque los símbolos tienen rutas de acceso completas a los archivos de origen.
Escriba estos comandos:
La aplicación interrumpe el depurador cuando se trata de su función
main
.WinDbg muestra el código fuente y la ventana Comando.
En el menú Depurar, seleccione Paso a paso (o seleccione F11). Continúe paso a paso hasta que llegue a
MyFunction
. Cuando llegue a la líneay = x / p2
, la aplicación se bloquea e interrumpe el depurador.El resultado es similar a este ejemplo:
(1450.1424): Integer divide-by-zero - code c0000094 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. MyApp!MyFunction+0x44: 00007ff6`3be11064 f77c2428 idiv eax,dword ptr [rsp+28h] ss:00000063`2036f808=00000000
Escriba este comando:
WinDbg muestra un análisis del problema (en este caso, división por 0).
FAULTING_IP: MyApp!MyFunction+44 [c:\myapp\myapp\myapp.cpp @ 7] 00007ff6`3be11064 f77c2428 idiv eax,dword ptr [rsp+28h] EXCEPTION_RECORD: ffffffffffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 00007ff63be11064 (MyApp!MyFunction+0x0000000000000044) ExceptionCode: c0000094 (Integer divide-by-zero) ExceptionFlags: 00000000 NumberParameters: 0 ... STACK_TEXT: 00000063`2036f7e0 00007ff6`3be110b8 : ... : MyApp!MyFunction+0x44 00000063`2036f800 00007ff6`3be1141d : ... : MyApp!main+0x38 00000063`2036f840 00007ff6`3be1154e : ... : MyApp!__tmainCRTStartup+0x19d 00000063`2036f8b0 00007ffc`b1cf16ad : ... : MyApp!mainCRTStartup+0xe 00000063`2036f8e0 00007ffc`b1fc4629 : ... : KERNEL32!BaseThreadInitThunk+0xd 00000063`2036f910 00000000`00000000 : ... : ntdll!RtlUserThreadStart+0x1d STACK_COMMAND: dt ntdll!LdrpLastDllInitializer BaseDllName ;dt ntdll!LdrpFailureData ;.cxr 0x0 ;kb FOLLOWUP_IP: MyApp!MyFunction+44 [c:\myapp\myapp\myapp.cpp @ 7] 00007ff6`3be11064 f77c2428 idiv eax,dword ptr [rsp+28h] FAULTING_SOURCE_LINE: c:\myapp\myapp\myapp.cpp FAULTING_SOURCE_FILE: c:\myapp\myapp\myapp.cpp FAULTING_SOURCE_LINE_NUMBER: 7 FAULTING_SOURCE_CODE: 3: void MyFunction(long p1, long p2, long p3) 4: { 5: long x = p1 + p2 + p3; 6: long y = 0; > 7: y = x / p2; 8: } 9: 10: void main () 11: { 12: long a = 2; ...
Resumen de comandos
- Comando
Contents
en el menúHelp
- .sympath (Establecer ruta de acceso de símbolo)
- .reload (Módulo Volver a cargar)
- x (Examinar símbolos)
- g (Ir)
- Comando
Break
en el menúDebug
- lm (Lista de módulos cargados)
- k (Mostrar seguimiento de pila)
- bu (Establecer punto de interrupción)
- bl (Lista de puntos de interrupción)
- ~ (Estado de subprocesos)
- ~s (Establecer subproceso actual)
- .sympath+ (Establecer ruta de acceso de símbolo) anexar a la ruta de acceso de símbolo existente
- .srcpath (Establecer ruta de acceso de origen)
- Comando
Step Into
en el menúDebug
(F11) - !analyze -v
- qd (Salir y desasociar)
Consulte también
Introducción a WinDbg (modo kernel)