Partilhar via


.jdinfo (Use JIT_DEBUG_INFO)

O comando .jdinfo usa uma estrutura JIT_DEBUG_INFO como a origem da exceção e o contexto para a depuração JIT (just in time). O endereço para a estrutura é passado para o comando .jdinfo usando o parâmetro %p especificado na entrada do Registro AeDebug.

Para obter mais informações sobre as chaves do Registro usadas, consulte Habilitando a depuração post-mortem. Para obter mais informações sobre contextos de registro, consulte Alterando contextos.

.jdinfo Address 

Parâmetros

Endereço
Especifica o endereço da estrutura JIT_DEBUG_INFO. O endereço para a estrutura é passado para o comando .jdinfo usando o parâmetro %p especificado na entrada do Registro AeDebug.

Ambiente

Modos

Modo de usuário

Destinos

Ao vivo, despejo de memória

Plataformas

Tudo

Exemplo

Este exemplo mostra como a entrada do Registro AeDebug pode ser configurada para usar o WinDbg pode ser usado como o depurador JIT.

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

Em seguida, quando ocorre uma falha, o depurador JIT configurado é invocado e o parâmetro %p é usado para passar o endereço da estrutura JIT_DEBUG_INFO para o comando .jdinfo que é executado após o início do 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=????????

Comentários

O comando .jdinfo usa as informações do Registro AeDebug introduzidas no Windows Vista. Para obter mais informações sobre as chaves do Registro usadas, consulte Habilitando a depuração post-mortem. O comando .jdinfo usa o endereço de um JIT_DEBUG_INFO que o sistema configurou para o AeDebug e define o contexto para a exceção que causou a falha.

Você pode usar o comando .jdinfo em vez de -g no AeDebug para que o depurador seja definido como o estado AeDebug sem exigir execução.

Esse estado pode ser vantajoso, pois em condições normais, quando ocorre uma exceção no modo de usuário, ocorre a seguinte sequência:

  1. O sistema operacional Microsoft Windows interrompe a execução do aplicativo.

  2. O depurador post-mortem é iniciado.

  3. O depurador é anexado ao aplicativo.

  4. O depurador emite um comando "Go". (Esse comando é causado pelo -g na chave AeDebug .)

  5. O destino tenta executar e pode ou não encontrar a mesma exceção.

  6. Essa exceção é interrompida no depurador.

Existem vários problemas que podem ocorrer devido a esses eventos:

  • As exceções nem sempre se repetem, possivelmente devido a uma condição transitória que não existe mais quando a exceção é reiniciada.

  • Outro evento, como uma exceção diferente, pode ocorrer. Não há como saber se é idêntico ao evento original.

  • Anexar um depurador envolve a injeção de um novo thread, que pode ser bloqueado se um thread estiver mantendo o bloqueio do carregador. Injetar um novo thread pode ser uma perturbação significativa do processo.

Se você usar -c .jdinfo em vez de -g em sua chave AeDebug , nenhuma execução ocorrerá. Em vez disso, as informações de exceção são recuperadas da estrutura JIT_DEBUG_INFO usando a variável %p.

Por exemplo, considere a seguinte chave AeDebug .

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

O exemplo a seguir é ainda menos invasivo. A opção -pv faz com que o depurador seja anexado de forma não invasiva, o que não injeta novos threads no destino.

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

Se você usar essa opção não invasiva, sair do depurador não encerrará o processo. Você pode usar o comando .kill (Kill Process) para encerrar o processo.

Se você quiser usar isso para depuração de arquivo de despejo, use .dump /j para adicionar a estrutura JIT_DEBUG_INFO ao arquivo de despejo, quando o arquivo de despejo for criado.

A estrutura JIT_DEBUG_INFO é definida da seguinte forma.

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;

Você pode usar o comando dt para exibir a estrutura 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

Exibindo o registro de exceção, a pilha de chamadas e o LastEvent usando o WinDbg

Depois que o comando .jdinfo tiver sido usado para definir o contexto para o momento da falha, você poderá exibir o registro de exceção retornado por .jdinfo, a pilha de chamadas e o lastevent, conforme mostrado abaixo, para investigar a 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)