Controladores de Windows depuración: laboratorio paso a paso (modo kernel de eco)

bp

Establece un punto de interrupción que estará activo hasta que se descargue el módulo en el que se encuentra.

Bu

Establece un punto de interrupción que no se resuelve cuando se descarga el módulo y se vuelve a habilitar cuando se vuelve a cargar el módulo.

Bm

Establece un punto de interrupción para un símbolo. Este comando usará bu o bp adecuadamente y permite usar caracteres comodín * para establecer puntos de interrupción en todos los símbolos que coincidan (como todos los métodos de una clase).

Para obtener más información, vea Depuración de código fuente en WinDbg en la documentación de referencia de depuración.

-En el sistema host

  1. Use la interfaz de usuario de WinDbg para confirmar que el modode origen de depuración está habilitado en la sesión actual de WinDbg.

  2. Agregue la ubicación del código local a la ruta de acceso de origen escribiendo el siguiente comando.

    .srcpath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
    
  3. Agregue la ubicación del símbolo local a la ruta de acceso del símbolo escribiendo el siguiente comando.

    .sympath+ C:\DriverSamples\KMDF_Echo_Sample\driver\AutoSync
    
  4. Usaremos el comando x para examinar los símbolos asociados al controlador de eco para determinar el nombre de función que se usará para el punto de interrupción. Podemos usar un carácter comodín o Ctrl+F para buscar el nombre de la función DeviceAdd.

    0: kd> x ECHO!EchoEvt*
    8b4c7490          ECHO!EchoEvtIoQueueContextDestroy (void *)
    8b4c7000          ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *)
    8b4c7820          ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *)
    8b4cb0e0          ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *)
    8b4c75d0          ECHO!EchoEvtIoWrite (struct WDFQUEUE__ *, struct WDFREQUEST__ *, unsigned int)
    8b4cb170          ECHO!EchoEvtDeviceAdd (struct WDFDRIVER__ *, struct 
    …
    

    La salida anterior muestra que el método DeviceAdd para nuestro controlador de eco es ECHO! EchoEvtDeviceAdd.

    Como alternativa, podríamos revisar el código fuente para buscar el nombre de función deseado para nuestro punto de interrupción.

  5. Establezca el punto de interrupción con el comando bm con el nombre del controlador, seguido del nombre de la función (por ejemplo, AddDevice)donde desea establecer el punto de interrupción, separado por un signo de exclamación. Usaremos AddDevice para ver cómo se carga el controlador.

    0: kd> bm ECHO!EchoEvtDeviceAdd
      1: fffff801`0bf9b1c0 @!"ECHO!EchoEvtDeviceAdd"
    

    Note
    Puede usar una sintaxis diferente junto con variables de configuración como < module > ! < symbol > , < clase > :: método <> ,' < file.cpp : número > de <><><> línea ', u omitir una serie de veces condición # . Para obtener más información, vea Puntos de interrupción condicionales en WinDbg yotros Windows depuradores .

  6. Escriba el comando bl para enumerar los puntos de interrupción actuales para confirmar que el punto de interrupción se estableció.

    0: kd> bl
    1 e fffff801`0bf9b1c0     0001 (0001) ECHO!EchoEvtDeviceAdd
    

    La "e" de la salida mostrada anteriormente indica que el punto de interrupción número 1 está habilitado para activarse.

  7. Reinicie la ejecución de código en el sistema de destino escribiendo el comando gog.

  8. - En el sistema de destino

    En Windows, abra Administrador de dispositivos el icono o escriba mmc devmgmt.msc. En Administrador de dispositivos, expanda el nodo Ejemplos.

  9. Mantenga presionada (o haga clic con el botón derecho) la entrada del controlador DE ECO DE KMDF y seleccione Deshabilitar en el menú.

  10. Seleccione y mantenga presionada (o haga clic con el botón derecho) la entrada del controlador DE ECO DE KMDF de nuevo y seleccione Habilitar en el menú.

  11. - En el sistema host

    Cuando el controlador está habilitado, se debe activar el punto de interrupción de depuración AddDevice y se debe detener la ejecución del código del controlador en el sistema de destino. Cuando se encuentra el punto de interrupción, la ejecución debe detenerse al principio de la rutina AddDevice. La salida del comando de depuración mostrará "Punto de interrupción 1 alcanzado".

    windbg que muestra las variables locales de código de ejemplo y las ventanas de comandos.

  12. Para pasar por el código línea a línea, escriba el comando p o presione F10 hasta llegar al siguiente final de la rutina AddDevice. El carácter de llave "}" se resaltará como se muestra.

    Ventana de código que muestra el carácter de llave resaltado al principio de la rutina adddevice.

  13. En la sección siguiente, examinaremos el estado de las variables después de que se haya ejecutado el código DeviceAdd.

Note
Modificación del estado del punto de interrupción

Puede modificar los puntos de interrupción existentes mediante los siguientes comandos:

bl

Enumera los puntos de interrupción.

Bc

Borra un punto de interrupción de la lista. Use bc * para borrar todos los puntos de interrupción.

Bd

Deshabilita un punto de interrupción. Use bd * para deshabilitar todos los puntos de interrupción.

be

Habilita un punto de interrupción. Use ser * para habilitar todos los puntos de interrupción.

Como alternativa, también puede modificar puntos de interrupción seleccionando Editar puntosde interrupción en WinDbg. Tenga en cuenta que el cuadro de diálogo de punto de interrupción solo funciona con los puntos de interrupción existentes. Se deben establecer nuevos puntos de interrupción desde la línea de comandos.

Note
Establecimiento de puntos de interrupción de acceso a la memoria

También puede establecer puntos de interrupción que se disparen cuando se accede a una ubicación de memoria. Use el comando ba (break on access), con la sintaxis siguiente.

ba <access> <size> <address> {options}
Opción Descripción

h

execute (cuando la CPU captura una instrucción de la dirección)

r

lectura y escritura (cuando la CPU lee o escribe en la dirección)

w

write (cuando la CPU escribe en la dirección)

Tenga en cuenta que solo puede establecer cuatro puntos de interrupción de datos en un momento dado y es el usuario el que debe asegurarse de que alinea los datos correctamente o no desencadenará el punto de interrupción (las palabras deben terminar en direcciones divisibles por 2, las palabras deben ser divisibles por 4 y las cuatro palabras por 0 u 8).

Por ejemplo, para establecer un punto de interrupción de lectura y escritura en una dirección de memoria específica, podría usar un comando como este.

ba r 4 0x0003f7bf0

Note
Paso a paso por el código desde el depurador ventana Comandos

A continuación se muestran los comandos que puede usar para pasar por el código (con los cortes cortos de teclado asociados que se muestran entre paréntesis).

  • Interrumpir (Ctrl+Interrumpir): este comando interrumpirá un sistema mientras el sistema se esté ejecutando y esté en comunicación con WinDbg (la secuencia del depurador del kernel es Ctrl+C).

  • Ejecutar hasta el cursor (F7 o Ctrl+F10): coloque el cursor en una ventana de origen o desensamblado en la que quiera que se rompa la ejecución y, a continuación, presione F7; La ejecución de código se ejecutará hasta ese punto. Tenga en cuenta que si el flujo de ejecución de código no alcanza el punto indicado por el cursor (no se ejecuta una instrucción IF), WinDbg no se interrumpirá, porque la ejecución del código no llegó al punto indicado.

  • Ejecutar (F5): se ejecuta hasta que se encuentra un punto de interrupción o se produce un evento como una comprobación de errores.

  • Paso a paso por procedimientos (F10): este comando hace que la ejecución del código continúe una instrucción o una instrucción a la vez. Si se encuentra una llamada, la ejecución de código pasa por encima de la llamada sin escribir la rutina llamada. (Si el lenguaje de programación es C o C++ y WinDbg está en modo de origen, el modo de origen puede estar activado o desactivado mediante Depurar Modo de origen).

  • Paso a paso por instrucciones (F11): este comando es como el paso a paso por procedimientos, salvo que la ejecución de una llamada entra en la rutina llamada.

  • Paso a paso por procedimientos (Mayús+F11): este comando hace que la ejecución se ejecute y salga de la rutina actual (lugar actual en la pila de llamadas). Esto es útil si ha visto suficiente de la rutina.

Para obtener más información, vea Depuración de código fuente en WinDbg en la documentación de referencia de depuración.

Sección 8: Visualización de variables y pilas de llamadas

En la sección 8, mostrará información sobre variables y pilas de llamadas.

En este laboratorio se da por supuesto que está detenido en la rutina AddDevice mediante el proceso descrito anteriormente. Para ver la salida que se muestra aquí, repita los pasos descritos anteriormente, si es necesario.

- En el sistema host

Visualización de variables

Use el elemento demenú ver local para mostrar las variables locales.

ventana de variables locales windbg.

Variables globales

Puede encontrar la ubicación de una dirección de variable global escribiendo ? nombre > de variable.

Variables locales

Puede mostrar los nombres y valores de todas las variables locales para un fotograma determinado escribiendo el comando dv.

0: kd> dv
         Driver = 0x00001fff`7ff9c838
     DeviceInit = 0xffffd001`51978190
         status = 0n0

Callstacks

Note
La pila de llamadas es la cadena de llamadas de función que han llevado a la ubicación actual del contador del programa. La función superior de la pila de llamadas es la función actual y la siguiente es la función que llamó a la función actual, y así sucesivamente.

Para mostrar la pila de llamadas, use los comandos k*.

kb

Muestra la pila y los tres primeros parámetros.

kp

Muestra las pilas y la lista completa de parámetros.

kn

Permite ver la pila con la información del marco junto a ella.

-En el sistema host

  1. Si desea mantener disponible la pila de llamadas, puede seleccionar Verpila de llamadas para verlo. Seleccione las columnas de la parte superior de la ventana para alternar la presentación de información adicional.

windbg muestra la ventana de pilas de llamadas.

  1. Use el comando kn para mostrar la pila de llamadas durante la depuración del código del adaptador de ejemplo en un estado de interrupción.
3: kd> kn
# Child-SP          RetAddr           Call Site
00 ffffd001`51978110 fffff801`0942f55b ECHO!EchoEvtDeviceAdd+0x66 [c:\Samples\kmdf echo sample\c++\driver\autosync\driver.c @ 138]
01 (Inline Function) --------`-------- Wdf01000!FxDriverDeviceAdd::Invoke+0x30 [d:\wbrtm\minkernel\wdf\framework\shared\inc\private\common\fxdrivercallbacks.hpp @ 61]
02 ffffd001`51978150 fffff801`eed8097d Wdf01000!FxDriver::AddDevice+0xab [d:\wbrtm\minkernel\wdf\framework\shared\core\km\fxdriverkm.cpp @ 72]
03 ffffd001`51978570 fffff801`ef129423 nt!PpvUtilCallAddDevice+0x35 [d:\9142\minkernel\ntos\io\pnpmgr\verifier.c @ 104]
04 ffffd001`519785b0 fffff801`ef0c4112 nt!PnpCallAddDevice+0x63 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 7397]
05 ffffd001`51978630 fffff801`ef0c344f nt!PipCallDriverAddDevice+0x6e2 [d:\9142\minkernel\ntos\io\pnpmgr\enum.c @ 3390]
...

La pila de llamadas muestra que el kernel (nt) llamó Plug and Play código (PnP), que llamó al código de marco de trabajo del controlador (WDF) que posteriormente llamó a la función DeviceAdd del controlador de eco.

Sección 9: Mostrar procesos y subprocesos

Procesos

En la sección 9, mostrará información sobre el proceso y los subprocesos que se ejecutan en modo kernel.

Note
Puede mostrar o establecer la información del proceso mediante la extensión del depurador !process. Estableceremos un punto de interrupción para examinar el proceso que se usa cuando se reproduce un sonido.

  1. - En el sistema host

    Escriba el comando dv para examinar las variables de configuración regional asociadas a la rutina EchoEvtIo como se muestra.

    0: kd> dv ECHO!EchoEvtIo*
    ECHO!EchoEvtIoQueueContextDestroy
    ECHO!EchoEvtIoWrite
    ECHO!EchoEvtIoRead         
    
  2. Borre los puntos de interrupción anteriores mediante bc *.

    0: kd> bc *  
    
    1. Establezca un punto de interrupción de símbolos en las rutinas EchoEvtIo mediante el comando siguiente.
    0: kd> bm ECHO!EchoEvtIo*
      2: aade5490          @!”ECHO!EchoEvtIoQueueContextDestroy”
      3: aade55d0          @!”ECHO!EchoEvtIoWrite”
      4: aade54c0          @!”ECHO!EchoEvtIoRead”
    
  3. Enumera los puntos de interrupción para confirmar que el punto de interrupción está establecido correctamente.

    0: kd> bl
    1 e aabf0490 [c:\Samples\kmdf echo sample\c++\driver\autosync\queue.c @ 197]    0001 (0001) ECHO!EchoEvtIoQueueContextDestroy
    ...
    
  4. Escriba g para reiniciar la ejecución del código.

    0: kd> g
    
  5. - En el sistema de destino

    Ejecute el EchoApp.exe prueba de controladores en el sistema de destino.

  6. - En el sistema host

    Cuando se ejecute la aplicación de prueba, se llamará a la rutina de E/S del controlador. Esto hará que se desenlame el punto de interrupción y se detenga la ejecución del código del controlador en el sistema de destino.

    Breakpoint 2 hit
    ECHO!EchoEvtIoWrite:
    fffff801`0bf95810 4c89442418      mov     qword ptr [rsp+18h],r8
    
  7. Use el comando !process para mostrar el proceso actual que está implicado en la ejecución de echoapp.exe.

    0: kd> !process
    PROCESS ffffe0007e6a7780
        SessionId: 1  Cid: 03c4    Peb: 7ff7cfec4000  ParentCid: 0f34
        DirBase: 1efd1b000  ObjectTable: ffffc001d77978c0  HandleCount:  34.
        Image: echoapp.exe
        VadRoot ffffe000802c79f0 Vads 30 Clone 0 Private 135. Modified 5. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001cf270050
        ElapsedTime                       00:00:00.052
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         33824
        QuotaPoolUsage[NonPagedPool]      4464
        Working Set Sizes (now,min,max)  (682, 50, 345) (2728KB, 200KB, 1380KB)
        PeakWorkingSetSize                652
        VirtualSize                       16 Mb
        PeakVirtualSize                   16 Mb
        PageFaultCount                    688
        MemoryPriority                    BACKGROUND
        BasePriority                      8
        CommitCharge                      138
    
            THREAD ffffe00080e32080  Cid 03c4.0ec0  Teb: 00007ff7cfece000 Win32Thread: 0000000000000000 RUNNING on processor 1
    

    La salida muestra que el proceso está asociado al echoapp.exe que se estaba ejecutando cuando se alcanzó el punto de interrupción en el evento de escritura del controlador. Para obtener más información, vea !process.

  8. Use !process 0 0 para mostrar información de resumen de todos los procesos. En la salida, use CTRL+F para buscar la misma dirección de proceso para el proceso asociado a la echoapp.exe imagen. En el ejemplo siguiente, la dirección del proceso es ffffe0007e6a7780.

    ...
    
    PROCESS ffffe0007e6a7780
        SessionId: 1  Cid: 0f68    Peb: 7ff7cfe7a000  ParentCid: 0f34
        DirBase: 1f7fb9000  ObjectTable: ffffc001cec82780  HandleCount:  34.
        Image: echoapp.exe
    
    ...
    
  9. Registre el identificador de proceso asociado a echoapp.exe usar más adelante en este laboratorio. También puede usar CTRL+C para copiar la dirección en el búfer de copia para su uso posterior.

    ________________________________________________________________(echoapp.exe dirección del proceso)

  10. Escriba g según sea necesario en el depurador para ejecutar el código hacia delante hasta que echoapp.exe la ejecución. Alcanzará el punto de interrupción en el evento de lectura y escritura varias veces. Cuando echoapp.exe, presione CTRL+ScrLk (Ctrl+Interrumpir) para iniciar sesión en el depurador.

  11. Use el comando !process para confirmar que está ejecutando un proceso diferente. En la salida que se muestra a continuación, el proceso con el valor Image (Imagen) de System es diferente del valor echo image (Imagen de eco).

    1: kd> !process
    PROCESS ffffe0007b65d900
        SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
        DirBase: 001ab000  ObjectTable: ffffc001c9a03000  HandleCount: 786.
        Image: System
        VadRoot ffffe0007ce45930 Vads 14 Clone 0 Private 22. Modified 131605. Locked 64.
        DeviceMap ffffc001c9a0c220
        Token                             ffffc001c9a05530
        ElapsedTime                       21:31:02.516
    ...
    

    La salida anterior muestra que se estaba ejecutando un proceso del sistema ffffe0007b65d900, cuando se detuvo el sistema operativo.

  12. Ahora, use el comando !process para intentar ver el identificador de proceso que se había asociado a echoapp.exe que registró anteriormente. Proporcione la dirección echoapp.exe proceso que registró anteriormente, en lugar de la dirección de proceso de ejemplo que se muestra a continuación.

    0: kd> !process ffffe0007e6a7780
    TYPE mismatch for process object at 82a9acc0
    

    El objeto de proceso ya no está disponible, ya echoapp.exe proceso ya no se está ejecutando.

Hilos

Note
Los comandos para ver y establecer subprocesos son muy similares a los de los procesos. Use el comando !thread para ver subprocesos. Use .thread para establecer los subprocesos actuales.

  1. - En el sistema host

    Escriba g en el depurador para reiniciar la ejecución de código en el sistema de destino.

  2. - En el sistema de destino

    Ejecute el EchoApp.exe prueba de controladores en el sistema de destino.

  3. - En el sistema host

    Se alcanzará el punto de interrupción y se detendrá la ejecución del código.

    Breakpoint 4 hit
    ECHO!EchoEvtIoRead:
    aade54c0 55              push    ebp
    
  4. Para ver los subprocesos que se están ejecutando, escriba !thread. Debe mostrarse información similar a la siguiente:

    0: kd>  !thread
    THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
    IRP List:
        ffffe0007bc5be10: (0006,01f0) Flags: 00060a30  Mdl: 00000000
    Not impersonating
    DeviceMap                 ffffc001d83c6e80
    Owning Process            ffffe0008096c900       Image:         echoapp.exe
    ...
    

    Observe el nombre de la imagenechoapp.exe, que indica que estamos viendo el subproceso asociado a la aplicación de prueba.

    1. Use el comando !process para determinar si este es el único subproceso que se ejecuta en el proceso asociado a echoapp.exe. Tenga en cuenta que el número de subproceso del subproceso en ejecución en el proceso es el mismo subproceso que ejecuta el comando !thread mostrado.
    0: kd> !process
    PROCESS ffffe0008096c900
        SessionId: 1  Cid: 0b28    Peb: 7ff7d00df000  ParentCid: 0f34
        DirBase: 1fb746000  ObjectTable: ffffc001db6b52c0  HandleCount:  34.
        Image: echoapp.exe
        VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001cf5dc050
        ElapsedTime                       00:00:00.048
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         33824
        QuotaPoolUsage[NonPagedPool]      4464
        Working Set Sizes (now,min,max)  (681, 50, 345) (2724KB, 200KB, 1380KB)
        PeakWorkingSetSize                651
        VirtualSize                       16 Mb
        PeakVirtualSize                   16 Mb
        PageFaultCount                    686
        MemoryPriority                    BACKGROUND
        BasePriority                      8
        CommitCharge                      138
    
            THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
    
  5. Use el comando !process 0 0 para buscar la dirección del proceso de dos procesos relacionados y registrar esa dirección de proceso aquí.

    Cmd.exe: _____________________________________________________________________________________

    EchoApp.exe: ________________________________________________________________

    0: kd> !process 0 0 
    
    …
    
    PROCESS ffffe0007bbde900
        SessionId: 1  Cid: 0f34    Peb: 7ff72dfa7000  ParentCid: 0c64
        DirBase: 19c5fa000  ObjectTable: ffffc001d8c2f300  HandleCount:  31.
        Image: cmd.exe
    …
    PROCESS ffffe0008096c900
        SessionId: 1  Cid: 0b28    Peb: 7ff7d00df000  ParentCid: 0f34
        DirBase: 1fb746000  ObjectTable: ffffc001db6b52c0  HandleCount:  34.
        Image: echoapp.exe
    …
    

    Nota También puede usar !process 0 17 para mostrar información detallada sobre cada proceso. La salida de este comando puede ser larga. La salida se puede buscar mediante Ctrl+F.

  6. Use el comando !process para enumerar la información del proceso de ambos procesos que ejecutan el equipo. Proporcione la dirección del proceso desde la salida !process 0 0, no la dirección que se muestra a continuación.

    Esta salida de ejemplo es para el cmd.exe de proceso que se registró anteriormente. Tenga en cuenta que el nombre de imagen de este identificador de proceso es cmd.exe.

    0: kd>  !process ffffe0007bbde900
    PROCESS ffffe0007bbde900
        SessionId: 1  Cid: 0f34    Peb: 7ff72dfa7000  ParentCid: 0c64
        DirBase: 19c5fa000  ObjectTable: ffffc001d8c2f300  HandleCount:  31.
        Image: cmd.exe
        VadRoot ffffe0007bb8e7b0 Vads 25 Clone 0 Private 117. Modified 20. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001d8c48050
        ElapsedTime                       21:33:05.840
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         24656
        QuotaPoolUsage[NonPagedPool]      3184
        Working Set Sizes (now,min,max)  (261, 50, 345) (1044KB, 200KB, 1380KB)
        PeakWorkingSetSize                616
        VirtualSize                       2097164 Mb
        PeakVirtualSize                   2097165 Mb
        PageFaultCount                    823
        MemoryPriority                    FOREGROUND
        BasePriority                      8
        CommitCharge                      381
    
            THREAD ffffe0007cf34880  Cid 0f34.0f1c  Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable
                ffffe0008096c900  ProcessObject
            Not impersonating
    ...
    

    Esta salida de ejemplo es para el echoapp.exe de proceso que se registró anteriormente.

    0: kd>  !process ffffe0008096c900
    PROCESS ffffe0008096c900
        SessionId: 1  Cid: 0b28    Peb: 7ff7d00df000  ParentCid: 0f34
        DirBase: 1fb746000  ObjectTable: ffffc001db6b52c0  HandleCount:  34.
        Image: echoapp.exe
        VadRoot ffffe000800cf920 Vads 30 Clone 0 Private 135. Modified 8. Locked 0.
        DeviceMap ffffc001d83c6e80
        Token                             ffffc001cf5dc050
        ElapsedTime                       00:00:00.048
        UserTime                          00:00:00.000
        KernelTime                        00:00:00.000
        QuotaPoolUsage[PagedPool]         33824
        QuotaPoolUsage[NonPagedPool]      4464
        Working Set Sizes (now,min,max)  (681, 50, 345) (2724KB, 200KB, 1380KB)
        PeakWorkingSetSize                651
        VirtualSize                       16 Mb
        PeakVirtualSize                   16 Mb
        PageFaultCount                    686
        MemoryPriority                    BACKGROUND
        BasePriority                      8
        CommitCharge                      138
    
            THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
            IRP List:
                ffffe0007bc5be10: (0006,01f0) Flags: 00060a30  Mdl: 00000000
            Not impersonating
    ...
    
  7. Registre aquí la primera dirección de subproceso asociada a los dos procesos.

    Cmd.exe: _________________________________________________

    EchoApp.exe: ________________________________________________________

  8. Use ! Comando Thread para mostrar información sobre el subproceso actual.

    0: kd>  !Thread
    THREAD ffffe000809a0880  Cid 0b28.1158  Teb: 00007ff7d00dd000 Win32Thread: 0000000000000000 RUNNING on processor 0
    IRP List:
        ffffe0007bc5be10: (0006,01f0) Flags: 00060a30  Mdl: 00000000
    Not impersonating
    DeviceMap                 ffffc001d83c6e80
    Owning Process            ffffe0008096c900       Image:         echoapp.exe
    Attached Process          N/A            Image:         N/A
    ...
    

    Como se esperaba, el subproceso actual es el subproceso asociado a echoapp.exe y se encuentra en estado en ejecución.

  9. Use ! Comando Thread para mostrar información sobre el subproceso asociado a cmd.exe proceso. Proporcione la dirección del subproceso que registró anteriormente.

    0: kd> !Thread ffffe0007cf34880
    THREAD ffffe0007cf34880  Cid 0f34.0f1c  Teb: 00007ff72dfae000 Win32Thread: 0000000000000000 WAIT: (UserRequest) UserMode Non-Alertable
        ffffe0008096c900  ProcessObject
    Not impersonating
    DeviceMap                 ffffc001d83c6e80
    Owning Process            ffffe0007bbde900       Image:         cmd.exe
    Attached Process          N/A            Image:         N/A
    Wait Start TickCount      4134621        Ticks: 0
    Context Switch Count      4056           IdealProcessor: 0             
    UserTime                  00:00:00.000
    KernelTime                00:00:01.421
    Win32 Start Address 0x00007ff72e9d6e20
    Stack Init ffffd0015551dc90 Current ffffd0015551d760
    Base ffffd0015551e000 Limit ffffd00155518000 Call 0
    Priority 14 BasePriority 8 UnusualBoost 3 ForegroundBoost 2 IoPriority 2 PagePriority 5
    Child-SP          RetAddr           : Args to Child                                                           : Call Site
    ffffd001`5551d7a0 fffff801`eed184fe : fffff801`eef81180 ffffe000`7cf34880 00000000`fffffffe 00000000`fffffffe : nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109]
    ffffd001`5551d8e0 fffff801`eed17f79 : ffff03a5`ca56a3c8 000000de`b6a6e990 000000de`b6a6e990 00007ff7`d00df000 : nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347]
    ffffd001`5551d980 fffff801`eecea340 : ffffd001`5551da18 00000000`00000000 00000000`00000000 00000000`00000388 : nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619]
    ...
    

    Este subproceso está asociado a cmd.exe y está en estado de espera.

  10. Proporcione la dirección del subproceso en espera CMD.exe para cambiar el contexto a ese subproceso en espera.

    0: kd> .Thread ffffe0007cf34880
    Implicit thread is now ffffe000`7cf34880
    
  11. Use el comando k para ver la pila de llamadas asociada al subproceso en espera.

    0: kd> k
      *** Stack trace for last set context - .thread/.cxr resets it
    # Child-SP          RetAddr           Call Site
    00 ffffd001`5551d7a0 fffff801`eed184fe nt!KiSwapContext+0x76 [d:\9142\minkernel\ntos\ke\amd64\ctxswap.asm @ 109]
    01 ffffd001`5551d8e0 fffff801`eed17f79 nt!KiSwapThread+0x14e [d:\9142\minkernel\ntos\ke\thredsup.c @ 6347]
    02 ffffd001`5551d980 fffff801`eecea340 nt!KiCommitThreadWait+0x129 [d:\9142\minkernel\ntos\ke\waitsup.c @ 619]
    03 ffffd001`5551da00 fffff801`ef02e642 nt!KeWaitForSingleObject+0x2c0 [d:\9142\minkernel\ntos\ke\wait.c @ 683]
    ...
    

    Los elementos de pila de llamadas como KiCommitThreadWait indican que este subproceso no se está ejecutando como se espera.

Note
Para obtener más información sobre subprocesos y procesos, vea las siguientes referencias:

Subprocesos y procesos

Cambiar contextos

Sección 10: IRQL, Registra y finaliza la sesión de WinDbg

Visualización del IRQL guardado

En la sección 10, se mostrará el IRQL y el contenido de los regsqls.

- En el sistema host

El nivel de solicitud de interrupción (IRQL) se usa para administrar la prioridad del mantenimiento de interrupciones. Cada procesador tiene una configuración IRQL que los subprocesos pueden generar o reducir. Las interrupciones que se producen en o por debajo de la configuración irQL del procesador se enmascaran y no interferirán con la operación actual. Las interrupciones que se producen por encima de la configuración de IRQL del procesador tienen prioridad sobre la operación actual. La extensión !irql muestra el nivel de solicitud de interrupción (IRQL) en el procesador actual del equipo de destino antes de que se produjese la interrupción del depurador. Cuando el equipo de destino entra en el depurador, el IRQL cambia, pero el IRQL que era efectivo justo antes de la interrupción del depurador se guarda y se muestra mediante !irql.

0: kd> !irql
Debugger saved IRQL for processor 0x0 -- 2 (DISPATCH_LEVEL)

Visualización de los registros

-En el sistema host

Muestre el contenido de los registros para el subproceso actual en el procesador actual mediante el comando r (Registros).

0: kd> r
rax=000000000000c301 rbx=ffffe00173eed880 rcx=0000000000000001
rdx=000000d800000000 rsi=ffffe00173eed8e0 rdi=ffffe00173eed8f0
rip=fffff803bb757020 rsp=ffffd001f01f8988 rbp=ffffe00173f0b620
 r8=000000000000003e  r9=ffffe00167a4a000 r10=000000000000001e
r11=ffffd001f01f88f8 r12=0000000000000000 r13=ffffd001f01efdc0
r14=0000000000000001 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
nt!DbgBreakPointWithStatus:
fffff803`bb757020 cc              int     3

Como alternativa, puede mostrar el contenido de los registros seleccionando verregistros. Para obtener más información, vea r (Registros).

Ver el contenido de los registros puede ser útil al ejecutar código de lenguaje de ensamblado y en otros escenarios. Para obtener más información sobre el desensamblado del lenguaje de ensamblado, vea Desensamblado x86 anotado y Desensamblado x64 anotado.

Para obtener información sobre el contenido del registro, vea Arquitectura x86 y Arquitectura x64.

Finalización de la sesión de WinDbg

-En el sistema host

Para finalizar una sesión de depuración en modo de usuario, devuelva el depurador al modo inactivo y establezca la aplicación de destino para que se ejecute de nuevo, escriba el comando qd (Salir y separar).

Asegúrese de usar el comando g para permitir que el equipo de destino ejecute código, de modo que se pueda usar. También es una buena idea borrar los puntos de interrupción mediante bc *, para que el equipo de destino no se interrumpirá e intente conectarse al depurador del equipo host.

0: kd> qd

Para obtener más información, vea Finalizar una sesión de depuración en WinDbg en la documentación de referencia de depuración.

Sección 11: Windows recursos de depuración

Hay información adicional disponible sobre la Windows depuración. Tenga en cuenta que algunos de estos libros usarán versiones anteriores de Windows como Windows Vista en sus ejemplos, pero los conceptos analizados son aplicables a la mayoría de las versiones de Windows.

Libros

  • Advanced Windows Debugging (Depuración avanzada de Windows) de Daniel Hewardt y Daniel Pravat

  • Inside Windows Debugging: A Practical Guide to Debugging and Tracing Strategies in Windows® by TarikAmi

  • Windows Internals de Mark E. Russinvl, David A.Vl y Alex Ionescu

Vídeo

The Defrag Tools Show WinDbg Episodes 13-29 https://channel9.msdn.com/Shows/Defrag-Tools

Proveedores de entrenamiento:

OSR https://www.osr.com/

Técnicas de depuración estándar

Técnicas de depuración especializadas

Tareas iniciales con Windows depuración

En este laboratorio se presenta el depurador de kernel de WinDbg. WinDbg se usa para depurar el código de controlador de ejemplo del modo de kernel de eco.

Objetivos de laboratorio

Este laboratorio incluye ejercicios que presentan las herramientas de depuración, enseñan comandos de depuración comunes, ilustran el uso de puntos de interrupción y muestran el uso de las extensiones de depuración.

En este laboratorio, se usa una conexión de depuración de kernel activa para explorar lo siguiente:

  • Uso de los Windows del depurador
  • Uso de comandos estándar (pilas de llamadas, variables, subprocesos, IRQL)
  • Uso de comandos avanzados de depuración de controladores (!commands)
  • Uso de símbolos
  • Establecer puntos de interrupción en la depuración en vivo
  • Visualización de pilas de llamadas
  • Mostrar el árbol Plug and Play dispositivo
  • Trabajo con contexto de subproceso y proceso

Nota Al trabajar con el depurador Windows, hay dos tipos de depuración que se pueden realizar: depuración en modo de usuario o kernel.

Modo de usuario: las aplicaciones y subsistemas se ejecutan en el equipo en modo de usuario. Los procesos que se ejecutan en modo de usuario lo hacen dentro de sus propios espacios de direcciones virtuales. Están restringidos a obtener acceso directo a muchas partes del sistema, incluido el hardware del sistema, la memoria que no se asignó para su uso y otras partes del sistema que podrían poner en peligro la integridad del sistema. Dado que los procesos que se ejecutan en modo de usuario están aislados eficazmente del sistema y otros procesos de modo de usuario, no pueden interferir con estos recursos.

Modo kernel: el modo kernel es el modo de acceso del procesador en el que se ejecutan el sistema operativo y los programas con privilegios. El código en modo kernel tiene permiso para acceder a cualquier parte del sistema y no está restringido como el código de modo de usuario. Puede obtener acceso a cualquier parte de cualquier otro proceso que se ejecute en modo de usuario o modo kernel. Gran parte de la funcionalidad básica del sistema operativo y muchos controladores de dispositivos de hardware se ejecutan en modo kernel.

Este laboratorio se centrará en la depuración en modo kernel, ya que es el método que se usa para depurar muchos controladores de dispositivo.

En este ejercicio se tratan los comandos de depuración que se usan con frecuencia durante la depuración en modo de usuario y en modo kernel. En el ejercicio también se tratan las extensiones de depuración (a veces denominadas "!commands") que se usan para la depuración en modo kernel.

Configuración del laboratorio

Necesitará el siguiente hardware para poder completar el laboratorio.

  • Un equipo portátil o de escritorio (host) que ejecuta Windows 10
  • Un equipo portátil o de escritorio (destino) que ejecuta Windows 10
  • Un concentrador o enrutador de red y cables de red para conectar los dos equipos
  • Acceso a Internet para descargar archivos de símbolos

Necesitará el siguiente software para poder completar el laboratorio.

  • Programa para la mejora
  • Kit de desarrollo de software de Windows (SDK) para Windows 10
  • Windows Driver Kit (WDK) para Windows 10
  • El controlador de eco de ejemplo para Windows 10

El laboratorio tiene las once secciones siguientes.

Sección 1: Conectar a una sesión winDbg en modo kernel

En la sección 1, configurará la depuración de red en el host y el sistema de destino.

Los equipos de este laboratorio deben configurarse para usar una conexión de red Ethernet para la depuración del kernel.

Este laboratorio usa dos equipos. Windows depurador se ejecuta en el sistema host y el controlador eco de KMDF se ejecuta en el sistema de destino.

Use un concentrador o enrutador de red y cables de red para conectar los dos equipos.

dos pc conectados con una flecha doble.

Para trabajar con aplicaciones en modo kernel y usar WinDbg, se recomienda usar KDNET a través del transporte Ethernet. Para obtener información sobre cómo usar el protocolo de transporte Ethernet, vea Tareas iniciales con WinDbg (modo kernel). Para obtener más información sobre cómo configurar el equipo de destino, vea Preparar un equipo para la implementación manual del controlador y Configurar automáticamente la depuración de kernel de red KDNET.

Configuración de la depuración en modo kernel mediante Ethernet

Para habilitar la depuración en modo kernel en el sistema de destino, realice los pasos siguientes.

- En el sistema host

  1. Abra un símbolo del sistema en el sistema host y escriba ipconfig para determinar su dirección IP.
C:\>ipconfig
Windows IP Configuration
Ethernet adapter Ethernet:
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b%3
   Autoconfiguration IPv4 Address. . : 169.182.1.1
   Subnet Mask . . . . . . . . . . . : 255.255.0.0
   Default Gateway . . . . . . . . . :
  1. Registre la dirección IP del sistema host: _________________________________________________

- En el sistema de destino

  1. Abra un símbolo del sistema en el sistema de destino y use el comando ping para confirmar la conectividad de red entre los dos sistemas. Use la dirección IP real del sistema host que registró en lugar de 169.182.1.1 que se muestra en la salida de ejemplo.
C:\> ping 169.182.1.1

Pinging 169.182.1.1 with 32 bytes of data:
Reply from 169.182.1.1: bytes=32 time=1ms TTL=255
Reply from 169.182.1.1: bytes=32 time<1ms TTL=255
Reply from 169.182.1.1: bytes=32 time<1ms TTL=255
Reply from 169.182.1.1: bytes=32 time<1ms TTL=255

Ping statistics for 169.182.1.1:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 1ms, Average = 0ms

Habilite la depuración en modo kernel en el sistema de destino siguiendo estos pasos.

Importante

Antes de usar BCDEdit para cambiar la información de arranque, es posible que tenga que suspender temporalmente Windows características de seguridad como BitLocker y Arranque seguro en el equipo de prueba. Vuelva a habilitar estas características de seguridad cuando se completen las pruebas y administre correctamente el equipo de prueba, cuando las características de seguridad estén deshabilitadas.

  1. En el equipo de destino, abra una ventana del símbolo del sistema como administrador. Escriba este comando para habilitar la depuración.

    C:\> bcdedit /set {default} DEBUG YES
    
  2. Escriba este comando para habilitar la firma de prueba.

    C:\> bcdedit /set TESTSIGNING ON 
    
  3. Escriba este comando para establecer la dirección IP del sistema host. Use la dirección IP del sistema host que registró anteriormente, no la que se muestra.

    C:\> bcdedit /dbgsettings net hostip:192.168.1.1 port:50000 key:2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    

Advertencia Para aumentar la seguridad de la conexión y reducir el riesgo de las solicitudes de conexión aleatorias del depurador de cliente, considere la posibilidad de usar una clave aleatoria generada automáticamente. Para obtener más información, consulte Configuración automática de la depuración de kernel de red KDNET.

  1. Escriba este comando para confirmar que dbgsettings están establecidos correctamente.

    C:\> bcdedit /dbgsettings
    key                     2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    debugtype               NET
    hostip                  169.168.1.1
    port                    50000
    dhcp                    Yes
    The operation completed successfully.
    

Note
Firewalls y depuradores

Si recibe un mensaje emergente del firewall y desea usar el depurador, active las tres casillas.

Alerta de seguridad de Windows: el firewall de Windows ha bloqueado algunas características de esta aplicación.

- En el sistema host

  1. En el equipo host, abra una ventana del símbolo del sistema como administrador. Usaremos la versión x64 de WinDbg.exe del kit de controladores de Windows (WDK) que se instaló como parte de la instalación del kit de Windows. De forma predeterminada, se encuentra aquí.

    C:\> Cd C:\Program Files(x86)\Windows Kits\10\Debuggers\x64 
    

Nota

En este laboratorio se da por supuesto que ambos equipos ejecutan una versión de 64 bits de Windows en el destino y el host. Si ese no es el caso, el mejor enfoque es ejecutar el mismo "valor de bits" de las herramientas en el host en el que se ejecuta el destino. Por ejemplo, si el destino ejecuta 32 bits Windows, ejecute una versión 32 del depurador en el host. Para obtener más información, vea Elegir las herramientas de depuración de 32 o 64 bits.

  1. Inicie WinDbg con la depuración de usuario remoto mediante el siguiente comando. El valor de la clave y el puerto coinciden con lo establecido anteriormente mediante BCDEdit en el destino.

    WinDbg –k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    

- En el sistema de destino

Reinicie el sistema de destino.

-En el sistema host

En un minuto o dos, la salida de depuración debe mostrarse en el sistema host.

Microsoft (R) Windows Debugger Version 10.0.17074.1002 AMD64
Copyright (c) Microsoft Corporation. All rights reserved.

Using NET for debugging
Opened WinSock 2.0
Waiting to reconnect...
Connected to target 169.182.1.1 on port 50005 on local IP 169.182.1.2
You can get the target MAC address by running .kdtargetmac command.
Connected to Windows 10 16299 x64 target at (Wed Feb 28 17:16:23.051 2018 (UTC - 8:00)), ptr64 TRUE
Kernel Debugger connection established.  (Initial Breakpoint requested)
Symbol search path is: srv*
Executable search path is: 
Windows 10 Kernel Version 16299 MP (4 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 16299.15.amd64fre.rs3_release.170928-1534
Machine Name:
Kernel base = 0xfffff800`9540d000 PsLoadedModuleList = 0xfffff800`95774110
Debug session time: Wed Feb 28 17:16:23.816 2018 (UTC - 8:00)
System Uptime: 0 days 0:00:20.534

El depurador ventana Comandos es la ventana de información de depuración principal de WinDbg. Puede escribir comandos del depurador y ver la salida del comando en esta ventana.

El depurador ventana Comandos se divide en dos paneles. Escriba comandos en el panel más pequeño (el panel de entrada de comandos) en la parte inferior de la ventana y vea la salida del comando en el panel más grande en la parte superior de la ventana.

En el panel de entrada de comandos, use las teclas de flecha arriba y flecha abajo para desplazarse por el historial de comandos. Cuando aparezca un comando, puede editarlo o presionar ENTRAR para ejecutar el comando.

Sección 2: Comandos y técnicas de depuración en modo kernel

En la sección 2, usará comandos de depuración para mostrar información sobre el sistema de destino.

- En el sistema host

Habilitar el lenguaje de marcado del depurador (DML) con .prefer_dml

Algunos comandos de depuración muestran texto mediante el lenguaje de marcado del depurador que puede seleccionar para recopilar rápidamente más información.

  1. Use Ctrl+Interrumpir (bloqueo de desplazamiento) en WinDBg para interrumpir el código que se ejecuta en el sistema de destino. El sistema de destino puede tardar un poco en responder.

Depurador de Windows que muestra la salida de la ventana de comandos de una conexión de kernel activa.

  1. Escriba el siguiente comando para habilitar DML en el depurador ventana Comandos.
0: kd> .prefer_dml 1
DML versions of commands on by default

Uso de .hh para obtener ayuda

Puede acceder a la ayuda del comando de referencia mediante el comando .hh.

  1. Escriba el siguiente comando para ver la ayuda de referencia de comandos para .prefer_dml.
0: kd> .hh .prefer_dml

El archivo de ayuda del depurador mostrará ayuda para el comando .prefer_dml depuración.

aplicación de ayuda del depurador que muestra ayuda para el comando .prefer-dml.

Mostrar la versión de Windows en el sistema de destino

  1. Para mostrar información detallada de la versión en el sistema de destino, escriba el comando vertarget (Mostrar versión del equipo de destino) en la ventana WinDbg.
0: kd> vertarget
Windows 10 Kernel Version 9926 MP (4 procs) Free x64
Product: WinNt, suite: TerminalServer SingleUserTS
Built by: 9926.0.amd64fre.fbl_awesome1501.150119-1648
Machine Name: ""
Kernel base = 0xfffff801`8d283000 PsLoadedModuleList = 0xfffff801`8d58aef0
Debug session time: Fri Feb 20 10:15:17.807 2015 (UTC - 8:00)
System Uptime: 0 days 01:31:58.931

Enumeración de los módulos cargados

  1. Para comprobar que está trabajando con el proceso de modo de kernel correcto, para lo que debe mostrar los módulos cargados, escriba el comando lm (Enumerar módulos cargados) en la ventana de WinDbg.
0: Kd> lm
start             end                 module name
fffff801`09200000 fffff801`0925f000   volmgrx    (no symbols)           
fffff801`09261000 fffff801`092de000   mcupdate_GenuineIntel   (no symbols)           
fffff801`092de000 fffff801`092ec000   werkernel   (export symbols)       werkernel.sys
fffff801`092ec000 fffff801`0934d000   CLFS       (export symbols)       CLFS.SYS
fffff801`0934d000 fffff801`0936f000   tm         (export symbols)       tm.sys
fffff801`0936f000 fffff801`09384000   PSHED      (export symbols)       PSHED.dll
fffff801`09384000 fffff801`0938e000   BOOTVID    (export symbols)       BOOTVID.dll
fffff801`0938e000 fffff801`093f7000   spaceport   (no symbols)           
fffff801`09400000 fffff801`094cf000   Wdf01000   (no symbols)           
fffff801`094d9000 fffff801`09561000   CI         (export symbols)       CI.dll
...

Nota La salida que se ha omitido se indica con "... " en este laboratorio.

  1. Para solicitar información detallada sobre un módulo específico, use la opción v (detallado) como se muestra.
0: Kd> lm v m tcpip
Browse full module list
start             end                 module name
fffff801`09eeb000 fffff801`0a157000   tcpip      (no symbols)           
    Loaded symbol image file: tcpip.sys
    Image path: \SystemRoot\System32\drivers\tcpip.sys
    Image name: tcpip.sys
    Browse all global symbols  functions  data
    Timestamp:        Sun Nov 09 18:59:03 2014 (546029F7)
    CheckSum:         00263DB1
    ImageSize:        0026C000
    Translations:     0000.04b0 0000.04e4 0409.04b0 0409.04e4

Unable to enumerate user-mode unloaded modules, Win32 error 0n30
  1. Dado que aún no hemos establecido la ruta de acceso de símbolos y los símbolos cargados, hay información limitada disponible en el depurador.

Sección 3: Descarga y compilación del controlador de eco kmdf

En la sección 3, descargará y compilará el controlador de eco KMDF.

Normalmente, trabajaría con su propio código de controlador al usar WinDbg. Para familiarizarse con la operación WinDbg, se usa el controlador de ejemplo "Echo" de la plantilla KMDF. Con el código fuente disponible, también será más fácil comprender la información que se muestra en WinDbg. Además, este ejemplo se usa para ilustrar cómo puede realizar un solo paso a través del código en modo kernel nativo. Esta técnica puede ser muy valiosa para depurar problemas complejos de código en modo kernel.

Para descargar y compilar el controlador de audio de ejemplo Echo, realice los pasos siguientes.

  1. Descargue y extraiga el ejemplo de eco de KMDF de GitHub

    Puede usar un explorador para ver el ejemplo de eco en GitHub aquí:

    https://github.com/Microsoft/Windows-driver-samples/tree/master/general/echo/kmdf

    Puede leer sobre el ejemplo aquí:

    https://github.com/microsoft/Windows-driver-samples/blob/master/general/echo/kmdf/README.md

    Puede examinar todos los ejemplos de controladores Windows aquí:

    https://github.com/Microsoft/Windows-driver-samples

    El ejemplo de eco de KMDF se encuentra en la carpeta general.

    github windows-driver-samples que resalta la carpeta general y el botón descargar zip.

    a. En este laboratorio se muestra cómo descargar los ejemplos de controladores en un archivo ZIP.

    https://github.com/Microsoft/Windows-driver-samples/archive/master.zip

    b. Descargue el master.zip en el disco duro local.

    c. Seleccione y mantenga presionado (o haga clic con el botón derecho)Windows-driver-samples-master.zipy elija Extraer todo. Especifique una nueva carpeta o busque una existente que almacenará los archivos extraídos. Por ejemplo, puede especificar C:\DriverSamples\ como la nueva carpeta en la que se extraen los archivos.

    d. Una vez extraídos los archivos, vaya a la subcarpeta siguiente.

    C:\DriverSamples\general\echo\kmdf

  2. Abra la solución de controlador en Visual Studio

    En Microsoft Visual Studio, seleccione Archivo abrir Project/Solución... y vaya a la carpeta que contiene los archivos extraídos (por ejemplo, C:\DriverSamples\general\echo\kmdf). Haga doble clic en el archivo de solución kmdfecho para abrirlo.

    En Visual Studio, busque el Explorador de soluciones. (Si aún no está abierto, elija Explorador de soluciones en el menú Ver). En Explorador de soluciones, puede ver una solución que tiene tres proyectos.

    visual Studio con el archivo device.c cargado desde el proyecto kmdfecho.

  3. Establecer la configuración y la plataforma del ejemplo

    En Explorador de soluciones, mantenga presionado (o haga clic con el botón derecho) Solución "kmdfecho" (3 proyectos)y elija Administrador de configuración. Asegúrese de que la configuración y la configuración de la plataforma son las mismas para los tres proyectos. De forma predeterminada, la configuración se establece en "Win10 Debug" y la plataforma se establece en "Win64" para todos los proyectos. Si realiza cambios en la configuración o la plataforma de un proyecto, debe realizar los mismos cambios para los tres proyectos restantes.

  4. Establecer la biblioteca en tiempo de ejecución

    Establecer la biblioteca en tiempo de ejecución: abra la página de propiedades del controlador de eco y busque Generación de código de C/C++. Cambie la biblioteca en tiempo de ejecución de la versión dll a una versión que no es dll. Sin esta configuración, tendrá que instalar el entorno de ejecución MSVC en el equipo de destino por separado.

    Página de propiedades echo que resalta la configuración de la biblioteca en tiempo de ejecución.

  5. Comprobación de la firma del controlador

    Además, en las propiedades del controlador, asegúrese de que modo de firmade controlador está establecido en "Signo de prueba". Esto es necesario porque Windows requiere que los controladores estén firmados.

    Página de propiedades echo que resalta la configuración del modo de signo.

  6. Compile el ejemplo mediante Visual Studio

    En Visual Studio, seleccione Compilar soluciónde compilación.

    Si todo va bien, las ventanas de compilación deben mostrar un mensaje que indica que la compilación de los tres proyectos se ha hecho correctamente.

  7. Buscar los archivos de controlador creados

    En Explorador de archivos, vaya a la carpeta que contiene los archivos extraídos para el ejemplo. Por ejemplo, navegaría a C:\DriverSamples\general\echo\kmdf, si es la carpeta que especificó anteriormente. Dentro de esa carpeta, la ubicación de los archivos de controlador compilados varía en función de la configuración y la configuración de la plataforma que haya seleccionado en el Administrador de configuración. Por ejemplo, si deja sin modificar la configuración predeterminada, los archivos de controlador compilados se guardarán en una carpeta denominada \x64\Debug para una compilación de depuración de 64 bits.

    Vaya a la carpeta que contiene los archivos creados para el controlador autosync:

    C:\DriverSamples\general\echo\kmdf\driver\AutoSync\x64\Debug.

    La carpeta debe contener estos archivos:

    Archivo Descripción
    Echo.sys Archivo de controlador.
    Echo.inf Archivo de información (INF) que contiene la información necesaria para instalar el controlador.

    Además, el archivo echoapp.exe se ha creado y debe estar ubicado aquí: C:\DriverSamples\general\echo\kmdf\exe\x64\Debug

    Archivo Descripción
    EchoApp.exe Un archivo de prueba ejecutable del símbolo del sistema que se comunica con echo.sys controlador.
  8. Busque una unidad usb o configure un recurso compartido de red para copiar los archivos de controlador creados y la echoApp de prueba del host al sistema de destino.

En la sección siguiente, copiará el código en el sistema de destino e instalará y probará el controlador.

Sección 4: Instalación del ejemplo de controlador de eco kmdf en el sistema de destino

En la sección 4, usará devcon para instalar el controlador de ejemplo de eco.

El equipo donde se instala el controlador se denomina equipo de destino o equipo de prueba. Normalmente, se trata de un equipo independiente del equipo en el que desarrolla y compila el paquete de controladores. El equipo donde desarrolla y compila el controlador se denomina equipo host.

El proceso de mover el paquete de controladores al equipo de destino e instalar el controlador se denomina implementación del controlador.

Antes de implementar un controlador firmado de prueba, debe preparar el equipo de destino habilitando la firma de pruebas. También debe buscar la herramienta DevCon en la instalación de WDK y copiarla en el sistema de destino.

Para instalar el controlador en el sistema de destino, realice los pasos siguientes.

- En el sistema de destino

Habilitación de controladores firmados de prueba

Habilite la capacidad de ejecutar controladores firmados de prueba:

a. Abra Windows Configuración.

b. En Actualización y seguridad, seleccione Recuperación.

c. En Inicio avanzado, seleccione Reiniciar ahora.

d. Cuando se reinicie el equipo, seleccione Opciones de inicio. En Windows 10, seleccione Solucionarproblemas opciones avanzadas Opciones de inicio Configuración y, a continuación, seleccione el botón Reiniciar.

e. Seleccione Deshabilitar el cumplimiento de la firma del controlador presionando la tecla F7.

f. Reinicie el equipo de destino.

- En el sistema host

Vaya a la carpeta Herramientas de la instalación de WDK y busque la herramienta DevCon. Por ejemplo, busque en la carpeta siguiente:

C:\Archivos de programa (x86)\Windows Kits\10\Tools\x64\devcon.exe

Cree una carpeta en el destino para el paquete de controladores creado (por ejemplo, C:\EchoDriver). Copie devcon.exe en el sistema de destino. Busque el certificado .cer en el sistema host, que se encuentra en la misma carpeta del equipo host en la carpeta que contiene los archivos de controlador creados. Copie todos los archivos del controlador integrado descrito anteriormente en el equipo host y guárdelos en la misma carpeta que creó en el equipo de destino.

- En el sistema de destino

En el equipo de destino, mantenga presionado (o haga clic con el botón derecho) el archivo de certificado y seleccione Instalar y, a continuación, siga las indicaciones para instalar el certificado de prueba.

Si necesita instrucciones más detalladas para configurar el equipo de destino, vea Preparar un equipo para la implementación manual del controlador.

- En el sistema de destino

Instalación del controlador

En las instrucciones siguientes se muestra cómo instalar y probar el controlador de ejemplo. Esta es la sintaxis general de la herramienta devcon que usará para instalar el controlador:

Devcon install INF file hardware ID (Id. de hardware de archivo INF de instalación de devcon) ><>

El archivo INF necesario para instalar este controlador es echo.inf. El archivo inf contiene el identificador de hardware para instalar el echo.sys. Para el ejemplo de eco, el identificador de hardware es root\ECHO.

En el equipo de destino, abra una ventana del símbolo del sistema como administrador. Vaya a la carpeta del paquete de controladores y escriba el siguiente comando:

devcon install echo.inf root\ECHO Si recibe un mensaje de error sobre que devcon no se reconoce, intente agregar la ruta de acceso a la herramienta devcon. Por ejemplo, si lo copió en una carpeta denominada C:\Tools, intente usar el siguiente comando:

c:\tools\devcon install echo.inf root\ECHO Aparecerá un cuadro de diálogo que indica que el controlador de prueba es un controlador sin signo. Seleccione Instalar este controlador de todos modos para continuar.

Advertencia de seguridad de Windows: Windows no puede comprobar el publicador de este software de controlador.

Sugerencia

 Si tiene algún problema con la instalación, consulte el siguiente archivo para obtener más información. %windir%\inf\setupapi.dev.log

Después de instalar correctamente el controlador de ejemplo, ya está listo para probarlo.

Examine el controlador en Administrador de dispositivos

En el equipo de destino, en una ventana del símbolo del sistema, escriba devmgmt open Administrador de dispositivos. En Administrador de dispositivos, en el menú Ver, elija Dispositivos por tipo. En el árbol de dispositivos, busque Controlador de eco WDF de ejemplo en el nodo Dispositivo de ejemplo.

árbol del administrador de dispositivos con el controlador de eco wdf de ejemplo resaltado.

Prueba del controlador

Escriba echoapp para iniciar la aplicación de eco de prueba para confirmar que el controlador es funcional.

C:\Samples\KMDF_Echo_Sample> echoapp
DevicePath: \\?\root#sample#0005#{cdc35b6e-0be4-4936-bf5f-5537380a7c1a}
Opened device successfully
512 Pattern Bytes Written successfully
512 Pattern Bytes Read successfully
Pattern Verified successfully
30720 Pattern Bytes Written successfully
30720 Pattern Bytes Read successfully
Pattern Verified successfully

Sección 5: Uso de WinDbg para mostrar información sobre el controlador

En la sección 5, establecerá la ruta de acceso de símbolos y usará los comandos del depurador del kernel para mostrar información sobre el controlador de ejemplo de eco kmdf.

Para ver información sobre el controlador, realice los pasos siguientes.

-En el sistema host

  1. Si cerró el depurador, ábralo de nuevo con el siguiente comando en la ventana del símbolo del sistema del administrador.

    WinDbg -k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  2. Use Ctrl+Interrumpir (Bloqueo de desplazamiento) para interrumpir el código que se ejecuta en el sistema de destino.

Establecimiento de la ruta de acceso del símbolo

  1. Para establecer la ruta de acceso de símbolos al servidor de símbolos de Microsoft en el entorno de WinDbg, use el comando .symfix.

    0: kd> .symfix
    
  2. Para agregar la ubicación del símbolo local para usar los símbolos locales, agregue la ruta de acceso mediante .sympath+ y, a continuación, .reload /f.

    0: kd> .sympath+ C:\DriverSamples\general\echo\kmdf
    0: kd> .reload /f
    

    Nota El comando .reload con la opción /f force elimina toda la información de símbolos del módulo especificado y vuelve a cargar los símbolos. En algunos casos, este comando también recarga o descarga el propio módulo.

Nota Debe cargar los símbolos adecuados para usar la funcionalidad avanzada que proporciona WinDbg. Si no tiene símbolos configurados correctamente, recibirá mensajes que indican que los símbolos no están disponibles al intentar usar la funcionalidad que depende de los símbolos.

0:000> dv
Unable to enumerate locals, HRESULT 0x80004005
Private symbols (symbols.pri) are required for locals.
Type “.hh dbgerr005” for details.

Note
Servidores de símbolos

Hay una serie de enfoques que se pueden usar para trabajar con símbolos. En muchas situaciones, puede configurar el equipo para acceder a símbolos desde un servidor de símbolos que Microsoft proporciona cuando se necesitan. En este tutorial se da por supuesto que se usará este enfoque. Si los símbolos del entorno están en una ubicación diferente, modifique los pasos para usar esa ubicación. Para obtener información adicional, vea Ruta de acceso de símbolos Windows depurador.

Note
Información sobre los requisitos de símbolos de código fuente

Para realizar la depuración de origen, debe compilar una versión activada (depuración) de los archivos binarios. El compilador creará archivos de símbolos (archivos .pdb). Estos archivos de símbolos mostrarán al depurador cómo se corresponden las instrucciones binarias con las líneas de origen. Los propios archivos de origen reales también deben ser accesibles para el depurador.

Los archivos de símbolos no contienen el texto del código fuente. Para la depuración, es mejor si el vinculador no optimiza el código. La depuración de código fuente y el acceso a variables locales son más difíciles y, a veces, casi imposibles, si el código se ha optimizado. Si tiene problemas para ver variables locales o líneas de origen, establezca las siguientes opciones de compilación:

set COMPILE_DEBUG=1
set ENABLE_OPTIMIZER=0
  1. Escriba lo siguiente en el área de comandos del depurador para mostrar información sobre el controlador de eco :

    0: kd> lm m echo* v
    Browse full module list
    start             end                 module name
    fffff801`4ae80000 fffff801`4ae89000   ECHO       (private pdb symbols)  C:\Samples\KMDF_ECHO_SAMPLE\echo.pdb
        Loaded symbol image file: ECHO.sys
        Image path: \SystemRoot\system32\DRIVERS\ECHO.sys
        Image name: ECHO.sys
    ...  
    

    Para obtener información, vea lm.

  2. Dado que establecemos prefer_dml =1 anteriormente, algunos elementos de la salida son vínculos de acceso rápido que puede seleccionar. Seleccione el vínculo Examinar todos los símbolos globales en la salida de depuración para mostrar información sobre los símbolos de elementos que comienzan por la letra "a".

    0: kd> x /D Echo!a*
    
  3. Como resulta, el ejemplo de eco no contiene símbolos que comiencen por la letra "a", por lo que escriba para mostrar información sobre todos los símbolos asociados con el controlador de eco que comienzan por x ECHO!Echo* Echo.

    0: kd> x ECHO!Echo*
    fffff801`0bf95690 ECHO!EchoEvtIoQueueContextDestroy (void *)
    fffff801`0bf95000 ECHO!EchoEvtDeviceSelfManagedIoStart (struct WDFDEVICE__ *)
    fffff801`0bf95ac0 ECHO!EchoEvtTimerFunc (struct WDFTIMER__ *)
    fffff801`0bf9b120 ECHO!EchoEvtDeviceSelfManagedIoSuspend (struct WDFDEVICE__ *)
    ...
    

    Para obtener información, vea x (Examinar símbolos).

  4. La extensión !lmi muestra información detallada sobre un módulo. Escriba !lmi echo. La salida debe ser similar al texto que se muestra a continuación.

    0: kd> !lmi echo
    Loaded Module Info: [echo] 
             Module: ECHO
       Base Address: fffff8010bf94000
         Image Name: ECHO.sys
    … 
    
  5. Use la extensión !dh para mostrar información de encabezado como se muestra a continuación.

    0: kd> !dh echo
    
    File Type: EXECUTABLE IMAGE
    FILE HEADER VALUES
         14C machine (i386)
           6 number of sections
    54AD8A42 time date stamp Wed Jan 07 11:34:26 2015
    ...
    
  6. Establecimiento de la máscara de depuración

    Escriba lo siguiente para cambiar la máscara de bits de depuración predeterminada para que todos los mensajes de depuración del sistema de destino se muestren en el depurador.

    0: kd> ed nt!Kd_DEFAULT_MASK  0xFFFFFFFF
    

    Algunos controladores mostrarán información adicional cuando se usa la 0xFFFFFFFF de datos. Establezca la máscara en 0x00000000 si desea reducir la cantidad de información que se muestra.

    0: kd> ed nt!Kd_DEFAULT_MASK  0x00000000
    

    Use el comando dd para mostrar confirmar que la máscara está establecida para mostrar todos los mensajes del depurador.

    0: kd> dd nt!kd_DEFAULT_MASK 
    fffff802`bb4057c0  ffffffff 00000000 00000000 00000000
    fffff802`bb4057d0  00000000 00000000 00000000 00000000
    fffff802`bb4057e0  00000001 00000000 00000000 00000000
    fffff802`bb4057f0  00000000 00000000 00000000 00000000
    fffff802`bb405800  00000000 00000000 00000000 00000000
    fffff802`bb405810  00000000 00000000 00000000 00000000
    fffff802`bb405820  00000000 00000000 00000000 00000000
    fffff802`bb405830  00000000 00000000 00000000 00000000
    

Sección 6: Mostrar información Plug and Play árbol de dispositivos

En la sección 6, mostrará información sobre el controlador de dispositivo de ejemplo de eco y su lugar en el Plug and Play dispositivo.

La información sobre el controlador de dispositivo en Plug and Play árbol de dispositivos puede ser útil para solucionar problemas. Por ejemplo, si un controlador de dispositivo no está en el árbol de dispositivos, puede haber un problema con la instalación del controlador de dispositivo.

Para obtener más información sobre la extensión de depuración del nodo de dispositivo, vea !devnode.

-En el sistema host

  1. Para ver todos los nodos de dispositivo en Plug and Play árbol de dispositivos, escriba el comando !devnode 0 1.

    0: kd> !devnode 0 1
    Dumping IopRootDeviceNode (= 0xffffe0005a3a8d30)
    DevNode 0xffffe0005a3a8d30 for PDO 0xffffe0005a3a9e50
      InstancePath is "HTREE\ROOT\0"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
      DevNode 0xffffe0005a3a3d30 for PDO 0xffffe0005a3a4e50
        InstancePath is "ROOT\volmgr\0000"
        ServiceName is "volmgr"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeEnumerateCompletion (0x30d)
        DevNode 0xffffe0005a324560 for PDO 0xffffe0005bd95ca0…
    …
    
  2. Use Ctrl+F para buscar en la salida que se genera para buscar el nombre del controlador de dispositivo, echo.

    cuadro de diálogo buscar que muestra el término eco que se busca.

  3. Se debe cargar el controlador del dispositivo de eco. Use el comando !devnode 0 1 echo para mostrar Plug and Play información asociada a nuestro controlador de dispositivo de eco, como se muestra a continuación.

    0: Kd> !devnode 0 1 echo
    Dumping IopRootDeviceNode (= 0xffffe0007b725d30)
    DevNode 0xffffe0007b71a630 for PDO 0xffffe0007b71a960
      InstancePath is "ROOT\SAMPLE\0000"
      ServiceName is "ECHO"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
    …
    
  4. La salida mostrada en el comando anterior incluye el PDO asociado a la instancia en ejecución de nuestro controlador, en este ejemplo se 0xffffe0007b71a960. Escriba el comando !devobj PDO address para mostrar Plug and Play información asociada al controlador de dispositivo de eco. Use la dirección PDO que !devnode muestra en el equipo, no la que se muestra aquí.

    0: kd> !devobj 0xffffe0007b71a960
    Device object (ffffe0007b71a960) is for:
     0000000e \Driver\PnpManager DriverObject ffffe0007b727e60
    Current Irp 00000000 RefCount 0 Type 00000004 Flags 00001040
    Dacl ffffc102c9b36031 DevExt 00000000 DevObjExt ffffe0007b71aab0 DevNode ffffe0007b71a630 
    ExtensionFlags (0x00000800)  DOE_DEFAULT_SD_PRESENT
    Characteristics (0x00000180)  FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN
    AttachedDevice (Upper) ffffe000801fee20 \Driver\ECHO
    Device queue is not busy.
    
  5. La salida mostrada en el comando !devnode 0 1 incluye la dirección PDO asociada a la instancia en ejecución de nuestro controlador, en este ejemplo se 0xffffe0007b71a960. Escriba el comando !devstack PDO address para mostrar Plug and Play información asociada al controlador de dispositivo. Use la dirección PDO que !devnode muestra en el equipo, no la que se muestra a continuación.

    0: kd> !devstack 0xffffe0007b71a960
      !DevObj           !DrvObj            !DevExt           ObjectName
      ffffe000801fee20  \Driver\ECHO       ffffe0007f72eff0  
    > ffffe0007b71a960  \Driver\PnpManager 00000000  0000000e
    !DevNode ffffe0007b71a630 :
      DeviceInst is "ROOT\SAMPLE\0000"
      ServiceName is "ECHO"
    

La salida muestra que tenemos una pila de controladores de dispositivo bastante sencilla. El controlador de eco es un elemento secundario del nodo PnPManager. PnPManager es un nodo raíz.

\Driver\ECHO

\Driver\PnpManager

En este diagrama se muestra un árbol de nodos de dispositivo más complejo.

árbol de nodos de dispositivo con unos 20 nodos.

Nota Para obtener más información sobre pilas de controladores más complejas, consulte Pilas de controladores y Nodos de dispositivo y pilas de dispositivos.

Sección 7: Trabajar con puntos de interrupción y código fuente

En la sección 7, establecerá puntos de interrupción y un solo paso a través del código fuente del modo kernel.

Note
Establecimiento de puntos de interrupción mediante comandos

Para poder pasar por el código y comprobar los valores de las variables en tiempo real, es necesario habilitar los puntos de interrupción y establecer una ruta de acceso al código fuente.

Los puntos de interrupción se usan para detener la ejecución de código en una línea de código determinada. A continuación, puede avanzar en el código desde ese punto para depurar esa sección específica de código.

Para establecer un punto de interrupción mediante un comando debug, use uno de los siguientes comandos b.