!analyze 拡張機能の使用

クラッシュしたターゲット コンピューターまたはアプリケーションをデバッグする最初の手順は、!analyze 拡張コマンドを使用することです。 この拡張機能は、大量の自動分析を実行します。 この解析の結果はデバッガーの [Command] ウィンドウに表示されます。

データの完全な詳細表示のためには、-v オプションを使用する必要があります。 その他のオプションの詳細については、!analyze のリファレンス ページを参照してください。

ユーザー モードでの !analyze -v の例

この例では、例外が発生したユーザー モード アプリケーションにデバッガーをアタッチしています。

0:000> !analyze -v
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

Debugger SolutionDb Connection::Open failed 80004005

インターネットに接続している場合、デバッガーは Microsoft が管理するクラッシュ解決策のデータベースにアクセスしようとします。 この場合、エラー メッセージが表示され、コンピューターがインターネットにアクセスできなかったか、Web サイトが機能していなかったことが示されます。

FAULTING_IP: 
ntdll!PropertyLengthAsVariant+73
77f97704 cc               int     3

FAULTING_IP フィールドは、障害発生時の命令ポインターを示します。

EXCEPTION_RECORD:  ffffffff -- (.exr ffffffffffffffff)
ExceptionAddress: 77f97704 (ntdll!PropertyLengthAsVariant+0x00000073)
   ExceptionCode: 80000003 (Break instruction exception)
  ExceptionFlags: 00000000
NumberParameters: 3
   Parameter[0]: 00000000
   Parameter[1]: 00010101
   Parameter[2]: ffffffff

EXCEPTION_RECORD フィールドは、このクラッシュの例外レコードを示します。 この情報は、.exr (例外レコードの表示) コマンドを使用しても表示できます。

BUGCHECK_STR:  80000003

BUGCHECK_STR フィールドは、例外コードを示します。 名前が誤解を招くかもしれませんが、bug check という用語は、実際にはカーネル モードでのクラッシュを意味しています。 ユーザー モードでのデバッグでは、例外コードが表示されます。この場合は 0x80000003 です。

DEFAULT_BUCKET_ID:  APPLICATION_FAULT

DEFAULT_BUCKET_ID フィールドは、この障害が属する一般的な障害のカテゴリを示します。

PROCESS_NAME:  MyApp.exe

PROCESS_NAME フィールドは、例外を発生させたプロセスの名前を示します。

LAST_CONTROL_TRANSFER:  from 01050963 to 77f97704

「LAST_CONTROL_TRANSFER」フィールドは、スタック上の最後の呼び出しを示します。 この場合、アドレス 0x01050963 のコードが 0x77F97704 の関数を呼び出しました。 これらのアドレスを ln (一番近いシンボルの一覧表示) コマンドで使用すると、これらのアドレスがどのモジュールと関数に存在するかを特定できます。

STACK_TEXT:  
0006b9dc 01050963 00000000 0006ba04 000603fd ntdll!PropertyLengthAsVariant+0x73
0006b9f0 010509af 00000002 0006ba04 77e1a449 MyApp!FatalErrorBox+0x55 [D:\source_files\MyApp\util.c @ 541]
0006da04 01029f4e 01069850 0000034f 01069828 MyApp!ShowAssert+0x47 [D:\source_files\MyApp\util.c @ 579]
0006db6c 010590c3 000e01ea 0006fee4 0006feec MyApp!SelectColor+0x103 [D:\source_files\MyApp\colors.c @ 849]
0006fe04 77e11d0a 000e01ea 00000111 0000413c MyApp!MainWndProc+0x1322 [D:\source_files\MyApp\MyApp.c @ 1031]
0006fe24 77e11bc8 01057da1 000e01ea 00000111 USER32!UserCallWinProc+0x18
0006feb0 77e172b4 0006fee4 00000001 010518bf USER32!DispatchMessageWorker+0x2d0
0006febc 010518bf 0006fee4 00000000 01057c5d USER32!DispatchMessageA+0xb
0006fec8 01057c5d 0006fee4 77f82b95 77f83920 MyApp!ProcessQCQPMessage+0x3b [D:\source_files\MyApp\util.c @ 2212]
0006ff70 01062cbf 00000001 00683ed8 00682b88 MyApp!main+0x1e6 [D:\source_files\MyApp\MyApp.c @ 263]
0006ffc0 77e9ca90 77f82b95 77f83920 7ffdf000 MyApp!mainCRTStartup+0xff [D:\source_files\MyApp\crtexe.c @ 338]
0006fff0 00000000 01062bc0 00000000 000000c8 KERNEL32!BaseProcessStart+0x3d

STACK_TEXT フィールドは、障害が発生したコンポーネントのスタック トレースを示します。

FOLLOWUP_IP: 
MyApp!FatalErrorBox+55
01050963 5e               pop     esi

FOLLOWUP_NAME:  dbg

SYMBOL_NAME:  MyApp!FatalErrorBox+55

MODULE_NAME:  MyApp

IMAGE_NAME:  MyApp.exe

DEBUG_FLR_IMAGE_TIMESTAMP:  383490a9

!analyze は、エラーの原因となった可能性がある命令を特定すると、FOLLOWUP_IP フィールドに表示します。 SYMBOL_NAME、MODULE_NAME、IMAGE_NAME、および DEBUG_FLR_IMAGE_TIMESTAMP フィールドは、この命令に対応するシンボル、モジュール、イメージの名前、イメージのタイムスタンプを示します。

STACK_COMMAND:  .ecxr ; kb

STACK_COMMAND フィールドは、STACK_TEXT を取得するために使用されたコマンドを示します。 このコマンドを使用して、このスタック トレースを繰り返し表示したり、このコマンドを少し変更して、関連するスタック情報を取得したりできます。

BUCKET_ID:  80000003_MyApp!FatalErrorBox+55

BUCKET_ID フィールドは、現在の障害が属する特定の障害のカテゴリを示します。 このカテゴリは、デバッガーが解析出力に表示する他の情報を特定するのに役立ちます。

Followup: dbg
---------

FOLLOWUP_NAME および Followup フィールドについては、「Followup フィールドと triage.ini ファイル」を参照してください。

他にもさまざまなフィールドが表示される可能性があります。

  • 制御が無効なアドレスに移行した場合、FAULTING_IP フィールドにその無効なアドレスが含まれます。 FOLLOWUP_IP フィールドではなく、FAILED_INSTRUCTION_ADDRESS フィールドに、そのアドレスから逆アセンブルされたコードが示されますが、この逆アセンブルは意味をなさない可能性があります。 この状況では、SYMBOL_NAME、MODULE_NAME、IMAGE_NAME、および DEBUG_FLR_IMAGE_TIMESTAMP フィールドは、この命令の呼び出し元を参照します。

  • プロセッサが誤動作した場合、SINGLE_BIT_ERROR、TWO_BIT_ERROR、または POSSIBLE_INVALID_CONTROL_TRANSFER フィールドが表示される可能性があります。

  • メモリの破損が疑われる場合、CHKIMG_EXTENSION フィールドは、調査に使用する必要がある !chkimg 拡張機能コマンドを示します。

カーネル モードの !analyze -v の例

この例では、デバッガーがクラッシュ直後のコンピューターにアタッチされています。

kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pagable (or completely invalid) address at an
interrupt request level (IRQL) that is too high.  This is usually
caused by drivers using improper addresses.
If kernel debugger is available get stack backtrace.

表示の最初の要素は、バグ チェック コードとこのタイプのバグ チェックに関する情報を示します。 表示されるテキストの一部は、この特定の例に当てはまらない場合があります。 各バグ チェックの詳細については、「バグ チェック コード リファレンス」セクションを参照してください。

Arguments:
Arg1: 00000004, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000001, value 0 = read operation, 1 = write operation
Arg4: f832035c, address which referenced memory

次にバグ チェック パラメーターが表示されます。 その後にそれぞれの説明が続きます。 たとえば、3 番目のパラメーターは 1 で、その後のコメントは、書き込み操作が失敗したことを示しています。

## Debugging Details:


WRITE_ADDRESS:  00000004 Nonpaged pool

CURRENT_IRQL:  2

次のいくつかのフィールドは、クラッシュの性質によって異なります。 この場合、WRITE_ADDRESS および CURRENT_IRQL フィールドが表示されます。 これらは、バグ チェック パラメーターで示された情報を再述しているだけです。 「Nonpaged pool」というステートメントと「an attempt was made to access a pagable (or completely invalid) address」というバグ チェック テキストを比較することで、アドレスが無効であったことがわかります。 この場合の無効なアドレスは 0x00000004 でした。

FAULTING_IP: 
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204           mov     [edx+0x4],eax

FAULTING_IP フィールドは、障害発生時の命令ポインターを示します。

DEFAULT_BUCKET_ID:  DRIVER_FAULT

DEFAULT_BUCKET_ID フィールドは、この障害が属する一般的な障害のカテゴリを示します。

BUGCHECK_STR:  0xD1

BUGCHECK_STR フィールドは、以前に見たことがあるバグチェック コードを示します。 場合によっては、追加のトリアージ情報が付加されることがあります。

TRAP_FRAME:  f8950dfc -- (.trap fffffffff8950dfc)
.trap fffffffff8950dfc
ErrCode = 00000002
eax=81cc86dc ebx=81cc80e0 ecx=81e55688 edx=00000000 esi=81cc8028 edi=8052cf3c
eip=f832035c esp=f8950e70 ebp=f8950e90 iopl=0         nv up ei pl nz ac po nc
cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010216
USBPORT!USBPORT_BadRequestFlush+7c:
f832035c 894204           mov     [edx+0x4],eax     ds:0023:00000004=????????
.trap
Resetting default context

TRAP_FRAME フィールドは、このクラッシュのトラップ フレームを示します。 この情報は、.trap (トラップ フレームの表示) コマンドを使用しても表示できます。

LAST_CONTROL_TRANSFER:  from f83206e0 to f832035c

「LAST_CONTROL_TRANSFER」フィールドは、スタック上の最後の呼び出しを示します。 この場合、アドレス 0xF83206E0 のコードが 0xF832035C の関数を呼び出しました。 ln (一番近いシンボルの一覧表示) コマンドを使用すると、これらのアドレスがどのモジュールと関数に存在するかを確認できます。

STACK_TEXT:  
f8950e90 f83206e0 024c7262 00000000 f8950edc USBPORT!USBPORT_BadRequestFlush+0x7c
f8950eb0 804f5561 81cc8644 81cc8028 6d9a2f30 USBPORT!USBPORT_DM_TimerDpc+0x10c
f8950fb4 804f5644 6e4be98e 00000000 ffdff000 nt!KiTimerListExpire+0xf3
f8950fe0 8052c47c 8053cf20 00000000 00002e42 nt!KiTimerExpiration+0xb0
f8950ff4 8052c16a efdefd44 00000000 00000000 nt!KiRetireDpcList+0x31

STACK_TEXT フィールドは、障害が発生したコンポーネントのスタック トレースを示します。

FOLLOWUP_IP: 
USBPORT!USBPORT_BadRequestFlush+7c
f832035c 894204           mov     [edx+0x4],eax

FOLLOWUP_IP フィールドは、エラーの原因となった可能性がある命令の逆アセンブルを示します。

FOLLOWUP_NAME:  usbtri

SYMBOL_NAME:  USBPORT!USBPORT_BadRequestFlush+7c

MODULE_NAME:  USBPORT

IMAGE_NAME:  USBPORT.SYS

DEBUG_FLR_IMAGE_TIMESTAMP:  3b7d868b

SYMBOL_NAME、MODULE_NAME、IMAGE_NAME、DBG_FLR_IMAGE_TIMESTAMP フィールドは、スタックトレース内の各命令について、有効である場合は、その命令に関連するシンボル、モジュール、イメージ、イメージ タイムスタンプ情報を表示し、有効でない場合は、呼び出し元の命令に関連する情報を表示します。

STACK_COMMAND:  .trap fffffffff8950dfc ; kb

STACK_COMMAND フィールドは、STACK_TEXT を取得するために使用されたコマンドを示します。 このコマンドを使用して、このスタック トレースを繰り返し表示したり、このコマンドを少し変更して、関連するスタック情報を取得したりできます。

BUCKET_ID:  0xD1_W_USBPORT!USBPORT_BadRequestFlush+7c

BUCKET_ID フィールドは、現在の障害が属する特定の障害のカテゴリを示します。 このカテゴリは、デバッガーが解析出力に表示する他の情報を特定するのに役立ちます。

FOLLOWUP_NAME および Followup フィールドについては、「Followup フィールドと triage.ini ファイル」を参照してください。

他にもさまざまなフィールドが表示される可能性があります。

  • 制御が無効なアドレスに移行した場合、FAULTING_IP フィールドにその無効なアドレスが含まれます。 FOLLOWUP_IP フィールドではなく、FAILED_INSTRUCTION_ADDRESS フィールドに、そのアドレスから逆アセンブルされたコードが示されますが、この逆アセンブルは意味をなさない可能性があります。 この状況では、SYMBOL_NAME、MODULE_NAME、IMAGE_NAME、および DBG_FLR_IMAGE_TIMESTAMP フィールドは、この命令の呼び出し元を参照します。

  • プロセッサが誤動作した場合、SINGLE_BIT_ERROR、TWO_BIT_ERROR、または POSSIBLE_INVALID_CONTROL_TRANSFER フィールドが表示される可能性があります。

  • メモリの破損が疑われる場合、CHKIMG_EXTENSION フィールドは、調査に使用する必要がある !chkimg 拡張機能コマンドを示します。

  • バグ チェックがデバイス ドライバーのコード内で発生した場合、そのドライバーの名前が BUGCHECKING_DRIVER フィールドに表示されることがあります。

Followup フィールドと triage.ini ファイル

ユーザー モードとカーネル モードの両方で、現在のスタック フレームの所有者が特定できれば、その情報が Followup フィールドに表示されます。 この情報は次の方法で特定されます。

  1. !analyze 拡張機能を使用すると、デバッガーはスタックの最上位フレームから始めて、そのフレームがエラーの原因かどうかを特定します。 そうでない場合は、次のフレームが解析されます。 このプロセスは、障害がある可能性のあるフレームが見つかるまで続けられます。

  2. デバッガーは、このフレーム内のモジュールと関数の所有者を特定しようとします。 所有者が特定できれば、このフレームに障害があると見なされます。

  3. 所有者が特定できない場合、デバッガーは次のスタック フレームに進み、所有者が特定されるまで (またはスタックが完全に調べられるまで) このプロセスを続けます。 この検索で所有者が見つかった最初のフレームに障害があると見なされます。 デバッガーがスタック全体を調べても情報が見つからない場合、Followup フィールドは表示されません。

  4. 問題のあるフレームの所有者が Followup フィールドに表示されます。 !analyze -v を使用する場合、FOLLOWUP_IP、SYMBOL_NAME、MODULE_NAME、IMAGE_NAME、および DBG_FLR_IMAGE_TIMESTAMP フィールドがこのフレームを参照します。

Followup フィールドで有用な情報を表示するには、先に、モジュールと関数の所有者の名前を含む triage.ini ファイルを作成する必要があります。

triage.ini ファイルでは、エラーが発生する可能性のあるすべてのモジュールの所有者を指定する必要があります。 実際の所有者の代わりに情報文字列を使用できますが、この文字列にはスペースを含めることはできません。 モジュールに問題が発生しないことが確実な場合は、そのモジュールを省略するか、スキップするように指定できます。 また、個々の関数の所有者を指定することも可能で、トリアージ プロセスの粒度をさらに細かくすることができます。

triage.ini ファイルの構文の詳細については、「モジュールと関数の所有者の指定」を参照してください。

その他の !analyze 手法

クラッシュや例外が発生していない場合、!analyze はターゲットの現在の状態を示す非常に短いテキストを表示します。 特定の状況では、クラッシュが発生したかのように解析を強制的に行いたい場合があります。 このタスクを実行するには、!analyze -f を使用します。

ユーザー モードで例外が発生しているが、根本的な問題がハングしたスレッドであると考える場合は、現在のスレッドを調査対象のスレッドに設定し、!analyze -hang を使用します。 この拡張機能は、スレッド スタック解析を実行して、他のスレッドをブロックしているスレッドがあるかどうかを特定します。

カーネル モードで、バグ チェックが発生したが根本的な問題はハングしたスレッドであると考える場合は、!analyze -hang を使用します。 この拡張機能は、システムが保持しているロックを調査し、DPC キュー チェーンをスキャンして、ハングしたスレッドの兆候を表示します。 問題がカーネル モードでのリソースのデッドロックであると考える場合は、!deadlock 拡張機能と共に、ドライバー検証ツールの [デッドロック検出] オプションを使用してください。

既知の問題が自動的に無視されるようにすることもできます。 そのためには、先に、既知の問題のリストを含む XML ファイルを作成する必要があります。 !analyze -c -loadKnownIssuesFile 拡張機能を使用して、このファイルを読み込みます。 その後、例外や中断が発生した場合は、!analyze -c 拡張機能を使用します。 例外が既知の問題のいずれかに一致する場合、ターゲットは実行を再開します。 ターゲットが実行を再開しない場合は、!analyze -v を使用して問題の原因を特定できます。

関連項目

詳細については、以下のトピックを参照してください。

!analyze

バグ チェック コード リファレンス

Windows デバッガー (WinDbg) を使用したクラッシュ ダンプ分析

WinDbg によるカーネル モード ダンプ ファイルの分析