BOOL SymGetSymFromAddr( IN HANDLE hProcess, IN DWORD Address, OUT LPDWORD Displacement, IN OUT PIMAGEHLP_SYMBOL Symbol);
この関数はNT4.0または95で使用可能である。
引数の意味は以下の通り。
hProcess | SymInitializeで渡したプロセスハンドル。 |
Address | 検索の元となるアドレス。 |
Displacement | Addressのシンボルの先頭からの距離。 |
Symbol | 取得結果のシンボル情報。 |
戻り値は、関数の実行に成功したか否かを表す真偽値である。
void TestStackWalk(); void Test1(); void Test2(); void Test3(); LONG CALLBACK SWFilter(EXCEPTION_POINTERS *ExInfo); void TestStackWalk() { /* SWFilter()を例外フィルタとして設定しておく */ SetUnhandledExceptionFilter(SWFilter); Test1(); } void Test1() { Test2(); } void Test2() { Test3(); } void Test3() { /* 例外の発生するコード。SWFilter()関数が呼ばれる */ *(DWORD *)NULL = 0; } /* 例外発生時に関数の呼び出し履歴を表示する、例外フィルタ関数 */ LONG CALLBACK SWFilter(EXCEPTION_POINTERS *ExInfo) { STACKFRAME sf; BOOL bResult; PIMAGEHLP_SYMBOL pSym; DWORD Disp; printf("例外発生。\n"); /* シンボル情報格納用バッファの初期化 */ pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc(GMEM_FIXED, 10000); pSym->SizeOfStruct = 10000; pSym->MaxNameLength = 10000 - sizeof(IMAGEHLP_SYMBOL); /* スタックフレームの初期化 */ ZeroMemory(&sf, sizeof(sf)); sf.AddrPC.Offset = ExInfo->ContextRecord->Eip; sf.AddrStack.Offset = ExInfo->ContextRecord->Esp; sf.AddrFrame.Offset = ExInfo->ContextRecord->Ebp; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Mode = AddrModeFlat; /* シンボルハンドラの初期化 */ SymInitialize(GetCurrentProcess(), NULL, TRUE); /* スタックフレームを順に表示していく */ for(;;) { /* 次のスタックフレームの取得 */ bResult = StackWalk( IMAGE_FILE_MACHINE_I386, GetCurrentProcess(), GetCurrentThread(), &sf, NULL, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL); /* 失敗ならば、ループを抜ける */ if(!bResult || sf.AddrFrame.Offset == 0) break; /* プログラムカウンタから関数名を取得 */ bResult = SymGetSymFromAddr(GetCurrentProcess(), sf.AddrPC.Offset, &Disp, pSym); /* 取得結果を表示 */ if(bResult) printf("0x%08x %s() + 0x%x\n", sf.AddrPC.Offset, pSym->Name, Disp); else printf("%08x, ---", sf.AddrPC.Offset); } /* 後処理 */ SymCleanup(GetCurrentProcess()); GlobalFree(pSym); return(EXCEPTION_EXECUTE_HANDLER); }