Depuración paso a paso de controladores de Windows (modo kernel de eco)

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

Objetivos del 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 cómo usar las extensiones de depuración.

En este laboratorio, se usa una conexión de depuración de kernel activa para explorar las siguientes acciones:

  • Usar los comandos del depurador de Windows
  • Usar comandos estándar (pilas de llamadas, variables, subprocesos, IRQL)
  • Usar comandos avanzados de depuración de controladores (!commands)
  • Usar símbolos
  • Establecimiento de puntos de interrupción en la depuración en directo
  • Visualización de pilas de llamadas
  • Mostrar el árbol de dispositivos Plug and Play
  • Trabajar con subprocesos y contexto de proceso

Depuración en modo de usuario y kernel

Al trabajar con el depurador de Windows, puede realizar dos tipos de depuración:

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 está asignada 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 de otros procesos en modo de usuario, no pueden interferir con estos recursos.

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

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

Configuración del laboratorio

Necesita el siguiente hardware para completar el laboratorio:

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

Necesita el siguiente software para completar el laboratorio:

  • Visual Studio
  • Kit de desarrollo de software de Windows (SDK) para Windows 10
  • Kit de controladores de Windows (WDK) para Windows 10
  • Controlador de eco de ejemplo para Windows 10

El laboratorio tiene las secciones siguientes:

Conexión a una sesión winDbg en modo kernel

En esta sección, configure la depuración de red en el sistema host y 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. El depurador de Windows se ejecuta en el sistema host y el controlador de eco del marco de controladores del modo kernel (KMDF) se ejecuta en el sistema de destino .

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

Diagrama que ilustra dos equipos conectados a través de un concentrador de red o enrutador.

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, consulte Introducción a WinDbg (modo kernel). Para obtener más información sobre cómo configurar el equipo de destino, consulte Preparación de un equipo para la implementación manual de controladores y Configuración de la depuración automática del 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:

  1. En el sistema host, abra una ventana del símbolo del sistema y escriba ipconfig para determinar su dirección IP.

    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 . . . . . . . . . :
    
  2. Registre la dirección IP del sistema host: ______________________________________

  3. En el sistema de destino, abra una ventana del símbolo del sistema y use el comando para confirmar la ping conectividad de red entre los dos sistemas.

    ping 169.182.1.1
    

    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.

    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 completando los pasos siguientes.

Importante

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

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

    bcdedit /set {default} DEBUG YES
    
  2. Escriba este comando para habilitar la firma de pruebas:

    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.

    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 del depurador de cliente aleatorio, use una clave aleatoria generada automáticamente. Para obtener más información, consulte Configuración de la depuración automática del kernel de red KDNET.

  4. Escriba este comando para confirmar que los valores de dbgsettings están establecidos correctamente:

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

    Nota

    Si recibe un mensaje del firewall y desea usar el depurador, seleccione los tres cuadros.

    Captura de pantalla del cuadro de diálogo Alerta de Seguridad de Windows que indica que Firewall de Windows bloqueó algunas características de una aplicación.

  5. En el equipo host, abra una ventana del símbolo del sistema como administrador. Este laboratorio usa 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. Cambie al directorio WinDbg predeterminado, la ubicación predeterminada se muestra a continuación.

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

    En estos laboratorios se supone que ambos equipos ejecutan una versión de 64 bits de Windows tanto en el destino como en el host. Si no es así, el mejor enfoque es ejecutar el mismo bit de herramientas en el host que ejecuta el destino. Por ejemplo, si el destino ejecuta Windows de 32 bits, ejecute una versión de 32 bits del depurador en el host. Para obtener más información, consulte Elección de las herramientas de depuración de 32 o 64 bits.

  6. Abra WinDbg con depuración de usuario remoto mediante el comando siguiente. Los valores de la clave y el puerto coinciden con los valores establecidos anteriormente mediante BCDEdit en el equipo de destino.

    WinDbg –k net:port=50000,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  7. Reinicie el sistema de destino.

  8. 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
    

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

La ventana Comando del depurador se divide en dos paneles. Escriba comandos en el panel más pequeño, que es 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 de la parte superior de la ventana.

En el panel de entrada de comandos, use las teclas 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.

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

En esta sección, use comandos de depuración para mostrar información sobre el sistema de destino.

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

  1. En el sistema host, use Ctrl+Bloqueo de desplazamiento en WinDBg para dividir en el código que se ejecuta en el sistema de destino. El sistema de destino puede tardar algún tiempo en responder.

    Pantalla principal del depurador en la que se muestra la salida de la ventana de comandos desde una conexión de kernel activa.

  2. Escriba el siguiente comando para habilitar DML en la ventana Comando del depurador:

    0: kd> .prefer_dml 1
    DML versions of commands on by default
    
  3. Puede acceder a la ayuda del comando de referencia mediante el .hh comando . 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 muestra ayuda para el .prefer_dml comando .

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

  4. 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 de 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
    
  5. Para comprobar que está trabajando con el proceso correcto en modo kernel, escriba el comando lm (Enumerar módulos cargados) en la ventana de WinDbg para mostrar los módulos cargados:

    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
    ...
    

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

  6. Para solicitar información detallada sobre un módulo específico, use la v opción (detallado):

    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
    

    No hay ninguna ruta de acceso de símbolo establecida y símbolos cargados, por lo que la información limitada está disponible en el depurador.

Descarga y compilación del controlador de eco KMDF

En esta sección, descargue y compile 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, este laboratorio usa el controlador de ejemplo de plantilla de KMDF "Echo". El código fuente está disponible para ayudar a comprender la información que se muestra en WinDbg. Este ejemplo también se usa para ilustrar cómo puede recorrer el código en modo kernel nativo de un solo paso. Esta técnica puede ser valiosa para depurar problemas complejos de código en modo kernel.

Para descargar y compilar el controlador de audio de ejemplo echo:

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

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

    Captura de pantalla de la página windows-driver-samples de GitHub en la que se resalta la carpeta general y se descarga el botón zip.

    1. Descargue los ejemplos de controladores en un archivo ZIP: Ejemplos de controladores

    2. Descargue el archivo ZIP en su disco duro local.

    3. Seleccione y mantenga presionado o haga clic con el botón derecho en el archivo ZIP y seleccione Extraer todo. Especifique una nueva carpeta o vaya a una existente para almacenar los archivos extraídos. Por ejemplo, podría especificar C:\DriverSamples\ como la nueva carpeta en la que extraer los archivos.

    4. Una vez extraídos los archivos, vaya a la subcarpeta siguiente: C:\DriverSamples\general\echo\kmdf

  2. En Microsoft Visual Studio, seleccione Archivo>abrir>proyecto o 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 esta ventana aún no está abierta, seleccione Explorador de soluciones en el menú Ver. En Explorador de soluciones, puede ver una solución que tiene tres proyectos.

    Captura de pantalla de Visual Studio que muestra el archivo device.c cargado desde el proyecto kmdfecho.

  3. Establezca la configuración y la plataforma del ejemplo. En Explorador de soluciones, seleccione y mantenga presionado o haga clic con el botón derecho en Solución 'kmdfecho' (3 proyectos) y seleccione Configuration Manager. 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 algún cambio de configuración o plataforma para un proyecto, realice los mismos cambios para los tres proyectos restantes.

  4. Los ejemplos de controladores deben modificarse para usar valores que no se superpongan con los controladores existentes. Consulte De código de ejemplo a controlador de producción: qué cambiar en los ejemplos sobre cómo crear un ejemplo de controlador único que coexista con los controladores reales existentes instalados en Windows.

  5. Establezca la biblioteca en tiempo de ejecución. Abra la página de propiedades del controlador de eco y busque C/C++>Code Generation. Cambie la biblioteca en tiempo de ejecución a Depuración multiproceso (/MTd). Para obtener más información sobre las opciones de compilación, vea /MD, /MT, /LD (Usar Run-Time biblioteca).

    Captura de pantalla de la página de propiedades echo en Visual Studio en la que se resalta la configuración de la biblioteca en tiempo de ejecución.

  6. En las propiedades del controlador, asegúrese de que elmodo de firma> de controladores esté establecido en Signo de prueba.

    Captura de pantalla de la página de propiedades echo en Visual Studio en la que se resalta la configuración del modo de inicio de sesión.

  7. En Visual Studio, seleccione Compilar>solución de compilación.

    Las ventanas de compilación deben mostrar un mensaje que indica que la compilación de los tres proyectos se realizó correctamente.

Sugerencia

Si encuentra un mensaje de error de compilación, use el número de error de compilación para determinar una corrección. Por ejemplo, el error de MSBuild MSB8040 describe cómo trabajar con bibliotecas mitigadas por spectre.

  1. En Explorador de archivos, vaya a la carpeta que contiene los archivos extraídos para el ejemplo. Por ejemplo, vaya 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 Configuration Manager. Si deja la configuración predeterminada sin cambios, los archivos de controlador compilados se guardan en una carpeta denominada \x64\Debug para una compilación de depuración de 64 bits.

    Vaya a la carpeta que contiene los archivos compilados para el controlador Autosync: C:\DriverSamples\general\echo\kmdf\driver\AutoSync\x64\Debug.

    La carpeta debe contener estos archivos:

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

    Además, el archivo echoapp.exe se creó y debe encontrarse 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 el controlador echo.sys.
  2. Busque una unidad usb o configure un recurso compartido de red para copiar los archivos de controlador creados y echoApp de prueba desde el host al sistema de destino.

En la sección siguiente, copie el código en el sistema de destino e instale y pruebe el controlador.

Instalación del ejemplo de controlador de eco KMDF en el sistema de destino

En esta sección, use la herramienta 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, este equipo es 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, prepare el equipo de destino habilitando la firma de prueba. 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, siga estos pasos.

En el sistema de destino, habilite los controladores firmados de prueba:

  1. Abra Configuración de Windows.

  2. En Actualizar y seguridad, seleccione Recuperación.

  3. En Inicio avanzado, seleccione Reiniciar ahora.

  4. Cuando se reinicie el equipo, seleccione Opciones de inicio. En Windows 10, seleccione Solucionar problemas>de opciones> avanzadasConfiguración de inicio y, a continuación, seleccione Reiniciar.

  5. Seleccione Deshabilitar cumplimiento de firmas de controlador presionando la tecla F7.

  6. 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 siguiente carpeta: C:\Archivos de programa (x86)\Windows Kits\10\Tools\x64\devcon.exe.

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

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

Si necesita instrucciones más detalladas para configurar el equipo de destino, consulte Preparación de un equipo para la implementación manual de controladores.

Las instrucciones siguientes muestran cómo instalar y probar el controlador de ejemplo. Esta es la sintaxis general de la herramienta devcon que se usa para instalar el controlador:

devcon install <INF file> <hardware ID>

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 devcon que no se reconoce, intente agregar la ruta de acceso a la herramienta devcon . Por ejemplo, si lo copió en una carpeta denominada C:\Tools, pruebe a usar el siguiente comando:

c:\tools\devcon install echo.inf root\ECHO

Aparece un cuadro de diálogo que indica que el controlador de prueba es un controlador sin firmar. Seleccione Instalar este controlador de todos modos para continuar.

Captura de pantalla de Seguridad de Windows advertencia que indica que Windows no puede comprobar el publicador del software del 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, está listo para probarlo.

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

Captura de pantalla de Administrador de dispositivos árbol que resalta el controlador de eco WDF de ejemplo.

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

Usar WinDbg para mostrar información sobre el controlador

En esta sección, establezca la ruta de acceso del símbolo y use los comandos del depurador de kernel para mostrar información sobre el controlador de ejemplo de eco KMDF.

Para ver información sobre el controlador:

  1. En el sistema host, si cerró el depurador, ábralo de nuevo mediante 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 dividir el código que se ejecuta en el sistema de destino.

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

    0: kd> .symfix
    
  4. 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
    

    El .reload comando con la opción force elimina toda la /f 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.

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

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

Hay muchos enfoques que se pueden usar para trabajar con símbolos. En muchas situaciones, puede configurar el equipo para tener acceso a símbolos desde un servidor de símbolos que Microsoft proporciona cuando se necesitan. Este laboratorio usa ese enfoque. Si los símbolos de su entorno están en una ubicación diferente, modifique los pasos para usar esa ubicación. Para obtener más información, vea Ruta de acceso de símbolo para el depurador de Windows.

Para realizar la depuración de origen, debe crear una versión comprobada (depuración) de los archivos binarios. El compilador crea archivos de símbolos (archivos .pdb ). Estos archivos de símbolos muestran 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 enlazador no optimiza el código. La depuración de origen 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 el siguiente comando 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 más información, consulte lm.

  2. Dado que este conjunto de laboratorio se estableció prefer_dml anteriormente, algunos elementos de la salida son vínculos activos que puede seleccionar. Seleccione el vínculo Examinar todos los símbolos globales de 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. El ejemplo de eco no contiene ningún símbolo que empiece por la letra "a", por lo que escriba x ECHO!Echo* para mostrar información sobre todos los símbolos asociados con el controlador de eco que comienzan por "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 más información, vea x (Examinar símbolos).

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

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

    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. 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 muestran información adicional cuando se usa la máscara de 0xFFFFFFFF. 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 dd comando para 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
    

Mostrar Plug and Play información del árbol de dispositivos

En esta sección, muestra información sobre el controlador de dispositivo de ejemplo de eco y dónde reside en el árbol de dispositivos Plug and Play.

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

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

  1. En el sistema host, para ver todos los nodos de dispositivo del árbol de dispositivos Plug and Play, escriba el !devnode 0 1 comando .

    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, eco.

    Captura de pantalla del cuadro de diálogo Buscar en WinDbg buscando el término

  3. Se debe cargar el controlador del dispositivo de eco. Use el !devnode 0 1 echo comando para mostrar Plug and Play información asociada al controlador de dispositivo de eco, como se muestra en este ejemplo:

    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 del controlador, en este ejemplo, 0xffffe0007b71a960. Escriba el !devobj <PDO address> comando para mostrar Plug and Play información asociada al controlador del dispositivo de eco. Use la dirección PDO que se muestra en el equipo, no la que !devnode 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 que se muestra en el !devnode 0 1 comando incluye la dirección PDO asociada a la instancia en ejecución del controlador, en este ejemplo se 0xffffe0007b71a960. Escriba el !devstack <PDO address> comando para mostrar Plug and Play información asociada al controlador de dispositivo. Use la dirección PDO que !devnode se muestra en el equipo, no la que se muestra en este ejemplo.

    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 tiene 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.

Diagrama que ilustra un árbol de nodos de dispositivo que consta de aproximadamente 20 nodos.

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

Trabajar con puntos de interrupción y código fuente

En esta sección, establezca puntos de interrupción y código fuente del modo kernel de un solo paso.

Para poder recorrer el código y comprobar los valores de las variables en tiempo real, habilite los puntos de interrupción y establezca una ruta de acceso al código fuente.

Los puntos de interrupción detienen la ejecución del código en una línea de código determinada. Avance adelante en el código desde ese punto para depurar esa sección específica del código.

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

Get-Help Descripción
bp Establece un punto de interrupción activo hasta que se descarga el módulo en el que se encuentra.
bu Establece un punto de interrupción sin resolver cuando el módulo se descarga y vuelve a habilitar cuando se vuelve a cargar el módulo.
bm Establece un punto de interrupción para un símbolo. Este comando usa bu o bp adecuadamente y permite usar caracteres comodín (*) para establecer puntos de interrupción en cada símbolo que coincida, como todos los métodos de una clase.

Para obtener más información, consulte Depuración de código fuente en WinDbg.

  1. En el sistema host, use la interfaz de usuario de WinDbg para confirmar que elmodo de origen de depuración> está habilitado en la sesión actual de WinDbg.

  2. Escriba el siguiente comando para agregar la ubicación del código local a la ruta de acceso de origen:

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

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

    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 muestra que el DeviceAdd método para el controlador de eco es ECHO!EchoEvtDeviceAdd.

    Como alternativa, revise el código fuente para buscar el nombre de la función para el punto de interrupción.

  5. Establezca el punto de interrupción con el bm comando con el nombre del controlador, seguido del nombre de la función, por ejemplo, AddDevice, donde desea establecer el punto de interrupción, separados por un signo de exclamación. Este laboratorio usa AddDevice para watch el controlador que se va a cargar.

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

    Puede usar una sintaxis diferente junto con la configuración de variables como <module>!<symbol>, <class>::<method>'<file.cpp>:<line number>', o omitir un número de veces <condition> <#>. Para obtener más información, vea Puntos de interrupción condicionales en WinDbg y otros depuradores de Windows.

  6. Enumere los puntos de interrupción actuales para confirmar que el punto de interrupción se estableció escribiendo el bl comando :

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

    La "e" de la salida que se muestra aquí indica que el número de punto de interrupción 1 está habilitado para activarse.

  7. Reinicie la ejecución de código en el sistema de destino escribiendo el g comando (go).

  8. En el sistema de destino, en Windows, abra Administrador de dispositivos mediante el icono o escriba mmc devmgmt.msc. En Administrador de dispositivos, expanda el nodo Ejemplos.

  9. Seleccione y mantenga presionado o haga clic con el botón derecho en la entrada del controlador de eco KMDF y seleccione Deshabilitar en el menú.

  10. Seleccione y mantenga presionado o haga clic con el botón derecho en la entrada del controlador de eco KMDF de nuevo y seleccione Habilitar en el menú.

  11. En el sistema host, cuando el controlador está habilitado, el punto de interrupción AddDevice debug debe activarse. La ejecución del código del controlador en el sistema de destino debe detenerse. Cuando se alcanza el punto de interrupción, la ejecución se debe detener al principio de la rutina AddDevice . La salida del comando de depuración muestra Breakpoint 1 hit.

    Captura de pantalla de WinDbg en la que se muestran las ventanas locales de código de ejemplo y comandos.

  12. Recorra la línea de código por línea escribiendo el p comando o presionando F10 hasta llegar al siguiente final de la rutina AddDevice . El carácter de llave (}) está resaltado como se muestra.

    Captura de pantalla de la ventana de código con el carácter de llave resaltado al principio de la rutina AddDevice.

En la sección siguiente, examine el estado de las variables después de ejecutar el código DeviceAdd.

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

Get-Help Descripción
bl Listas 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 be * para habilitar todos los puntos de interrupción.

Como alternativa, también puede modificar puntos de interrupción en la interfaz de usuario de WinDbg.

También puede establecer puntos de interrupción que se activan cuando se accede a una ubicación de memoria. Use el ba comando (interrumpir en el acceso), con la sintaxis siguiente:

ba <access> <size> <address> {options}
Opción Descripción
e 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

Solo puede establecer cuatro puntos de interrupción de datos en un momento dado. Es necesario asegurarse de que está alineando los datos correctamente para desencadenar el punto de interrupción. Las palabras deben terminar en direcciones divisibles en 2, las palabras dwords deben ser divisibles por 4 y cuatro palabras por 0 o 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 ejemplo.

ba r 4 0x0003f7bf0

Puede usar los siguientes comandos para recorrer el código con los cortes cortos de teclado asociados que se muestran entre paréntesis.

  • Interrumpir (Ctrl+Interrumpir). Este comando interrumpe un sistema siempre que el sistema se esté ejecutando y esté en comunicación con WinDbg. La secuencia del depurador de kernel es Ctrl+C.
  • Ejecute hasta el cursor (F7 o Ctrl+F10). Coloque el cursor en una ventana de origen o desensamblado donde quiera que se interrumpa la ejecución y presione F7. La ejecución del código se ejecuta en ese punto. Si el flujo de ejecución de código no alcanza el punto indicado por el cursor, WinDbg no se interrumpirá. Esta situación puede ocurrir si no se ejecuta una instrucción IF.
  • Ejecute (F5). Ejecute hasta que se encuentre un punto de interrupción o se produzca un evento como una comprobación de errores.
  • Paso a paso por encima (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 la llamada sin entrar en la rutina llamada. Si el lenguaje de programación es C o C++ y WinDbg está en modo de origen, el modo de origen se puede activar o desactivar mediante elmodode origen de depuración>.
  • Paso a paso (F11). Este comando es similar al paso a paso, salvo que la ejecución de una llamada entra en la rutina llamada.
  • Salir (Mayús+F11). Este comando hace que la ejecución se ejecute y salga de la rutina actual o del lugar actual en la pila de llamadas. Este comando es útil si ha visto suficiente de la rutina.

Para obtener más información, consulte Depuración de código fuente en WinDbg.

Visualización de variables y pilas de llamadas

En esta sección, muestra información sobre las variables y las pilas de llamadas.

En este laboratorio se supone 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, para mostrar variables, use el elemento de menú ver>local para mostrar variables locales.

Captura de pantalla de WinDbg que muestra la ventana variables locales.

Para buscar la ubicación de una dirección de variable global, escriba ? <variable name>.

  • Salir (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 (clásico) 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 las variables y las pilas de llamadas.

En este laboratorio se supone 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

Mostrar variables

Use el elemento de menú ver>local para mostrar variables locales.

Captura de pantalla de WinDbg que muestra la ventana variables locales.

Variables globales

Para encontrar la ubicación de una dirección de variable global, escriba ? <nombre de> variable.

Variables locales

Puede mostrar los nombres y valores de todas las variables locales para un marco determinado escribiendo el comando dv . Para mostrar los nombres y valores de todas las variables locales de un marco específico, escriba el dv comando :

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

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, etc.

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

Get-Help Descripción
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 de marco junto a ella.
  1. En el sistema host, si desea mantener la pila de llamadas disponible, seleccione Ver>pila de llamadas para verlo. Seleccione las columnas de la parte superior de la ventana para alternar la presentación de información adicional.

    Captura de pantalla de WinDbg que muestra la ventana pilas de llamadas.

  2. Use el kn comando 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ó a Plug and Play código (PnP) que llamó al código de marco de controlador (WDF) que posteriormente llamó a la función del controlador DeviceAdd de eco.

Visualización de procesos y subprocesos

En esta sección, muestra información sobre los procesos y subprocesos que se ejecutan en modo kernel.

Procesos

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

  1. En el sistema host, escriba el dv comando para examinar las variables de configuración regional asociadas a la EchoEvtIo rutina:

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

    0: kd> bc *  
    
  3. Establezca un punto de interrupción de símbolos en las EchoEvtIo rutinas mediante el siguiente comando:

    0: kd> bm ECHO!EchoEvtIo*
      2: aade5490          @!”ECHO!EchoEvtIoQueueContextDestroy”
      3: aade55d0          @!”ECHO!EchoEvtIoWrite”
      4: aade54c0          @!”ECHO!EchoEvtIoRead”
    
  4. Enumere 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
    ...
    
  5. Escriba g para reiniciar la ejecución del código:

    0: kd> g
    
  6. En el sistema de destino, ejecute el EchoApp.exe programa de prueba de controladores en el sistema de destino.

  7. En el sistema host, cuando se ejecuta la aplicación de prueba, se llama a la rutina de E/S del controlador. Esta llamada hace que se active 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
    
  8. Use el !process comando para mostrar el proceso actual implicado en la ejecución deechoapp.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 subprocesoechoapp.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.

  9. !process 0 0 Use para mostrar información de resumen para todos los procesos. En la salida, use Ctrl+F para buscar la misma dirección de proceso para el proceso asociado a la imagen deechoapp.exe . En el ejemplo, 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
    
    ...
    
  10. Registre el identificador de proceso asociado a echoapp.exe para usarlo 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.

    _____________________________________________________(dirección del proceso de echoapp.exe)

  11. Escriba g según sea necesario en el depurador para ejecutar el código hasta queechoapp.exe termine de ejecutarse. Alcanza el punto de interrupción en el evento de lectura y escritura muchas veces. Cuando finaliceechoapp.exe , interrumpa en el depurador presionando Ctrl+ScrLk (Ctrl+Interrumpir).

  12. Use el !process comando para confirmar que está ejecutando un proceso diferente. En la salida que se muestra aquí, el proceso con el valor Image de System es diferente del valor Echo Image.

    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 muestra que se estaba ejecutando un proceso del sistema ffffe0007b65d900 al detener el sistema operativo.

  13. Use el !process comando para intentar ver el identificador de proceso asociado a echoapp.exe que registró anteriormente. Proporcione la dirección del proceso deechoapp.exe que registró anteriormente, en lugar de la dirección del proceso de ejemplo que se muestra en este ejemplo.

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

    El objeto de proceso ya no está disponible, ya que el proceso deechoapp.exe ya no se está ejecutando.

Subprocesos

Los comandos para ver y establecer subprocesos son similares a los comandos de los procesos. Use el comando !thread para ver los 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 programa de prueba de controladores de EchoApp.exe.

  3. En el sistema host, se alcanza el punto de interrupción y se detiene la ejecución del código.

    Breakpoint 4 hit
    ECHO!EchoEvtIoRead:
    aade54c0 55              push    ebp
    
  4. Para ver los subprocesos que se ejecutan, escriba !thread. Se debe mostrar información similar al ejemplo 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
    ...
    

    Anote el nombre de la imagen de echoapp.exe. Esto indica que está viendo el subproceso asociado a la aplicación de prueba.

  5. Use el !process comando para determinar si este subproceso es el único subproceso que se ejecuta en el proceso asociado a echoapp.exe. El número de subproceso del subproceso en ejecución en el proceso es el mismo subproceso que ejecuta el !thread comando que se muestra.

    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
    
  6. Use el !process 0 0 comando 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
    …
    

    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.

  7. Use el comando para enumerar la !process información del proceso para ambos procesos que ejecutan el equipo. Proporcione la dirección del proceso de la !process 0 0 salida, no la dirección que se muestra en este ejemplo.

    Esta salida de ejemplo es para el identificador de proceso decmd.exe que se registró anteriormente. El nombre de la 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 identificador de proceso deechoapp.exe 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
    ...
    
  8. Registre aquí la primera dirección del subproceso asociada a los dos procesos.

    Cmd.exe: ____________________________________________________

    EchoApp.exe: _________________________________________________

  9. Use el !Thread comando 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 está en estado de ejecución.

  10. Use el !Thread comando 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 un estado de espera.

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

    0: kd> .Thread ffffe0007cf34880
    Implicit thread is now ffffe000`7cf34880
    
  12. Use el k comando 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 según lo esperado.

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

IRQL, registra y finaliza la sesión de WinDbg

En esta sección, muestra el nivel de solicitud de interrupción (IRQL) y el contenido de los registros.

Visualización del IRQL guardado

IrQL se usa para administrar la prioridad del mantenimiento de interrupciones. Cada procesador tiene una configuración IRQL que los subprocesos pueden aumentar o reducir. Las interrupciones que se producen en o debajo de la configuración irQL del procesador se enmascaran y no interfieren con la operación actual. Las interrupciones que se producen encima de la configuración irQL del procesador tienen prioridad sobre la operación actual.

En el sistema host, la extensión !irql muestra irQL en el procesador actual del equipo de destino antes de que se produjera la interrupción del depurador. Cuando el equipo de destino se divide en el depurador, el IRQL cambia, pero irQL que era efectivo justo antes de que se guarde la interrupción del depurador y se muestre 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 del subproceso actual en el procesador actual mediante el comando r (Registers).

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 Ver>registros. Para obtener más información, consulte r (Registros).

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

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

Finalizar la sesión de WinDbg

Si desea dejar asociado el depurador, pero quiere trabajar en el destino, borre los puntos de interrupción mediante bc *, para que el equipo de destino no intente conectarse al depurador del equipo host. A continuación, use el g comando para permitir que el equipo de destino se ejecute de nuevo.

Para finalizar la sesión de depuración, en el sistema host, interrumpa en el depurador y escriba el qd comando (Salir y desasociar) o seleccione Detener depuración en el menú.

0: kd> qd

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

Recursos de depuración de Windows

Hay más información disponible en la depuración de Windows. Algunos de estos libros usan versiones anteriores de Windows como Windows Vista en sus ejemplos, pero los conceptos descritos son aplicables a la mayoría de las versiones de Windows.

Consulte también