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:
- Sección 1: Conexión a una sesión WinDbg en modo kernel
- Sección 2: Comandos y técnicas de depuración en modo kernel
- Sección 3: Descarga y compilación del controlador de audio Sysvad
- Sección 4: Instalación del controlador de audio Sysvad en el sistema de destino
- Sección 5: Uso de WinDbg para mostrar información sobre el controlador
- Sección 6: Visualización de información del árbol de dispositivos Plug and Play
- Sección 7: Trabajo con puntos de interrupción y código fuente
- Sección 8: Consulta de variables
- Sección 9: Visualización de pilas de llamadas
- Sección 10: Visualización de procesos y subprocesos
- Sección 11: IRQL, registros y desensamblaje
- Sección 12: Trabajo con memoria
- Sección 13: Finalización de la sesión de WinDbg
- Sección 14: Recursos de depuración de Windows
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.
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
- 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 . . . . . . . . . :
Registre la dirección IP del sistema host: ______________________________________
Registre el nombre de host del sistema host: ______________________________________
-> En el sistema de destino
- 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.
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.
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
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
- 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.
- 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.
<- En el sistema host
- 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
- 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.
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.
- 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.
- 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.
- 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.
Visualización de la versión de Windows en el sistema de destino
- 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
- 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.
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
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
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.
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.
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.
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.
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.
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. 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.
Habilitación de controladores firmados de prueba
Para habilitar la capacidad de ejecutar controladores firmados de prueba:
Abra Configuración de Windows.
En Actualización y seguridad, seleccione Recuperación.
En Inicio avanzado, seleccione Reiniciar ahora.
Cuando se reinicie el equipo, seleccione Solución de problemas.
A continuación, seleccione Opciones avanzadas, Configuración de inicio y, después, Reiniciar.
Seleccione Deshabilitar aplicación de firmas del controlador pulsando la tecla F7.
El equipo comenzará con los nuevos valores en su lugar.
-> 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.
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
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.
Después de instalar correctamente el controlador de ejemplo, ya está listo para probarlo.
Prueba del controlador de audio Sysvad
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.
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.
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
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
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
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
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
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.
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.
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).
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
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
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… ...
Use Ctrl+F para buscar en la salida que se genera el nombre del controlador de dispositivo, sysvad.
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.
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)
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.
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
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.
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). |
Use la interfaz de usuario de WinDbg para confirmar que Depuración>Modo de origen está habilitado en la sesión actual de WinDbg.
Añada la ubicación de su código local a la ruta de origen escribiendo el siguiente comando.
.sympath+ C:\WDK_Samples\Sysvad
Añada la ubicación del símbolo local a la ruta de símbolos escribiendo el siguiente comando.
.sympath+ C:\WDK_Samples\Sysvad
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
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.
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
Reinicie la ejecución de código en el sistema de destino escribiendo el comando g.
->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ú.
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ú.
<- 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
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.
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.
<- 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.
Borre los puntos de interrupción anteriores mediante bc *.
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"
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
Reinicie la ejecución de código en el sistema de destino escribiendo el comando g.
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.
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
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
Pulse F10 para recorrer el código paso a paso.
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.
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
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.
Borre los puntos de interrupción anteriores y asegúrese de que el depurador está conectado al equipo de destino.
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.
Use el comando dv para examinar las variables de configuración regional asociadas a tabletaudiosample! CMiniportWaveRT::New*.
kd> dv tabletaudiosample!CMiniportWaveRT::New*
Borrado de los puntos de interrupción anteriores
bc *
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"
Reinicie la ejecución de código en el sistema de destino escribiendo el comando g.
-> 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.
<- 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. --*/ { ...
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
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
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
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
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
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.
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); } ...
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.
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:
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.
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.
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.
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 *
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"
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"
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
Use la opción de menú Ver>Local para visualizar variables locales. Anote el valor actual de la variable IVolume.
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
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; }
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.
Pulse F10 para ir a la última línea de código de SetDeviceChannelVolume.
return ntStatus;
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.
También puede visualizar la ubicación de memoria de IVolume mediante el comando ? (Evaluar expresión).
kd> ? lVolume Evaluate expression: -79711507126684 = ffffb780`b7eee664
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
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
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.
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
Sobrescriba esa dirección de memoria con nuevos caracteres mediante el comando eb.
kd> eb 0xffffb780`b7eee664 11 11 11 11 11
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/