// StackWalk.cpp : コンソール アプリケーション用のエントリ ポイントの定義 // #include "stdafx.h" #include #if defined(_M_AMD64) || defined(_M_IA64) #define _IMAGEHLP64 #endif #ifndef _DBGHELP_ #if !defined(IMAGEAPI) #define IMAGEAPI /*DECLSPEC_IMPORT*/ __stdcall #endif #define MAX_SYM_NAME 2000 // // symbol type enumeration // typedef enum { SymNone = 0, SymCoff, SymCv, SymPdb, SymExport, SymDeferred, SymSym, // .sym file SymDia, SymVirtual, NumSymTypes } SYM_TYPE; // // symbol data structure // typedef struct _IMAGEHLP_SYMBOL64 { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOL64) DWORD64 Address; // virtual address including dll base address DWORD Size; // estimated size of symbol, can be zero DWORD Flags; // info about the symbols, see the SYMF defines DWORD MaxNameLength; // maximum size of symbol name in 'Name' CHAR Name[1]; // symbol name (null terminated string) } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; typedef struct _IMAGEHLP_SYMBOL64_PACKAGE { IMAGEHLP_SYMBOL64 sym; CHAR name[MAX_SYM_NAME + 1]; } IMAGEHLP_SYMBOL64_PACKAGE, *PIMAGEHLP_SYMBOL64_PACKAGE; typedef struct _IMAGEHLP_SYMBOLW64 { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOLW64) DWORD64 Address; // virtual address including dll base address DWORD Size; // estimated size of symbol, can be zero DWORD Flags; // info about the symbols, see the SYMF defines DWORD MaxNameLength; // maximum size of symbol name in 'Name' WCHAR Name[1]; // symbol name (null terminated string) } IMAGEHLP_SYMBOLW64, *PIMAGEHLP_SYMBOLW64; typedef struct _IMAGEHLP_SYMBOLW64_PACKAGE { IMAGEHLP_SYMBOLW64 sym; WCHAR name[MAX_SYM_NAME + 1]; } IMAGEHLP_SYMBOLW64_PACKAGE, *PIMAGEHLP_SYMBOLW64_PACKAGE; #if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) #define IMAGEHLP_SYMBOL IMAGEHLP_SYMBOL64 #define PIMAGEHLP_SYMBOL PIMAGEHLP_SYMBOL64 #define IMAGEHLP_SYMBOL_PACKAGE IMAGEHLP_SYMBOL64_PACKAGE #define PIMAGEHLP_SYMBOL_PACKAGE PIMAGEHLP_SYMBOL64_PACKAGE #define IMAGEHLP_SYMBOLW IMAGEHLP_SYMBOLW64 #define PIMAGEHLP_SYMBOLW PIMAGEHLP_SYMBOLW64 #define IMAGEHLP_SYMBOLW_PACKAGE IMAGEHLP_SYMBOLW64_PACKAGE #define PIMAGEHLP_SYMBOLW_PACKAGE PIMAGEHLP_SYMBOLW64_PACKAGE #else typedef struct _IMAGEHLP_SYMBOL { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOL) DWORD Address; // virtual address including dll base address DWORD Size; // estimated size of symbol, can be zero DWORD Flags; // info about the symbols, see the SYMF defines DWORD MaxNameLength; // maximum size of symbol name in 'Name' CHAR Name[1]; // symbol name (null terminated string) } IMAGEHLP_SYMBOL, *PIMAGEHLP_SYMBOL; typedef struct _IMAGEHLP_SYMBOL_PACKAGE { IMAGEHLP_SYMBOL sym; CHAR name[MAX_SYM_NAME + 1]; } IMAGEHLP_SYMBOL_PACKAGE, *PIMAGEHLP_SYMBOL_PACKAGE; typedef struct _IMAGEHLP_SYMBOLW { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_SYMBOLW) DWORD Address; // virtual address including dll base address DWORD Size; // estimated size of symbol, can be zero DWORD Flags; // info about the symbols, see the SYMF defines DWORD MaxNameLength; // maximum size of symbol name in 'Name' WCHAR Name[1]; // symbol name (null terminated string) } IMAGEHLP_SYMBOLW, *PIMAGEHLP_SYMBOLW; typedef struct _IMAGEHLP_SYMBOLW_PACKAGE { IMAGEHLP_SYMBOLW sym; WCHAR name[MAX_SYM_NAME + 1]; } IMAGEHLP_SYMBOLW_PACKAGE, *PIMAGEHLP_SYMBOLW_PACKAGE; #endif // // these values are used for synthesized file types // that can be passed in as image headers instead of // the standard ones from ntimage.h // #define DBHHEADER_DEBUGDIRS 0x1 typedef struct _MODLOAD_DATA { DWORD ssize; // size of this struct DWORD ssig; // signature identifying the passed data PVOID data; // pointer to passed data DWORD size; // size of passed data DWORD flags; // options } MODLOAD_DATA, *PMODLOAD_DATA; // // StackWalking API // typedef enum { AddrMode1616, AddrMode1632, AddrModeReal, AddrModeFlat } ADDRESS_MODE; typedef struct _tagADDRESS64 { DWORD64 Offset; WORD Segment; ADDRESS_MODE Mode; } ADDRESS64, *LPADDRESS64; #if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) #define ADDRESS ADDRESS64 #define LPADDRESS LPADDRESS64 #else typedef struct _tagADDRESS { DWORD Offset; WORD Segment; ADDRESS_MODE Mode; } ADDRESS, *LPADDRESS; #endif // // This structure is included in the STACKFRAME structure, // and is used to trace through usermode callbacks in a thread's // kernel stack. The values must be copied by the kernel debugger // from the DBGKD_GET_VERSION and WAIT_STATE_CHANGE packets. // // // New KDHELP structure for 64 bit system support. // This structure is preferred in new code. // typedef struct _KDHELP64 { // // address of kernel thread object, as provided in the // WAIT_STATE_CHANGE packet. // DWORD64 Thread; // // offset in thread object to pointer to the current callback frame // in kernel stack. // DWORD ThCallbackStack; // // offset in thread object to pointer to the current callback backing // store frame in kernel stack. // DWORD ThCallbackBStore; // // offsets to values in frame: // // address of next callback frame DWORD NextCallback; // address of saved frame pointer (if applicable) DWORD FramePointer; // // Address of the kernel function that calls out to user mode // DWORD64 KiCallUserMode; // // Address of the user mode dispatcher function // DWORD64 KeUserCallbackDispatcher; // // Lowest kernel mode address // DWORD64 SystemRangeStart; // // Address of the user mode exception dispatcher function. // Added in API version 10. // DWORD64 KiUserExceptionDispatcher; // // Stack bounds, added in API version 11. // DWORD64 StackBase; DWORD64 StackLimit; DWORD64 Reserved[5]; } KDHELP64, *PKDHELP64; #if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) #define KDHELP KDHELP64 #define PKDHELP PKDHELP64 #else typedef struct _KDHELP { // // address of kernel thread object, as provided in the // WAIT_STATE_CHANGE packet. // DWORD Thread; // // offset in thread object to pointer to the current callback frame // in kernel stack. // DWORD ThCallbackStack; // // offsets to values in frame: // // address of next callback frame DWORD NextCallback; // address of saved frame pointer (if applicable) DWORD FramePointer; // // Address of the kernel function that calls out to user mode // DWORD KiCallUserMode; // // Address of the user mode dispatcher function // DWORD KeUserCallbackDispatcher; // // Lowest kernel mode address // DWORD SystemRangeStart; // // offset in thread object to pointer to the current callback backing // store frame in kernel stack. // DWORD ThCallbackBStore; // // Address of the user mode exception dispatcher function. // Added in API version 10. // DWORD KiUserExceptionDispatcher; // // Stack bounds, added in API version 11. // DWORD StackBase; DWORD StackLimit; DWORD Reserved[5]; } KDHELP, *PKDHELP; #endif typedef struct _tagSTACKFRAME64 { ADDRESS64 AddrPC; // program counter ADDRESS64 AddrReturn; // return address ADDRESS64 AddrFrame; // frame pointer ADDRESS64 AddrStack; // stack pointer ADDRESS64 AddrBStore; // backing store pointer PVOID FuncTableEntry; // pointer to pdata/fpo or NULL DWORD64 Params[4]; // possible arguments to the function BOOL Far; // WOW far call BOOL Virtual; // is this a virtual frame? DWORD64 Reserved[3]; KDHELP64 KdHelp; } STACKFRAME64, *LPSTACKFRAME64; #if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) #define STACKFRAME STACKFRAME64 #define LPSTACKFRAME LPSTACKFRAME64 #else typedef struct _tagSTACKFRAME { ADDRESS AddrPC; // program counter ADDRESS AddrReturn; // return address ADDRESS AddrFrame; // frame pointer ADDRESS AddrStack; // stack pointer PVOID FuncTableEntry; // pointer to pdata/fpo or NULL DWORD Params[4]; // possible arguments to the function BOOL Far; // WOW far call BOOL Virtual; // is this a virtual frame? DWORD Reserved[3]; KDHELP KdHelp; ADDRESS AddrBStore; // backing store pointer } STACKFRAME, *LPSTACKFRAME; #endif // // module data structure // typedef struct _IMAGEHLP_MODULE64 { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) DWORD64 BaseOfImage; // base load address of module DWORD ImageSize; // virtual size of the loaded module DWORD TimeDateStamp; // date/time stamp from pe header DWORD CheckSum; // checksum from the pe header DWORD NumSyms; // number of symbols in the symbol table SYM_TYPE SymType; // type of symbols loaded CHAR ModuleName[32]; // module name CHAR ImageName[256]; // image name // new elements: 07-Jun-2002 CHAR LoadedImageName[256]; // symbol file name CHAR LoadedPdbName[256]; // pdb file name DWORD CVSig; // Signature of the CV record in the debug directories CHAR CVData[MAX_PATH * 3]; // Contents of the CV record DWORD PdbSig; // Signature of PDB GUID PdbSig70; // Signature of PDB (VC 7 and up) DWORD PdbAge; // DBI age of pdb BOOL PdbUnmatched; // loaded an unmatched pdb BOOL DbgUnmatched; // loaded an unmatched dbg BOOL LineNumbers; // we have line number information BOOL GlobalSymbols; // we have internal symbol information BOOL TypeInfo; // we have type information // new elements: 17-Dec-2003 BOOL SourceIndexed; // pdb supports source server BOOL Publics; // contains public symbols } IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64; typedef struct _IMAGEHLP_MODULEW64 { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) DWORD64 BaseOfImage; // base load address of module DWORD ImageSize; // virtual size of the loaded module DWORD TimeDateStamp; // date/time stamp from pe header DWORD CheckSum; // checksum from the pe header DWORD NumSyms; // number of symbols in the symbol table SYM_TYPE SymType; // type of symbols loaded WCHAR ModuleName[32]; // module name WCHAR ImageName[256]; // image name // new elements: 07-Jun-2002 WCHAR LoadedImageName[256]; // symbol file name WCHAR LoadedPdbName[256]; // pdb file name DWORD CVSig; // Signature of the CV record in the debug directories WCHAR CVData[MAX_PATH * 3]; // Contents of the CV record DWORD PdbSig; // Signature of PDB GUID PdbSig70; // Signature of PDB (VC 7 and up) DWORD PdbAge; // DBI age of pdb BOOL PdbUnmatched; // loaded an unmatched pdb BOOL DbgUnmatched; // loaded an unmatched dbg BOOL LineNumbers; // we have line number information BOOL GlobalSymbols; // we have internal symbol information BOOL TypeInfo; // we have type information // new elements: 17-Dec-2003 BOOL SourceIndexed; // pdb supports source server BOOL Publics; // contains public symbols } IMAGEHLP_MODULEW64, *PIMAGEHLP_MODULEW64; #if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) #define IMAGEHLP_MODULE IMAGEHLP_MODULE64 #define PIMAGEHLP_MODULE PIMAGEHLP_MODULE64 #define IMAGEHLP_MODULEW IMAGEHLP_MODULEW64 #define PIMAGEHLP_MODULEW PIMAGEHLP_MODULEW64 #else typedef struct _IMAGEHLP_MODULE { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE) DWORD BaseOfImage; // base load address of module DWORD ImageSize; // virtual size of the loaded module DWORD TimeDateStamp; // date/time stamp from pe header DWORD CheckSum; // checksum from the pe header DWORD NumSyms; // number of symbols in the symbol table SYM_TYPE SymType; // type of symbols loaded CHAR ModuleName[32]; // module name CHAR ImageName[256]; // image name CHAR LoadedImageName[256]; // symbol file name } IMAGEHLP_MODULE, *PIMAGEHLP_MODULE; typedef struct _IMAGEHLP_MODULEW { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE) DWORD BaseOfImage; // base load address of module DWORD ImageSize; // virtual size of the loaded module DWORD TimeDateStamp; // date/time stamp from pe header DWORD CheckSum; // checksum from the pe header DWORD NumSyms; // number of symbols in the symbol table SYM_TYPE SymType; // type of symbols loaded WCHAR ModuleName[32]; // module name WCHAR ImageName[256]; // image name WCHAR LoadedImageName[256]; // symbol file name } IMAGEHLP_MODULEW, *PIMAGEHLP_MODULEW; #endif // // source file line data structure // typedef struct _IMAGEHLP_LINE64 { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE64) PVOID Key; // internal DWORD LineNumber; // line number in file PCHAR FileName; // full filename DWORD64 Address; // first instruction of line } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64; typedef struct _IMAGEHLP_LINEW64 { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE64) PVOID Key; // internal DWORD LineNumber; // line number in file PWSTR FileName; // full filename DWORD64 Address; // first instruction of line } IMAGEHLP_LINEW64, *PIMAGEHLP_LINEW64; #if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) #define IMAGEHLP_LINE IMAGEHLP_LINE64 #define PIMAGEHLP_LINE PIMAGEHLP_LINE64 #else typedef struct _IMAGEHLP_LINE { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE) PVOID Key; // internal DWORD LineNumber; // line number in file PCHAR FileName; // full filename DWORD Address; // first instruction of line } IMAGEHLP_LINE, *PIMAGEHLP_LINE; typedef struct _IMAGEHLP_LINEW { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_LINE64) PVOID Key; // internal DWORD LineNumber; // line number in file PCHAR FileName; // full filename DWORD64 Address; // first instruction of line } IMAGEHLP_LINEW, *PIMAGEHLP_LINEW; #endif // // source file structure // typedef struct _SOURCEFILE { DWORD64 ModBase; // base address of loaded module PCHAR FileName; // full filename of source } SOURCEFILE, *PSOURCEFILE; typedef struct _SOURCEFILEW { DWORD64 ModBase; // base address of loaded module PWSTR FileName; // full filename of source } SOURCEFILEW, *PSOURCEFILEW; typedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)( HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead ); typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess, DWORD64 AddrBase ); typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)( HANDLE hProcess, DWORD64 Address ); typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)( HANDLE hProcess, HANDLE hThread, LPADDRESS64 lpaddr ); typedef BOOL (IMAGEAPI *PFN_StackWalk64) ( DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress ); #if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) #define PREAD_PROCESS_MEMORY_ROUTINE PREAD_PROCESS_MEMORY_ROUTINE64 #define PFUNCTION_TABLE_ACCESS_ROUTINE PFUNCTION_TABLE_ACCESS_ROUTINE64 #define PGET_MODULE_BASE_ROUTINE PGET_MODULE_BASE_ROUTINE64 #define PTRANSLATE_ADDRESS_ROUTINE PTRANSLATE_ADDRESS_ROUTINE64 #define PFN_StackWalk PFN_StackWalk64 #else typedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE)( HANDLE hProcess, DWORD lpBaseAddress, PVOID lpBuffer, DWORD nSize, PDWORD lpNumberOfBytesRead ); typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE)( HANDLE hProcess, DWORD AddrBase ); typedef DWORD (__stdcall *PGET_MODULE_BASE_ROUTINE)( HANDLE hProcess, DWORD Address ); typedef DWORD (__stdcall *PTRANSLATE_ADDRESS_ROUTINE)( HANDLE hProcess, HANDLE hThread, LPADDRESS lpaddr ); typedef BOOL (IMAGEAPI *PFN_StackWalk) ( DWORD MachineType, HANDLE hProcess, HANDLE hThread, LPSTACKFRAME StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE TranslateAddress ); #endif typedef PVOID (IMAGEAPI * PFN_SymFunctionTableAccess64) ( HANDLE hProcess, DWORD64 AddrBase ); #if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) #define PFN_SymFunctionTableAccess PFN_SymFunctionTableAccess64 #else typedef PVOID (IMAGEAPI *PFN_SymFunctionTableAccess) ( HANDLE hProcess, DWORD AddrBase ); #endif typedef DWORD64 (IMAGEAPI *PFN_SymGetModuleBase64) ( HANDLE hProcess, DWORD64 qwAddr ); #if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) #define PFN_SymGetModuleBase PFN_SymGetModuleBase64 #else typedef DWORD (IMAGEAPI *PFN_SymGetModuleBase) ( HANDLE hProcess, DWORD dwAddr ); #endif typedef BOOL (IMAGEAPI *PFN_SymGetSymFromAddr64) ( HANDLE hProcess, DWORD64 qwAddr, PDWORD64 pdwDisplacement, PIMAGEHLP_SYMBOL64 Symbol ); #if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) #define PFN_SymGetSymFromAddr PFN_SymGetSymFromAddr64 #else typedef BOOL (IMAGEAPI *PFN_SymGetSymFromAddr) ( HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_SYMBOL Symbol ); #endif typedef BOOL (IMAGEAPI *PFN_SymGetLineFromAddr64) ( HANDLE hProcess, DWORD64 qwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line64 ); typedef BOOL (IMAGEAPI *PFN_SymGetLineFromAddrW64) ( HANDLE hProcess, DWORD64 qwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINEW64 Line64 ); #if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) #define PFN_SymGetLineFromAddr PFN_SymGetLineFromAddr64 #define PFN_SymGetLineFromAddrW PFN_SymGetLineFromAddrW64 #else typedef BOOL (IMAGEAPI *PFN_SymGetLineFromAddr) ( HANDLE hProcess, DWORD dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE Line ); #endif typedef BOOL (IMAGEAPI *PFN_SymGetModuleInfo64) ( HANDLE hProcess, DWORD64 qwAddr, PIMAGEHLP_MODULE64 ModuleInfo ); typedef BOOL (IMAGEAPI *PFN_SymGetModuleInfoW64) ( HANDLE hProcess, DWORD64 qwAddr, PIMAGEHLP_MODULEW64 ModuleInfo ); #if !defined(_IMAGEHLP_SOURCE_) && defined(_IMAGEHLP64) #define PFN_SymGetModuleInfo PFN_SymGetModuleInfo64 #define PFN_SymGetModuleInfoW PFN_SymGetModuleInfoW64 #else typedef BOOL (IMAGEAPI *PFN_SymGetModuleInfo) ( HANDLE hProcess, DWORD dwAddr, PIMAGEHLP_MODULE ModuleInfo ); typedef BOOL (IMAGEAPI *PFN_SymGetModuleInfoW) ( HANDLE hProcess, DWORD dwAddr, PIMAGEHLP_MODULEW ModuleInfo ); #endif #endif /* _DBGHELP_ */ typedef BOOL (IMAGEAPI *PFN_SymCleanup) ( HANDLE hProcess ); typedef BOOL (IMAGEAPI *PFN_SymInitialize) ( HANDLE hProcess, PCSTR UserSearchPath, BOOL fInvadeProcess ); HMODULE g_hModuleDbgHelp = NULL; HGLOBAL g_hGlobalSym = NULL; const DWORD g_dwImageHelpSize = 10000; PFN_SymCleanup g_pfn_SymCleanup = NULL; PFN_SymInitialize g_pfn_SymInitialize = NULL; PFN_SymFunctionTableAccess g_pfn_SymFunctionTableAccess = NULL; PFN_SymGetModuleBase g_pfn_SymGetModuleBase = NULL; PFN_SymGetSymFromAddr g_pfn_SymGetSymFromAddr = NULL; PFN_SymGetLineFromAddr g_pfn_SymGetLineFromAddr = NULL; PFN_SymGetModuleInfo g_pfn_SymGetModuleInfo = NULL; PFN_StackWalk g_pfn_StackWalk = NULL; char g_strMiniDump[4*1024]; char g_strExeName[2*1024]; static LPTOP_LEVEL_EXCEPTION_FILTER g_pfn_OrigFilter = NULL; static LONG __stdcall CrashHandlerExceptionFilter( EXCEPTION_POINTERS * pExPtrs ); unsigned int WINAPI DumpStackTrace( LPVOID pData ) { //fprintf( stderr, "DumpStackTrace: start\n" ); EXCEPTION_POINTERS * pExPtrs = (EXCEPTION_POINTERS *)pData; if ( pExPtrs == NULL ) { return FALSE; } HANDLE hProcess = NULL; hProcess = ::GetCurrentProcess(); HANDLE hThread = NULL; hThread = ::GetCurrentThread(); STACKFRAME sf; PIMAGEHLP_SYMBOL pSym = NULL; pSym = (PIMAGEHLP_SYMBOL)::GlobalLock( g_hGlobalSym ); if ( pSym == NULL ) { return FALSE; } ZeroMemory( pSym, sizeof(IMAGEHLP_SYMBOL) ); pSym->SizeOfStruct = g_dwImageHelpSize; pSym->MaxNameLength = g_dwImageHelpSize - sizeof(IMAGEHLP_SYMBOL); ZeroMemory( &(sf), sizeof(sf) ); #if defined(_M_AMD64) sf.AddrPC.Offset = pExPtrs->ContextRecord->Rip; sf.AddrStack.Offset = pExPtrs->ContextRecord->Rsp; sf.AddrFrame.Offset = pExPtrs->ContextRecord->Rbp; #endif #if defined(_M_IX86) sf.AddrPC.Offset = pExPtrs->ContextRecord->Eip; sf.AddrStack.Offset = pExPtrs->ContextRecord->Esp; sf.AddrFrame.Offset = pExPtrs->ContextRecord->Ebp; #endif #if defined(_M_IA64) // 実機検証できていません sf.AddrPC.Offset = pExPtrs->ContextRecord->StIIP; sf.AddrStack.Offset = pExPtrs->ContextRecord->IntSp; sf.AddrFrame.Offset = pExPtrs->ContextRecord->RsBSP; sf.AddrBStore.Offset = pExPtrs->ContextRecord->RsBSP; #endif sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Mode = AddrModeFlat; g_pfn_SymInitialize( hProcess, NULL, TRUE ); for ( ; ; ) { BOOL BRet = g_pfn_StackWalk( #if defined(_M_AMD64) IMAGE_FILE_MACHINE_AMD64, #endif #if defined(_M_IA64) IMAGE_FILE_MACHINE_IA64, #endif #if defined(_M_IX86) IMAGE_FILE_MACHINE_I386, #endif hProcess, hThread, &(sf), #if defined(_M_IX86) NULL, #else &(pExPtrs->ContextRecord), #endif NULL, g_pfn_SymFunctionTableAccess, g_pfn_SymGetModuleBase, NULL ); if ( ! BRet ) { //fprintf( stderr, "StackWalk: failed\n" ); break; } if ( sf.AddrFrame.Offset == 0 ) { break; } #if defined(_IMAGEHLP64) DWORD64 dwDisp; #else DWORD dwDisp; #endif BOOL BRetSymFromAddr = FALSE; BRetSymFromAddr = g_pfn_SymGetSymFromAddr( hProcess, sf.AddrPC.Offset, &dwDisp, pSym ); #if defined(_IMAGEHLP64) if ( BRetSymFromAddr ) { printf( "0x%016X %s() + 0x%x\n", sf.AddrPC.Offset, pSym->Name, dwDisp ); } else { printf( "0x%016X\n", sf.AddrPC.Offset ); } #else if ( BRetSymFromAddr ) { printf( "0x%08X %s() + 0x%x\n", sf.AddrPC.Offset, pSym->Name, dwDisp ); } else { printf( "0x%08X\n", sf.AddrPC.Offset ); } #endif IMAGEHLP_MODULE ih_module; ZeroMemory( &(ih_module), sizeof(ih_module) ); ih_module.SizeOfStruct = sizeof(ih_module); BRet = g_pfn_SymGetModuleInfo( hProcess, sf.AddrPC.Offset, &(ih_module) ); if ( BRet ) { printf( " %s\n", ih_module.ImageName ); } else { printf( " %s\n", "" ); } { DWORD dwDisp; IMAGEHLP_LINE ih_line; ZeroMemory( &(ih_line), sizeof(ih_line) ); ih_line.SizeOfStruct = sizeof(ih_line); BRet = g_pfn_SymGetLineFromAddr( hProcess, sf.AddrPC.Offset, &dwDisp, &ih_line ); if ( BRet ) { printf( " %s(%lu)\n", ih_line.FileName, ih_line.LineNumber ); } } } // for ( ; ; ) g_pfn_SymCleanup( hProcess ); ::GlobalUnlock( g_hGlobalSym ); pSym = NULL; return TRUE; } static LONG __stdcall CrashHandlerExceptionFilter( EXCEPTION_POINTERS * pExPtrs ) { //LONG lRet = EXCEPTION_CONTINUE_SEARCH; LONG lRet = EXCEPTION_EXECUTE_HANDLER; if ( g_hModuleDbgHelp == NULL ) { return lRet; } #if 0 { unsigned int dwThreadId = 0; HANDLE hThread = (HANDLE) ::_beginthreadex( NULL, 0, DumpStackTrace, pExPtrs, 0, &dwThreadId ); if ( hThread != (HANDLE)-1 ) { ::WaitForSingleObject( hThread, INFINITE ); ::CloseHandle( hThread ); hThread = NULL; } } #else DumpStackTrace( pExPtrs ); #endif return lRet; } void setMyCrashHandler( void ) { g_pfn_OrigFilter = ::SetUnhandledExceptionFilter( CrashHandlerExceptionFilter ); } void unsetMyCrashHandler( void ) { if ( g_pfn_OrigFilter ) { ::SetUnhandledExceptionFilter( g_pfn_OrigFilter ); } } void crashMe( void ) { int i = 10; int j = 0; int k = 0; k = i/j; } int main(int argc, char* argv[]) { printf("Hello World!\n"); g_hModuleDbgHelp = NULL; g_hModuleDbgHelp = ::LoadLibrary( "dbghelp.dll" ); if ( g_hModuleDbgHelp ) { g_pfn_SymCleanup = (PFN_SymCleanup)::GetProcAddress( g_hModuleDbgHelp, "SymCleanup" ); g_pfn_SymInitialize = (PFN_SymInitialize)::GetProcAddress( g_hModuleDbgHelp, "SymInitialize" ); #if defined(_IMAGEHLP64) g_pfn_SymFunctionTableAccess = (PFN_SymFunctionTableAccess)::GetProcAddress( g_hModuleDbgHelp, "SymFunctionTableAccess64" ); g_pfn_SymGetModuleBase = (PFN_SymGetModuleBase)::GetProcAddress( g_hModuleDbgHelp, "SymGetModuleBase64" ); g_pfn_SymGetSymFromAddr = (PFN_SymGetSymFromAddr)::GetProcAddress( g_hModuleDbgHelp, "SymGetSymFromAddr64" ); g_pfn_SymGetLineFromAddr = (PFN_SymGetLineFromAddr)::GetProcAddress( g_hModuleDbgHelp, "SymGetLineFromAddr64" ); g_pfn_SymGetModuleInfo = (PFN_SymGetModuleInfo)::GetProcAddress( g_hModuleDbgHelp, "SymGetModuleInfo64" ); g_pfn_StackWalk = (PFN_StackWalk)::GetProcAddress( g_hModuleDbgHelp, "StackWalk64" ); #else g_pfn_SymFunctionTableAccess = (PFN_SymFunctionTableAccess)::GetProcAddress( g_hModuleDbgHelp, "SymFunctionTableAccess" ); g_pfn_SymGetModuleBase = (PFN_SymGetModuleBase)::GetProcAddress( g_hModuleDbgHelp, "SymGetModuleBase" ); g_pfn_SymGetSymFromAddr = (PFN_SymGetSymFromAddr)::GetProcAddress( g_hModuleDbgHelp, "SymGetSymFromAddr" ); g_pfn_SymGetLineFromAddr = (PFN_SymGetLineFromAddr)::GetProcAddress( g_hModuleDbgHelp, "SymGetLineFromAddr" ); g_pfn_SymGetModuleInfo = (PFN_SymGetModuleInfo)::GetProcAddress( g_hModuleDbgHelp, "SymGetModuleInfo" ); g_pfn_StackWalk = (PFN_StackWalk)::GetProcAddress( g_hModuleDbgHelp, "StackWalk" ); #endif g_hGlobalSym = ::GlobalAlloc(GMEM_FIXED, g_dwImageHelpSize); } setMyCrashHandler(); crashMe(); unsetMyCrashHandler(); if ( g_hModuleDbgHelp ) { ::GlobalFree( g_hGlobalSym ); g_hGlobalSym = NULL; g_pfn_SymCleanup = NULL; g_pfn_SymInitialize = NULL; g_pfn_SymFunctionTableAccess = NULL; g_pfn_SymGetModuleBase = NULL; g_pfn_SymGetSymFromAddr = NULL; g_pfn_SymGetLineFromAddr = NULL; g_pfn_SymGetModuleInfo = NULL; g_pfn_StackWalk = NULL; ::FreeLibrary( g_hModuleDbgHelp ); g_hModuleDbgHelp = NULL; } return 0; }