다음을 통해 공유


.jdinfo(JIT_DEBUG_INFO 사용)

.jdinfo 명령은 JIT(Just-In-Time) 디버깅을 위한 예외 및 컨텍스트의 원본으로 JIT_DEBUG_INFO 구조를 사용합니다. 구조체에 대한 주소는 AeDebug 레지스트리 항목에 지정된 %p 매개 변수를 사용하여 .jdinfo 명령에 전달됩니다.

사용된 레지스트리 키에 대한 자세한 내용은 사후 관리 디버깅 사용을 참조 하세요. 레지스터 컨텍스트에 대한 자세한 내용은 컨텍스트 변경을 참조 하세요.

.jdinfo Address 

매개 변수

주소
JIT_DEBUG_INFO 구조체의 주소를 지정합니다. 구조체에 대한 주소는 AeDebug 레지스트리 항목에 지정된 %p 매개 변수를 사용하여 .jdinfo 명령에 전달됩니다.

환경

모드

사용자 모드

대상

라이브, 크래시 덤프

Platforms

모두

예제

이 예제에서는 WinDbg를 사용하도록 AeDebug 레지스트리 항목을 구성하는 방법을 JIT 디버거로 사용할 수 있습니다.

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

그런 다음 크래시가 발생하면 구성된 JIT 디버거가 호출되고 %p 매개 변수를 사용하여 디버거가 시작된 후 실행되는 .jdinfo 명령에 JIT_DEBUG_INFO 구조체의 주소를 전달합니다.

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=????????

설명

.jdinfo 명령은 Windows Vista에 도입된 AeDebug 레지스트리 정보를 사용합니다. 사용된 레지스트리 키에 대한 자세한 내용은 사후 관리 디버깅 사용을 참조 하세요. .jdinfo 명령은 시스템이 AeDebug대해 설정한 JIT_DEBUG_INFO 주소를 사용하고 컨텍스트를 크래시가 발생한 예외로 설정합니다.

AeDebug에서 -g 대신 .jdinfo 명령을 사용하여 실행 없이 디버거를 AeDebug 상태로 설정할 수 있습니다.

이 상태는 일반적인 조건에서 사용자 모드 예외가 발생할 때 다음 시퀀스가 발생하므로 유리할 수 있습니다.

  1. Microsoft Windows 운영 체제는 애플리케이션 실행을 중지합니다.

  2. 사후 배포 디버거가 시작됩니다.

  3. 디버거가 애플리케이션에 연결됩니다.

  4. 디버거는 "Go" 명령을 실행합니다. (이 명령은 AeDebug 키의 -g에 의해 발생합니다.)

  5. 대상은 실행을 시도하며 동일한 예외가 발생할 수도 있고 그렇지 않을 수도 있습니다.

  6. 이 예외는 디버거에 침입합니다.

이러한 이벤트로 인해 발생할 수 있는 몇 가지 문제가 있습니다.

  • 예외가 다시 시작될 때 더 이상 존재하지 않는 일시적인 조건으로 인해 예외가 항상 반복되는 것은 아닙니다.

  • 다른 예외와 같은 다른 이벤트가 발생할 수 있습니다. 원래 이벤트와 동일한지 여부를 알 수 있는 방법은 없습니다.

  • 디버거를 연결하려면 새 스레드를 삽입해야 하며, 스레드가 로더 잠금을 보유하고 있는 경우 차단할 수 있습니다. 새 스레드를 삽입하는 것은 프로세스에 상당한 방해가 될 수 있습니다.

AeDebug 키에서 -g 대신 -c .jdinfo를 사용하는 경우 실행이 발생하지 않습니다. 대신 예외 정보는 %p 변수를 사용하여 JIT_DEBUG_INFO 구조체에서 검색됩니다.

예를 들어 다음 AeDebug 키를 고려합니다.

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

다음 예제는 훨씬 덜 침습적입니다. -pv 스위치를 사용하면 디버거가 비침범적으로 연결되며, 이는 대상에 새 스레드를 삽입하지 않습니다.

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

이 비침범성 옵션을 사용하는 경우 디버거를 종료해도 프로세스가 종료되지 않습니다. .kill(프로세스 종료) 명령을 사용하여 프로세스를 종료할 수 있습니다.

덤프 파일 디버깅에 이 값을 사용하려면 덤프 파일을 만들 때 .dump /j를 사용하여 덤프 파일에 JIT_DEBUG_INFO 구조를 추가해야 합니다.

JIT_DEBUG_INFO 구조체는 다음과 같이 정의됩니다.

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;

dt 명령을 사용하여 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

WinDbg를 사용하여 예외 레코드, 호출 스택 및 LastEvent 보기

.jdinfo 명령을 사용하여 컨텍스트를 실패 시점으로 설정한 후 아래와 같이 .jdinfo, 호출 스택 및 lastevent에서 반환된 예외 레코드를 보고 원인을 조사할 수 있습니다.

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)