BOOL CALLBACK DebugInfoCallback ( HANDLE /* hProcess */ , ULONG ActionCode, ULONG64 CallbackData, ULONG64 UserContext ) { // Note: This function should return TRUE only if it handles the event, // otherwise it must return FALSE (see documentation). CSymbolEngine* pEngine = (CSymbolEngine*)UserContext; if( pEngine == 0 ) { _ASSERTE( !_T("Engine pointer is null.") ); return FALSE; } if( ActionCode == CBA_DEBUG_INFO ) { if( CallbackData != 0 ) { _ASSERTE( !::IsBadStringPtr( (const TCHAR*)CallbackData, UINT_MAX ) ); pEngine->OnEngineNotify( TString( (const TCHAR*)CallbackData ) ); return TRUE; } } return FALSE; }
static DWORD64 __stdcall GetModBase ( HANDLE hProcess , DWORD64 dwAddr ) #endif { // Check in the symbol engine first. IMAGEHLP_MODULE stIHM ; // This is what the MFC stack trace routines forgot to do so their // code will not get the info out of the symbol engine. stIHM.SizeOfStruct = sizeof ( IMAGEHLP_MODULE ) ; if ( g_cSym.SymGetModuleInfo ( dwAddr , &stIHM ) ) { return ( stIHM.BaseOfImage ) ; } else { // Let's go fishing. MEMORY_BASIC_INFORMATION stMBI ; if ( 0 != VirtualQueryEx ( hProcess , (LPCVOID)dwAddr , &stMBI , sizeof ( stMBI ) ) ) { // Try and load it. DWORD dwNameLen = 0 ; TCHAR szFile[ MAX_PATH ] ; dwNameLen = GetModuleFileName ( (HINSTANCE) stMBI.AllocationBase , szFile , MAX_PATH ); HANDLE hFile = NULL ; if ( 0 != dwNameLen ) { hFile = CreateFile ( szFile , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , 0 , 0 ) ; } g_cSym.SymLoadModule ( hFile , ( dwNameLen ? szFile : NULL ) , NULL , (DWORD)stMBI.AllocationBase , 0 ) ; return ( (DWORD)stMBI.AllocationBase ) ; } } return ( 0 ) ; }
void xrCore::_initialize (LPCSTR _ApplicationName, LogCallback cb, BOOL init_fs, LPCSTR fs_fname) { strcpy_s (ApplicationName,_ApplicationName); if (0==init_counter) { #ifdef XRCORE_STATIC _clear87 (); _control87 ( _PC_53, MCW_PC ); _control87 ( _RC_CHOP, MCW_RC ); _control87 ( _RC_NEAR, MCW_RC ); _control87 ( _MCW_EM, MCW_EM ); #endif // Init COM so we can use CoCreateInstance // HRESULT co_res = CoInitializeEx (NULL, COINIT_MULTITHREADED); strcpy_s (Params,sizeof(Params),GetCommandLine()); _strlwr_s (Params,sizeof(Params)); string_path fn,dr,di; // application path GetModuleFileName(GetModuleHandle(MODULE_NAME),fn,sizeof(fn)); _splitpath (fn,dr,di,0,0); strconcat (sizeof(ApplicationPath),ApplicationPath,dr,di); #ifndef _EDITOR strcpy_s (g_application_path,sizeof(g_application_path),ApplicationPath); #endif // working path if( strstr(Params,"-wf") ) { string_path c_name; sscanf (strstr(Core.Params,"-wf ")+4,"%[^ ] ",c_name); SetCurrentDirectory (c_name); } GetCurrentDirectory(sizeof(WorkingPath),WorkingPath); // User/Comp Name DWORD sz_user = sizeof(UserName); GetUserName (UserName,&sz_user); DWORD sz_comp = sizeof(CompName); GetComputerName (CompName,&sz_comp); // Mathematics & PSI detection CPU::Detect (); Memory._initialize (strstr(Params,"-mem_debug") ? TRUE : FALSE); DUMP_PHASE; InitLog (); _initialize_cpu (); #ifdef DEBUG #ifndef DEDICATED_SERVER Debug._initialize (FALSE); #else Debug._initialize (TRUE); #endif #endif rtc_initialize (); xr_FS = xr_new<CLocatorAPI> (); xr_EFS = xr_new<EFS_Utils> (); //. R_ASSERT (co_res==S_OK); } if (init_fs){ u32 flags = 0; if (0!=strstr(Params,"-build")) flags |= CLocatorAPI::flBuildCopy; if (0!=strstr(Params,"-ebuild")) flags |= CLocatorAPI::flBuildCopy|CLocatorAPI::flEBuildCopy; #ifdef DEBUG if (strstr(Params,"-cache")) flags |= CLocatorAPI::flCacheFiles; else flags &= ~CLocatorAPI::flCacheFiles; #endif // DEBUG #ifdef _EDITOR // for EDITORS - no cache flags &=~ CLocatorAPI::flCacheFiles; #endif // _EDITOR flags |= CLocatorAPI::flScanAppRoot; #ifndef _EDITOR #ifndef ELocatorAPIH if (0!=strstr(Params,"-file_activity")) flags |= CLocatorAPI::flDumpFileActivity; #endif #endif FS._initialize (flags,0,fs_fname); Msg ("'%s' build %d, %s\n","xrCore",build_id, build_date); EFS._initialize (); #ifdef DEBUG #ifndef _EDITOR Msg ("CRT heap 0x%08x",_get_heap_handle()); Msg ("Process heap 0x%08x",GetProcessHeap()); #endif #endif // DEBUG } SetLogCB (cb); LPAPI_VERSION ver = ImagehlpApiVersion(); if ( NULL == GetProcAddress ( GetModuleHandle("dbghelp.dll"), "EnumerateLoadedModulesEx") ) { string256 msg; DWORD dwVer[2]; WORD *v4 = (WORD*) &dwVer; CSymbolEngine SE; SE.GetInMemoryFileVersion("dbghelp.dll", dwVer[0], dwVer[1]); sprintf_s(msg, 256, "”старевший файл dbghelp.dll (%d.%d.%d.%d), его рекомендуетс¤ удалить.", v4[1], v4[0], v4[3], v4[2]); MessageBox(NULL, msg, "DebugHlp Warning", MB_OK); } init_counter++; }
void DoStackTrace ( LPTSTR szString , DWORD dwSize ) { HANDLE hProcess = GetCurrentProcess ( ) ; // If the symbol engine is not initialized, do it now. if ( FALSE == g_bSymIsInit ) { DWORD dwOpts = SymGetOptions ( ) ; // Turn on load lines. SymSetOptions ( dwOpts | SYMOPT_LOAD_LINES ) ; if ( FALSE == g_cSym.SymInitialize ( hProcess , NULL , FALSE ) ) { TRACE ( "DiagAssert : Unable to initialize the " "symbol engine!!!\n" ) ; #ifdef _DEBUG DebugBreak ( ) ; #endif } else { g_bSymIsInit = TRUE ; } } // The symbol engine is initialized so do the stack walk. // The array of addresses. ADDRVECTOR vAddrs ; // The thread information. CONTEXT stCtx ; stCtx.ContextFlags = CONTEXT_FULL ; // Get the thread context. Since I am doing this on the CURRENT // executing thread, the context will be from down in the bowls of // KERNEL32.DLL. Probably GetThreadContext itself. if ( GetThreadContext ( GetCurrentThread ( ) , &stCtx ) ) { STACKFRAME stFrame ; DWORD dwMachine ; ZeroMemory ( &stFrame , sizeof ( STACKFRAME ) ) ; stFrame.AddrPC.Mode = AddrModeFlat ; #if defined (_M_IX86) dwMachine = IMAGE_FILE_MACHINE_I386 ; stFrame.AddrPC.Offset = stCtx.Eip ; stFrame.AddrStack.Offset = stCtx.Esp ; stFrame.AddrFrame.Offset = stCtx.Ebp ; stFrame.AddrStack.Mode = AddrModeFlat ; stFrame.AddrFrame.Mode = AddrModeFlat ; #elif defined (_M_ALPHA) dwMachine = IMAGE_FILE_MACHINE_ALPHA ; stFrame.AddrPC.Offset = (unsigned long)stCtx.Fir ; #else #error ( "Unknown machine!" ) #endif // Loop for the first 512 stack elements. for ( DWORD i = 0 ; i < 512 ; i++ ) { if ( FALSE == StackWalk ( dwMachine , hProcess , hProcess , &stFrame , &stCtx , NULL , SymFunctionTableAccess , GetModBase , NULL ) ) { break ; } // Also check that the address is not zero. Sometimes // StackWalk returns TRUE with a frame of zero. if ( 0 != stFrame.AddrPC.Offset ) { vAddrs.push_back ( stFrame.AddrPC.Offset ) ; } } // Now start converting the addresses. DWORD dwSizeLeft = dwSize ; DWORD dwSymSize ; TCHAR szSym [ MAX_PATH * 2 ] ; LPTSTR szCurrPos = szString ; BOOL bSeenDiagAssert = FALSE ; ADDRVECTOR::iterator loop ; for ( loop = vAddrs.begin ( ) ; loop != vAddrs.end ( ) ; loop++ ) { dwSymSize = ConvertAddress ( *loop , szSym ) ; // Throw out everything with DiagAssert.cpp in it. if ( _tcsstr ( szSym , _T ( "DiagAssert.cpp" ) ) ) { bSeenDiagAssert = TRUE ; continue ; } // Throw out anything before the functions in // DiagAssert.cpp if ( FALSE == bSeenDiagAssert ) { continue ; } if ( dwSizeLeft < dwSymSize ) { break ; } _tcscpy ( szCurrPos , szSym ) ; szCurrPos += dwSymSize ; dwSizeLeft -= dwSymSize ; } } }
static DWORD ConvertAddress ( DWORD dwAddr , LPTSTR szOutBuff ) { char szTemp [ MAX_PATH + sizeof ( IMAGEHLP_SYMBOL ) ] ; PIMAGEHLP_SYMBOL pIHS = (PIMAGEHLP_SYMBOL)&szTemp ; IMAGEHLP_MODULE stIHM ; LPTSTR pCurrPos = szOutBuff ; ZeroMemory ( pIHS , MAX_PATH + sizeof ( IMAGEHLP_SYMBOL ) ) ; ZeroMemory ( &stIHM , sizeof ( IMAGEHLP_MODULE ) ) ; pIHS->SizeOfStruct = sizeof ( IMAGEHLP_SYMBOL ) ; pIHS->Address = dwAddr ; pIHS->MaxNameLength = MAX_PATH ; stIHM.SizeOfStruct = sizeof ( IMAGEHLP_MODULE ) ; // Always stick the address in first. pCurrPos += wsprintf ( pCurrPos , _T ( "0x%08X " ) , dwAddr ) ; // Get the module name. if ( 0 != g_cSym.SymGetModuleInfo ( dwAddr , &stIHM ) ) { // Strip off the path. LPTSTR szName = _tcsrchr ( stIHM.ImageName , _T ( '\\' ) ) ; if ( NULL != szName ) { szName++ ; } else { szName = stIHM.ImageName ; } pCurrPos += wsprintf ( pCurrPos , _T ( "%s: " ) , szName ) ; } else { pCurrPos += wsprintf ( pCurrPos , _T ( "<unknown module>: " ) ); } // Get the function. DWORD dwDisp ; if ( 0 != g_cSym.SymGetSymFromAddr ( dwAddr , &dwDisp , pIHS ) ) { if ( 0 == dwDisp ) { pCurrPos += wsprintf ( pCurrPos , _T ( "%s" ) , pIHS->Name); } else { pCurrPos += wsprintf ( pCurrPos , _T ( "%s + %d bytes" ) , pIHS->Name , dwDisp ) ; } // If I got a symbol, give the source and line a whirl. IMAGEHLP_LINE stIHL ; ZeroMemory ( &stIHL , sizeof ( IMAGEHLP_LINE ) ) ; stIHL.SizeOfStruct = sizeof ( IMAGEHLP_LINE ) ; if ( 0 != g_cSym.SymGetLineFromAddr ( dwAddr , &dwDisp , &stIHL ) ) { // Put this on the next line and indented a bit. pCurrPos += wsprintf ( pCurrPos , _T ( "\n\t\t%s, Line %d" ) , stIHL.FileName , stIHL.LineNumber ) ; if ( 0 != dwDisp ) { pCurrPos += wsprintf ( pCurrPos , _T ( " + %d bytes" ) , dwDisp ) ; } } } else { pCurrPos += wsprintf ( pCurrPos , _T ( "<unknown symbol>" ) ) ; } // Tack on a CRLF. pCurrPos += wsprintf ( pCurrPos , _T ( "\n" ) ) ; return ( pCurrPos - szOutBuff ) ; }
static DWORD __stdcall GetModBase ( HANDLE hProcess , DWORD dwAddr ) { // Check in the symbol engine first. IMAGEHLP_MODULE stIHM ; // This is what the MFC stack trace routines forgot to do so their // code will not get the info out of the symbol engine. stIHM.SizeOfStruct = sizeof ( IMAGEHLP_MODULE ) ; // Check to see if the module is already loaded. if ( g_cSym.SymGetModuleInfo ( dwAddr , &stIHM ) ) { return ( stIHM.BaseOfImage ) ; } else { // The module is not loaded, so let's go fishing. MEMORY_BASIC_INFORMATION stMBI ; // Do the VirtualQueryEx to see if I can find the start of // this module. Since the HMODULE is the start of a module // in memory, viola, this will give me the HMODULE. if ( 0 != VirtualQueryEx ( hProcess , (LPCVOID)dwAddr , &stMBI , sizeof ( stMBI ) ) ) { // Try and load it. DWORD dwNameLen = 0 ; TCHAR szFile[ MAX_PATH ] ; // Using the address base for the memory location, try // to grab the module filename. dwNameLen = GetModuleFileName ( (HINSTANCE) stMBI.AllocationBase , szFile , MAX_PATH ); HANDLE hFile = NULL ; if ( 0 != dwNameLen ) { // Very cool, I found the DLL. Now open it up for // reading. hFile = CreateFile ( szFile , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , 0 , 0 ) ; } // Go ahead and try to load the module anyway. #ifdef _DEBUG DWORD dwRet = #endif g_cSym.SymLoadModule ( hFile , ( dwNameLen ? szFile : NULL ) , NULL , (DWORD)stMBI.AllocationBase , 0 ) ; #ifdef _DEBUG if ( 0 == dwRet ) { TRACE ( "SymLoadModule failed : 0x%08X\n" , GetLastError ( ) ) ; } #endif // _DEBUG return ( (DWORD)stMBI.AllocationBase ) ; } } return ( 0 ) ; }
void DoStackTrace ( LPTSTR szString , DWORD dwSize , DWORD dwNumSkip ) { HANDLE hProcess = GetCurrentProcess ( ) ; // If the symbol engine is not initialized, do it now. if ( FALSE == g_bSymIsInit ) { DWORD dwOpts = SymGetOptions ( ) ; // Turn on load lines. SymSetOptions ( dwOpts | SYMOPT_LOAD_LINES ) ; if ( FALSE == g_cSym.SymInitialize ( hProcess , NULL , FALSE ) ) { //dsi_PrintToConsole("DoStackTrace : Unable to initialize the symbol engine!!!"); } else { g_bSymIsInit = TRUE ; } } // The symbol engine is initialized so do the stack walk. // The array of addresses. ADDRVECTOR vAddrs ; // The thread information. CONTEXT stCtx ; stCtx.ContextFlags = CONTEXT_FULL ; if ( GetThreadContext ( GetCurrentThread ( ) , &stCtx ) ) { STACKFRAME stFrame ; DWORD dwMachine ; ZeroMemory ( &stFrame , sizeof ( STACKFRAME ) ) ; stFrame.AddrPC.Mode = AddrModeFlat ; #ifdef _M_IX86 dwMachine = IMAGE_FILE_MACHINE_I386 ; #else dwMachine = IMAGE_FILE_MACHINE_AMD64; #endif #ifdef _M_IX86 stFrame.AddrPC.Offset = stCtx.Eip ; stFrame.AddrStack.Offset = stCtx.Esp ; #else stFrame.AddrPC.Offset = stCtx.Rip ; stFrame.AddrStack.Offset = stCtx.Rsp ; #endif stFrame.AddrStack.Mode = AddrModeFlat ; #ifdef _M_IX86 stFrame.AddrFrame.Offset = stCtx.Ebp ; #else stFrame.AddrFrame.Offset = stCtx.Rbp ; #endif stFrame.AddrFrame.Mode = AddrModeFlat ; // Loop for the first 512 stack elements. for ( DWORD i = 0 ; i < 512 ; i++ ) { if ( FALSE == StackWalk ( dwMachine , hProcess , hProcess , &stFrame , &stCtx , NULL , SymFunctionTableAccess , GetModBase , NULL ) ) { // [KLS 4/5/02] The optimization bug doesn't occur if you touch the // variable "i" here (e.g., call dsi_PrintToConsole("i = %d", i); ) // ...I love compiler bugs ;) break ; } if ( i > dwNumSkip ) { // Also check that the address is not zero. Sometimes // StackWalk returns TRUE with a frame of zero. if ( 0 != stFrame.AddrPC.Offset ) { vAddrs.push_back ( stFrame.AddrPC.Offset ) ; } } } // Now start converting the addresses. DWORD dwSizeLeft = dwSize ; DWORD dwSymSize ; TCHAR szSym [ MAX_PATH * 2 ] ; LPTSTR szCurrPos = szString ; ADDRVECTOR::iterator loop ; for ( loop = vAddrs.begin ( ) ; loop != vAddrs.end ( ) ; loop++ ) { dwSymSize = ConvertAddress ( *loop , szSym ) ; if ( dwSizeLeft < dwSymSize ) { break ; } _tcscpy ( szCurrPos , szSym ) ; szCurrPos += dwSymSize ; dwSizeLeft -= dwSymSize ; } } }