.jdinfo(使用 JIT_DEBUG_INFO)

.jdinfo 命令使用JIT_DEBUG_INFO结构作为异常和上下文的源,以便进行实时 (JIT) 调试。 使用 AeDebug 注册表项中指定的 %p 参数将结构地址传递给 .jdinfo 命令。

有关使用的注册表项的详细信息,请参阅 “启用事后调试”。 有关注册上下文的详细信息,请参阅 更改上下文

.jdinfo Address 

参数

地址
指定JIT_DEBUG_INFO结构的地址。 使用 AeDebug 注册表项中指定的 %p 参数将结构地址传递给 .jdinfo 命令。

环境

模式

用户模式

目标

实时、崩溃转储

平台

全部

示例

此示例演示如何将 AeDebug 注册表项配置为使用 WinDbg 可用作 JIT 调试器。

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

然后,发生崩溃时,将调用配置的 JIT 调试器,并使用 %p 参数将JIT_DEBUG_INFO结构的地址传递给 启动调试器后执行的 .jdinfo 命令。

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的地址,并将上下文设置为导致崩溃的异常。

可以使用 .jdinfo 命令而不是 AeDebug 中的 -g 将调试器设置为 AeDebug 状态,而无需执行。

此状态可能比较有利,因为在通常情况下,发生用户模式异常时,会发生以下序列:

  1. Microsoft Windows 操作系统停止执行应用程序。

  2. 启动事后调试器。

  3. 调试器附加到应用程序。

  4. 调试器发出“Go”命令。 (此命令是由 AeDebug 键中的 -g 引起的。

  5. 目标尝试执行并可能遇到相同的异常。

  6. 此异常中断到调试器中。

由于这些事件,可能会出现以下几个问题:

  • 异常并不总是重复的,可能是由于重启异常时不再存在的暂时性条件。

  • 可能会发生另一个事件,例如不同的异常。 无法知道它是否与原始事件相同。

  • 附加调试器涉及注入新线程,如果线程持有加载程序锁,则可以阻止该线程。 注入新线程可能是进程的严重干扰。

如果在 AeDebug 键中使用 -c .jdinfo 而不是 -g,则不会执行。 而是使用 %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 (Kill Process) 命令结束进程。

如果要将此用于转储文件调试,则应使用 .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)