#include #include #include #pragma comment(lib, "dbghelp.lib") // dbghelpライブラリをリンク // 例外ハンドラ関数 LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS* exceptionPointers) { // 例外情報の取得 EXCEPTION_RECORD* exceptionRecord = exceptionPointers->ExceptionRecord; CONTEXT* context = exceptionPointers->ContextRecord; // 例外コードの表示 printf("例外コード: 0x%08lX\n", exceptionRecord->ExceptionCode); // 例外が発生したアドレスの表示 printf("例外アドレス: 0x%08p\n", exceptionRecord->ExceptionAddress); // その他の例外情報の表示 printf("その他の例外情報:\n"); printf("ExceptionFlags: 0x%08lX\n", exceptionRecord->ExceptionFlags); printf("NumberParameters: %d\n", exceptionRecord->NumberParameters); for (DWORD i = 0; i < exceptionRecord->NumberParameters; ++i) { printf("ExceptionInformation[%d]: 0x%p\n", i, (void*)exceptionRecord->ExceptionInformation[i]); } // スタックトレースの表示 printf("スタックトレース:\n"); // シンボル情報の初期化 SymInitialize(GetCurrentProcess(), NULL, TRUE); // スタックフレームの初期化 CONTEXT contextCopy = *context; STACKFRAME64 stackFrame; memset(&stackFrame, 0, sizeof(stackFrame)); // スタックトレースの取得 stackFrame.AddrPC.Mode = AddrModeFlat; stackFrame.AddrStack.Mode = AddrModeFlat; stackFrame.AddrFrame.Mode = AddrModeFlat; #if defined(_WIN64) stackFrame.AddrPC.Offset = contextCopy.Rip; stackFrame.AddrStack.Offset = contextCopy.Rsp; stackFrame.AddrFrame.Offset = contextCopy.Rbp; #else stackFrame.AddrPC.Offset = contextCopy.Eip; stackFrame.AddrStack.Offset = contextCopy.Esp; stackFrame.AddrFrame.Offset = contextCopy.Ebp; #endif while (StackWalk64( IMAGE_FILE_MACHINE_I386, // マシンタイプ(x86) GetCurrentProcess(), // プロセスハンドル GetCurrentThread(), // スレッドハンドル &stackFrame, // スタックフレーム情報 &contextCopy, // コンテキスト情報 NULL, // ReadMemoryRoutine SymFunctionTableAccess64, // FunctionTableAccessRoutine SymGetModuleBase64, // GetModuleBaseRoutine NULL // TranslateAddress )) { DWORD64 address = stackFrame.AddrPC.Offset; printf("0x%08llX\n", address); } // レジスタの値の表示 printf("レジスタの値:\n"); #if defined(_WIN64) printf("Rax: 0x%016llX\n", context->Rax); printf("Rbx: 0x%016llX\n", context->Rbx); printf("Rcx: 0x%016llX\n", context->Rcx); printf("Rdx: 0x%016llX\n", context->Rdx); printf("Rsi: 0x%016llX\n", context->Rsi); printf("Rdi: 0x%016llX\n", context->Rdi); printf("Rbp: 0x%016llX\n", context->Rbp); printf("Rsp: 0x%016llX\n", context->Rsp); printf("Rip: 0x%016llX\n", context->Rip); printf("R8 : 0x%016llX\n", context->R8); printf("R9 : 0x%016llX\n", context->R9); printf("R10: 0x%016llX\n", context->R10); printf("R11: 0x%016llX\n", context->R11); printf("R12: 0x%016llX\n", context->R12); printf("R13: 0x%016llX\n", context->R13); printf("R14: 0x%016llX\n", context->R14); printf("R15: 0x%016llX\n", context->R15); #else printf("Eax: 0x%08lX\n", context->Eax); printf("Ebx: 0x%08lX\n", context->Ebx); printf("Ecx: 0x%08lX\n", context->Ecx); printf("Edx: 0x%08lX\n", context->Edx); printf("Esi: 0x%08lX\n", context->Esi); printf("Edi: 0x%08lX\n", context->Edi); printf("Ebp: 0x%08lX\n", context->Ebp); printf("Esp: 0x%08lX\n", context->Esp); printf("Eip: 0x%08lX\n", context->Eip); #endif // シンボル情報の後処理 SymCleanup(GetCurrentProcess()); // 続行するために例外処理を継続する return EXCEPTION_CONTINUE_SEARCH; } int main() { // 例外ハンドラを設定 SetUnhandledExceptionFilter(ExceptionHandler); // シンボル情報の初期化 SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES); SymInitialize(GetCurrentProcess(), NULL, TRUE); // 例外を発生させる int* p = NULL; *p = 10; // シンボル情報の後処理 SymCleanup(GetCurrentProcess()); return 0; }