SymGetSymFromAddr 特定のアドレスに対応するシンボル情報の取得

Cの宣言:

BOOL SymGetSymFromAddr(
	IN HANDLE hProcess,
	IN DWORD Address,
	OUT LPDWORD Displacement,
	IN OUT PIMAGEHLP_SYMBOL Symbol);

説明:

Addressで指定したアドレスを含んでいるシンボルの情報を検索し、結果をSymbolに格納する。

この関数はNT4.0または95で使用可能である。

引数の意味は以下の通り。
hProcess SymInitializeで渡したプロセスハンドル。
Address 検索の元となるアドレス。
Displacement Addressのシンボルの先頭からの距離。
Symbol 取得結果のシンボル情報。

戻り値は、関数の実行に成功したか否かを表す真偽値である。

Cのサンプル:

下記TestStackWalk関数は、不正なメモリアクセスによって例外が発生する。例外ハンドラとして設定されているSWFilter関数は、スタックフレームを呼び出し元へ順に辿っていくことにより、例外発生時の関数呼び出し履歴を表示する。
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);
}
(original text:1999/01/11 更新)

本ドキュメントの内容は保証しません。本ドキュメントによって生じた結果について、一切の責任を負いません。