Tareas iniciales con WinDbg (modo de usuario)

WinDbg es un depurador en modo kernel y en modo de usuario que se incluye en Herramientas de depuración para Windows. Aquí se proporcionan ejercicios prácticos que le ayudarán a empezar a usar WinDbg como depurador en modo de usuario.

Para obtener información sobre cómo obtener herramientas de depuración para Windows, vea Herramientas de depuración para Windows (WinDbg, KD, CDB, NTSD).

Después de instalar las herramientas de depuración, busque los directorios de instalación de las versiones de 64 bits (x64) y 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

Iniciar Bloc de notas y adjuntar WinDbg

  1. Vaya al directorio de instalación y abra WinDbg.exe.

  2. En el menú Archivo, elija Abrir ejecutable. En el cuadro de diálogo Abrir ejecutable, vaya a la carpeta que contiene notepad.exe (normalmente, C:\Windows\System32). En Nombre de archivo,escriba notepad.exe. seleccione Open(Abrir).

    captura de pantalla de windbg después de iniciar el Bloc de notas.

  3. Cerca de la parte inferior de la ventana de WinDbg, en la línea de comandos, escriba este comando:

    .sympath srv*

    La salida es similar a la siguiente:

    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 (nombres de función, nombres de variables y similares).

    Escriba este comando, que indica a WinDbg que realice su búsqueda inicial y carga de archivos de símbolos:

    .reload

  4. Para ver los símbolos del módulo Notepad.exe, escriba este comando:

    x bloc de notas!*

    Nota Si no ve ninguna salida, vuelva a escribir .reload.

    Para ver los símbolos en el Notepad.exe que contienen main, use el comando examinar símbolos como este para enumerar los módulos que coinciden con la máscara:

    x notepad!wWin*

    La salida es similar a la siguiente:

    00007ff6`6e76b0a0 notepad!wWinMain (wWinMain)
    00007ff6`6e783db0 notepad!wWinMainCRTStartup (wWinMainCRTStartup)
    
  5. Para colocar un punto de interrupción en el bloc de notas!wWinMain, escriba este comando:

    bu notepad!wWinMain

    Para comprobar que se ha establecido el punto de interrupción, escriba este comando:

    Bl

    La salida es similar a la siguiente:

    0 e Disable Clear  00007ff6`6e76b0a0     0001 (0001)  0:**** notepad!wWinMain
    
  6. Para iniciar Bloc de notas en ejecución, escriba este comando:

    g

    Bloc de notas ejecuta hasta que llega a la función WinMain y, a continuación, se interrumpe en 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 en el Bloc de notas, escriba este comando:

    Lm

    La salida es similar a la siguiente:

    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 la pila, escriba este comando:

    K

    La salida es similar a la siguiente:

    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
    
  7. Para empezar a Bloc de notas de nuevo, escriba este comando:

    g

  8. Para interrumpir la sesión Bloc de notas, elija Interrumpir en el menú Archivo.

  9. Para establecer y comprobar un punto de interrupción en ZwWriteFile,escriba estos comandos:

    bu ntdll! ZwWriteFile

    Bl

  10. Escriba g para volver a Bloc de notas en ejecución. En la Bloc de notas, escriba texto y elija Guardar en el menú Archivo. El código en ejecución se interrumpe cuando se trata de ZwCreateFile. Escriba k para ver el seguimiento de la pila.

    captura de pantalla del seguimiento de pila en windbg.

    En la ventana WinDbg, a la izquierda de la línea de comandos, observe 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. Por lo tanto, estamos viendo el seguimiento de pila para el subproceso 11 (que se ejecuta en el procesador 0).

  11. Para ver una lista de todos los subprocesos del Bloc de notas, escriba este comando (la tilde):

    ~

    La salida es similar a la siguiente:

    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, hay 14 subprocesos con índices de 0 a 13.

  12. Para ver el seguimiento de pila del subproceso 0, escriba estos comandos:

    ~0s

    K

    La salida es similar a la siguiente:

    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
    
  13. Para salir de la depuración y desasocuir del Bloc de notas, escriba este comando:

    Qd

Inicie su propia aplicación y adjunte WinDbg

Supongamos que ha escrito y creado esta pequeña aplicación de consola.

...
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, se supone que la aplicación compilada (MyApp.exe) y el archivo de símbolos (MyApp.pdb) están en C:\MyApp\x64\Debug. También se supone que el código fuente de la aplicación está en C:\MyApp\MyApp y que la máquina de destino se MyApp.exe.

  1. Abra WinDbg.

  2. En el menú Archivo, elija Abrir ejecutable. En el cuadro de diálogo Abrir ejecutable, vaya a C:\MyApp\x64\Debug. En Nombre de archivo,escriba MyApp.exe. seleccione Open(Abrir).

  3. Escriba estos comandos:

    .symfix

    .sympath+ C:\MyApp\x64\Debug

    Ahora WinDbg sabe dónde encontrar símbolos y código fuente para la aplicación. En este caso, no es necesario establecer la ubicación del código fuente con .srcpath porque los símbolos tienen rutas de acceso completas a los archivos de origen.

  4. Escriba estos comandos:

    .reload

    bu MyApp!main

    g

    La aplicación se interrumpe en el depurador cuando se trata de su función principal.

    WinDbg muestra el código fuente y el ventana Comandos.

    captura de pantalla del código fuente en windbg.

  5. En el menú Depurar, elija Depurar paso a paso por instrucciones (o presione F11). Continúe con la ejecución paso a paso hasta que haya entrado en MyFunction. Cuando se entra en la línea , la aplicación se bloquea y y = x / p2 se interrumpe en el depurador. La salida es similar a la siguiente:

    (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
    
  6. Escriba este comando:

    !analyze -v

    WinDbg muestra un análisis del problema (división por 0 en este caso).

    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

Vea también

Tareas iniciales con WinDbg (modo kernel)

Operación del depurador

Técnicas de depuración

Herramientas de depuración Windows (WinDbg, KD, CDB, NTSD)

Depuración mediante la versión preliminar de WinDbg