Share via


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

Este laboratorio proporciona ejercicios prácticos que muestran cómo depurar el controlador de dispositivo en modo kernel de audio Sysvad.

Microsoft Windows Debugger (WinDbg) es una eficaz herramienta de depuración basada en Windows que puede usar para realizar la depuración en modo de usuario y en modo kernel. WinDbg proporciona depuración de nivel de origen para el kernel de Windows, los controladores en modo kernel y los servicios del sistema, así como para las aplicaciones y controladores en modo de usuario.

WinDbg puede recorrer el código fuente, establecer puntos de interrupción, ver variables (incluidos objetos de C++), seguimientos de pila y memoria. La ventana Comando del depurador permite al usuario emitir una amplia variedad de comandos.

Configuración del laboratorio

Necesitará el siguiente hardware para poder completar el laboratorio:

  • Un equipo portátil o de escritorio (host) que ejecute Windows 10
  • Un equipo portátil o de escritorio (destino) que ejecute Windows 10
  • Un concentrador de red/enrutador 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.

  • Microsoft Visual Studio 2017
  • Kit de desarrollo de software de Windows (SDK) para Windows 10
  • Kit de controladores de Windows (WDK) para Windows 10
  • Controlador de audio Sysvad de ejemplo para Windows 10

Para obtener información sobre cómo descargar e instalar el WDK, consulte Descarga del Kit para controladores de Windows (WDK).

Tutorial de depuración de Sysvad

Este laboratorio le guiará por el proceso de depuración de un controlador en modo kernel. En los ejercicios se usa el ejemplo de controlador de audio virtual Syvad. Dado que el controlador de audio Syvad no interactúa con el hardware de audio real, se puede usar en la mayoría de los dispositivos. En este laboratorio se detallan las siguientes tareas:

Laboratorio de controladores de eco

El controlador de eco es un controlador más sencillo que el controlador de audio Sysvad. Si no está familiarizado con WinDbg, puede considerar la posibilidad de completar primero Controladores universales de depuración: laboratorio paso a paso (modo kernel eco) . En este laboratorio se reutilizan las instrucciones de configuración de ese laboratorio, por lo que si ha completado ese laboratorio, puede omitir las secciones 1 y 2 de aquí.

Sección 1: Conexión a una sesión WinDbg en modo kernel

En la sección 1, configurará 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. WinDbg se ejecuta en el sistema host y el controlador Sysvad se ejecuta en el sistema de destino.

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

Diagrama en el que se muestran 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 del controlador 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, siga los pasos siguientes.

<- En el sistema host

  1. Abra un símbolo del sistema en el sistema host y escriba ipconfig /all para determinar su dirección IP.
C:\>ipconfig /all
Windows IP Configuration

 Host Name . . . . . . . . . . . . : TARGETPC
...

Ethernet adapter Ethernet:
   Connection-specific DNS Suffix  . :
   Link-local IPv6 Address . . . . . : fe80::c8b6:db13:d1e8:b13b3
   Autoconfiguration IPv4 Address. . : 169.182.1.1
   Subnet Mask . . . . . . . . . . . : 255.255.0.0
   Default Gateway . . . . . . . . . :
  1. Registre la dirección IP del sistema host: ______________________________________

  2. Registre el nombre de host 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

Para usar la utilidad KDNET para habilitar la depuración en modo kernel en el sistema de destino, siga estos pasos.

  1. En el sistema host, busque el directorio KDNET de WDK. De forma predeterminada, se encuentra aquí.

    C:\Archivos de programa (x86)\Windows Kits\10\Debuggers\x64

En este laboratorio 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 en el que se ejecuta el destino. Por ejemplo, si el destino ejecuta Windows de 32 bits, ejecute una versión de 32 del depurador en el host. Para obtener más información, consulte Elección de herramientas de depuración de 32 o 64 bits.

  1. Localice estos dos archivos y cópielos en un recurso compartido de red o una unidad USB, de modo que estén disponibles en el equipo de destino.

    kdnet.exe

    VerifiedNICList.xml

  2. En el equipo de destino, abra una ventana de símbolo del sistema como administrador. Escriba este comando para validar que la NIC del equipo de destino es compatible.

C:\KDNET>kdnet

Network debugging is supported on the following NICs:
busparams=0.25.0, Intel(R) 82579LM Gigabit Network Connection, KDNET is running on this NIC.kdnet.exe
  1. Escriba este comando para establecer la dirección IP del sistema host. 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. Elija una dirección de puerto única para cada par de destino/host con el que trabaje, como 50010.
C:\>kdnet 169.182.1.1 50010

Enabling network debugging on Intel(R) 82577LM Gigabit Network Connection.
Key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p

Importante

Antes de usar BCDEdit para cambiar la información de arranque, es posible que deba suspender temporalmente las 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 finalicen las pruebas y administre correctamente el equipo de prueba cuando se deshabiliten las características de seguridad. El arranque seguro normalmente está deshabilitado en UEFI. Para acceder a la configuración de UEFI, vaya a Sistema, Recuperación, Inicio avanzado. Después, seleccione Solucionar problemas, Opciones avanzadas, Configuración de firmware de UEFI. Tenga cuidado, ya que establecer incorrectamente las opciones de UEFI o deshabilitar BitLocker, puede hacer que el sistema sea inoperable.

  1. Escriba este comando para confirmar que dbgsettings está configurado correctamente.
C:\> bcdedit /dbgsettings
busparams               0.25.0
key                     2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
debugtype               NET
hostip                  169.182.1.1
port                    50010
dhcp                    Yes
The operation completed successfully.

Copie la clave única generada automáticamente en un archivo de texto para evitar tener que escribirla en el equipo host. Copie el archivo de texto con la clave en el sistema host.

NotaFirewalls y depuradores

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

Captura de pantalla de alerta de seguridad de Windows que indica que el firewall de Windows ha bloqueado algunas características de una aplicación.

<- En el sistema host

  1. En el equipo host, abra una ventana de símbolo del sistema como administrador. Cambie al directorio WinDbg.exe. Usaremos la versión x64 de WinDbg.exe del Kit para controladores de Windows (WDK) que se instaló como parte de la instalación del kit de Windows.
C:\> Cd C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 
  1. Inicie WinDbg con depuración de usuario remoto mediante el siguiente comando. El valor de la clave y el puerto coinciden con lo que estableció anteriormente mediante BCDEdit en el destino.
C:\> WinDbg –k net:port=50010,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.

Captura de pantalla del depurador de Windows que muestra la salida de la ventana de comandos desde una conexión de kernel activa.

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. Los comandos se escriben en el panel más pequeño (el panel de entrada de comandos) en la parte inferior de la ventana y la salida del comando se ve en el panel más grande de 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 pulsar 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 visualizar información sobre el sistema de destino.

<- En el sistema host

Habilitación del 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 (Bloq Despl) en WinDBg para irrumpir en el código que se ejecuta en el sistema de destino. El sistema de destino puede tardar un poco en responder.
  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

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.

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

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

  1. Para visualizar 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. Puede comprobar que está trabajando con el proceso correcto en modo kernel visualizando los módulos cargados escribiendo el comando lm (Enumerar módulos cargados) en la ventana 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.

Dado que todavía tenemos que establecer la ruta de acceso del símbolo y los símbolos cargados, la información disponible en el depurador es limitada.

Sección 3: Descarga y compilación del controlador de audio Sysvad

En la sección 3, descargará y compilará el controlador de audio Sysvad.

Normalmente, trabajaría con su propio código de controlador al usar WinDbg. Para familiarizarse con la depuración de controladores de audio, se usa el controlador de ejemplo de audio virtual Sysvad. Este ejemplo se utiliza para ilustrar cómo se puede recorrer paso a paso el código nativo en modo kernel. 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 de Sysvad, siga los pasos siguientes.

  1. Descarga y extracción del ejemplo de audio Sysvad de GitHub

    Puede usar un explorador para ver el ejemplo de Sysvad y el archivo Readme.md aquí:

    https://github.com/Microsoft/Windows-driver-samples/tree/main/audio/sysvad

    Captura de pantalla del repositorio de GitHub que muestra la carpeta general y el botón Descargar ZIP.

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

    a. Descargue el archivo master.zip en la unidad de disco duro local.

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

    b. Seleccione y mantenga pulsado (o haga clic con el botón derecho) Windows-driver-samples-master.zip y elija Extraer todo. Especifique una nueva carpeta o vaya a una existente que almacenará los archivos extraídos. Por ejemplo, podría especificar C:\WDK_Samples\ como la nueva carpeta en la que se extraerán los archivos.

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

    C:\WDK_Samples\Sysvad

  2. Apertura de la solución del controlador en Visual Studio

    En Visual Studio, seleccione Archivo>Abrir>Project/Solution... y vaya a la carpeta que contiene los archivos extraídos (por ejemplo, C:\WDK_Samples\Sysvad). Haga doble clic en el archivo de la solución Syvad.

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

    Captura de pantalla de Visual Studio con el archivo adapter.cpp cargado desde el proyecto Sysvad.

  3. Establecimiento de la configuración y la plataforma del ejemplo

    En el Explorador de soluciones, seleccione y mantenga pulsada (o haga clic con el botón derecho) la Solución "sysvad" (7 de 7 proyectos) y elija Administrador de configuración. Asegúrese de que la configuración y las opciones de plataforma sean las mismas para los cuatro 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, debe realizar los mismos cambios para los tres proyectos restantes.

    Nota En este laboratorio se supone que se usa Windows de 64 bits. Si usa Windows de 32 bits, compile el controlador para 32 bits.

  4. Comprobación de la firma de controladores

    Busque TabletAudioSample. Abra la página de propiedades del controlador Sysvad y asegúrese de que Firma de controladores>Modo de firma esté establecido en Firma de prueba.

  5. 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 para obtener información sobre cómo crear un ejemplo de controlador único que coexista con los controladores reales existentes instalados en Windows.

  6. Compilación del ejemplo con Visual Studio

    En Visual Studio, seleccione Compilar>Compilar solución.

    Las ventanas de compilación deberían mostrar un mensaje indicando que la compilación se ha realizado correctamente para los seis proyectos.

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 MSBuild MSB8040 describe cómo trabajar con bibliotecas con mitigación de Spectre.

  1. Búsqueda de los archivos de controlador compilados

    En el Explorador de archivos, vaya a la carpeta que contiene los archivos extraídos para el ejemplo. Por ejemplo, vaya a C:\WDK_Samples\Sysvad, 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 de los ajustes de la plataforma que seleccionó en Administrador de configuración. Por ejemplo, si dejó la configuración predeterminada sin cambios, los archivos de controlador compilados se habrán guardado 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 TabletAudioSample:

    C:\WDK_Samples\Sysvad\TabletAudioSample\x64\Debug. La carpeta contendrá el controlador de .SYS TabletAudioSample, el archivo pdp de símbolos y el archivo inf. También tendrá que localizar los archivos dll DelayAPO, KWSApo y KeywordDetectorContosoAdapter y los archivos de símbolos.

    Para instalar el controlador, necesitará los siguientes archivos.

    Nombre de archivo Descripción
    TabletAudioSample.sys El archivo del controlador.
    TabletAudioSample.pdb El archivo de símbolos del controlador.
    tabletaudiosample.inf Archivo de información (INF) que contiene información necesaria para instalar el controlador.
    KeywordDetectorContosoAdapter.dll Detector de palabras clave de ejemplo.
    KeywordDetectorContosoAdapter.pdb Archivo de símbolos del detector de palabras clave de ejemplo.
    DelayAPO.dll Un APO de retraso de ejemplo.
    DelayAPO.pdb El archivo de símbolos de APO de retraso.
    KWSApo.dll APO de marcador de palabra clave de ejemplo.
    KWSApo.pdb Archivo de símbolos de marcador de palabra clave.
    TabletAudioSample.cer El archivo de certificado TabletAudioSample.
  2. Busque una unidad USB o configure un recurso compartido de red para copiar los archivos de controlador creados 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 controlador de audio Sysvad de ejemplo en el sistema de destino

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

-> En el sistema de destino

El equipo en el que 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, debe preparar el equipo de destino activando la firma de prueba. Después, estará listo para ejecutar el ejemplo de controlador compilado en el sistema de destino.

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

  1. Habilitación de controladores firmados de prueba

    Para habilitar la capacidad de ejecutar controladores firmados de prueba:

    1. Abra Configuración de Windows.

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

    3. En Inicio avanzado, seleccione Reiniciar ahora.

    4. Cuando se reinicie el equipo, seleccione Solución de problemas.

    5. A continuación, seleccione Opciones avanzadas, Configuración de inicio y, después, Reiniciar.

    6. Seleccione Deshabilitar aplicación de firmas del controlador pulsando la tecla F7.

    7. El equipo comenzará con los nuevos valores en su lugar.

  2. -> En el sistema de destino

    Instalación del controlador

    En las instrucciones siguientes se muestra cómo instalar y probar el controlador de ejemplo.

    El archivo INF necesario para instalar este controlador es TabletAudioSample.inf. En el equipo de destino, abra una ventana de símbolo del sistema como administrador. Vaya a la carpeta del paquete de controladores, haga clic con el botón derecho en el archivo TabletAudioSample.inf y seleccione Instalar.

    Aparecerá 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 advertencia de Seguridad de Windows que indica que Windows no puede comprobar el publicador.

    Sugerencia

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

    Para obtener instrucciones más detalladas, consulte Configuración de un equipo para la implementación de controladores, las pruebas y la depuración.

    El archivo INF contiene el identificador de hardware para instalar tabletaudiosample.sys. Para el ejemplo de Syvad, el identificador de hardware es: root\sysvad_TabletAudioSample

  3. Análisis del controlador en Administrador de dispositivos

    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, seleccione Dispositivos por tipo.

    En el árbol de dispositivos, busque Dispositivo de audio virtual (WDM) - Ejemplo de tableta en el nodo Dispositivo de audio. Suele estar bajo el nodo Controladores de sonido, vídeo y juegos. Confirme que está instalado y activo.

    Resalte el controlador para el hardware real en el equipo en Administrador de dispositivos. A continuación, seleccione y mantenga pulsado (o haga clic con el botón derecho) el controlador y seleccione Deshabilitar para deshabilitar el controlador.

    Confirme en Administrador de dispositivos que el controlador de hardware de audio muestra la flecha hacia abajo, lo que indica que está deshabilitado.

    Captura de pantalla del árbol de Administrador de dispositivos con el ejemplo de tableta de dispositivo de audio virtual resaltado.

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

Prueba del controlador de audio Sysvad

  1. 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, seleccione Dispositivos por tipo. En el árbol de dispositivos, busque Dispositivo de audio virtual (WDM) - Ejemplo de tableta.

  2. Abra el Panel de control y vaya a Hardware y sonido>Administrar dispositivos de audio. En el cuadro de diálogo Sonido, seleccione el icono del altavoz etiquetado como Dispositivo de audio virtual (WDM) - Ejemplo de tableta y, a continuación, seleccione Establecer valor predeterminado, pero no seleccione Aceptar. Esto mantendrá abierto el cuadro de diálogo Sonido.

  3. Busque un archivo MP3 u otro archivo de audio en el equipo de destino y haga doble clic para reproducirlo. A continuación, en el cuadro de diálogo Sonido, compruebe que hay actividad en el indicador de nivel de volumen asociado al controlador Dispositivo de audio virtual (WDM) - Ejemplo de tableta.

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

En la sección 5, establecerá la ruta de acceso del símbolo y usará comandos del depurador de kernel para visualizar información sobre el controlador de ejemplo Sysvad.

Los símbolos permiten a WinDbg mostrar información adicional, como nombres de variables, que puede ser muy valiosa a la hora de depurar. WinDbg usa los formatos de símbolos de depuración de Microsoft Visual Studio para la depuración de nivel de origen. Puede acceder a cualquier símbolo o variable desde un módulo que tenga archivos de símbolos PDB.

Para cargar el depurador, siga 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. Reemplace la clave y el puerto por lo que configuró anteriormente.

    C:\> WinDbg –k net:port=50010,key=2steg4fzbj2sz.23418vzkd4ko3.1g34ou07z4pev.1sp3yo9yz874p
    
  2. Use Ctrl+Interrumpir (Bloq Despl) para irrumpir en el código que se ejecuta en el sistema de destino.

Establecimiento de la ruta de acceso de símbolos

  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:\WDK_Samples\Sysvad
    0: kd> .reload /f
    

    Nota El comando .reload con la opción de aplicación /f 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 Para usar todas las funciones avanzadas que proporciona WinDbg, debe cargar los símbolos adecuados. 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.

NotaServidores 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 son necesarios. En este tutorial se supone 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 más información, consulte Ruta de acceso de símbolo para el depurador de Windows.

NotaDescripción de los requisitos de símbolos de código fuente

Para realizar la depuración de origen, debe crear una versión comprobada (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 las instrucciones binarias corresponden a las líneas de origen. Los propios archivos de origen 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 las 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 Sysvad.

    0: kd> lm m tabletaudiosample v
    Browse full module list
    start             end                 module name
    fffff801`14b40000 fffff801`14b86000   tabletaudiosample   (private pdb symbols)  C:\Debuggers\sym\TabletAudioSample.pdb\E992C4803EBE48C7B23DC1596495CE181\TabletAudioSample.pdb
        Loaded symbol image file: tabletaudiosample.sys
        Image path: \SystemRoot\system32\drivers\tabletaudiosample.sys
        Image name: tabletaudiosample.sys
        Browse all global symbols  functions  data
        Timestamp:        Thu Dec 10 12:20:26 2015 (5669DE8A)
        CheckSum:         0004891E
    ...  
    

    Para obtener más información, consulte lm.

  2. 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 con la letra a.

  3. Dado que DML está habilitado, algunos elementos de la salida son vínculos activos que puede seleccionar. Seleccione el vínculo de datos de la salida de depuración para mostrar información sobre los símbolos de elementos que comienzan con la letra a.

    0: kd> x /D /f tabletaudiosample!a*
     A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    
    fffff806`9adb1000 tabletaudiosample!AddDevice (struct _DRIVER_OBJECT *, struct _DEVICE_OBJECT *)
    

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

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

    0: kd> !lmi tabletaudiosample
    Loaded Module Info: [tabletaudiosample] 
             Module: tabletaudiosample
       Base Address: fffff8069ad90000
         Image Name: tabletaudiosample.sys
       Machine Type: 34404 (X64)
         Time Stamp: 58ebe848 Mon Apr 10 13:17:12 2017
               Size: 48000
           CheckSum: 42df7
    Characteristics: 22  
    Debug Data Dirs: Type  Size     VA  Pointer
                 CODEVIEW    a7,  e5f4,    d1f4 RSDS - GUID: {5395F0C5-AE50-4C56-AD31-DD5473BD318F}
                   Age: 1, Pdb: C:\Windows-driver-samples-master\audio\sysvad\TabletAudioSample\x64\Debug\TabletAudioSample.pdb
                       ??   250,  e69c,    d29c [Data not mapped]
         Image Type: MEMORY   - Image read successfully from loaded memory.
        Symbol Type: PDB      - Symbols loaded successfully from image header.
                     C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdb
           Compiler: Resource - front end [0.0 bld 0] - back end [14.0 bld 24210]
        Load Report: private symbols & lines, not source indexed 
                     C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\sym\TabletAudioSample.pdb\5395F0C5AE504C56AD31DD5473BD318F1\TabletAudioSample.pdb
    
  5. Use la extensión !dh para mostrar información de encabezado como se muestra a continuación.

    0: kd> !dh tabletaudiosample 
    
    File Type: EXECUTABLE IMAGE
    FILE HEADER VALUES
        8664 machine (X64)
           9 number of sections
    5669DE8A time date stamp Thu Dec 10 12:20:26 2015
    
           0 file pointer to symbol table
           0 number of symbols
          F0 size of optional header
          22 characteristics
                Executable
                App can handle >2gb addresses
    ...
    

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

En la sección 6, mostrará información sobre el controlador de dispositivo de ejemplo Sysvad 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 Plug and Play puede resultar útil para solucionar problemas. Por ejemplo, si un controlador de dispositivo no reside 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, consulte !devnode.

<-En el sistema host

  1. Para ver todos los nodos de dispositivo en el árbol de dispositivos Plug and Play, escriba el comando !devnode 0 1. Este comando puede tardar un par de minutos en ejecutarse. Durante ese tiempo, se mostrará "*Busy" en el área de estado de WinDbg.

    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 el nombre del controlador de dispositivo, sysvad.

    Cuadro de diálogo Buscar con el término

    Una entrada de nodo de dispositivo con un nombre de sysvad_TabletAudioSample estará presente en la salida de !devnode para Syvad.

      DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0
        InstancePath is "ROOT\sysvad_TabletAudioSample\0000"
        ServiceName is "sysvad_tabletaudiosample"
        State = DeviceNodeStarted (0x308)
    ...
    

    Tenga en cuenta que se muestran la dirección PDO y la dirección DevNode.

  3. Use el comando !devnode 0 1 sysvad_TabletAudioSample para mostrar información de Plug and Play asociada a nuestro controlador de dispositivo Sysvad.

    0: kd> !devnode 0 1 sysvad_TabletAudioSample
    Dumping IopRootDeviceNode (= 0xffffe00082df8d30)
    DevNode 0xffffe00086e68190 for PDO 0xffffe00089c575a0
      InstancePath is "ROOT\sysvad_TabletAudioSample\0000"
      ServiceName is "sysvad_tabletaudiosample"
      State = DeviceNodeStarted (0x308)
      Previous State = DeviceNodeEnumerateCompletion (0x30d)
      DevNode 0xffffe000897fb650 for PDO 0xffffe00089927e30
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{64097438-cdc0-4007-a19e-62e789062e20}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00086d2f5f0 for PDO 0xffffe00089939ae0
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{78880f4e-9571-44a4-a9df-960bde446487}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00089759bb0 for PDO 0xffffe000875aa060
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{7cad07f2-d0a0-4b9b-8100-8dc735e9c447}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00087735010 for PDO 0xffffe000872068c0
        InstancePath is "SWD\MMDEVAPI\{0.0.0.00000000}.{fc38551b-e69f-4b86-9661-ae6da78bc3c6}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00088457670 for PDO 0xffffe0008562b830
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{0894b831-c9fe-4c56-86a6-092380fc5628}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe000893dbb70 for PDO 0xffffe00089d68060
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{15eb6b5c-aa54-47b8-959a-0cff2c1500db}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe00088e6f250 for PDO 0xffffe00089f6e990
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{778c07f0-af9f-43f2-8b8d-490024f87239}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
      DevNode 0xffffe000862eb4b0 for PDO 0xffffe000884443a0
        InstancePath is "SWD\MMDEVAPI\{0.0.1.00000000}.{e4b72c7c-be50-45df-94f5-0f2922b85983}"
        State = DeviceNodeStarted (0x308)
        Previous State = DeviceNodeStartPostWork (0x307)
    
  4. La salida mostrada en el comando anterior incluye el PDO asociado a la instancia en ejecución de nuestro controlador, en este ejemplo es 0xffffe00089c575a0. Escriba el comando !devobj<Dirección de PDO> para mostrar la información de Plug and Play asociada al controlador de dispositivo Sysvad. Usa la dirección PDO que !devnode muestra en el equipo, no la que se muestra aquí.

    0: kd> !devobj 0xffffe00089c575a0
    Device object (ffffe00089c575a0) is for:
    0000004e \Driver\PnpManager DriverObject ffffe00082d47e60
    Current Irp 00000000 RefCount 65 Type 0000001d Flags 00001040
    SecurityDescriptor ffffc102b0f6d171 DevExt 00000000 DevObjExt ffffe00089c576f0 DevNode ffffe00086e68190 
    ExtensionFlags (0000000000)  
    Characteristics (0x00000180)  FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN
    AttachedDevice (Upper) ffffe00088386a50 \Driver\sysvad_tabletaudiosample
    Device queue is not busy.
    
  5. La salida que se muestra en el comando !devobj incluye el nombre del dispositivo conectado: \Driver\sysvad_tabletaudiosample. Use el comando !drvobj con una máscara de bits de 2 para mostrar información asociada al dispositivo conectado.

    0: kd> !drvobj \Driver\sysvad_tabletaudiosample 2
    Driver object (ffffe0008834f670) is for:
    \Driver\sysvad_tabletaudiosample
    DriverEntry:   fffff80114b45310  tabletaudiosample!FxDriverEntry
    DriverStartIo: 00000000 
    DriverUnload:  fffff80114b5fea0                tabletaudiosample!DriverUnload
    AddDevice:     fffff80114b5f000  tabletaudiosample!AddDevice
    
    Dispatch routines:
    [00] IRP_MJ_CREATE                      fffff80117b49a20             portcls!DispatchCreate
    [01] IRP_MJ_CREATE_NAMED_PIPE           fffff8015a949a00          nt!IopInvalidDeviceRequest
    [02] IRP_MJ_CLOSE                       fffff80115e26f90                ks!DispatchCleanup
    [03] IRP_MJ_READ                        fffff80115e32710                ks!DispatchRead
    [04] IRP_MJ_WRITE                       fffff80115e327e0              ks!DispatchWrite
    [05] IRP_MJ_QUERY_INFORMATION           fffff8015a949a00         nt!IopInvalidDeviceRequest
    [06] IRP_MJ_SET_INFORMATION             fffff8015a949a00              nt!IopInvalidDeviceRequest
    [07] IRP_MJ_QUERY_EA                    fffff8015a949a00         nt!IopInvalidDeviceRequest
    [08] IRP_MJ_SET_EA                      fffff8015a949a00              nt!IopInvalidDeviceRequest
    [09] IRP_MJ_FLUSH_BUFFERS               fffff80115e32640  ks!DispatchFlush
    [0a] IRP_MJ_QUERY_VOLUME_INFORMATION    fffff8015a949a00           nt!IopInvalidDeviceRequest
    [0b] IRP_MJ_SET_VOLUME_INFORMATION      fffff8015a949a00               nt!IopInvalidDeviceRequest
    [0c] IRP_MJ_DIRECTORY_CONTROL           fffff8015a949a00           nt!IopInvalidDeviceRequest
    [0d] IRP_MJ_FILE_SYSTEM_CONTROL         fffff8015a949a00         nt!IopInvalidDeviceRequest
    [0e] IRP_MJ_DEVICE_CONTROL              fffff80115e27480               ks!DispatchDeviceIoControl
    [0f] IRP_MJ_INTERNAL_DEVICE_CONTROL     fffff8015a949a00   nt!IopInvalidDeviceRequest
    [10] IRP_MJ_SHUTDOWN                    fffff8015a949a00      nt!IopInvalidDeviceRequest
    [11] IRP_MJ_LOCK_CONTROL                fffff8015a949a00  nt!IopInvalidDeviceRequest
    [12] IRP_MJ_CLEANUP                     fffff8015a949a00           nt!IopInvalidDeviceRequest
    [13] IRP_MJ_CREATE_MAILSLOT             fffff8015a949a00               nt!IopInvalidDeviceRequest
    [14] IRP_MJ_QUERY_SECURITY              fffff80115e326a0 ks!DispatchQuerySecurity
    [15] IRP_MJ_SET_SECURITY                fffff80115e32770      ks!DispatchSetSecurity
    [16] IRP_MJ_POWER                       fffff80117b3dce0            portcls!DispatchPower
    [17] IRP_MJ_SYSTEM_CONTROL              fffff80117b13d30              portcls!PcWmiSystemControl
    [18] IRP_MJ_DEVICE_CHANGE               fffff8015a949a00 nt!IopInvalidDeviceRequest
    [19] IRP_MJ_QUERY_QUOTA                 fffff8015a949a00  nt!IopInvalidDeviceRequest
    [1a] IRP_MJ_SET_QUOTA                   fffff8015a949a00       nt!IopInvalidDeviceRequest
    [1b] IRP_MJ_PNP                         fffff80114b5f7d0 tabletaudiosample!PnpHandler
    
  6. Escriba el comando !devstack<Dirección de PDO> para mostrar la información de Plug and Play asociada al controlador de dispositivo. La salida mostrada en el comando !devnode 0 1 incluye la dirección de PDO asociada a la instancia en ejecución de nuestro controlador. En este ejemplo es 0xffffe00089c575a0. Use la dirección de PDO que !devnode muestra en el equipo, no la que se muestra a continuación.

    0: kd> !devstack 0xffffe00089c575a0
      !DevObj           !DrvObj            !DevExt           ObjectName
      ffffe00088d212e0  \Driver\ksthunk    ffffe00088d21430  0000007b
      ffffe00088386a50  \Driver\sysvad_tabletaudiosampleffffe00088386ba0  0000007a
    > ffffe00089c575a0  \Driver\PnpManager 00000000  0000004e
    !DevNode ffffe00086e68190 :
      DeviceInst is "ROOT\sysvad_TabletAudioSample\0000"
      ServiceName is "sysvad_tabletaudiosample"
    

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

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

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

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

Sección 7: Trabajo con puntos de interrupción

En la sección 7, trabajará con puntos de interrupción para detener la ejecución de código en puntos específicos.

Establecimiento de puntos de interrupción mediante comandos

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 del código.

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

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 el módulo se descarga y se vuelve a habilitar cuando el módulo se vuelve a cargar.

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

  1. Use la interfaz de usuario de WinDbg para confirmar que Depuración>Modo de origen está habilitado en la sesión actual de WinDbg.

  2. Añada la ubicación de su código local a la ruta de origen escribiendo el siguiente comando.

    .sympath+ C:\WDK_Samples\Sysvad
    
  3. Añada la ubicación del símbolo local a la ruta de símbolos escribiendo el siguiente comando.

    .sympath+ C:\WDK_Samples\Sysvad
    
  4. Establecimiento de la máscara de depuración

    Como está trabajando con un controlador, puede ser útil ver todos los mensajes que puede mostrar. 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
    
  5. Establezca el punto de interrupción con el comando bm utilizando el nombre del controlador, seguido del nombre de la función (AddDevice) donde desea establecer el punto de interrupción, separados por un signo de exclamación.

    0: kd> bm tabletaudiosample!AddDevice
    breakpoint 1 redefined
      1: fffff801`14b5f000 @!"tabletaudiosample!AddDevice"
    

    Puede usar una sintaxis diferente junto con la configuración de variables como <module>!<symbol>, <class>::<method>,‘<file.cpp>:<line number>’ u omitir un número de veces <condition><#>. Para obtener más información, consulta Using Breakpoints.

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

    0: kd> bl
    1 e fffff801`14b5f000     0001 (0001) tabletaudiosample!AddDevice
    
  7. Reinicie la ejecución de código en el sistema de destino escribiendo el comando g.

  8. ->En el sistema de destino

    En Windows, abra Administrador de dispositivos mediante el icono o escribiendo mmc devmgmt.msc. En Administrador de dispositivos expanda el nodo Controladores de sonido, vídeo y juegos. Seleccione y mantenga pulsada (o haga clic con el botón derecho) la entrada del controlador de audio virtual y seleccione Deshabilitar en el menú.

  9. Vuelva a seleccionar y mantener pulsada (o haga clic con el botón derecho) la entrada del controlador de audio virtual y seleccione Habilitar en el menú.

  10. <- En el sistema host

    Esto debería hacer que Windows vuelva a cargar el controlador, que llama a AddDevice. Esto hará que el punto de interrupción de depuración AddDevice se active y se detendrá la ejecución del código de controlador en el sistema de destino.

    Breakpoint 1 hit
    tabletaudiosample!AddDevice:
    fffff801`14baf000 4889542410      mov     qword ptr [rsp+10h],rdx
    

    Si la ruta de acceso de origen está establecida correctamente, debe detenerse en la rutina AddDevice en adapter.cpp

    {
        PAGED_CODE();
    
        NTSTATUS        ntStatus;
        ULONG           maxObjects;
    
        DPF(D_TERSE, ("[AddDevice]"));
    
        maxObjects = g_MaxMiniports;
    
        #ifdef SYSVAD_BTH_BYPASS
        // 
        // Allow three (3) Bluetooth hands-free profile devices.
        //
        maxObjects += g_MaxBthHfpMiniports * 3; 
        #endif // SYSVAD_BTH_BYPASS
    
        // Tell the class driver to add the device.
        //
        ntStatus = 
            PcAddAdapterDevice
            ( 
                DriverObject,
                PhysicalDeviceObject,
                PCPFNSTARTDEVICE(StartDevice),
                maxObjects,
                0
            );
        return ntStatus;
    } // AddDevice
    
  11. Recorra el código línea a línea escribiendo el comando p o pulsando F10. Puede avanzar desde el código sysvad AddDevice a PpvUtilCall, PnpCallAddDevice y luego al código PipCallDriverAddDevice de Windows. Puede proporcionar un número al comando p para avanzar varias líneas, por ejemplo p 5.

  12. Cuando haya terminado de recorrer el código, use el comando g para reiniciar la ejecución en el sistema de destino.

Establecimiento de puntos de interrupción de acceso a memoria

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

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

e

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

r

leer/escribir (cuando la CPU lee o escribe en la dirección)

t

escribir (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 depende de usted asegurarse de que está alineando sus datos correctamente o no activará el punto de interrupción (las palabras deben terminar en direcciones divisibles por 2, las dwords deben ser divisibles por 4, y las quadwords por 0 u 8).

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

ba r 4 fffff800`7bc9eff0

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 be * para habilitar todos los puntos de interrupción

Como alternativa, también puede modificar puntos de interrupción seleccionando editar>puntos de interrupción. Tenga en cuenta que el cuadro de diálogo de punto de interrupción solo funciona con puntos de interrupción existentes. Los nuevos puntos de interrupción deben establecerse desde la línea de comandos.

Establecimiento de un punto de interrupción en MixerVolume

Se llama a diferentes partes del código del controlador de audio para responder a varios eventos, después de cargar el controlador del dispositivo. En la sección siguiente, establecemos un punto de interrupción que se activará cuando el usuario ajuste el control de volumen del controlador de audio virtual.

Para establecer un punto de interrupción en MixerVolume, siga los pasos siguientes.

  1. <- En el sistema host

    Para buscar el método que cambia el volumen, use el comando x para enumerar los símbolos de CAdapterCommon, que contienen el volumen de cadena.

    kd> x tabletaudiosample!CAdapterCommon::*
    ...
    fffff800`7bce26a0 tabletaudiosample!CAdapterCommon::MixerVolumeWrite (unsigned long, unsigned long, long)
    …
    

    Use CTRL+F para buscar hacia arriba en la salida del volumen y busque el método MixerVolumeWrite.

  2. Borre los puntos de interrupción anteriores mediante bc *.

  3. Establezca un punto de interrupción de símbolos en la rutina CAdapterCommon::MixerVolumeWrite mediante el siguiente comando.

    kd> bm tabletaudiosample!CAdapterCommon::MixerVolumeWrite
      1: fffff801`177b26a0 @!"tabletaudiosample!CAdapterCommon::MixerVolumeWrite"
    
  4. Enumere los puntos de interrupción para confirmar que el punto de interrupción está establecido correctamente.

    kd> bl
    1 e fffff801`177b26a0 [c:\WDK_Samples\audio\sysvad\common.cpp @ 1668]    0001 (0001) tabletaudiosample!CAdapterCommon::MixerVolumeWrite
    
  5. Reinicie la ejecución de código en el sistema de destino escribiendo el comando g.

  6. En el Panel de control, seleccione Hardware y sonido>Sonido. Seleccione y mantenga pulsada (o haga clic con el botón derecho) Ejemplo de descripción del receptor y seleccione Propiedades. Seleccione la pestaña Niveles. Ajuste el volumen del control deslizante.

  7. Esto debería hacer que SetMixerVolume se active y la ejecución del código de controlador en el sistema de destino debería detenerse.

    kd> g
    Breakpoint 1 hit
    tabletaudiosample!CAdapterCommon::MixerVolumeWrite:
    fffff801`177b26a0 44894c2420      mov     dword ptr [rsp+20h],r9d
    

    Debe detenerse en esta línea en common.cpp

    {
        if (m_pHW)
        {
            m_pHW->SetMixerVolume(Index, Channel, Value);
        }
    } // MixerVolumeWrite
    
  8. Use el comando dv para visualizar las variables actuales y sus valores. En la sección siguiente de este laboratorio se proporciona más información sobre las variables.

    2: kd> dv
               this = 0x00000000`00000010
             ulNode = 0x344
          ulChannel = 0x210a45f8
            lVolume = 0n24
    
  9. Pulse F10 para recorrer el código paso a paso.

  10. Pulse F5 para finalizar la ejecución del código MixerVolumeWrite.

Resumen: recorrido paso a paso por el código desde la ventana Comando del depurador

A continuación se muestran los comandos que puede usar para recorrer el código (con los métodos abreviados del teclado asociados que se muestran entre paréntesis).

  • Interrumpir (Ctrl+Interrumpir): este comando interrumpirá 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).

  • Paso a paso por procedimientos (F10): este comando hace que la ejecución del código continúe con una instrucción o una instrucción a la vez. Si se encuentra una llamada, la ejecución del código pasa por 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 se puede activar o desactivar mediante Depuración>Modo de origen).

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

  • Paso a paso para 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.

  • Ejecutar hasta el cursor (F7 o Ctrl+F10): coloque el cursor en una ventana de origen o desensamblado donde desee que se interrumpa la ejecución y pulse F7; la ejecución del código se ejecutará en ese punto. Tenga en cuenta que si el flujo de ejecución de código no llega al punto indicado por el cursor (por ejemplo, no se ejecuta una instrucción IF), WinDbg no se interrumpirá, ya que la ejecución del código no alcanzó el 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.

Opciones avanzadas

  • Establecer instrucciones en la línea actual (Ctrl+Mayús+I): en una ventana de origen, puede colocar el cursor en una línea, escribir este método abreviado de teclado y la ejecución del código comenzará desde ese punto en cuanto deje que continúe (por ejemplo, con F5 o F10). Esto es útil si desea volver a intentar una secuencia, pero requiere cierta atención. Por ejemplo, los registros y las variables no se establecen en lo que serían si la ejecución de código hubiera alcanzado esa línea de forma natural.

  • Configuración directa del registro de eip: puede colocar un valor en el registro de eip y en cuanto pulse F5 (o F10, F11, etc.), la ejecución comienza desde esa dirección. Esto es similar a establecer instrucciones en la línea actual designada por el cursor, salvo que especifica la dirección de una instrucción de ensamblado.

Puede ser más fácil recorrer la interfaz de usuario en lugar de hacerlo desde la línea de comandos, por lo que se recomienda este método. Si es necesario, se pueden usar los siguientes comandos para recorrer un archivo de código fuente en la línea de comandos:

  • .lines: habilita la información de línea de origen.

  • bp main: establece el punto de interrupción inicial al principio del módulo.

  • l+t: la ejecución paso a paso se realizará mediante la línea de origen.

  • Seleccione Depurar>Modo de origen para acceder al modo de origen; el comando L+t no es suficiente.

  • l+s: las líneas de origen se mostrarán en el símbolo del sistema.

  • g : ejecuta el programa hasta que se escribe "main".

  • p: ejecuta una línea de origen.

Para obtener más información, consulte Depuración de código fuente en WinDbg (clásico) en la documentación de referencia de depuración.

Establecimiento de puntos de interrupción en el código

Para establecer un punto de interrupción en el código, agregue la instrucción DebugBreak() y vuelva a generar el proyecto y a instalar el controlador. Este punto de interrupción se activará cada vez que el controlador esté habilitado, por lo que sería una técnica que se usará en las primeras fases de desarrollo, no en el código de producción. Esta técnica no es tan flexible como establecer dinámicamente puntos de interrupción mediante los comandos de punto de interrupción.

Sugerencia: puede que desee conservar una copia del controlador Sysvad con el punto de interrupción agregado para un trabajo de laboratorio adicional.

  1. Establezca una interrupción para que se produzca cada vez que se ejecute el método AddDevice agregando la instrucción DebugBreak() al código de ejemplo.

    ...
        // Insert the DebugBreak() statment before the  PcAddAdapterDevice is called.
        //
    
        DebugBreak()
    
        // Tell the class driver to add the device.
        //
        ntStatus = 
            PcAddAdapterDevice
            ( 
                DriverObject,
                PhysicalDeviceObject,
                PCPFNSTARTDEVICE(StartDevice),
                maxObjects,
                0
            );
    
        return ntStatus;
    } // AddDevice
    
  2. Siga todos los pasos descritos anteriormente para recompilar el controlador en Microsoft Visual Studio y volver a instalarlo en la máquina de destino. Asegúrese de desinstalar el controlador existente antes de instalar el controlador actualizado.

  3. Borre los puntos de interrupción anteriores y asegúrese de que el depurador está conectado al equipo de destino.

  4. Cuando el código se ejecuta y llega a la instrucción DebugBreak, la ejecución se detendrá y se mostrará un mensaje.

    KERNELBASE!DebugBreak:
    77b3b770 defe     __debugbreak
    

Sección 8: Visualización de variables

En la sección 8, usará comandos del depurador para visualizar variables.

Puede ser útil examinar las variables a medida que se ejecuta el código para confirmar que el código funciona según lo previsto. En este laboratorio se examinan las variables a medida que el controlador de audio genera sonido.

  1. Use el comando dv para examinar las variables de configuración regional asociadas a tabletaudiosample! CMiniportWaveRT::New*.

    kd> dv tabletaudiosample!CMiniportWaveRT::New*
    
  2. Borrado de los puntos de interrupción anteriores

    bc *
    
  3. Establezca un punto de interrupción de símbolos en las rutinas CMiniportWaveStreamMSVAD mediante el siguiente comando.

    0: kd> bm tabletaudiosample!CMiniportWaveRT::NewStream
      1: fffff801`177dffc0 @!"tabletaudiosample!CMiniportWaveRT::NewStream"
    
  4. Reinicie la ejecución de código en el sistema de destino escribiendo el comando g.

  5. -> En el sistema de destino

    Busque un archivo multimedia pequeño (como un archivo de sonido de notificación de Windows con una extensión de archivo .wav) y seleccione el archivo para reproducirlo. Por ejemplo, puede usar Ring05.wav ubicado en el directorio Windows\Media.

  6. <- En el sistema host

    Cuando se reproduce el archivo multimedia, el punto de interrupción debería activarse y la ejecución del código de controlador en el sistema de destino debería detenerse.

    Breakpoint 1 hit
    tabletaudiosample!CMiniportWaveRT::NewStream:
    fffff801`177dffc0 44894c2420      mov     dword ptr [rsp+20h],r9d
    

    La ventana de código fuente debe resaltar la llave de la entrada a la función NewStream.

    /*++
    
    Routine Description:
    
      The NewStream function creates a new instance of a logical stream 
      associated with a specified physical channel. Callers of NewStream should 
      run at IRQL PASSIVE_LEVEL.
    
    Arguments:
    
      OutStream -
    
      OuterUnknown -
    
      Pin - 
    
      Capture - 
    
      DataFormat -
    
    Return Value:
    
      NT status code.
    
    --*/
    {
    
    ...
    
  7. Variables locales

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

    0: kd> dv
                    this = 0xffffe000`4436f8e0
               OutStream = 0xffffe000`49d2f130
            OuterUnknown = 0xffffe000`4436fa30
                     Pin = 0
                 Capture = 0x01 '
              DataFormat = 0xffffe000`44227790
    signalProcessingMode = {487E9220-E000-FFFF-30F1-D24900E0FFFF}
                ntStatus = 0n1055
                  stream = 0x00000000`00000200
    
  8. Uso de DML para mostrar variables

    Para usar DML para explorar variables, seleccione los elementos subrayados. La acción de seleccionar crea un comando dx (Mostrar expresión NatVis) que permite explorar en profundidad las estructuras de datos anidadas.

    0: kd> dx -r1 (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380))
    (*((tabletaudiosample!CMiniportWaveRT *)0xffffe001d10b8380)) :  [Type: CMiniportWaveRT]
        [+0x020] m_lRefCount      : 0
        [+0x028] m_pUnknownOuter  : 0xffffe001d1477e50 : [Type: IUnknown *]
        [+0x030] m_ulLoopbackAllocated : 0x2050
        [+0x034] m_ulSystemAllocated : 0x180
        [+0x038] m_ulOffloadAllocated : 0x0
        [+0x03c] m_dwCaptureAllocatedModes : 0x0
    
    0: kd> dx -r1 (*((tabletaudiosample!_GUID *)0xffffd001c8acd348))
    (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) : {487E9220-E000-FFFF-30F1-D24900E0FFFF} [Type: _GUID]
        [<Raw View>]    
    
    0: kd> dx -r1 -n (*((tabletaudiosample!_GUID *)0xffffd001c8acd348))
    (*((tabletaudiosample!_GUID *)0xffffd001c8acd348)) :  [Type: _GUID]
        [+0x000] Data1            : 0x487e9220
        [+0x004] Data2            : 0xe000
        [+0x006] Data3            : 0xffff
        [+0x008] Data4            :  [Type: unsigned char [8]]
    
    0: kd> dx -r1 -n (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350))
    (*((tabletaudiosample!unsigned char (*)[8])0xffffd001c8acd350)) :  [Type: unsigned char [8]]
        [0]              : 0x30
        [1]              : 0xf1
        [2]              : 0xd2
        [3]              : 0x49
        [4]              : 0x0
        [5]              : 0xe0
        [6]              : 0xff
        [7]              : 0xff
    
  9. Variables globales

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

    0: kd> ? signalProcessingMode
    Evaluate expression: -52768896396472 = ffffd001`c8acd348
    
  10. Esto devuelve la ubicación de memoria de la variable, en este caso ffffd001'c8acd348. Puede ver el contenido de la ubicación de memoria volcando el valor de esa ubicación, escribiendo el comando dd utilizando la ubicación de memoria devuelta por el comando anterior.

    0: kd> dd ffffd001`c8acd348
    ffffd001`c8acd348  487e9220 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd358  4837c468 ffffe000 18221570 ffffc000
    ffffd001`c8acd368  4436f8e0 ffffe000 487e9220 ffffe000
    ffffd001`c8acd378  18ab145b fffff801 4837c420 ffffe000
    ffffd001`c8acd388  4436f8e0 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd398  4436fa30 ffffe000 00000000 00000000
    ffffd001`c8acd3a8  00000001 00000000 44227790 ffffe000
    ffffd001`c8acd3b8  18adc7f9 fffff801 495972a0 ffffe000
    
  11. También puede usar nombres de variable con el comando dd.

    0: kd> dd signalProcessingMode
    ffffd001`c8acd348  487e9220 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd358  4837c468 ffffe000 18221570 ffffc000
    ffffd001`c8acd368  4436f8e0 ffffe000 487e9220 ffffe000
    ffffd001`c8acd378  18ab145b fffff801 4837c420 ffffe000
    ffffd001`c8acd388  4436f8e0 ffffe000 49d2f130 ffffe000
    ffffd001`c8acd398  4436fa30 ffffe000 00000000 00000000
    ffffd001`c8acd3a8  00000001 00000000 44227790 ffffe000
    ffffd001`c8acd3b8  18adc7f9 fffff801 495972a0 ffffe000
    
  12. Visualización de variables

    Use la opción de menú Ver>Locales para visualizar variables locales. Esta interfaz también proporciona esta capacidad para explorar en profundidad las estructuras de datos más complejas.

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

  13. Use p o F10 para avanzar aproximadamente 10 líneas en el código hasta que resalte la línea de código ntStatus = IsFormatSupported(Pin, Capture, DataFormat);.

        PAGED_CODE();
    
        ASSERT(OutStream);
        ASSERT(DataFormat);
    
        DPF_ENTER(("[CMiniportWaveRT::NewStream]"));
    
        NTSTATUS                    ntStatus = STATUS_SUCCESS;
        PCMiniportWaveRTStream      stream = NULL;
        GUID                        signalProcessingMode = AUDIO_SIGNALPROCESSINGMODE_DEFAULT;
    
        *OutStream = NULL;
    
         //
        // If the data format attributes were specified, extract them.
        //
        if ( DataFormat->Flags & KSDATAFORMAT_ATTRIBUTES )
        {
            // The attributes are aligned (QWORD alignment) after the data format
            PKSMULTIPLE_ITEM attributes = (PKSMULTIPLE_ITEM) (((PBYTE)DataFormat) + ((DataFormat->FormatSize + FILE_QUAD_ALIGNMENT) & ~FILE_QUAD_ALIGNMENT));
            ntStatus = GetAttributesFromAttributeList(attributes, attributes->Size, &signalProcessingMode);
        }
    
        // Check if we have enough streams.
        //
        if (NT_SUCCESS(ntStatus))
        {
            ntStatus = ValidateStreamCreate(Pin, Capture, signalProcessingMode);
        }
    
        // Determine if the format is valid.
        //
        if (NT_SUCCESS(ntStatus))
        {
            ntStatus = IsFormatSupported(Pin, Capture, DataFormat);
        }
    
    ...
    
  14. Use el comando dv para mostrar los nombres y los valores de todas las variables locales para un marco determinado. Tenga en cuenta que, como se esperaba, los valores son diferentes de la última vez que se ejecutó este comando, ya que se ha ejecutado código adicional que cambia las variables locales y algunas variables ahora no están en el marco actual o sus valores han cambiado.

    2: kd> dv
                    this = 0xffffe001`d1182000
               OutStream = 0xffffe001`d4776d20
            OuterUnknown = 0xffffe001`d4776bc8
                     Pin = 0
                 Capture = 0x00 '
              DataFormat = 0xffffe001`cd7609b0
    signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE}
                ntStatus = 0n0
                  stream = 0x00000000`00000000
    

Sección 9: Visualización de pilas de llamadas

En la sección 9, verá las pilas de llamadas para examinar el código de llamada o autor de la llamada.

La pila de llamadas es la cadena de llamadas a la 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 función siguiente es la función que llamó a la función actual, etc.

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 de marco junto a ella.

Si desea mantener la pila de llamadas disponible, puede seleccionar Ver>Pila de llamadas para verla. Seleccione las columnas de la parte superior de la ventana para alternar la presentación de información adicional.

Interfaz WinDbg que muestra la ventana de pila de llamadas.

Esta salida muestra la pila de llamadas durante la depuración del código del adaptador de ejemplo en un estado de interrupción.

0: kd> kb
# RetAddr           : Args to Child                                                           : Call Site
00 fffff800`7a0fa607 : ffffe001`d1182000 ffffe001`d4776d20 ffffe001`d4776bc8 ffffe001`00000000 : tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
01 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d122bb10 ffffe001`ceb81750 ffffe001`d173f058 : portcls!CPortPinWaveRT::Init+0x2e7
02 fffff800`7a0fc7f9 : ffffe001`d4776bc0 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d122bb10 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
04 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
05 fffff800`7bd314b1 : ffffe001`d122bb10 ffffd001`c3098590 ffffe001`d122bd90 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
06 fffff803`cda1bfa8 : 00000000`00000024 00000000`00000000 00000000`00000000 ffffe001`d122bb10 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 fffff803`cda7b306 : 00000000`000001f0 ffffe001`d48ce690 ffffe001`d13d6400 ffffe001`d13d64c0 : nt!IopParseDevice+0x7c8
08 fffff803`cda12916 : 00000000`000001f0 ffffd001`c30988d0 ffffe001`d13d6490 fffff803`cda7b250 : nt!IopParseFile+0xb6
09 fffff803`cda1131c : ffffe001`d2ccb001 ffffd001`c30989e0 00ffffe0`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
0a fffff803`cd9fedb8 : ffffe001`00000001 ffffe001`d48ce690 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
0b fffff803`cd9fe919 : 000000ee`6d1fc8d8 000000ee`6d1fc788 000000ee`6d1fc7e0 000000ee`6d1fc7d0 : nt!IopCreateFile+0x3d8
0c fffff803`cd752fa3 : ffffc000`1f296870 fffff803`cd9d9fbd ffffd001`c3098be8 00000000`00000000 : nt!NtCreateFile+0x79
0d 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13
0e 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
0f 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
10 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
11 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e

Puede usar DML para explorar aún más el código. Al seleccionar la primera entrada 00, se usa el comando .frame (Establecer contexto local) para establecer el contexto y, a continuación, el comando dv (Mostrar variables locales) muestra las variables locales.

0: kd> .frame 0n0;dv /t /v
00 ffffd001`c30981d0 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream+0x1dc [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 597]
ffffd001`c30982b0 class CMiniportWaveRT * this = 0xffffe001`d1182000
ffffd001`c30982b8 struct IMiniportWaveRTStream ** OutStream = 0xffffe001`d4776d20
ffffd001`c30982c0 struct IPortWaveRTStream * OuterUnknown = 0xffffe001`d4776bc8
ffffd001`c30982c8 unsigned long Pin = 0
ffffd001`c30982d0 unsigned char Capture = 0x00 '
ffffd001`c30982d8 union KSDATAFORMAT * DataFormat = 0xffffe001`cd7609b0
ffffd001`c3098270 struct _GUID signalProcessingMode = {4780004E-7133-41D8-8C74-660DADD2C0EE}
ffffd001`c3098210 long ntStatus = 0n0
ffffd001`c3098218 class CMiniportWaveRTStream * stream = 0x00000000`00000000

Sección 10: Visualización de procesos y subprocesos

En la sección 10, usará comandos del depurador para mostrar procesos y subprocesos.

Process

Para cambiar el contexto del proceso actual, use el comando .process <proceso>. En el ejemplo siguiente se muestra cómo identificar un proceso y cambiarle el contexto.

  • Use el comando !process para mostrar el proceso actual implicado en la reproducción del sonido.

    Para obtener más información, consulte !process

La salida muestra que el proceso está asociado a audiodg.exe. Si todavía está en el punto de interrupción descrito en la sección anterior de este tema, el proceso actual debe asociarse a la imagen de audiodg.exe.

<- En el sistema host

0: kd> !process
PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
    VadRoot ffffe001d4222f70 Vads 70 Clone 0 Private 504. Modified 16. Locked 0.
    DeviceMap ffffc00019113080
    Token                             ffffc0001f1d4060
    ElapsedTime                       <Invalid>
    UserTime                          00:00:00.000
    KernelTime                        00:00:00.000
    QuotaPoolUsage[PagedPool]         81632
    QuotaPoolUsage[NonPagedPool]      9704
    Working Set Sizes (now,min,max)  (2154, 1814, 2109) (8616KB, 7256KB, 8436KB)
    PeakWorkingSetSize                2101
    VirtualSize                       2097192 Mb
    PeakVirtualSize                   2097192 Mb
    PageFaultCount                    2336
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      1573

        THREAD ffffe001d173e840  Cid 10f0.1dac  Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
            ffffe001d16c4dd0  NotificationEvent
            ffffe001d08b0840  ProcessObject

        THREAD ffffe001ceb77080  Cid 10f0.16dc  Teb: 000000ee6cf8d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001d112c840  Cid 10f0.0a4c  Teb: 000000ee6cf8f000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001d16c7840  Cid 10f0.13c4  Teb: 000000ee6cf91000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001cf2d1840  QueueObject

        THREAD ffffe001cec67840  Cid 10f0.0dbc  Teb: 000000ee6cf93000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject

        THREAD ffffe001d1117840  Cid 10f0.1d6c  Teb: 000000ee6cf95000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject

        THREAD ffffe001cdeae840  Cid 10f0.0298  Teb: 000000ee6cf97000 Win32Thread: 0000000000000000 RUNNING on processor 2

Tenga en cuenta que uno de los subprocesos asociados a este proceso está en estado RUNNING. Este subproceso admitía la reproducción del clip multimedia cuando se alcanzó el punto de interrupción.

Use el comando !process 0 0 para mostrar información de resumen de todos los procesos. En la salida del comando, use CTRL+F para buscar el identificador de proceso del proceso asociado a la imagen de audiodg.exe. En el ejemplo que se muestra a continuación, el identificador de proceso es ffffe001d147c840.

Registre el identificador de proceso asociado a audiodg.exe en el equipo para usarlo más adelante en este laboratorio. ________________________

...

PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
...

Escriba g en el depurador para ejecutar el código hacia delante hasta que el clip multimedia haya terminado de reproducirse. A continuación, interrumpa en el depurador pulsando Ctrl+ScrLk (Ctrl+Interrumpir) Use el comando !process para confirmar que ahora está ejecutando un proceso diferente.

!process
PROCESS ffffe001cd0ad040
    SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 001aa000  ObjectTable: ffffc00017214000  HandleCount: <Data Not Accessible>
    Image: System
    VadRoot ffffe001d402b820 Vads 438 Clone 0 Private 13417. Modified 87866. Locked 64.
    DeviceMap ffffc0001721a070
    Token                             ffffc00017216a60
    ElapsedTime                       05:04:54.716
    UserTime                          00:00:00.000
    KernelTime                        00:00:20.531
    QuotaPoolUsage[PagedPool]         0
    QuotaPoolUsage[NonPagedPool]      0
    Working Set Sizes (now,min,max)  (1720, 50, 450) (6880KB, 200KB, 1800KB)
    PeakWorkingSetSize                15853
    VirtualSize                       58 Mb
    PeakVirtualSize                   74 Mb
    PageFaultCount                    46128
   MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      66

        THREAD ffffe001cd0295c0  Cid 0004.000c  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
            fffff803cd8e0120  SynchronizationEvent

        THREAD ffffe001cd02a6c0  Cid 0004.0010  Teb: 0000000000000000 Win32Thread: 0000000000000000 WAIT: (Executive) KernelMode Non-Alertable
            fffff803cd8e0ba0  Semaphore Limit 0x7fffffff
...

La salida anterior muestra que se está ejecutando un proceso de sistema diferente de ffffe001cd0ad040. El nombre de la imagen muestra System, no audiodg.exe.

Ahora, use el comando !process para cambiar al proceso asociado a audiodg.exe. En el ejemplo, el identificador de proceso es ffffe001d147c840. Sustituya el identificador de proceso del ejemplo por el identificador de proceso que registró anteriormente.

0: kd> !process  ffffe001d147c840
PROCESS ffffe001d147c840
    SessionId: 0  Cid: 10f0    Peb: ee6cf8a000  ParentCid: 0434
    DirBase: d2122000  ObjectTable: ffffc0001f191ac0  HandleCount: <Data Not Accessible>
    Image: audiodg.exe
    VadRoot ffffe001d4222f70 Vads 60 Clone 0 Private 299. Modified 152. Locked 0.
    DeviceMap ffffc00019113080
    Token                             ffffc0001f1d4060
    ElapsedTime                       1 Day 01:53:14.490
    UserTime                          00:00:00.031
    KernelTime                        00:00:00.031
    QuotaPoolUsage[PagedPool]         81552
    QuotaPoolUsage[NonPagedPool]      8344
    Working Set Sizes (now,min,max)  (1915, 1814, 2109) (7660KB, 7256KB, 8436KB)
    PeakWorkingSetSize                2116
    VirtualSize                       2097189 Mb
    PeakVirtualSize                   2097192 Mb
    PageFaultCount                    2464
    MemoryPriority                    BACKGROUND
    BasePriority                      8
    CommitCharge                      1418

        THREAD ffffe001d173e840  Cid 10f0.1dac  Teb: 000000ee6cf8b000 Win32Thread: ffffe001d1118cf0 WAIT: (UserRequest) UserMode Non-Alertable
            ffffe001d16c4dd0  NotificationEvent
            ffffe001d08b0840  ProcessObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      338852         Ticks: 197682 (0:00:51:28.781)
        Context Switch Count      36             IdealProcessor: 0             
        UserTime                  00:00:00.015
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007ff7fb928de0
        Stack Init ffffd001c2ec6dd0 Current ffffd001c2ec60c0
        Base ffffd001c2ec7000 Limit ffffd001c2ec1000 Call 0
        Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

        THREAD ffffe001d115c080  Cid 10f0.15b4  Teb: 000000ee6cf9b000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d0bf0640  QueueObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      338852         Ticks: 197682 (0:00:51:28.781)
        Context Switch Count      1              IdealProcessor: 0             
        UserTime                  00:00:00.000
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007fff6978b350
        Stack Init ffffd001c3143dd0 Current ffffd001c3143520
        Base ffffd001c3144000 Limit ffffd001c313e000 Call 0
        Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

        THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 WAIT: (WrQueue) UserMode Alertable
            ffffe001d173e5c0  QueueObject
        Not impersonating
        DeviceMap                 ffffc00019113080
        Owning Process            ffffe001d147c840       Image:         audiodg.exe
        Attached Process          N/A            Image:         N/A
        Wait Start TickCount      518918         Ticks: 17616 (0:00:04:35.250)
        Context Switch Count      9              IdealProcessor: 1             
        UserTime                  00:00:00.000
        KernelTime                00:00:00.000
        Win32 Start Address 0x00007fff6978b350
        Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
        Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
        Priority 9 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
        Kernel stack not resident.

Dado que este código no está activo, todos los subprocesos están en estado WAIT, como se esperaba.

Subprocesos

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

Para explorar los subprocesos asociados al reproductor multimedia, vuelva a reproducir el clip multimedia. Si el punto de interrupción descrito en la sección anterior sigue en vigor, se detendrá en el contexto de audiodg.exe.

Use !thread -1 0 para mostrar información breve para el subproceso actual. Esto muestra la dirección del subproceso, los identificadores de subproceso y de proceso, la dirección del bloque de entorno de subprocesos (TEB), la dirección de la función Win32 (si existe) que se creó para ejecutar el subproceso y el estado de programación del subproceso.

0: kd> !thread -1 0
THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0

Para ver más información sobre el subproceso que se está ejecutando, escriba !thread. Debe mostrarse información similar a la siguiente.

0: kd> !thread
THREAD ffffe001d3a27040  Cid 10f0.17f4  Teb: 000000ee6cf9d000 Win32Thread: 0000000000000000 RUNNING on processor 0
IRP List:
    ffffe001d429e580: (0006,02c8) Flags: 000008b4  Mdl: 00000000
Not impersonating
DeviceMap                 ffffc00019113080
Owning Process            ffffe001d147c840       Image:         audiodg.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      537630         Ticks: 0
Context Switch Count      63             IdealProcessor: 1             
UserTime                  00:00:00.000
KernelTime                00:00:00.015
Win32 Start Address 0x00007fff6978b350
Stack Init ffffd001c70c6dd0 Current ffffd001c70c6520
Base ffffd001c70c7000 Limit ffffd001c70c1000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5
Child-SP          RetAddr           : Args to Child                                                           : Call Site
ffffd001`c70c62a8 fffff800`7a0fa607 : ffffe001`d4aec5c0 ffffe001`cdefd3d8 ffffe001`d4aec5c0 ffffe001`cdefd390 : tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
ffffd001`c70c62b0 fffff800`7a0fb2c3 : 00000000`00000000 ffffe001`d429e580 ffffe001`d4ea47b0 ffffe001`cdefd3d8 : portcls!CPortPinWaveRT::Init+0x2e7
ffffd001`c70c6340 fffff800`7a0fc7f9 : ffffe001`d4aec430 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 : portcls!CPortFilterWaveRT::NewIrpTarget+0x193
ffffd001`c70c63c0 fffff800`7a180552 : 00000000`00000000 ffffe001`d10b8380 ffffe001`d429e580 ffffe001`d4565600 : portcls!xDispatchCreate+0xd9
ffffd001`c70c6450 fffff800`7a109a9a : ffffe001`d10b84d0 ffffe001`d10b8380 00000000`00000000 ffffe001`00000000 : ks!KsDispatchIrp+0x272
ffffd001`c70c6510 fffff800`7bd314b1 : ffffe001`d429e580 ffffd001`c70c6590 ffffe001`d429e800 ffffe001`ce80da70 : portcls!DispatchCreate+0x7a
ffffd001`c70c6540 fffff803`cda1bfa8 : 00000000`00000025 00000000`00000000 00000000`00000000 ffffe001`d429e580 : ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
ffffd001`c70c65a0 fffff803`cda7b306 : 00000000`000002fc ffffe001`d5e0d510 00000000`00000000 ffffe001`d3341bd0 : nt!IopParseDevice+0x7c8
ffffd001`c70c6770 fffff803`cda12916 : 00000000`000002fc ffffd001`c70c68d0 ffffe001`d3341ba0 fffff803`cda7b250 : nt!IopParseFile+0xb6
ffffd001`c70c67d0 fffff803`cda1131c : ffffe001`ceb6c601 ffffd001`c70c69e0 00000000`00000040 ffffe001`cd127dc0 : nt!ObpLookupObjectName+0x776
ffffd001`c70c6970 fffff803`cd9fedb8 : ffff8ab8`00000001 ffffe001`d5e0d510 00000000`00000000 00000000`00000000 : nt!ObOpenObjectByNameEx+0x1ec
ffffd001`c70c6a90 fffff803`cd9fe919 : 000000ee`6d37c6e8 00000004`6d37c500 000000ee`6d37c5f0 000000ee`6d37c5e0 : nt!IopCreateFile+0x3d8
ffffd001`c70c6b40 fffff803`cd752fa3 : fffff6fb`7da05360 fffff6fb`40a6c0a8 fffff681`4d815760 ffff8ab8`92895e23 : nt!NtCreateFile+0x79
ffffd001`c70c6bd0 00007fff`69805b74 : 00007fff`487484e6 0000029b`00000003 00000000`0000012e 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`c70c6c40)
000000ee`6d37c568 00007fff`487484e6 : 0000029b`00000003 00000000`0000012e 00000000`00000000 00000000`00000000 : 0x00007fff`69805b74
000000ee`6d37c570 0000029b`00000003 : 00000000`0000012e 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007fff`487484e6
000000ee`6d37c578 00000000`0000012e : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000080 : 0x0000029b`00000003
000000ee`6d37c580 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000080 00000000`00000000 : 0x12e

Use el comando k para ver la pila de llamadas asociada al subproceso.

0: kd> k
# Child-SP          RetAddr           Call Site
00 ffffd001`c70c62a8 fffff800`7a0fa607 tabletaudiosample!CMiniportWaveRT::NewStream [c:\data1\threshold\audio\endpointscommon\minwavert.cpp @ 562]
01 ffffd001`c70c62b0 fffff800`7a0fb2c3 portcls!CPortPinWaveRT::Init+0x2e7
02 ffffd001`c70c6340 fffff800`7a0fc7f9 portcls!CPortFilterWaveRT::NewIrpTarget+0x193
03 ffffd001`c70c63c0 fffff800`7a180552 portcls!xDispatchCreate+0xd9
04 ffffd001`c70c6450 fffff800`7a109a9a ks!KsDispatchIrp+0x272
05 ffffd001`c70c6510 fffff800`7bd314b1 portcls!DispatchCreate+0x7a
06 ffffd001`c70c6540 fffff803`cda1bfa8 ksthunk!CKernelFilterDevice::DispatchIrp+0xf9
07 ffffd001`c70c65a0 fffff803`cda7b306 nt!IopParseDevice+0x7c8
08 ffffd001`c70c6770 fffff803`cda12916 nt!IopParseFile+0xb6
09 ffffd001`c70c67d0 fffff803`cda1131c nt!ObpLookupObjectName+0x776
0a ffffd001`c70c6970 fffff803`cd9fedb8 nt!ObOpenObjectByNameEx+0x1ec
0b ffffd001`c70c6a90 fffff803`cd9fe919 nt!IopCreateFile+0x3d8
0c ffffd001`c70c6b40 fffff803`cd752fa3 nt!NtCreateFile+0x79
0d ffffd001`c70c6bd0 00007fff`69805b74 nt!KiSystemServiceCopyEnd+0x13
0e 000000ee`6d37c568 00007fff`487484e6 0x00007fff`69805b74
0f 000000ee`6d37c570 0000029b`00000003 0x00007fff`487484e6
10 000000ee`6d37c578 00000000`0000012e 0x0000029b`00000003
11 000000ee`6d37c580 00000000`00000000 0x12e

Escriba g en el depurador para ejecutar el código hacia delante hasta que el clip multimedia haya terminado de reproducirse. A continuación, interrumpa en el depurador pulsando Ctrl - ScrLk (Ctrl-Break). Use el comando !thread para confirmar que ahora está ejecutando un subproceso diferente.

0: kd> !thread
THREAD ffffe001ce80b840  Cid 17e4.01ec  Teb: 00000071fa9b9000 Win32Thread: ffffe001d41690d0 RUNNING on processor 0
Not impersonating
DeviceMap                 ffffc0001974e2c0
Owning Process            ffffe001d1760840       Image:         rundll32.exe
Attached Process          N/A            Image:         N/A
Wait Start TickCount      538040         Ticks: 0
Context Switch Count      3181840        IdealProcessor: 0             
UserTime                  00:00:08.250
KernelTime                00:00:10.796
Win32 Start Address 0x00007ff6d2f24270
Stack Init ffffd001cd16afd0 Current ffffd001cd16a730
Base ffffd001cd16b000 Limit ffffd001cd165000 Call 0
Priority 8 BasePriority 8 UnusualBoost 0 ForegroundBoost 0 IoPriority 2 PagePriority 5

Child-SP          RetAddr           : Args to Child                                                           : Call Site
fffff803`cf373d18 fffff800`7a202852 : fffff803`cf373e60 00000000`00000001 ffffe001`cf4ed330 00000000`0000ffff : nt!DbgBreakPointWithStatus
fffff803`cf373d20 fffff803`cd6742c6 : ffffe001`cf4ed2f0 fffff803`cf373e60 00000000`00000001 00000000`0004e4b8 : kdnic!TXSendCompleteDpc+0x142
fffff803`cf373d60 fffff803`cd74d495 : 00000000`00000000 fffff803`cd923180 fffff803`cde1f4b0 fffff901`40669010 : nt!KiRetireDpcList+0x5f6
fffff803`cf373fb0 fffff803`cd74d2a0 : 00000000`00000090 0000000e`0000006a 00000000`00000092 00000000`00000000 : nt!KxRetireDpcList+0x5 (TrapFrame @ fffff803`cf373e70)
ffffd001`cd16a6c0 fffff803`cd74bd75 : 00000000`00000000 fffff803`cd74a031 00000000`00000000 00000000`00000000 : nt!KiDispatchInterruptContinue
ffffd001`cd16a6f0 fffff803`cd74a031 : 00000000`00000000 00000000`00000000 ffffe001`cff4d2a0 fffff803`cd67738e : nt!KiDpcInterruptBypass+0x25
ffffd001`cd16a700 fffff960`50cdb5a4 : fffff901`400006d0 00000000`00000001 fffff901`40000d60 ffffd001`cd16a9f0 : nt!KiInterruptDispatchNoLockNoEtw+0xb1 (TrapFrame @ ffffd001`cd16a700)
ffffd001`cd16a890 fffff960`50c66b2f : 00000000`00000000 fffff901`40669010 fffff901`42358580 fffff901`40000d60 : win32kfull!Win32FreePoolImpl+0x34
ffffd001`cd16a8c0 fffff960`50c68cd6 : 00000000`00000000 ffffd001`cd16a9f0 fffff901`400006d0 fffff901`400c0460 : win32kfull!EXLATEOBJ::vAltUnlock+0x1f
ffffd001`cd16a8f0 fffff803`cd752fa3 : 00000000`00000000 00000000`00000000 ffffe001`ce80b840 00000000`00000000 : win32kfull!NtGdiAlphaBlend+0x1d16
ffffd001`cd16add0 00007fff`674c1494 : 00007fff`674b1e97 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 : nt!KiSystemServiceCopyEnd+0x13 (TrapFrame @ ffffd001`cd16ae40)
00000071`fa74c9a8 00007fff`674b1e97 : 0000a7c6`daee0559 00000000`00000001 0000020b`741f3c50 00000000`00ffffff : 0x00007fff`674c1494
00000071`fa74c9b0 0000a7c6`daee0559 : 00000000`00000001 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 : 0x00007fff`674b1e97
00000071`fa74c9b8 00000000`00000001 : 0000020b`741f3c50 00000000`00ffffff 00000000`00000030 00000000`01010bff : 0x0000a7c6`daee0559
00000071`fa74c9c0 0000020b`741f3c50 : 00000000`00ffffff 00000000`00000030 00000000`01010bff 00000000`00000000 : 0x1
00000071`fa74c9c8 00000000`00ffffff : 00000000`00000030 00000000`01010bff 00000000`00000000 00000000`000000c0 : 0x0000020b`741f3c50
00000071`fa74c9d0 00000000`00000030 : 00000000`01010bff 00000000`00000000 00000000`000000c0 00000000`00000030 : 0xffffff
00000071`fa74c9d8 00000000`01010bff : 00000000`00000000 00000000`000000c0 00000000`00000030 00000071`00000030 : 0x30
00000071`fa74c9e0 00000000`00000000 : 00000000`000000c0 00000000`00000030 00000071`00000030 00000071`01ff8000 : 0x1010bff

El nombre de la imagen es rundll32.exe, que realmente no es el nombre de la imagen asociado con la reproducción del clip multimedia.

Nota Para establecer el subproceso actual, escriba .thread <número de subproceso>.

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

Subprocesos y procesos

Cambio de contextos

Sección 11: IRQL, registros y desensamblaje

Visualización del IRQL guardado

En la sección 11, visualizará el IRQL y el contenido de los registros.

<- 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 de IRQL que los subprocesos pueden aumentar o reducir. Las interrupciones que se producen en la configuración IRQL del procesador o por debajo de esta 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 la interrupción del depurador. Cuando el equipo de destino irrumpe en el depurador, el IRQL cambia, pero se guarda el IRQL que estaba vigente justo antes de la irrupción del depurador y se muestra mediante !irql.

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

<Visualización de los registros y desensamblaje

Visualización de los registros

Puede visualizar el contenido de los registros del 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 Ver>Registros.

Captura de pantalla de la ventana registros de WinDbg que muestra aproximadamente 12 registros.

La visualización del 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, consulte r (Registros).

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

Desensamblado

Puede desensamblar el código que está en ejecución para ver el código del lenguaje de ensamblado que se ejecuta seleccionando Ver>Desensamblado.

Captura de pantalla de la ventana de desensamblado de WinDbg que muestra el código del lenguaje de ensamblado.

Para obtener más información sobre el desensamblado del lenguaje de ensamblado, consulte Desensamblado anotado x86 y Desensamblado anotado x64.

Sección 12: Trabajo con memoria

En la sección 12, usará comandos del depurador para mostrar el contenido de la memoria.

Visualización de memoria

Es posible que tenga que examinar la memoria para identificar un problema o inspeccionar variables, punteros, etc. Puede mostrar memoria escribiendo uno de los siguientes comandos d* <dirección>.

db

Muestra datos en valores de bytes y caracteres ASCII.

dd

Muestra los datos como palabras de doble ancho (4 bytes).

du

Muestra los datos como caracteres Unicode.

dw

Muestra datos como valores de palabra (2 bytes) y caracteres ASCII.

Nota Si intenta visualizar una dirección no válida, su contenido se muestra como signos de interrogación (?).

Como alternativa, puede ver la memoria seleccionando Ver>Memoria. Use la lista desplegable Formato de visualización para cambiar cómo se muestra la memoria.

Captura de pantalla de la ventana de visualización de memoria de WinDbg con varias opciones de formato de visualización.

  1. Para ver los datos asociados al control de volumen, establezca un punto de interrupción para que se active en la rutina PropertyHandlerAudioEngineVolumeLevel mediante el comando bm. Antes de establecer el nuevo punto de interrupción, borraremos todos los puntos de interrupción anteriores mediante bc *.

    kd> bc *
    
  2. Establezca un punto de interrupción para activarse en la rutina PropertyHandlerAudioEngineVolumeLevel mediante el comando bm.

    kd> bm tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume
      1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"
    
  3. Enumere los puntos de interrupción para confirmar que el punto de interrupción está establecido correctamente.

    kd> bl
      1: fffff80f`02c3a4b0 @!"tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume"
    
  4. Use el comando g para reiniciar la ejecución del código.

    En el sistema de destino, ajuste el volumen de la bandeja del sistema. Esto hará que se active el punto de interrupción.

    Breakpoint 1 hit
    tabletaudiosample!CMiniportWaveRT::SetDeviceChannelVolume:
    fffff80f`02c3a4b0 44894c2420      mov     dword ptr [rsp+20h],r9d
    
  5. Use la opción de menú Ver>Local para visualizar variables locales. Anote el valor actual de la variable IVolume.

  6. Puede visualizar el tipo de datos y el valor actual de la variable IVolume en el código de ejemplo escribiendo el comando dt y el nombre de la variable.

    kd> dt lVolume
    Local var @ 0xa011ea50 Type long
    0n-6291456
    
  7. Se alcanza el punto de interrupción al entrar en SetDeviceChannelVolume.

    STDMETHODIMP_(NTSTATUS) CMiniportWaveRT::SetDeviceChannelVolume(_In_  ULONG _ulNodeId, _In_ UINT32 _uiChannel, _In_  LONG  _Volume)
    {
        NTSTATUS ntStatus = STATUS_INVALID_DEVICE_REQUEST;
    
        PAGED_CODE ();
    
        DPF_ENTER(("[CMiniportWaveRT::SetEndpointChannelVolume]"));
        IF_TRUE_ACTION_JUMP(_ulNodeId != KSNODE_WAVE_AUDIO_ENGINE, ntStatus = STATUS_INVALID_DEVICE_REQUEST, Exit);
    
        // Snap the volume level to our range of steppings.
        LONG lVolume = VOLUME_NORMALIZE_IN_RANGE(_Volume); 
    
        ntStatus = SetChannelVolume(_uiChannel, lVolume);
    Exit:
        return ntStatus;
    }
    
  8. Intente visualizar el valor en la ubicación de memoria de IVolume mediante el comando dt (Tipo de visualización).

    kd> dt dt lVolume
    Local var @ 0xffffb780b7eee664 Type long
    0n0
    

    Dado que todavía hay que definir la variable, no contiene información.

  9. Pulse F10 para ir a la última línea de código de SetDeviceChannelVolume.

        return ntStatus;
    
  10. Visualice el valor en la ubicación de memoria de IVolume mediante el comando dt (Tipo de visualización).

    kd> dt lVolume
    Local var @ 0xffffb780b7eee664 Type long
    0n-6291456
    

    Ahora que la variable está activa, se muestra un valor de 6291456 en este ejemplo.

  11. También puede visualizar la ubicación de memoria de IVolume mediante el comando ? (Evaluar expresión).

    kd> ? lVolume
    Evaluate expression: -79711507126684 = ffffb780`b7eee664
    
  12. La dirección mostrada, ffffb780'b7eee664 es la dirección de la variable lVolume. Use el comando dd para visualizar el contenido de la memoria en esa ubicación.

    kd>  dd ffffb780`b7eee664
    ffffb780`b7eee664  ffa00000 00000018 00000000 c52d7008
    ffffb780`b7eee674  ffffc98e e0495756 fffff80e c52d7008
    ffffb780`b7eee684  ffffc98e 00000000 fffff80e 00000000
    ffffb780`b7eee694  ffffc98e ffa00000 ffffb780 b7eee710
    ffffb780`b7eee6a4  ffffb780 00000000 00000000 c7477260
    ffffb780`b7eee6b4  ffffc98e b7eee7a0 ffffb780 b7eee6f0
    ffffb780`b7eee6c4  ffffb780 e04959ca fffff80e 00000000
    ffffb780`b7eee6d4  00000000 00000028 00000000 00000002
    
  13. Puede visualizar los cuatro primeros bytes de una dirección especificando el parámetro de intervalo L4.

    kd> dd ffffb780`b7eee664 l4
    ffffb780`b7eee664  ffa00000 00000018 00000000 c52d7008
    
  14. Para ver los distintos tipos de salida de memoria mostrados, escriba los comandos du, da y db.

    kd> du ffffb780`b7eee664 
    ffffb780`b7eee664  ""
    
    kd> a ffffb780`b7eee664 
    ffffb780`b7eee664  ""
    
    kd> db 0xffffae015ff97664 
    ffffae01`5ff97664  00 80 bc ff 18 00 00 00-00 00 00 00 08 50 e0 51  .............P.Q
    ffffae01`5ff97674  00 c0 ff ff 56 57 da 56-0e f8 ff ff 08 50 e0 51  ....VW.V.....P.Q
    ffffae01`5ff97684  00 c0 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00  ................
    ffffae01`5ff97694  00 c0 ff ff aa 80 bc ff-01 ae ff ff 10 77 f9 5f  .............w._
    ffffae01`5ff976a4  01 ae ff ff 40 00 00 00-00 e6 ff ff 10 dc 30 55  ....@.........0U
    ffffae01`5ff976b4  00 c0 ff ff a0 77 f9 5f-01 ae ff ff f0 76 f9 5f  .....w._.....v._
    ffffae01`5ff976c4  01 ae ff ff ca 59 da 56-0e f8 ff ff 00 00 00 00  .....Y.V........
    ffffae01`5ff976d4  00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00  ....(...........
    

    Use la opción df float para visualizar datos, como números de punto flotante de precisión sencilla (4 bytes).

    df ffffb780`b7eee664 
    ffffb780`b7eee664          -1.#QNAN   3.3631163e-044                0        -2775.002
    ffffb780`b7eee674          -1.#QNAN  -5.8032637e+019         -1.#QNAN        -2775.002
    ffffb780`b7eee684          -1.#QNAN                0         -1.#QNAN                0
    ffffb780`b7eee694          -1.#QNAN         -1.#QNAN         -1.#QNAN  -2.8479408e-005
    

Escritura en la memoria

De forma similar a los comandos que se usan para leer memoria, puede usar los comandos e* para cambiar el contenido de la memoria.

Comando Descripción

c/u

Cadena ASCII (no terminada en NULL)

eu

Cadena Unicode (no terminada en NULL)

Nuevo

Valores de palabras (2 bytes)

eza

Cadena ASCII terminada en NULL

ezu

Cadena Unicode terminada en NULL

eb

Valores de byte

ed

Valores de palabra doble (4 bytes)

El ejemplo siguiente muestra cómo sobrescribir la memoria.

  1. En primer lugar, busque la dirección de lVolume que se usa en el código de ejemplo.

    kd> ? lVolume
    Evaluate expression: -79711507126684 = ffffb780`b7eee664
    
  2. Sobrescriba esa dirección de memoria con nuevos caracteres mediante el comando eb.

    kd> eb 0xffffb780`b7eee664 11 11 11 11 11
    
  3. Visualice la ubicación de memoria para confirmar que los caracteres se han sobrescrito escribiendo el comando db.

    kd> db 0xffffb780`b7eee664
    ffffb780`b7eee664  11 11 11 11 11 00 00 00-00 00 00 00 08 70 2d c5  .............p-.
    ffffb780`b7eee674  8e c9 ff ff 56 57 49 e0-0e f8 ff ff 08 70 2d c5  ....VWI......p-.
    ffffb780`b7eee684  8e c9 ff ff 00 00 00 00-0e f8 ff ff 00 00 00 00  ................
    ffffb780`b7eee694  8e c9 ff ff 00 00 a0 ff-80 b7 ff ff 10 e7 ee b7  ................
    ffffb780`b7eee6a4  80 b7 ff ff 00 00 00 00-00 00 00 00 60 72 47 c7  ............`rG.
    ffffb780`b7eee6b4  8e c9 ff ff a0 e7 ee b7-80 b7 ff ff f0 e6 ee b7  ................
    ffffb780`b7eee6c4  80 b7 ff ff ca 59 49 e0-0e f8 ff ff 00 00 00 00  .....YI.........
    ffffb780`b7eee6d4  00 00 00 00 28 00 00 00-00 00 00 00 02 00 00 00  ....(...........
    

Como alternativa, puede modificar el contenido de la memoria en una ventana de inspección o variables locales. En la ventana inspección, puede ver variables que están fuera del contexto del marco actual. Modificarlas no es relevante si no están en el contexto.

Sección 13: Finalización de la sesión de WinDbg

<-En el sistema host

Si desea salir del depurador conectado, pero quiere trabajar en el destino, borre los puntos de interrupción mediante bc *, de modo que el equipo de destino no intente conectarse al depurador del equipo host. A continuación, use el comando g para permitir que el equipo de destino vuelva a ejecutarse.

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

0: kd> qd

Para obtener más información, consulte Finalización de una sesión de depuración en WinDbg (clásico) en la documentación de referencia de depuración.

Sección 14: Recursos de depuración de Windows

Hay información adicional disponible sobre la depuración de Windows. Tenga en cuenta que en algunas de estas referencias se utilizarán versiones anteriores de Windows, como Windows Vista, en sus ejemplos, pero los conceptos tratados son aplicables a la mayoría de las versiones de Windows.

Libros

  • Advanced Windows Debugging de Mario Hewardt y Daniel Pravat

  • Inside Windows Debugging: A Practical Guide to Debugging and Tracing Strategies in Windows® de Tarik Soulami

  • Windows Internals de Pavel Yosifovich, Alex Ionescu, Mark Russinovich y David Solomon

Vídeo

The Defrag Tools Show WinDbg Episodes 13-29: </shows/defrag-tools/>

Proveedores de formación:

OSR - https://www.osr.com/

Consulte también

Introducción a la depuración de Windows