.jdinfo (Verwenden von JIT_DEBUG_INFO)

Der Befehl .jdinfo verwendet eine JIT_DEBUG_INFO-Struktur als Quelle der Ausnahme und des Kontexts für das JiT-Debuggen (Just-in-Time). Die Adresse an die Struktur wird mithilfe des %p-Parameters, der im Registrierungseintrag AeDebug angegeben ist, an den Befehl .jdinfo übergeben.

Weitere Informationen zu den verwendeten Registrierungsschlüsseln finden Sie unter Aktivieren des Postmortemdebuggens. Weitere Informationen zum Registrieren von Kontexten finden Sie unter Ändern von Kontexten.

.jdinfo Address 

Parameter

Adresse
Gibt die Adresse der JIT_DEBUG_INFO-Struktur an. Die Adresse an die Struktur wird mithilfe des %p-Parameters, der im Registrierungseintrag AeDebug angegeben ist, an den Befehl .jdinfo übergeben.

Environment

Modi

Benutzermodus

Ziele

Liveabbild, Absturzabbild

Plattformen

All

Beispiel

Dieses Beispiel zeigt, wie der Registrierungseintrag AeDebug so konfiguriert werden kann, dass winDbg als JIT-Debugger verwendet werden kann.

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

Bei einem Absturz wird dann der konfigurierte JIT-Debugger aufgerufen, und der Parameter %p wird verwendet, um die Adresse der JIT_DEBUG_INFO-Struktur an den JDINFO-Befehl zu übergeben, der nach dem Start des Debuggers ausgeführt wird.

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

Hinweise

Der Befehl .jdinfo verwendet die registrierungsinformationen AeDebug , die in Windows Vista eingeführt wurden. Weitere Informationen zu den verwendeten Registrierungsschlüsseln finden Sie unter Aktivieren des Postmortemdebuggens. Der jdinfo-Befehl übernimmt die Adresse einer JIT_DEBUG_INFO, die das System für AeDebug eingerichtet hat, und legt den Kontext auf die Ausnahme fest, die den Absturz verursacht hat.

Sie können den Befehl .jdinfo anstelle von -g in AeDebug verwenden, damit Ihr Debugger auf den AeDebug-Zustand festgelegt wird, ohne dass eine Ausführung erforderlich ist.

Dieser Zustand kann vorteilhaft sein, da unter üblichen Bedingungen, wenn eine Benutzermodus-Ausnahme auftritt, die folgende Sequenz auftritt:

  1. Das Microsoft Windows-Betriebssystem stoppt die Ausführung der Anwendung.

  2. Der postmortem-Debugger wird gestartet.

  3. Der Debugger wird an die Anwendung angefügt.

  4. Der Debugger gibt einen "Go"-Befehl aus. (Dieser Befehl wird durch - g in der AeDebug-Taste verursacht.)

  5. Das Ziel versucht, auszuführen, und kann die gleiche Ausnahme aufweisen oder nicht.

  6. Diese Ausnahme bricht in den Debugger ein.

Es gibt mehrere Probleme, die aufgrund dieser Ereignisse auftreten können:

  • Ausnahmen wiederholen sich nicht immer, möglicherweise aufgrund einer vorübergehenden Bedingung, die beim Neustart der Ausnahme nicht mehr vorhanden ist.

  • Ein anderes Ereignis, z. B. eine andere Ausnahme, kann auftreten. Es gibt keine Möglichkeit zu wissen, ob es mit dem ursprünglichen Ereignis identisch ist.

  • Beim Anfügen eines Debuggers wird ein neuer Thread eingefügt, der blockiert werden kann, wenn ein Thread die Ladesperre hält. Das Einfügen eines neuen Threads kann eine erhebliche Störung des Prozesses sein.

Wenn Sie -c .jdinfo anstelle von -g in Ihrem AeDebug-Schlüssel verwenden, erfolgt keine Ausführung. Stattdessen werden die Ausnahmeinformationen mithilfe der Variablen %p aus der JIT_DEBUG_INFO-Struktur abgerufen.

Betrachten Sie beispielsweise den folgenden AeDebug-Schlüssel .

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

Das folgende Beispiel ist noch weniger invasiv. Der Switch -pv bewirkt, dass der Debugger nicht invasiv angefügt wird, wodurch keine neuen Threads in das Ziel eingefügt werden.

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

Wenn Sie diese nicht invasive Option verwenden, beendet das Beenden des Debuggers den Prozess nicht. Sie können den Befehl .kill (Kill Process) verwenden, um den Prozess zu beenden.

Wenn Sie dies für das Debuggen von Dumpdateien verwenden möchten, sollten Sie .dump /j verwenden, um die JIT_DEBUG_INFO-Struktur ihrer Dumpdatei hinzuzufügen, wenn die Dumpdatei erstellt wird.

Die JIT_DEBUG_INFO-Struktur wird wie folgt definiert.

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;

Sie können den Befehl dt verwenden, um die JIT_DEBUG_INFO-Struktur anzuzeigen.

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

Anzeigen von Ausnahmedatensatz, Anrufliste und LastEvent mithilfe von WinDbg

Nachdem der jdinfo-Befehl verwendet wurde, um den Kontext auf den Moment des Fehlers festzulegen, können Sie den von JDINFO zurückgegebenen Ausnahmedatensatz, den Aufrufstapel und das letzte Ereignis anzeigen, wie unten gezeigt, um die Ursache zu untersuchen.

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)