.jdinfo (Usar JIT_DEBUG_INFO)

El comando .jdinfo usa una estructura JIT_DEBUG_INFO como origen de la excepción y el contexto para la depuración Just-In-Time (JIT). La dirección a la estructura se pasa al comando .jdinfo mediante el parámetro %p especificado en la entrada del Registro AeDebug.

Para obtener más información sobre las claves del Registro usadas, consulte Habilitación de la depuración postmortem. Para obtener más información sobre los contextos de registro, vea Cambio de contextos.

.jdinfo Address 

Parámetros

Dirección
Especifica la dirección de la estructura JIT_DEBUG_INFO. La dirección a la estructura se pasa al comando .jdinfo mediante el parámetro %p especificado en la entrada del Registro AeDebug.

Entorno

Modos

Modo de usuario

Destinos

En tiempo real, volcado de errores

Platforms

All

Ejemplo

En este ejemplo se muestra cómo se puede configurar la entrada del Registro AeDebug para usar WinDbg como depurador JIT.

Debugger = "Path\WinDbg.EXE -p %ld -e %ld -c ".jdinfo 0x%p"

A continuación, cuando se produce un bloqueo, se invoca el depurador JIT configurado y el parámetro %p se usa para pasar la dirección de la estructura de JIT_DEBUG_INFO al comando .jdinfo que se ejecuta después de iniciar el depurador.

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

*** wait with pending attach
Executable search path is: 
...
ModLoad: 00000000`68a20000 00000000`68ac3000   C:\WINDOWS\WinSxS\amd64_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.9247_none_08e394a1a83e212f\MSVCR90.dll
(153c.5d0): Break instruction exception - code 80000003 (first chance)
Processing initial command '.jdinfo 0x00000000003E0000'
ntdll!DbgBreakPoint:
00007ffc`81a986a0 cc              int     3
0:003> .jdinfo 0x00000000003E0000
----- Exception occurred on thread 0:15c8
ntdll!ZwWaitForMultipleObjects+0x14:
00007ffc`81a959a4 c3              ret

----- Exception record at 00000000`003e0028:
ExceptionAddress: 00007ff791d81014 (CrashAV_x64!wmain+0x0000000000000014)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 0000000000000001
   Parameter[1]: 0000000000000000
Attempt to write to address 0000000000000000

----- Context record at 00000000`003e00c0:
rax=0000000000000000 rbx=0000000000000000 rcx=00007ffc81a954d4
rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000001
rip=00007ff791d81014 rsp=00000000006ff8b0 rbp=0000000000000000
 r8=00000000006ff808  r9=0000000000000000 r10=0000000000000000
r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0         nv up ei pl zr na po nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010246
CrashAV_x64!wmain+0x14:
00007ff7`91d81014 45891b          mov     dword ptr [r11],r11d ds:00000000`00000000=????????

Comentarios

El comando .jdinfo usa la información del Registro AeDebug introducida en Windows Vista. Para obtener más información sobre las claves del Registro usadas, consulte Habilitación de la depuración postmortem. El comando .jdinfo toma la dirección de un JIT_DEBUG_INFO que el sistema configuró para AeDebug y establece el contexto en la excepción que provocó el bloqueo.

Puede usar el comando .jdinfo en lugar de -g en AeDebug para que el depurador se establezca en el estado AeDebug sin necesidad de ejecución.

Este estado puede ser ventajoso, ya que, en condiciones habituales, cuando se produce una excepción en modo de usuario, se produce la siguiente secuencia:

  1. El sistema operativo Microsoft Windows detiene la ejecución de la aplicación.

  2. Se inicia el depurador postmortem.

  3. El depurador se asocia a la aplicación.

  4. El depurador emite un comando "Go". (Este comando se debe a -g en la clave AeDebug ).

  5. El destino intenta ejecutar y puede o no encontrar la misma excepción.

  6. Esta excepción se divide en el depurador.

Hay varios problemas que pueden producirse debido a estos eventos:

  • Las excepciones no siempre se repiten, posiblemente debido a una condición transitoria que ya no existe cuando se reinicia la excepción.

  • Otro evento, como una excepción diferente, puede producirse. No hay forma de saber si es idéntico al evento original.

  • La asociación de un depurador implica insertar un nuevo subproceso, que se puede bloquear si un subproceso contiene el bloqueo del cargador. La inserción de un nuevo subproceso puede ser una alteración significativa del proceso.

Si usa -c .jdinfo en lugar de -g en la clave AeDebug , no se produce ninguna ejecución. En su lugar, la información de excepción se recupera de la estructura JIT_DEBUG_INFO mediante la variable %p.

Por ejemplo, considere la siguiente clave AeDebug .

ntsd -p %ld -e %ld -c ".jdinfo 0x%p"

El ejemplo siguiente es incluso menos invasivo. El modificador -pv hace que el depurador se conecte de forma novasiva, que no inserta ningún subproceso nuevo en el destino.

ntsd -pv -p %ld -e %ld -c ".jdinfo 0x%p"

Si usa esta opción novasiva, salir del depurador no finaliza el proceso. Puede usar el comando .kill (Kill Process) para finalizar el proceso.

Si desea usarlo para la depuración de archivos de volcado de memoria, debe usar .dump /j para agregar la estructura JIT_DEBUG_INFO al archivo de volcado de memoria, cuando se cree el archivo de volcado.

La estructura JIT_DEBUG_INFO se define de la manera siguiente.

typedef struct _JIT_DEBUG_INFO {
    DWORD dwSize;
    DWORD dwProcessorArchitecture;
    DWORD dwThreadID;
    DWORD dwReserved0;
    ULONG64 lpExceptionAddress;
    ULONG64 lpExceptionRecord;
    ULONG64 lpContextRecord;
} JIT_DEBUG_INFO, *LPJIT_DEBUG_INFO;

Puede usar el comando dt para mostrar la estructura JIT_DEBUG_INFO.

0: kd> dt JIT_DEBUG_INFO
nt!JIT_DEBUG_INFO
   +0x000 dwSize           : Uint4B
   +0x004 dwProcessorArchitecture : Uint4B
   +0x008 dwThreadID       : Uint4B
  +0x00c dwReserved0      : Uint4B
   +0x010 lpExceptionAddress : Uint8B
   +0x018 lpExceptionRecord : Uint8B
   +0x020 lpContextRecord  : Uint8B

Visualización del registro de excepciones, pila de llamadas y LastEvent mediante WinDbg

Después de usar el comando .jdinfo para establecer el contexto en el momento del error, puede ver el registro de excepciones devuelto por .jdinfo, la pila de llamadas y el último evento, como se muestra a continuación, para investigar la causa.

0:000> .jdinfo  0x00000000003E0000
----- Exception occurred on thread 0:15c8
ntdll!NtWaitForMultipleObjects+0x14:
00007ffc`81a959a4 c3              ret

----- Exception record at 00000000`003e0028:
ExceptionAddress: 00007ff791d81014 (CrashAV_x64!wmain+0x0000000000000014)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 0000000000000001
   Parameter[1]: 0000000000000000
Attempt to write to address 0000000000000000
...

0:000> k
  *** Stack trace for last set context - .thread/.cxr resets it
# Child-SP          RetAddr           Call Site
00 00000000`006ff8b0 00007ff7`91d811d2 CrashAV_x64!wmain+0x14 [c:\my\my_projects\crash\crashav\crashav.cpp @ 14]
01 00000000`006ff8e0 00007ffc`7fa38364 CrashAV_x64!__tmainCRTStartup+0x11a [f:\dd\vctools\crt_bld\self_64_amd64\crt\src\crtexe.c @ 579]
02 00000000`006ff910 00007ffc`81a55e91 KERNEL32!BaseThreadInitThunk+0x14
03 00000000`006ff940 00000000`00000000 ntdll!RtlUserThreadStart+0x21

0:000> .lastevent
Last event: 153c.5d0: Break instruction exception - code 80000003 (first chance)
  debugger time: Thu Sep  8 12:55:08.968 2016 (UTC - 7:00)