はじめに
- Windows 環境でアプリケーションがクラッシュした場合、調査方法の一つとして「WinDbg」の利用が挙げられます。上記について簡単に紹介します。
WinDbgとは
- Windows 環境にて以下のような用途で利用されます。
- クラッシュダンプファイルの解析
- アプリケーションのライブデバッグ
- 以下のモードがあります。
- ユーザモード
- マシン上で起動しているアプリケーションを解析する場合
- カーネルモード
- ホストから別筐体のマシンのカーネルモジュール、ハードウェアを解析する場合
- ユーザモード
クラッシュダンプファイルの解析
続いて、WinDbg の使用例としてクラッシュダンプファイルの解析について記載します。
対象アプリケーション
関数 printArg の実行時にアクセス違反が生じるようにしています。
#include <iostream>
void printArg( int p_arg ) {
int *ptr = nullptr;
std::cout << "value:" << *ptr << std::endl;
}
int main() {
printArg( 10 );
}
WinDbg上での解析
- 対象アプリケーションのクラッシュ時のダンプファイルを取得します。
- ダンプファイルの解析前に、WinDbg でシンボルパス(シンボルファイル(.pdb)の探索パス)を設定します。詳細は、Windows デバッガーのシンボル パスで紹介されています。
- シンボルファイルで定義されたシンボル名(関数等の名前)より、デバッガは詳細な解析結果を取得できます。
- WinDbg で「Open Crash Dump」からダンプファイルを開きます。
- ダンプファイルの解析では主に「!analyze -v」のコマンドを実行します。以下は解析結果の例です。
- 例外コードやシンボル名より、SegFault.exe の printArg でアクセス違反が生じたと推察できます。
0:000> !analyze -v
*******************************************************************************
* *
* Exception Analysis *
* *
*******************************************************************************
...(中略)...
EXCEPTION_RECORD: (.exr -1)
ExceptionAddress: 00007ff7e66e2553 (SegFault!printArg+0x0000000000000053)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 0000000000000000
Parameter[1]: 0000000000000000
Attempt to read from address 0000000000000000
PROCESS_NAME: SegFault.exe
READ_ADDRESS: 0000000000000000
ERROR_CODE: (NTSTATUS) 0xc0000005 - 0x%p 0x%p Q B %s B
EXCEPTION_CODE_STR: c0000005
EXCEPTION_PARAMETER1: 0000000000000000
EXCEPTION_PARAMETER2: 0000000000000000
STACK_TEXT:
0000007c`efb9f880 00007ff7`e66e25d4 : 00007ff7`0000000a cccccccc`cccccccc cccccccc`cccccccc cccccccc`cccccccc : SegFault!printArg+0x53
0000007c`efb9f9a0 00007ff7`e66e2e89 : 0000d85b`00000001 00007fff`1bf44219 00000000`00000000 00007ff7`e66e46fd : SegFault!main+0x34
0000007c`efb9faa0 00007ff7`e66e2d2e : 00007ff7`e66ea000 00007ff7`e66ea220 00000000`00000000 00000000`00000000 : SegFault!invoke_main+0x39
0000007c`efb9faf0 00007ff7`e66e2bee : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : SegFault!__scrt_common_main_seh+0x12e
0000007c`efb9fb60 00007ff7`e66e2f19 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : SegFault!__scrt_common_main+0xe
0000007c`efb9fb90 00007fff`84797bd4 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : SegFault!mainCRTStartup+0x9
0000007c`efb9fbc0 00007fff`858cce51 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : kernel32!BaseThreadInitThunk+0x14
0000007c`efb9fbf0 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : ntdll!RtlUserThreadStart+0x21
...(中略)...
SYMBOL_NAME: SegFault!printArg+53
MODULE_NAME: SegFault
IMAGE_NAME: SegFault.exe
STACK_COMMAND: ~0s ; .ecxr ; kb
FAILURE_BUCKET_ID: NULL_POINTER_READ_c0000005_SegFault.exe!printArg
...(中略)...
---------
参考資料
日本マイクロソフト社のカンファレンス「de:code」について、過去の講演資料(ハードコアデバッギングシリーズ)では具体例を交えて詳しく紹介されています。