#include "stdafx.h" #ifdef WIN_PLATFORM #include #include #include "CrashHandle.h" #include "CommonFunction.h" using namespace std; //处理CRT runtime error引发的InvalidParameter 如果使用非Debug版CRT库,则参数都为NULL void InvalidParameterHandler( const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved ) { if ( !expression && !function && !file ) return; wchar_t szInvalidParamMsg[MAXSTRINGLEN]; wsprintf( szInvalidParamMsg, L"Invalid parameter detected in function %s. File: %s Line: %d\n", function, file, line ); ofstream of("CrtReport.txt",ios::ate|ios::app); of<< convert_wbcs_to_utf8( szInvalidParamMsg ) <ExceptionCode, exception_string(exception->ExceptionCode)); if ( exception->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ) { DUMP_PRINT( "Attempt to %s data at adress %p\r\n\r\n", exception->ExceptionInformation[0]?"write":"read", exception->ExceptionInformation[1] ); } DUMP_PRINT("\r\n----------------------------------------\r\nx86 Registers\r\n----------------------------------------\r\n"); DUMP_PRINT("eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\r\n", context->Eax, context->Ebx, context->Ecx, context->Edx, context->Esi, context->Edi); DUMP_PRINT( "eip=%08x esp=%08x ebp=%08x efl=%08x\r\n", context->Eip, context->Esp, context->Ebp, context->EFlags ); DUMP_PRINT( "cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x\r\n", context->SegCs, context->SegSs, context->SegDs, context->SegEs, context->SegFs, context->SegGs ); #if defined(_M_IX86) DUMP_PRINT( "eax=%08x ebx=%08x ecx=%08x edx=%08x esi=%08x edi=%08x\r\n", context->Eax, context->Ebx, context->Ecx, context->Edx, context->Esi, context->Edi); DUMP_PRINT( "eip=%08x esp=%08x ebp=%08x efl=%08x\r\n", context->Eip, context->Esp, context->Ebp, context->EFlags); DUMP_PRINT( "cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x\r\n", context->SegCs, context->SegSs, context->SegDs, context->SegEs, context->SegFs, context->SegGs); #elif defined(_M_X64) DUMP_PRINT( "Rax=%016I64x Rcx=%016I64x Rdx=%016I64x Rbx=%016I64x\r\n", context->Rax, context->Rcx, context->Rdx, context->Rbx); DUMP_PRINT( "Rsp=%016I64x Rbp=%016I64x Rsi=%016I64x Rdi=%016I64x\r\n", context->Rsp, context->Rbp, context->Rsi, context->Rdi); DUMP_PRINT( "R8= %016I64x R9= %016I64x R10= %016I64x R11=%016I64x\r\n", context->R8, context->R9, context->R10, context->R11); DUMP_PRINT( "R12=%016I64x R13=%016I64x R14=%016I64x R15=%016I64x\r\n", context->R12, context->R13, context->R14, context->R15); DUMP_PRINT( "cs=%04x ss=%04x ds=%04x es=%04x fs=%04x gs=%04x ss=%04x\r\n", context->SegCs, context->SegDs, context->SegEs, context->SegFs, context->SegGs, context->SegSs); #endif DUMP_PRINT("\r\n\r\n\r\n"); } } void CExceptionReport::Dump_CallStack(CONTEXT *context) { if ( !context ) return; DWORD dwOpts = SymGetOptions(); SymSetOptions ( dwOpts|SYMOPT_LOAD_LINES) ; STACKFRAME64 sf; memset( &sf, 0x0, sizeof(STACKFRAME64) ); sf.AddrPC.Offset = context->Eip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Offset = context->Esp; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Offset = context->Ebp; sf.AddrFrame.Mode = AddrModeFlat; #ifdef _X86_ #define CH_MACHINE IMAGE_FILE_MACHINE_I386 #elif _AMD64_ #define CH_MACHINE IMAGE_FILE_MACHINE_AMD64 #elif _IA64_ #define CH_MACHINE IMAGE_FILE_MACHINE_IA64 #endif DWORD machineType = CH_MACHINE; HANDLE hProcess = GetCurrentProcess(); HANDLE hThread = GetCurrentThread(); DUMP_PRINT("\r\n----------------------------------------\r\nStack Trace (Using DBGHELP.DLL)\r\n----------------------------------------\r\n"); int i = 0; for (;;) { //遍历堆栈祯 if( !StackWalk64( machineType, hProcess, hThread, &sf, context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL ) ) { break; } if ( sf.AddrFrame.Offset == 0 ) { break; } //获取模块信息 DWORD64 dwModBase ; dwModBase = SymGetModuleBase64 ( GetCurrentProcess ( ) , sf.AddrPC.Offset ) ; if ( 0 == dwModBase ) { break; } //打印模块起始端地址和函数偏移地址 DUMP_PRINT ("\r\n%04X:%08X ",context->SegCs, sf.AddrPC.Offset ); BYTE symbolBuffer[ MAXSTRINGLEN ]; PIMAGEHLP_SYMBOL64 pSymbol = (PIMAGEHLP_SYMBOL64)&symbolBuffer ; ZeroMemory ( pSymbol , MAXSTRINGLEN ) ; pSymbol->SizeOfStruct = sizeof ( IMAGEHLP_SYMBOL64 ) ; pSymbol->MaxNameLength = MAXSTRINGLEN - sizeof ( IMAGEHLP_SYMBOL64 ) ; pSymbol->Address = sf.AddrPC.Offset ; DWORD64 symDisplacement = 0; //获取这个地址所指向的信息 if ( SymGetSymFromAddr64( hProcess,sf.AddrPC.Offset, &symDisplacement,pSymbol) ) { //打印函数名 DUMP_PRINT("%s",pSymbol->Name); #ifdef _WIN64 #define k_PARAMFMTSTRING ( " (0x%016X 0x%016X 0x%016X 0x%016X)" ) #else #define k_PARAMFMTSTRING ( " (0x%08X 0x%08X 0x%08X 0x%08X)" ) #endif //打印函数的参数 DUMP_PRINT ( k_PARAMFMTSTRING , sf.Params[ 0 ] , sf.Params[ 1 ] , sf.Params[ 2 ] , sf.Params[ 3 ] ) ; IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) }; DWORD dwLineDisplacement; if ( SymGetLineFromAddr64( hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo ) == TRUE ) { DUMP_PRINT(" In %s Line:%d\r\n", StorkFileName(lineInfo.FileName ), lineInfo.LineNumber ); } } } } void CExceptionReport::ExceptionHandle(LPEXCEPTION_POINTERS lpEP) { if ( SymInitialize(GetCurrentProcess(),NULL,TRUE) ) { //1创建dump包 CreateMiniDump(); if ( mdumpFile.Init() ) { //2记录CPU信息 Dump_ProcessInfo( lpEP->ExceptionRecord, lpEP->ContextRecord ); //3记录调用堆栈 Dump_CallStack( lpEP->ContextRecord ); } SymCleanup(GetCurrentProcess()); } } #endif