Uso de la extensión !analyze
El primer paso para depurar un equipo o aplicación de destino bloqueado es usar el comando !analyze extension. Esta extensión realiza una gran cantidad de análisis automatizado. Los resultados de este análisis se muestran en la ventana Comando del depurador.
Debe usar la opción -v para obtener una visualización completa de los datos. Para obtener más información sobre otras opciones, consulte la página de referencia !analyze .
Un ejemplo de !analyze -v en modo de usuario
En este ejemplo, el depurador está asociado a una aplicación en modo de usuario que ha encontrado una excepción.
0:000> !analyze -v
*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************
Debugger SolutionDb Connection::Open failed 80004005
Si está conectado a Internet, el depurador intenta acceder a una base de datos de soluciones de bloqueo mantenidas por Microsoft. En este caso, se muestra un mensaje de error, que indica que la máquina no pudo acceder a Internet o que el sitio web no funcionaba.
FAULTING_IP:
ntdll!PropertyLengthAsVariant+73
77f97704 cc int 3
El campo FAULTING_IP muestra el puntero de instrucción en el momento del error.
EXCEPTION_RECORD: ffffffff -- (.exr ffffffffffffffff)
ExceptionAddress: 77f97704 (ntdll!PropertyLengthAsVariant+0x00000073)
ExceptionCode: 80000003 (Break instruction exception)
ExceptionFlags: 00000000
NumberParameters: 3
Parameter[0]: 00000000
Parameter[1]: 00010101
Parameter[2]: ffffffff
El campo EXCEPTION_RECORD muestra el registro de excepción de este bloqueo. Esta información también se puede ver mediante el comando .exr (Mostrar registro de excepciones).
BUGCHECK_STR: 80000003
El campo BUGCHECK_STR muestra el código de excepción. El nombre es un nombre incorrecto: el término comprobación de errores significa realmente un bloqueo en modo kernel. En la depuración en modo de usuario, se mostrará el código de excepción, en este caso, 0x80000003.
DEFAULT_BUCKET_ID: APPLICATION_FAULT
El campo DEFAULT_BUCKET_ID muestra la categoría general de errores a la que pertenece este error.
PROCESS_NAME: MyApp.exe
El campo PROCESS_NAME especifica el nombre del proceso que generó la excepción.
LAST_CONTROL_TRANSFER: from 01050963 to 77f97704
El campo LAST_CONTROL_TRANSFER muestra la última llamada en la pila. En este caso, el código de la dirección 0x01050963 llamó a una función en 0x77F97704. Puede usar estas direcciones con el comando ln (Enumerar símbolos más cercanos) para determinar en qué módulos y funciones residen estas direcciones.
STACK_TEXT:
0006b9dc 01050963 00000000 0006ba04 000603fd ntdll!PropertyLengthAsVariant+0x73
0006b9f0 010509af 00000002 0006ba04 77e1a449 MyApp!FatalErrorBox+0x55 [D:\source_files\MyApp\util.c @ 541]
0006da04 01029f4e 01069850 0000034f 01069828 MyApp!ShowAssert+0x47 [D:\source_files\MyApp\util.c @ 579]
0006db6c 010590c3 000e01ea 0006fee4 0006feec MyApp!SelectColor+0x103 [D:\source_files\MyApp\colors.c @ 849]
0006fe04 77e11d0a 000e01ea 00000111 0000413c MyApp!MainWndProc+0x1322 [D:\source_files\MyApp\MyApp.c @ 1031]
0006fe24 77e11bc8 01057da1 000e01ea 00000111 USER32!UserCallWinProc+0x18
0006feb0 77e172b4 0006fee4 00000001 010518bf USER32!DispatchMessageWorker+0x2d0
0006febc 010518bf 0006fee4 00000000 01057c5d USER32!DispatchMessageA+0xb
0006fec8 01057c5d 0006fee4 77f82b95 77f83920 MyApp!ProcessQCQPMessage+0x3b [D:\source_files\MyApp\util.c @ 2212]
0006ff70 01062cbf 00000001 00683ed8 00682b88 MyApp!main+0x1e6 [D:\source_files\MyApp\MyApp.c @ 263]
0006ffc0 77e9ca90 77f82b95 77f83920 7ffdf000 MyApp!mainCRTStartup+0xff [D:\source_files\MyApp\crtexe.c @ 338]
0006fff0 00000000 01062bc0 00000000 000000c8 KERNEL32!BaseProcessStart+0x3d
El campo STACK_TEXT muestra un seguimiento de pila del componente de error.
FOLLOWUP_IP:
MyApp!FatalErrorBox+55
01050963 5e pop esi
FOLLOWUP_NAME: dbg
SYMBOL_NAME: MyApp!FatalErrorBox+55
MODULE_NAME: MyApp
IMAGE_NAME: MyApp.exe
DEBUG_FLR_IMAGE_TIMESTAMP: 383490a9
Cuando !analyze determina la instrucción que probablemente ha causado el error, la muestra en el campo FOLLOWUP_IP. Los campos SYMBOL_NAME, MODULE_NAME, IMAGE_NAME y DEBUG_FLR_IMAGE_TIMESTAMP muestran el símbolo, el módulo, el nombre de imagen y la marca de tiempo de imagen correspondientes a esta instrucción.
STACK_COMMAND: .ecxr ; kb
El campo STACK_COMMAND muestra el comando que se usó para obtener el STACK_TEXT. Puede usar este comando para repetir esta presentación de seguimiento de pila o modificarla para obtener información relacionada de la pila.
BUCKET_ID: 80000003_MyApp!FatalErrorBox+55
El campo BUCKET_ID muestra la categoría específica de errores a los que pertenece el error actual. Esta categoría ayuda al depurador a determinar qué otra información se va a mostrar en la salida del análisis.
Followup: dbg
---------
Para obtener información sobre los campos FOLLOWUP_NAME y Seguimiento, vea El campo seguimiento y el archivo de triage.ini.
Hay una variedad de otros campos que pueden aparecer:
Si el control se transfirió a una dirección no válida, el campo FAULTING_IP contendrá esta dirección no válida. En lugar del campo FOLLOWUP_IP, el campo FAILED_INSTRUCTION_ADDRESS mostrará el código desensambblado de esta dirección, aunque este desensamblaje probablemente no tendrá sentido. En esta situación, los campos SYMBOL_NAME, MODULE_NAME, IMAGE_NAME y DEBUG_FLR_IMAGE_TIMESTAMP harán referencia al autor de la llamada de esta instrucción.
Si el procesador falla, es posible que vea los campos SINGLE_BIT_ERROR, TWO_BIT_ERROR o POSSIBLE_INVALID_CONTROL_TRANSFER.
Si parece que se ha producido daños en la memoria, el campo CHKIMG_EXTENSION especificará el comando de extensión !chkimg que se debe usar para investigar.
Ejemplo de !analyze -v en modo kernel
En este ejemplo, el depurador está asociado a un equipo que acaba de bloquearse.
kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pagable (or completely invalid) address at an
interrupt request level (IRQL) that is too high. This is usually
caused by drivers using improper addresses.
If kernel debugger is available get stack backtrace.
El primer elemento de la pantalla muestra el código de comprobación de errores e información sobre este tipo de comprobación de errores. Es posible que parte del texto mostrado no se aplique a esta instancia específica. Para obtener más información sobre cada comprobación de errores, consulte la sección Referencia de código de comprobación de errores.
Arguments:
Arg1: 00000004, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000001, value 0 = read operation, 1 = write operation
Arg4: f832035c, address which referenced memory
Los parámetros de comprobación de errores se muestran a continuación. Cada una de ellas va seguida de una descripción. Por ejemplo, el tercer parámetro es 1 y el comentario siguiente explica que esto indica que se produjo un error en una operación de escritura.
## Debugging Details:
WRITE_ADDRESS: 00000004 Nonpaged pool
CURRENT_IRQL: 2
Los siguientes campos varían en función de la naturaleza del bloqueo. En este caso, vemos campos WRITE_ADDRESS y CURRENT_IRQL. Simplemente se vuelve a indicar la información que se muestra en los parámetros de comprobación de errores. Al comparar la instrucción "Grupo no paginado" con el texto de comprobación de errores que lee "se intentó acceder a una dirección pagable (o completamente no válida), podemos ver que la dirección no era válida. La dirección no válida en este caso se 0x00000004.
FAULTING_IP:
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204 mov [edx+0x4],eax
El campo FAULTING_IP muestra el puntero de instrucción en el momento del error.
DEFAULT_BUCKET_ID: DRIVER_FAULT
El campo DEFAULT_BUCKET_ID muestra la categoría general de errores a la que pertenece este error.
BUGCHECK_STR: 0xD1
El campo BUGCHECK_STR muestra el código de comprobación de errores, que ya hemos visto. En algunos casos se anexa información adicional de evaluación de prioridades.
TRAP_FRAME: f8950dfc -- (.trap fffffffff8950dfc)
.trap fffffffff8950dfc
ErrCode = 00000002
eax=81cc86dc ebx=81cc80e0 ecx=81e55688 edx=00000000 esi=81cc8028 edi=8052cf3c
eip=f832035c esp=f8950e70 ebp=f8950e90 iopl=0 nv up ei pl nz ac po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010216
USBPORT!USBPORT_BadRequestFlush+7c:
f832035c 894204 mov [edx+0x4],eax ds:0023:00000004=????????
.trap
Resetting default context
El campo TRAP_FRAME muestra el marco de captura de este bloqueo. Esta información también se puede ver mediante el comando .trap (Display Trap Frame).
LAST_CONTROL_TRANSFER: from f83206e0 to f832035c
El campo LAST_CONTROL_TRANSFER muestra la última llamada en la pila. En este caso, el código de la dirección 0xF83206E0 llamó a una función en 0xF832035C. Puede usar el comando ln (Enumerar símbolos más cercanos) para determinar en qué módulo y función residen estas direcciones.
STACK_TEXT:
f8950e90 f83206e0 024c7262 00000000 f8950edc USBPORT!USBPORT_BadRequestFlush+0x7c
f8950eb0 804f5561 81cc8644 81cc8028 6d9a2f30 USBPORT!USBPORT_DM_TimerDpc+0x10c
f8950fb4 804f5644 6e4be98e 00000000 ffdff000 nt!KiTimerListExpire+0xf3
f8950fe0 8052c47c 8053cf20 00000000 00002e42 nt!KiTimerExpiration+0xb0
f8950ff4 8052c16a efdefd44 00000000 00000000 nt!KiRetireDpcList+0x31
El campo STACK_TEXT muestra un seguimiento de pila del componente de error.
FOLLOWUP_IP:
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204 mov [edx+0x4],eax
El campo FOLLOWUP_IP muestra el desensamblaje de la instrucción que probablemente ha causado el error.
FOLLOWUP_NAME: usbtri
SYMBOL_NAME: USBPORT!USBPORT_BadRequestFlush+7c
MODULE_NAME: USBPORT
IMAGE_NAME: USBPORT.SYS
DEBUG_FLR_IMAGE_TIMESTAMP: 3b7d868b
Los campos SYMBOL_NAME, MODULE_NAME, IMAGE_NAME y DBG_FLR_IMAGE_TIMESTAMP muestran la marca de tiempo de símbolo, módulo, imagen e imagen correspondiente a esta instrucción (si es válida) o al autor de la llamada de esta instrucción (si no lo es).
STACK_COMMAND: .trap fffffffff8950dfc ; kb
El campo STACK_COMMAND muestra el comando que se usó para obtener el STACK_TEXT. Puede usar este comando para repetir esta presentación de seguimiento de pila o modificarla para obtener información relacionada de la pila.
BUCKET_ID: 0xD1_W_USBPORT!USBPORT_BadRequestFlush+7c
El campo BUCKET_ID muestra la categoría específica de errores a los que pertenece el error actual. Esta categoría ayuda al depurador a determinar qué otra información se va a mostrar en la salida del análisis.
Para obtener información sobre los campos FOLLOWUP_NAME y Seguimiento, vea El campo seguimiento y el archivo de triage.ini.
Hay una variedad de otros campos que pueden aparecer:
Si el control se transfirió a una dirección no válida, el campo FAULTING_IP contendrá esta dirección no válida. En lugar del campo FOLLOWUP_IP, el campo FAILED_INSTRUCTION_ADDRESS mostrará el código desensambblado de esta dirección, aunque este desensamblaje probablemente no tendrá sentido. En esta situación, los campos SYMBOL_NAME, MODULE_NAME, IMAGE_NAME y DBG_FLR_IMAGE_TIMESTAMP harán referencia al autor de la llamada de esta instrucción.
Si el procesador falla, es posible que vea los campos SINGLE_BIT_ERROR, TWO_BIT_ERROR o POSSIBLE_INVALID_CONTROL_TRANSFER.
Si parece que se ha producido daños en la memoria, el campo CHKIMG_EXTENSION especificará el comando de extensión !chkimg que se debe usar para investigar.
Si se produjo una comprobación de errores en el código de un controlador de dispositivo, su nombre se puede mostrar en el campo BUGCHECKING_DRIVER.
Campo seguimiento y archivo de triage.ini
En el modo de usuario y en el modo kernel, el campo Seguimiento de la pantalla mostrará información sobre el propietario del marco de pila actual, si se puede determinar. Esta información se determina de la siguiente manera:
Cuando se usa la extensión !analyze , el depurador comienza con el marco superior de la pila y determina si es responsable del error. Si no es así, se analiza el siguiente fotograma. Este proceso continúa hasta que se encuentra un marco que podría estar en error.
El depurador intenta determinar el propietario del módulo y la función en este marco. Si se puede determinar el propietario, este marco se considera defectuoso.
Si no se puede determinar el propietario, el depurador pasa al siguiente marco de pila, etc., hasta que se determine el propietario (o la pila se examine completamente). El primer marco cuyo propietario se encuentra en esta búsqueda se considera defectuoso. Si la pila se agota sin que se encuentre información, no se muestra ningún campo Seguimiento.
El propietario del marco en error se muestra en el campo Seguimiento. Si se usa !analyze -v , los campos FOLLOWUP_IP, SYMBOL_NAME, MODULE_NAME, IMAGE_NAME y DBG_FLR_IMAGE_TIMESTAMP harán referencia a este marco.
Para que el campo Seguimiento muestre información útil, primero debe crear un archivo triage.ini que contenga los nombres del módulo y los propietarios de funciones.
El archivo triage.ini debe identificar los propietarios de todos los módulos que podrían tener errores. Puede usar una cadena informativa en lugar de un propietario real, pero esta cadena no puede contener espacios. Si está seguro de que un módulo no fallará, puede omitir este módulo o indicar que se debe omitir. También es posible especificar propietarios de funciones individuales, lo que proporciona al proceso de evaluación de prioridades una granularidad incluso más fina.
Para obtener más información sobre la sintaxis del archivo triage.ini, consulte Especificación de los propietarios de módulos y funciones.
Técnicas de !analyze adicionales
Si no se ha producido ningún bloqueo o excepción, !analyze mostrará un texto muy corto que proporciona el estado actual del destino. En determinadas situaciones, es posible que desee forzar que el análisis tenga lugar como si se hubiera producido un bloqueo. Use !analyze -f para realizar esta tarea.
En modo de usuario, si se ha producido una excepción, pero cree que el problema subyacente es un subproceso bloqueado, establezca el subproceso actual en el subproceso que está investigando y, a continuación, use !analyze -hang. Esta extensión realizará un análisis de pila de subprocesos para determinar si algún subproceso está bloqueando otros subprocesos.
En el modo kernel, si se ha producido una comprobación de errores, pero cree que el problema subyacente es un subproceso bloqueado, use !analyze -hang. Esta extensión investigará los bloqueos mantenidos por el sistema y examinará la cadena de colaS DPC y mostrará cualquier indicación de subprocesos bloqueados. Si cree que el problema es un interbloqueo de recursos en modo kernel, use la extensión !deadlock junto con la opción Detección de interbloqueo de Comprobador de controladores.
También puede omitir automáticamente los problemas conocidos. Para ello, primero debe crear un archivo XML que contenga una lista con formato de problemas conocidos. Use la extensión !analyze -c -load KnownIssuesFile para cargar este archivo. A continuación, cuando se produzca una excepción o interrupción, use la extensión !analyze -c . Si la excepción coincide con uno de los problemas conocidos, el destino reanudará la ejecución. Si el destino no se reanuda la ejecución, puede usar !analyze -v para determinar la causa del problema.
Consulte también
Consulte estos temas para obtener información adicional.
Bug Check Code Reference (Referencia de código de comprobación de errores)
Análisis de volcado de memoria mediante los depuradores de Windows (WinDbg)