From 4a0d27b3fdbb7fe949452e263320958b43ac555d Mon Sep 17 00:00:00 2001 From: "Neo][" Date: Wed, 14 Mar 2018 10:39:37 +0500 Subject: [PATCH 1/6] Reimplements the onboard functionality of the stack tracing --- src/xrCore/Debug/MiniDump.cpp | 1 - src/xrCore/Debug/StackTrace.cpp | 388 ------------------------------ src/xrCore/Debug/StackTrace.h | 77 ------ src/xrCore/Debug/SymbolEngine.h | 264 -------------------- src/xrCore/xrCore.vcxproj | 15 +- src/xrCore/xrCore.vcxproj.filters | 9 - src/xrCore/xrDebug.cpp | 254 +++++++++++++++---- src/xrCore/xrDebug.h | 38 +-- 8 files changed, 234 insertions(+), 812 deletions(-) delete mode 100644 src/xrCore/Debug/StackTrace.cpp delete mode 100644 src/xrCore/Debug/StackTrace.h delete mode 100644 src/xrCore/Debug/SymbolEngine.h diff --git a/src/xrCore/Debug/MiniDump.cpp b/src/xrCore/Debug/MiniDump.cpp index 3cd4bf3075d..1c8204ba9dc 100644 --- a/src/xrCore/Debug/MiniDump.cpp +++ b/src/xrCore/Debug/MiniDump.cpp @@ -7,7 +7,6 @@ Copyright (c) 1997-2001 John Robbins -- All rights reserved. #pragma warning(push) #pragma warning(disable : 4091) // 'typedef ': ignored on left of '' when no variable is declared #include "MiniDump.h" -#include "StackTrace.h" #pragma warning(pop) #include diff --git a/src/xrCore/Debug/StackTrace.cpp b/src/xrCore/Debug/StackTrace.cpp deleted file mode 100644 index e8ed966cf83..00000000000 --- a/src/xrCore/Debug/StackTrace.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/*---------------------------------------------------------------------- -"Debugging Applications" (Microsoft Press) -Copyright (c) 1997-2000 John Robbins -- All rights reserved. -----------------------------------------------------------------------*/ - -#include "stdafx.h" -#pragma warning(push) -#pragma warning(disable : 4091) // 'typedef ': ignored on left of '' when no variable is declared -#include "StackTrace.h" -#include "SymbolEngine.h" -#include "MiniDump.h" -#pragma warning(pop) -#include -#pragma comment(lib, "psapi.lib") - -/*////////////////////////////////////////////////////////////////////// -File Scope Defines -//////////////////////////////////////////////////////////////////////*/ -// The maximum symbol size handled in the module -#define MAX_SYM_SIZE 256 -#define BUFF_SIZE 1024 -#define SYM_BUFF_SIZE 512 - -/*////////////////////////////////////////////////////////////////////// -File Scope Global Variables -//////////////////////////////////////////////////////////////////////*/ - -// The original unhandled exception filter -static LPTOP_LEVEL_EXCEPTION_FILTER g_pfnOrigFilt = NULL; - -// The array of modules to limit crash handler to -static HMODULE* g_ahMod = NULL; -// The size, in items, of g_ahMod -static UINT g_uiModCount = 0; - -// The static buffer returned by various functions. This buffer -// allows data to be transferred without using the stack. -static TCHAR g_szBuff[BUFF_SIZE]; - -// The static symbol lookup buffer -static BYTE g_stSymbol[SYM_BUFF_SIZE]; - -// The static source file and line number structure -static IMAGEHLP_LINE g_stLine; - -// The stack frame used in walking the stack -static STACKFRAME g_stFrame; - -// The flag indicating that the symbol engine has been initialized -static BOOL g_bSymEngInit = FALSE; - -// The flag indicating that microsoft symbol server will be used -// static BOOL g_SymServerLookup = TRUE; - -/*////////////////////////////////////////////////////////////////////// -File Scope Function Declarations -//////////////////////////////////////////////////////////////////////*/ - -// The internal function that does all the stack walking -LPCTSTR __stdcall InternalGetStackTraceString(DWORD dwOpts, EXCEPTION_POINTERS* pExPtrs); - -// Initializes the symbol engine if needed -void InitializeSymbolEngine(void); - -// Cleans up the symbol engine if needed -void DeinitializeSymbolEngine(void); - -/*////////////////////////////////////////////////////////////////////// -Crash Handler Function Implementation -//////////////////////////////////////////////////////////////////////*/ - -LPCTSTR __stdcall GetFirstStackTraceString(DWORD dwOpts, EXCEPTION_POINTERS* pExPtrs) -{ - // All the error checking is in the InternalGetStackTraceString - // function. - - // Initialize the STACKFRAME structure. - ZeroMemory(&g_stFrame, sizeof(STACKFRAME)); - -#if defined(XR_X64) - g_stFrame.AddrPC.Offset = pExPtrs->ContextRecord->Rip; - g_stFrame.AddrPC.Mode = AddrModeFlat; - g_stFrame.AddrReturn.Offset = 0; - g_stFrame.AddrReturn.Mode = AddrModeFlat; - g_stFrame.AddrStack.Offset = pExPtrs->ContextRecord->Rsp; - g_stFrame.AddrStack.Mode = AddrModeFlat; - g_stFrame.AddrFrame.Offset = pExPtrs->ContextRecord->Rbp; - g_stFrame.AddrFrame.Mode = AddrModeFlat; -#elif defined(XR_X86) - g_stFrame.AddrPC.Offset = pExPtrs->ContextRecord->Eip; - g_stFrame.AddrPC.Mode = AddrModeFlat; - g_stFrame.AddrStack.Offset = pExPtrs->ContextRecord->Esp; - g_stFrame.AddrStack.Mode = AddrModeFlat; - g_stFrame.AddrFrame.Offset = pExPtrs->ContextRecord->Ebp; - g_stFrame.AddrFrame.Mode = AddrModeFlat; -#else - g_stFrame.AddrPC.Offset = (DWORD)pExPtrs->ContextRecord->Fir; - g_stFrame.AddrPC.Mode = AddrModeFlat; - g_stFrame.AddrReturn.Offset = (DWORD)pExPtrs->ContextRecord->IntRa; - g_stFrame.AddrReturn.Mode = AddrModeFlat; - g_stFrame.AddrStack.Offset = (DWORD)pExPtrs->ContextRecord->IntSp; - g_stFrame.AddrStack.Mode = AddrModeFlat; - g_stFrame.AddrFrame.Offset = (DWORD)pExPtrs->ContextRecord->IntFp; - g_stFrame.AddrFrame.Mode = AddrModeFlat; -#endif - - return InternalGetStackTraceString(dwOpts, pExPtrs); -} - -LPCTSTR __stdcall GetNextStackTraceString(DWORD dwOpts, EXCEPTION_POINTERS* pExPtrs) -{ - // All error checking is in InternalGetStackTraceString. - // Assume that GetFirstStackTraceString has already initialized the - // stack frame information. - return InternalGetStackTraceString(dwOpts, pExPtrs); -} - -#ifndef XR_X64 -BOOL __stdcall ReadCurrentProcessMemory(HANDLE, LPCVOID lpBaseAddress, LPVOID lpBuffer, DWORD nSize, LPDWORD lpNumberOfBytesRead) -#else -BOOL __stdcall ReadCurrentProcessMemory(HANDLE, LPCVOID lpBaseAddress, LPVOID lpBuffer, DWORD nSize, SIZE_T* lpNumberOfBytesRead) -#endif -{ - return ReadProcessMemory(GetCurrentProcess(), lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead); -} - -// The internal function that does all the stack walking -LPCTSTR __stdcall InternalGetStackTraceString(DWORD dwOpts, EXCEPTION_POINTERS* pExPtrs) -{ - // ASSERT(IsBadReadPtr(pExPtrs, sizeof(EXCEPTION_POINTERS)) == FALSE); - if (IsBadReadPtr(pExPtrs, sizeof(EXCEPTION_POINTERS)) == TRUE) - { - SetLastError(ERROR_INVALID_ADDRESS); - // TRACE0("GetStackTraceString - invalid pExPtrs!\n"); - return NULL; - } - - // The value that is returned - LPCTSTR szRet; - // A temporary variable for all to use. This variable saves - // stack space. - DWORD dwTemp; - // The module base address. I look this up right after the stack - // walk to ensure that the module is valid. - DWORD dwModBase; - - HANDLE hProcess = (HANDLE)GetCurrentProcessId(); - - __try - { - // Initialize the symbol engine in case it isn't initialized. - InitializeSymbolEngine(); - -#ifdef _WIN64 -#define CH_MACHINE IMAGE_FILE_MACHINE_IA64 -#else -#define CH_MACHINE IMAGE_FILE_MACHINE_I386 -#endif - // Note: If the source file and line number functions are used, - // StackWalk can cause an access violation. - BOOL bSWRet = StackWalk(CH_MACHINE, hProcess, GetCurrentThread(), &g_stFrame, pExPtrs->ContextRecord, - (PREAD_PROCESS_MEMORY_ROUTINE)ReadCurrentProcessMemory, SymFunctionTableAccess, SymGetModuleBase, NULL); - - if ((bSWRet == FALSE) || (g_stFrame.AddrFrame.Offset == 0)) - { - szRet = NULL; - __leave; - } - - // Before I get too carried away and start calculating - // everything, I need to double-check that the address returned - // by StackWalk really exists. I've seen cases in which - // StackWalk returns TRUE but the address doesn't belong to - // a module in the process. - dwModBase = SymGetModuleBase(hProcess, g_stFrame.AddrPC.Offset); - if (dwModBase == 0) - { - szRet = NULL; - __leave; - } - - int iCurr = 0; - -// At a minimum, put in the address. -#ifdef _WIN64 - iCurr += wsprintf(g_szBuff + iCurr, _T("0x%016I64X"), g_stFrame.AddrPC.Offset); -#else - // iCurr += wsprintf(g_szBuff + iCurr, _T("%04X:%08I64X"), pExPtrs->ContextRecord->SegCs, - // g_stFrame.AddrPC.Offset); - iCurr += wsprintf(g_szBuff + iCurr, _T("%04X:%08X"), pExPtrs->ContextRecord->SegCs, g_stFrame.AddrPC.Offset); -#endif - - // Output the parameters? - if ((dwOpts & GSTSO_PARAMS) == GSTSO_PARAMS) - { - iCurr += wsprintf(g_szBuff + iCurr, -#ifdef _WIN64 - _T(" (0x%016I64X 0x%016I64X 0x%016I64X 0x%016I64X)"), -#else - //_T(" (0x%08I64X 0x%08I64X 0x%08I64X 0x%08I64X)"), - _T(" (0x%08X 0x%08X 0x%08X 0x%08X)"), -#endif - g_stFrame.Params[0], g_stFrame.Params[1], g_stFrame.Params[2], g_stFrame.Params[3]); - } - // Output the module name. - if ((dwOpts & GSTSO_MODULE) == GSTSO_MODULE) - { - iCurr += wsprintf(g_szBuff + iCurr, _T(" ")); - // ASSERT(iCurr < (BUFF_SIZE - MAX_PATH)); - iCurr += GetModuleBaseName(GetCurrentProcess(), (HINSTANCE)dwModBase, g_szBuff + iCurr, BUFF_SIZE - iCurr); - } - - // ASSERT(iCurr < (BUFF_SIZE - MAX_PATH)); - DWORD_PTR dwDisp; - // Output the symbol name? - if ((dwOpts & GSTSO_SYMBOL) == GSTSO_SYMBOL) - { - // Start looking up the exception address. - PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)&g_stSymbol; - ZeroMemory(pSym, SYM_BUFF_SIZE); - pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL); - pSym->MaxNameLength = SYM_BUFF_SIZE - sizeof(IMAGEHLP_SYMBOL); - - if (SymGetSymFromAddr(hProcess, g_stFrame.AddrPC.Offset, &dwDisp, pSym) == TRUE) - { - iCurr += wsprintf(g_szBuff + iCurr, _T(", ")); - // Copy no more symbol information than there's room for. - dwTemp = lstrlen(pSym->Name); - if (dwTemp > (DWORD)(BUFF_SIZE - iCurr - (MAX_SYM_SIZE + 50))) - { - lstrcpyn(g_szBuff + iCurr, pSym->Name, BUFF_SIZE - iCurr - 1); - // Gotta leave now - szRet = g_szBuff; - __leave; - } - else - { - if (dwDisp > 0) - { - // iCurr += wsprintf(g_szBuff + iCurr, _T("%s() + %I64d byte(s)"), pSym->Name, dwDisp); - iCurr += wsprintf(g_szBuff + iCurr, _T("%s() + %d byte(s)"), pSym->Name, dwDisp); - } - else - { - iCurr += wsprintf(g_szBuff + iCurr, _T("%s"), pSym->Name); - } - } - } - else - { - // If the symbol wasn't found, the source file and line - // number won't be found either, so leave now. - szRet = g_szBuff; - __leave; - } - } - - // ASSERT(iCurr < (BUFF_SIZE - MAX_PATH)); - - // Output the source file and line number information? - if ((dwOpts & GSTSO_SRCLINE) == GSTSO_SRCLINE) - { - ZeroMemory(&g_stLine, sizeof(IMAGEHLP_LINE)); - g_stLine.SizeOfStruct = sizeof(IMAGEHLP_LINE); - - if (SymGetLineFromAddr(hProcess, g_stFrame.AddrPC.Offset, (PDWORD)&dwDisp, &g_stLine) == TRUE) - { - iCurr += wsprintf(g_szBuff + iCurr, _T(", ")); - - // Copy no more of the source file and line number - // information than there's room for. - dwTemp = lstrlen(g_stLine.FileName); - if (dwTemp > (DWORD)(BUFF_SIZE - iCurr - (MAX_PATH + 50))) - { - lstrcpyn(g_szBuff + iCurr, g_stLine.FileName, BUFF_SIZE - iCurr - 1); - // Gotta leave now - szRet = g_szBuff; - __leave; - } - else - { - if (dwDisp > 0) - { - iCurr += wsprintf(g_szBuff + iCurr, _T("%s, line %d + %d byte(s)"), g_stLine.FileName, - g_stLine.LineNumber, dwDisp); - } - else - { - iCurr += wsprintf(g_szBuff + iCurr, _T("%s, line %d"), g_stLine.FileName, g_stLine.LineNumber); - } - } - } - } - szRet = g_szBuff; - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - // int err = GetLastError(); - // char buf[1024]; - // sprintf(buf, "error %d", err); - // MessageBoxA(0, buf, "Flux Engine", 0); - // ASSERT(!"Crashed in InternalGetStackTraceString"); - szRet = NULL; - } - return szRet; -} - -BOOL __stdcall GetFirstStackTraceStringVB(DWORD dwOpts, EXCEPTION_POINTERS* pExPtrs, LPTSTR szBuff, UINT uiSize) -{ - // ASSERT(IsBadWritePtr(szBuff, uiSize) == FALSE); - if (IsBadWritePtr(szBuff, uiSize) == TRUE) - { - return FALSE; - } - - LPCTSTR szRet; - - __try - { - szRet = GetFirstStackTraceString(dwOpts, pExPtrs); - if (NULL == szRet) - { - __leave; - } - lstrcpyn(szBuff, szRet, std::min((UINT)lstrlen(szRet) + 1, uiSize)); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - szRet = NULL; - } - return szRet != NULL; -} - -BOOL __stdcall GetNextStackTraceStringVB(DWORD dwOpts, EXCEPTION_POINTERS* pExPtrs, LPTSTR szBuff, UINT uiSize) -{ - // ASSERT(IsBadWritePtr(szBuff, uiSize) == FALSE); - if (IsBadWritePtr(szBuff, uiSize) == TRUE) - { - return FALSE; - } - LPCTSTR szRet; - __try - { - szRet = GetNextStackTraceString(dwOpts, pExPtrs); - if (NULL == szRet) - { - __leave; - } - lstrcpyn(szBuff, szRet, std::min((UINT)lstrlen(szRet) + 1, uiSize)); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - szRet = NULL; - } - return szRet != NULL; -} - -// Initializes the symbol engine if needed -void InitializeSymbolEngine(void) -{ - // static char const ms_symsrv[] = "http://msdl.microsoft.com/download/symbols"; - if (!g_bSymEngInit) - { - // Set up the symbol engine. - DWORD dwOpts = SymGetOptions(); - // Turn on line loading and deferred loading. - SymSetOptions(dwOpts | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); - - HANDLE hProcess = (HANDLE)GetCurrentProcessId(); - SymInitialize(hProcess, NULL, TRUE); - // if (g_SymServerLookup) - //{ - // SymSetSearchPath(hProcess, ms_symsrv); - //} - - g_bSymEngInit = TRUE; - } -} - -// Cleans up the symbol engine if needed -void DeinitializeSymbolEngine(void) -{ - if (g_bSymEngInit) - { - SymCleanup((HANDLE)GetCurrentProcessId()); - g_bSymEngInit = FALSE; - } -} diff --git a/src/xrCore/Debug/StackTrace.h b/src/xrCore/Debug/StackTrace.h deleted file mode 100644 index 6e8a2eea1be..00000000000 --- a/src/xrCore/Debug/StackTrace.h +++ /dev/null @@ -1,77 +0,0 @@ -/*---------------------------------------------------------------------- -"Debugging Applications" (Microsoft Press) -Copyright (c) 1997-2000 John Robbins -- All rights reserved. -----------------------------------------------------------------------*/ - -#pragma once - -#include -#include - -/*////////////////////////////////////////////////////////////////////// -Type Definitions -//////////////////////////////////////////////////////////////////////*/ -// The type for the filter function called by the Crash Handler API. -typedef LONG(__stdcall* PFNCHFILTFN)(EXCEPTION_POINTERS* pExPtrs); - -/*////////////////////////////////////////////////////////////////////// -Crash Handler Function Definitions -//////////////////////////////////////////////////////////////////////*/ - -/*---------------------------------------------------------------------- -FUNCTION : GetFirstStackTraceString -GetNextStackTraceString -DISCUSSION : -These functions allow you to get the stack trace information for a -crash. Call GetFirstStackTraceString and then GetNextStackTraceString -to get the entire stack trace for a crash. -The options GSTSO_PARAMS, GSTSO_MODULE, GSTSO_SYMBOL, and -GSTSO_SRCLINE, appear in that order in the string. -PARAMETERS : -dwOpts - The options flags "Or" the following options together. -0 - Just put the PC address in the string. -GSTSO_PARAMS - Include the possible params. -GSTSO_MODULE - Include the module name as well. -GSTSO_SYMBOL - Include the symbol name of the stack -address. -GSTSO_SRCLINE - Include source and line info of the -stack address. -pExtPtrs - The exception pointers passed to the crash handler -function. -RETURNS : -!NULL - The requested stack trace string. -NULL - There was a problem. -----------------------------------------------------------------------*/ -#define GSTSO_PARAMS 0x01 -#define GSTSO_MODULE 0x02 -#define GSTSO_SYMBOL 0x04 -#define GSTSO_SRCLINE 0x08 -LPCTSTR __stdcall GetFirstStackTraceString(DWORD dwOpts, EXCEPTION_POINTERS* pExPtrs); -LPCTSTR __stdcall GetNextStackTraceString(DWORD dwOpts, EXCEPTION_POINTERS* pExPtrs); - -/*---------------------------------------------------------------------- -FUNCTION : GetFirstStackTraceStringVB -GetNextStackTraceStringVB -DISCUSSION : -The VB wrappers on GetFirstStackTraceString and -GetNextStackTraceString since VB cannot handle returning a string from -a DLL call. -PARAMETERS : -dwOpts - The options flags "Or" the following options together. -0 - Just put the PC address in the string. -GSTSO_PARAMS - Include the possible params. -GSTSO_MODULE - Include the module name as well. -GSTSO_SYMBOL - Include the symbol name the stack -address. -GSTSO_SRCLINE - Include source and line info for the -address. -pExtPtrs - The exception pointers passed to the crash handler -function. -szBuff - The output buffer. -uiSize - The size of the output buffer. -RETURNS : -TRUE - The string was copied into szBuff. -FALSE - There was a problem. -----------------------------------------------------------------------*/ -BOOL __stdcall GetFirstStackTraceStringVB(DWORD dwOpts, EXCEPTION_POINTERS* pExPtrs, LPTSTR szBuff, UINT uiSize); -BOOL __stdcall GetNextStackTraceStringVB(DWORD dwOpts, EXCEPTION_POINTERS* pExPtrs, LPTSTR szBuff, UINT uiSize); diff --git a/src/xrCore/Debug/SymbolEngine.h b/src/xrCore/Debug/SymbolEngine.h deleted file mode 100644 index 43ca6554cf7..00000000000 --- a/src/xrCore/Debug/SymbolEngine.h +++ /dev/null @@ -1,264 +0,0 @@ -/*---------------------------------------------------------------------- -"Debugging Applications" (Microsoft Press) -Copyright (c) 1997-2000 John Robbins -- All rights reserved. ------------------------------------------------------------------------- -This class is a paper-thin layer around the DBGHELP.DLL symbol engine. - -This class wraps only those functions that take the unique -HANDLE value. Other DBGHELP.DLL symbol engine functions are global in -scope, so I didn’t wrap them with this class. -----------------------------------------------------------------------*/ - -#pragma once - -#include -#include - -// Include these in case the user forgets to link against them. -#pragma comment(lib, "dbghelp.lib") -#pragma comment(lib, "version.lib") - -// The great Bugslayer idea of creating wrapper classes on structures -// that have size fields came from fellow MSJ columnist, Paul DiLascia. -// Thanks, Paul! - -// I didn’t wrap IMAGEHLP_SYMBOL because that is a variable-size -// structure. - -// The IMAGEHLP_MODULE wrapper class -struct CImageHlp_Module : public IMAGEHLP_MODULE -{ - CImageHlp_Module() - { - memset(this, NULL, sizeof(IMAGEHLP_MODULE)); - SizeOfStruct = sizeof(IMAGEHLP_MODULE); - } -}; - -// The IMAGEHLP_LINE wrapper class -struct CImageHlp_Line : public IMAGEHLP_LINE -{ - CImageHlp_Line() - { - memset(this, NULL, sizeof(IMAGEHLP_LINE)); - SizeOfStruct = sizeof(IMAGEHLP_LINE); - } -}; - -// The symbol engine class -class SymbolEngine -{ - /*---------------------------------------------------------------------- - Public Construction and Destruction - ----------------------------------------------------------------------*/ -public: - // To use this class, call the SymInitialize member function to - // initialize the symbol engine and then use the other member - // functions in place of their corresponding DBGHELP.DLL functions. - SymbolEngine(void) {} - virtual ~SymbolEngine(void) {} - /*---------------------------------------------------------------------- - Public Helper Information Functions - ----------------------------------------------------------------------*/ -public: - // Returns the file version of DBGHELP.DLL being used. - // To convert the return values into a readable format: - // wsprintf(szVer , - // _T("%d.%02d.%d.%d"), - // HIWORD(dwMS) , - // LOWORD(dwMS) , - // HIWORD(dwLS) , - // LOWORD(dwLS) ); - // szVer will contain a string like: 5.00.1878.1 - BOOL GetDbgHelpVersion(DWORD& dwMS, DWORD& dwLS) { return GetInMemoryFileVersion(_T("DBGHELP.DLL"), dwMS, dwLS); } - // Returns the file version of the PDB reading DLLs - BOOL GetPDBReaderVersion(DWORD& dwMS, DWORD& dwLS) - { - // First try MSDBI.DLL. - if (GetInMemoryFileVersion(_T("MSDBI.DLL"), dwMS, dwLS) == TRUE) - { - return TRUE; - } - else if (GetInMemoryFileVersion(_T("MSPDB60.DLL" ), dwMS, dwLS) == TRUE) - { - return TRUE; - } - // Just fall down to MSPDB50.DLL. - return GetInMemoryFileVersion(_T("MSPDB50.DLL"), dwMS, dwLS); - } - - // The worker function used by the previous two functions - BOOL GetInMemoryFileVersion(LPCTSTR szFile, DWORD& dwMS, DWORD& dwLS) - { - HMODULE hInstIH = GetModuleHandle(szFile); - - // Get the full filename of the loaded version. - TCHAR szImageHlp[MAX_PATH]; - GetModuleFileName(hInstIH, szImageHlp, MAX_PATH); - - dwMS = 0; - dwLS = 0; - - // Get the version information size. - DWORD dwVerInfoHandle; - DWORD dwVerSize; - - dwVerSize = GetFileVersionInfoSize(szImageHlp, &dwVerInfoHandle); - if (dwVerSize == 0) - return false; - - // Got the version size, now get the version information. - LPVOID lpData = (LPVOID) new TCHAR[dwVerSize]; - if (GetFileVersionInfo(szImageHlp, dwVerInfoHandle, dwVerSize, lpData) == false) - { - delete[] lpData; - return false; - } - - VS_FIXEDFILEINFO* lpVerInfo; - UINT uiLen; - BOOL bRet = VerQueryValue(lpData, _T("\\"), (LPVOID*)&lpVerInfo, &uiLen); - if (bRet) - { - dwMS = lpVerInfo->dwFileVersionMS; - dwLS = lpVerInfo->dwFileVersionLS; - } - - delete[] lpData; - return bRet; - } - - /*---------------------------------------------------------------------- - Public Initialization and Cleanup - ----------------------------------------------------------------------*/ -public: - BOOL SymInitialize(IN HANDLE hProcess, IN LPSTR UserSearchPath, IN BOOL fInvadeProcess) - { - m_hProcess = hProcess; - return ::SymInitialize(hProcess, UserSearchPath, fInvadeProcess); - } - - BOOL SymCleanup() { return ::SymCleanup(m_hProcess); } - /*---------------------------------------------------------------------- - Public Module Manipulation - ----------------------------------------------------------------------*/ -public: - BOOL SymEnumerateModules(IN PSYM_ENUMMODULES_CALLBACK EnumModulesCallback, IN PVOID UserContext) - { - return ::SymEnumerateModules(m_hProcess, EnumModulesCallback, UserContext); - } - - BOOL SymLoadModule(IN HANDLE hFile, IN PSTR ImageName, IN PSTR ModuleName, IN DWORD BaseOfDll, IN DWORD SizeOfDll) - { - return ::SymLoadModule(m_hProcess, hFile, ImageName, ModuleName, BaseOfDll, SizeOfDll); - } - - BOOL EnumerateLoadedModules(IN PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback, IN PVOID UserContext) - { - return ::EnumerateLoadedModules(m_hProcess, EnumLoadedModulesCallback, UserContext); - } - - BOOL SymUnloadModule(IN DWORD BaseOfDll) { return ::SymUnloadModule(m_hProcess, BaseOfDll); } - BOOL SymGetModuleInfo(IN DWORD dwAddr, OUT PIMAGEHLP_MODULE ModuleInfo) - { - return ::SymGetModuleInfo(m_hProcess, dwAddr, ModuleInfo); - } - - DWORD SymGetModuleBase(IN DWORD dwAddr) { return ::SymGetModuleBase(m_hProcess, dwAddr); } - /*---------------------------------------------------------------------- - Public Symbol Manipulation - ----------------------------------------------------------------------*/ -public: - BOOL SymEnumerateSymbols(IN DWORD BaseOfDll, IN PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback, IN PVOID UserContext) - { - return ::SymEnumerateSymbols(m_hProcess, BaseOfDll, EnumSymbolsCallback, UserContext); - } - - BOOL SymGetSymFromAddr(IN DWORD dwAddr, OUT PDWORD_PTR pdwDisplacement, OUT PIMAGEHLP_SYMBOL Symbol) - { - return ::SymGetSymFromAddr(m_hProcess, dwAddr, pdwDisplacement, Symbol); - } - - BOOL SymGetSymFromName(IN LPSTR Name, OUT PIMAGEHLP_SYMBOL Symbol) - { - return ::SymGetSymFromName(m_hProcess, Name, Symbol); - } - - BOOL SymGetSymNext(IN OUT PIMAGEHLP_SYMBOL Symbol) { return ::SymGetSymNext(m_hProcess, Symbol); } - BOOL SymGetSymPrev(IN OUT PIMAGEHLP_SYMBOL Symbol) { return ::SymGetSymPrev(m_hProcess, Symbol); } - /*---------------------------------------------------------------------- - Public Source Line Manipulation - ----------------------------------------------------------------------*/ -public: - BOOL SymGetLineFromAddr(IN DWORD dwAddr, OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE Line) - { -#ifdef DO_NOT_WORK_AROUND_SRCLINE_BUG - // Just pass along the values returned by the main function. - return ::SymGetLineFromAddr(m_hProcess, dwAddr, pdwDisplacement, Line); - -#else - // The problem is that the symbol engine finds only those source - // line addresses (after the first lookup) that fall exactly on - // a zero displacement. I’ll walk backward 100 bytes to - // find the line and return the proper displacement. - DWORD dwTempDis = 0; - while (::SymGetLineFromAddr(m_hProcess, dwAddr - dwTempDis, pdwDisplacement, Line) == false) - { - dwTempDis += 1; - if (100 == dwTempDis) - { - return FALSE; - } - } - // I found it and the source line information is correct, so - // change the displacement if I had to search backward to find - // the source line. - if (dwTempDis != 0) - { - *pdwDisplacement = dwTempDis; - } - return TRUE; -#endif // DO_NOT_WORK_AROUND_SRCLINE_BUG - } - - BOOL SymGetLineFromName(IN LPSTR ModuleName, IN LPSTR FileName, IN DWORD dwLineNumber, OUT PLONG plDisplacement, - IN OUT PIMAGEHLP_LINE Line) - { - return ::SymGetLineFromName(m_hProcess, ModuleName, FileName, dwLineNumber, plDisplacement, Line); - } - - BOOL SymGetLineNext(IN OUT PIMAGEHLP_LINE Line) { return ::SymGetLineNext(m_hProcess, Line); } - BOOL SymGetLinePrev(IN OUT PIMAGEHLP_LINE Line) { return ::SymGetLinePrev(m_hProcess, Line); } - BOOL SymMatchFileName(IN LPSTR FileName, IN LPSTR Match, OUT LPSTR* FileNameStop, OUT LPSTR* MatchStop) - { - return ::SymMatchFileName(FileName, Match, FileNameStop, MatchStop); - } - - /*---------------------------------------------------------------------- - Public Miscellaneous Members - ----------------------------------------------------------------------*/ -public: - LPVOID SymFunctionTableAccess(DWORD AddrBase) { return ::SymFunctionTableAccess(m_hProcess, AddrBase); } - BOOL SymGetSearchPath(OUT LPSTR SearchPath, IN DWORD SearchPathLength) - { - return ::SymGetSearchPath(m_hProcess, SearchPath, SearchPathLength); - } - - BOOL SymSetSearchPath(IN LPSTR SearchPath) { return ::SymSetSearchPath(m_hProcess, SearchPath); } -#ifdef XR_X64 - BOOL SymRegisterCallback(IN PSYMBOL_REGISTERED_CALLBACK CallbackFunction, IN ULONG64 UserContext) -#else - BOOL SymRegisterCallback(IN PSYMBOL_REGISTERED_CALLBACK CallbackFunction, IN PVOID UserContext) -#endif - { - return ::SymRegisterCallback(m_hProcess, CallbackFunction, UserContext); - } - /*---------------------------------------------------------------------- - Protected Data Members - ----------------------------------------------------------------------*/ -protected: - // The unique value that will be used for this instance of the - // symbol engine. This value doesn’t have to be an actual - // process value, just a unique value. - HANDLE m_hProcess; -}; diff --git a/src/xrCore/xrCore.vcxproj b/src/xrCore/xrCore.vcxproj index 9f12182d0f0..8318e095b59 100644 --- a/src/xrCore/xrCore.vcxproj +++ b/src/xrCore/xrCore.vcxproj @@ -102,7 +102,7 @@ _USRDLL;XRCORE_EXPORTS;CRYPTO_BUILD;%(PreprocessorDefinitions) - PowrProf.lib;%(AdditionalDependencies) + PowrProf.lib;DbgHelp.lib;%(AdditionalDependencies) for /r "$(xrSdkDir)binaries/$(PlatformShortName)" %%f in (*.dll *.pdb) do @xcopy /Q /D "%%f" "$(OutDir)" @@ -117,7 +117,7 @@ _USRDLL;XRCORE_EXPORTS;CRYPTO_BUILD;%(PreprocessorDefinitions) - PowrProf.lib;%(AdditionalDependencies) + PowrProf.lib;DbgHelp.lib;%(AdditionalDependencies) for /r "$(xrSdkDir)binaries/$(PlatformShortName)" %%f in (*.dll *.pdb) do @xcopy /Q /D "%%f" "$(OutDir)" @@ -130,7 +130,7 @@ _USRDLL;XRCORE_EXPORTS;CRYPTO_BUILD;%(PreprocessorDefinitions) - PowrProf.lib;%(AdditionalDependencies) + PowrProf.lib;DbgHelp.lib;%(AdditionalDependencies) for /r "$(xrSdkDir)binaries/$(PlatformShortName)" %%f in (*.dll *.pdb) do @xcopy /Q /D "%%f" "$(OutDir)" @@ -145,7 +145,7 @@ _USRDLL;XRCORE_EXPORTS;CRYPTO_BUILD;%(PreprocessorDefinitions) - PowrProf.lib;%(AdditionalDependencies) + PowrProf.lib;DbgHelp.lib;%(AdditionalDependencies) for /r "$(xrSdkDir)binaries/$(PlatformShortName)" %%f in (*.dll *.pdb) do @xcopy /Q /D "%%f" "$(OutDir)" @@ -158,7 +158,7 @@ _USRDLL;XRCORE_EXPORTS;CRYPTO_BUILD;%(PreprocessorDefinitions) - PowrProf.lib;%(AdditionalDependencies) + PowrProf.lib;DbgHelp.lib;%(AdditionalDependencies) for /r "$(xrSdkDir)binaries/$(PlatformShortName)" %%f in (*.dll *.pdb) do @xcopy /Q /D "%%f" "$(OutDir)" @@ -173,7 +173,7 @@ _USRDLL;XRCORE_EXPORTS;CRYPTO_BUILD;%(PreprocessorDefinitions) - PowrProf.lib;%(AdditionalDependencies) + PowrProf.lib;DbgHelp.lib;%(AdditionalDependencies) for /r "$(xrSdkDir)binaries/$(PlatformShortName)" %%f in (*.dll *.pdb) do @xcopy /Q /D "%%f" "$(OutDir)" @@ -198,7 +198,6 @@ - @@ -315,8 +314,6 @@ CppHeader - - diff --git a/src/xrCore/xrCore.vcxproj.filters b/src/xrCore/xrCore.vcxproj.filters index 8b01f1e0c20..ba6f794daf8 100644 --- a/src/xrCore/xrCore.vcxproj.filters +++ b/src/xrCore/xrCore.vcxproj.filters @@ -273,9 +273,6 @@ Debug core - - Debug core - XML @@ -629,12 +626,6 @@ Debug core - - Debug core - - - Debug core - Common diff --git a/src/xrCore/xrDebug.cpp b/src/xrCore/xrDebug.cpp index 5ffe07577f1..d913ada4fba 100644 --- a/src/xrCore/xrDebug.cpp +++ b/src/xrCore/xrDebug.cpp @@ -7,7 +7,6 @@ #include "xrCore/Threading/Lock.hpp" #pragma warning(push) #pragma warning(disable : 4091) // 'typedef ': ignored on left of '' when no variable is declared -#include "Debug/StackTrace.h" #include "Debug/MiniDump.h" #pragma warning(pop) #include @@ -45,6 +44,14 @@ static BOOL bException = FALSE; #define USE_OWN_MINI_DUMP #endif +#if defined XR_X64 +# define MACHINE_TYPE IMAGE_FILE_MACHINE_AMD64 +#elif defined XR_X86 +# define MACHINE_TYPE IMAGE_FILE_MACHINE_I386 +#else +# error CPU architecture is not supported. +#endif + namespace { @@ -70,57 +77,204 @@ xrDebug::CrashHandler xrDebug::OnCrash = nullptr; xrDebug::DialogHandler xrDebug::OnDialog = nullptr; string_path xrDebug::BugReportFile; bool xrDebug::ErrorAfterDialog = false; -StackTraceInfo xrDebug::StackTrace = {}; +bool xrDebug::m_SymEngineInitialized = false; void xrDebug::SetBugReportFile(const char* fileName) { strcpy_s(BugReportFile, fileName); } -void xrDebug::LogStackTrace(const char* header) + +bool xrDebug::GetNextStackFrameSring(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string& frameStr) { - if (!shared_str_initialized) - return; - StackTrace.Count = BuildStackTrace(StackTrace.Frames, StackTrace.Capacity, StackTrace.LineCapacity); - Msg("%s", header); - for (size_t i = 1; i < StackTrace.Count; i++) - Msg("%s", StackTrace[i]); + BOOL result = StackWalk( + MACHINE_TYPE, + GetCurrentProcess(), + GetCurrentThread(), + stackFrame, + threadCtx, + nullptr, + SymFunctionTableAccess, + SymGetModuleBase, + nullptr + ); + + if (result == FALSE || stackFrame->AddrPC.Offset == 0) + { + return false; + } + + frameStr.clear(); + string512 formatBuff; + + /// + /// Module name + /// + HINSTANCE hModule = (HINSTANCE)SymGetModuleBase(GetCurrentProcess(), stackFrame->AddrPC.Offset); + if (hModule && GetModuleFileName(hModule, formatBuff, _countof(formatBuff))) + { + frameStr.append(formatBuff); + } + + /// + /// Address + /// + xr_sprintf(formatBuff, _countof(formatBuff), " at %p", stackFrame->AddrPC.Offset); + frameStr.append(formatBuff); + + /// + /// Function info + /// + BYTE arrSymBuffer[512]; + ZeroMemory(arrSymBuffer, sizeof(arrSymBuffer)); + PIMAGEHLP_SYMBOL functionInfo = reinterpret_cast(arrSymBuffer); + functionInfo->SizeOfStruct = sizeof(*functionInfo); + functionInfo->MaxNameLength = sizeof(arrSymBuffer) - sizeof(*functionInfo) + 1; + DWORD_PTR dwFunctionOffset; + + result = SymGetSymFromAddr( + GetCurrentProcess(), + stackFrame->AddrPC.Offset, + &dwFunctionOffset, + functionInfo + ); + + if (result) + { + if (dwFunctionOffset) + { + xr_sprintf(formatBuff, _countof(formatBuff), " %s() + %Iu byte(s)", functionInfo->Name, dwFunctionOffset); + } + else + { + xr_sprintf(formatBuff, _countof(formatBuff), " %s()", functionInfo->Name); + } + frameStr.append(formatBuff); + } + + /// + /// Source info + /// + DWORD dwLineOffset; + IMAGEHLP_LINE sourceInfo = { 0 }; + sourceInfo.SizeOfStruct = sizeof(sourceInfo); + + result = SymGetLineFromAddr( + GetCurrentProcess(), + stackFrame->AddrPC.Offset, + &dwLineOffset, + &sourceInfo + ); + + if (result) + { + if (dwLineOffset) + { + xr_sprintf( + formatBuff, + _countof(formatBuff), + " in %s line %u + %u byte(s)", + sourceInfo.FileName, + sourceInfo.LineNumber, + dwLineOffset + ); + } + else + { + xr_sprintf(formatBuff, _countof(formatBuff), " in %s line %u", sourceInfo.FileName, sourceInfo.LineNumber); + } + frameStr.append(formatBuff); + } + + return true; } -size_t xrDebug::BuildStackTrace(char* buffer, size_t capacity, size_t lineCapacity) +bool xrDebug::InitializeSymbolEngine() { - // XXX: add support for x86_64 - CONTEXT context; - EXCEPTION_POINTERS ex_ptrs; - void* ebp; - context.ContextFlags = CONTEXT_FULL; - if (GetThreadContext(GetCurrentThread(), &context)) - { -#if defined(XR_X64) - context.Rip = (DWORD64)GetInstructionPtr(); - context.Rbp = (DWORD64)&ebp; - context.Rsp = (DWORD64)&context; -#elif defined(XR_X86) - context.Eip = (DWORD)GetInstructionPtr(); - context.Ebp = (DWORD)&ebp; - context.Esp = (DWORD)&context; + if (!m_SymEngineInitialized) + { + DWORD dwOptions = SymGetOptions(); + SymSetOptions(dwOptions | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); + + if (SymInitialize(GetCurrentProcess(), nullptr, TRUE)) + { + m_SymEngineInitialized = true; + } + } + + return m_SymEngineInitialized; +} + +void xrDebug::DeinitializeSymbolEngine(void) +{ + if (m_SymEngineInitialized) + { + SymCleanup(GetCurrentProcess()); + + m_SymEngineInitialized = false; + } +} + +xr_vector xrDebug::BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesCount) +{ + SStringVec traceResult; + STACKFRAME stackFrame = { 0 }; + xr_string frameStr; + + if (!InitializeSymbolEngine()) + { + Msg("[xrDebug::BuildStackTrace]InitializeSymbolEngine failed with error: %d", GetLastError()); + return traceResult; + } + + traceResult.reserve(maxFramesCount); + +#if defined XR_X64 + stackFrame.AddrPC.Mode = AddrModeFlat; + stackFrame.AddrPC.Offset = threadCtx->Rip; + stackFrame.AddrStack.Mode = AddrModeFlat; + stackFrame.AddrStack.Offset = threadCtx->Rsp; + stackFrame.AddrFrame.Mode = AddrModeFlat; + stackFrame.AddrFrame.Offset = threadCtx->Rbp; +#elif defined XR_X86 + stackFrame.AddrPC.Mode = AddrModeFlat; + stackFrame.AddrPC.Offset = threadCtx->Eip; + stackFrame.AddrStack.Mode = AddrModeFlat; + stackFrame.AddrStack.Offset = threadCtx->Esp; + stackFrame.AddrFrame.Mode = AddrModeFlat; + stackFrame.AddrFrame.Offset = threadCtx->Ebp; +#else +# error CPU architecture is not supported. #endif - ex_ptrs.ContextRecord = &context; - ex_ptrs.ExceptionRecord = 0; - return BuildStackTrace(&ex_ptrs, buffer, capacity, lineCapacity); - } - return 0; + + while ( + GetNextStackFrameSring(&stackFrame, threadCtx, frameStr) + && + traceResult.size() <= maxFramesCount + ) + { + traceResult.push_back(frameStr); + } + + DeinitializeSymbolEngine(); + + return traceResult; } -size_t xrDebug::BuildStackTrace(EXCEPTION_POINTERS* exPtrs, char* buffer, size_t capacity, size_t lineCapacity) +SStringVec xrDebug::BuildStackTrace(u16 maxFramesCount) +{ + CONTEXT currentThreadCtx = { 0 }; + + RtlCaptureContext(¤tThreadCtx); /// GetThreadContext cann't be used on the current thread + currentThreadCtx.ContextFlags = CONTEXT_FULL; + + return BuildStackTrace(¤tThreadCtx, maxFramesCount); +} + +void xrDebug::LogStackTrace(const char* header) { - memset(buffer, 0, capacity*lineCapacity); - auto flags = GSTSO_MODULE | GSTSO_SYMBOL | GSTSO_SRCLINE; - auto traceDump = GetFirstStackTraceString(flags, exPtrs); - int frameCount = 0; - while (traceDump) - { - lstrcpy(buffer + frameCount * lineCapacity, traceDump); - frameCount++; - traceDump = GetNextStackTraceString(flags, exPtrs); - } - return frameCount; + SStringVec stackTrace = BuildStackTrace(); + Msg("%s", header); + for each (const auto& frame in stackTrace) + { + Msg("%s", frame.c_str()); + } } void xrDebug::GatherInfo(char* assertionInfo, const ErrorLocation& loc, const char* expr, const char* desc, @@ -174,13 +328,13 @@ void xrDebug::GatherInfo(char* assertionInfo, const ErrorLocation& loc, const ch #ifdef USE_OWN_ERROR_MESSAGE_WINDOW buffer += sprintf(buffer, "stack trace:\n\n"); #endif // USE_OWN_ERROR_MESSAGE_WINDOW - BuildStackTrace(StackTrace.Frames, StackTrace.Capacity, StackTrace.LineCapacity); - for (size_t i = 2; i < StackTrace.Count; i++) + xr_vector stackTrace = BuildStackTrace(); + for (size_t i = 2; i < stackTrace.size(); i++) { if (shared_str_initialized) - Log(StackTrace[i]); + Log(stackTrace[i].c_str()); #ifdef USE_OWN_ERROR_MESSAGE_WINDOW - buffer += sprintf(buffer, "%s\n", StackTrace[i]); + buffer += sprintf(buffer, "%s\n", stackTrace[i].c_str()); #endif // USE_OWN_ERROR_MESSAGE_WINDOW } if (shared_str_initialized) @@ -431,18 +585,18 @@ LONG WINAPI xrDebug::UnhandledFilter(EXCEPTION_POINTERS* exPtrs) if (!ErrorAfterDialog && !strstr(GetCommandLine(), "-no_call_stack_assert")) { CONTEXT save = *exPtrs->ContextRecord; - StackTrace.Count = BuildStackTrace(exPtrs, StackTrace.Frames, StackTrace.Capacity, StackTrace.LineCapacity); + xr_vector stackTrace = BuildStackTrace(exPtrs->ContextRecord, 1024); *exPtrs->ContextRecord = save; if (shared_str_initialized) Msg("stack trace:\n"); if (!IsDebuggerPresent()) os_clipboard::copy_to_clipboard("stack trace:\r\n\r\n"); string4096 buffer; - for (size_t i = 0; i < StackTrace.Count; i++) + for (size_t i = 0; i < stackTrace.size(); i++) { if (shared_str_initialized) - Log(StackTrace[i]); - sprintf(buffer, "%s\r\n", StackTrace[i]); + Log(stackTrace[i].c_str()); + sprintf(buffer, "%s\r\n", stackTrace[i].c_str()); #ifdef DEBUG if (!IsDebuggerPresent()) os_clipboard::update_clipboard(buffer); diff --git a/src/xrCore/xrDebug.h b/src/xrCore/xrDebug.h index 89fe84483b0..cf2d4e67d62 100644 --- a/src/xrCore/xrDebug.h +++ b/src/xrCore/xrDebug.h @@ -1,16 +1,13 @@ #pragma once #include "xrCore/_types.h" +#include "xrCommon/xr_string.h" +#include "xrCommon/xr_vector.h" #include -struct StackTraceInfo -{ - static const size_t Capacity = 100; - static const size_t LineCapacity = 256; - char Frames[Capacity * LineCapacity]; - size_t Count; - - char* operator[](size_t i) { return Frames + i * LineCapacity; } -}; +#pragma warning(push) +#pragma warning(disable : 4091) /// 'typedef ': ignored on left of '' when no variable is declared +#include +#pragma warning(pop) class ErrorLocation { @@ -44,13 +41,14 @@ class XRCORE_API xrDebug using UnhandledExceptionFilter = LONG(WINAPI*)(EXCEPTION_POINTERS* exPtrs); private: + static const u16 MaxFramesCountDefault = 512; + static UnhandledExceptionFilter PrevFilter; static OutOfMemoryCallbackFunc OutOfMemoryCallback; static CrashHandler OnCrash; static DialogHandler OnDialog; static string_path BugReportFile; static bool ErrorAfterDialog; - static StackTraceInfo StackTrace; public: xrDebug() = delete; @@ -64,9 +62,7 @@ class XRCORE_API xrDebug static DialogHandler GetDialogHandler() { return OnDialog; } static void SetDialogHandler(DialogHandler handler) { OnDialog = handler; } static const char* ErrorToString(long code); - static void SetBugReportFile(const char* fileName); - static void LogStackTrace(const char* header); - static size_t BuildStackTrace(char* buffer, size_t capacity, size_t lineCapacity); + static void SetBugReportFile(const char* fileName); static void GatherInfo(char* assertionInfo, const ErrorLocation& loc, const char* expr, const char* desc, const char* arg1 = nullptr, const char* arg2 = nullptr); static void Fatal(const ErrorLocation& loc, const char* format, ...); @@ -78,13 +74,27 @@ class XRCORE_API xrDebug const char* arg1 = nullptr, const char* arg2 = nullptr); static void DoExit(const std::string& message); + /// + /// Note: DbgHelp is singlethreaded, so you must synchronize calls to these functions + /// + static void LogStackTrace(const char* header); + static xr_vector BuildStackTrace(u16 maxFramesCount = MaxFramesCountDefault); private: static void FormatLastError(char* buffer, const size_t& bufferSize); - static size_t BuildStackTrace(EXCEPTION_POINTERS* exPtrs, char* buffer, size_t capacity, size_t lineCapacity); static void SetupExceptionHandler(const bool& dedicated); static LONG WINAPI UnhandledFilter(EXCEPTION_POINTERS* exPtrs); static void WINAPI PreErrorHandler(INT_PTR); static void SaveMiniDump(EXCEPTION_POINTERS* exPtrs); + + /// + /// Next members relates to stack tracing + /// + static bool m_SymEngineInitialized; + + static xr_vector BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesCount); + static bool GetNextStackFrameSring(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string& frameStr); + static bool InitializeSymbolEngine(); + static void DeinitializeSymbolEngine(void); }; // for debug purposes only From 8380d8730d4879985310a37cbd4b3dcafb7c659d Mon Sep 17 00:00:00 2001 From: "Neo][" Date: Wed, 14 Mar 2018 14:50:10 +0500 Subject: [PATCH 2/6] Adds .editorconfig(formatting and code style settings for VS and other editors). Fixes code indentation and other typos. --- src/.editorconfig | 7 + src/xrCore/xrDebug.cpp | 327 ++++++++++++++++++++--------------------- src/xrCore/xrDebug.h | 36 ++--- 3 files changed, 188 insertions(+), 182 deletions(-) create mode 100644 src/.editorconfig diff --git a/src/.editorconfig b/src/.editorconfig new file mode 100644 index 00000000000..36fb7ba67c2 --- /dev/null +++ b/src/.editorconfig @@ -0,0 +1,7 @@ +# top-most EditorConfig file +root = true + +# 4 space indentation +[*.{cpp,h,hpp}] +indent_style = space +indent_size = 4 \ No newline at end of file diff --git a/src/xrCore/xrDebug.cpp b/src/xrCore/xrDebug.cpp index d913ada4fba..595754804d3 100644 --- a/src/xrCore/xrDebug.cpp +++ b/src/xrCore/xrDebug.cpp @@ -54,7 +54,6 @@ static BOOL bException = FALSE; namespace { - ICN void* GetInstructionPtr() { #ifdef _MSC_VER @@ -81,200 +80,200 @@ bool xrDebug::m_SymEngineInitialized = false; void xrDebug::SetBugReportFile(const char* fileName) { strcpy_s(BugReportFile, fileName); } -bool xrDebug::GetNextStackFrameSring(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string& frameStr) +bool xrDebug::GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string& frameStr) { - BOOL result = StackWalk( - MACHINE_TYPE, - GetCurrentProcess(), - GetCurrentThread(), - stackFrame, - threadCtx, - nullptr, - SymFunctionTableAccess, - SymGetModuleBase, - nullptr - ); - - if (result == FALSE || stackFrame->AddrPC.Offset == 0) - { - return false; - } - - frameStr.clear(); - string512 formatBuff; - - /// - /// Module name - /// - HINSTANCE hModule = (HINSTANCE)SymGetModuleBase(GetCurrentProcess(), stackFrame->AddrPC.Offset); - if (hModule && GetModuleFileName(hModule, formatBuff, _countof(formatBuff))) - { - frameStr.append(formatBuff); - } - - /// - /// Address - /// - xr_sprintf(formatBuff, _countof(formatBuff), " at %p", stackFrame->AddrPC.Offset); - frameStr.append(formatBuff); - - /// - /// Function info - /// - BYTE arrSymBuffer[512]; - ZeroMemory(arrSymBuffer, sizeof(arrSymBuffer)); - PIMAGEHLP_SYMBOL functionInfo = reinterpret_cast(arrSymBuffer); - functionInfo->SizeOfStruct = sizeof(*functionInfo); - functionInfo->MaxNameLength = sizeof(arrSymBuffer) - sizeof(*functionInfo) + 1; - DWORD_PTR dwFunctionOffset; - - result = SymGetSymFromAddr( - GetCurrentProcess(), - stackFrame->AddrPC.Offset, - &dwFunctionOffset, - functionInfo - ); - - if (result) - { - if (dwFunctionOffset) - { - xr_sprintf(formatBuff, _countof(formatBuff), " %s() + %Iu byte(s)", functionInfo->Name, dwFunctionOffset); - } - else - { - xr_sprintf(formatBuff, _countof(formatBuff), " %s()", functionInfo->Name); - } - frameStr.append(formatBuff); - } - - /// - /// Source info - /// - DWORD dwLineOffset; - IMAGEHLP_LINE sourceInfo = { 0 }; - sourceInfo.SizeOfStruct = sizeof(sourceInfo); - - result = SymGetLineFromAddr( - GetCurrentProcess(), - stackFrame->AddrPC.Offset, - &dwLineOffset, - &sourceInfo - ); - - if (result) - { - if (dwLineOffset) - { - xr_sprintf( - formatBuff, - _countof(formatBuff), - " in %s line %u + %u byte(s)", - sourceInfo.FileName, - sourceInfo.LineNumber, - dwLineOffset - ); - } - else - { - xr_sprintf(formatBuff, _countof(formatBuff), " in %s line %u", sourceInfo.FileName, sourceInfo.LineNumber); - } - frameStr.append(formatBuff); - } - - return true; + BOOL result = StackWalk( + MACHINE_TYPE, + GetCurrentProcess(), + GetCurrentThread(), + stackFrame, + threadCtx, + nullptr, + SymFunctionTableAccess, + SymGetModuleBase, + nullptr + ); + + if (result == FALSE || stackFrame->AddrPC.Offset == 0) + { + return false; + } + + frameStr.clear(); + string512 formatBuff; + + /// + /// Module name + /// + HINSTANCE hModule = (HINSTANCE)SymGetModuleBase(GetCurrentProcess(), stackFrame->AddrPC.Offset); + if (hModule && GetModuleFileName(hModule, formatBuff, _countof(formatBuff))) + { + frameStr.append(formatBuff); + } + + /// + /// Address + /// + xr_sprintf(formatBuff, _countof(formatBuff), " at %p", stackFrame->AddrPC.Offset); + frameStr.append(formatBuff); + + /// + /// Function info + /// + BYTE arrSymBuffer[512]; + ZeroMemory(arrSymBuffer, sizeof(arrSymBuffer)); + PIMAGEHLP_SYMBOL functionInfo = reinterpret_cast(arrSymBuffer); + functionInfo->SizeOfStruct = sizeof(*functionInfo); + functionInfo->MaxNameLength = sizeof(arrSymBuffer) - sizeof(*functionInfo) + 1; + DWORD_PTR dwFunctionOffset; + + result = SymGetSymFromAddr( + GetCurrentProcess(), + stackFrame->AddrPC.Offset, + &dwFunctionOffset, + functionInfo + ); + + if (result) + { + if (dwFunctionOffset) + { + xr_sprintf(formatBuff, _countof(formatBuff), " %s() + %Iu byte(s)", functionInfo->Name, dwFunctionOffset); + } + else + { + xr_sprintf(formatBuff, _countof(formatBuff), " %s()", functionInfo->Name); + } + frameStr.append(formatBuff); + } + + /// + /// Source info + /// + DWORD dwLineOffset; + IMAGEHLP_LINE sourceInfo = { 0 }; + sourceInfo.SizeOfStruct = sizeof(sourceInfo); + + result = SymGetLineFromAddr( + GetCurrentProcess(), + stackFrame->AddrPC.Offset, + &dwLineOffset, + &sourceInfo + ); + + if (result) + { + if (dwLineOffset) + { + xr_sprintf( + formatBuff, + _countof(formatBuff), + " in %s line %u + %u byte(s)", + sourceInfo.FileName, + sourceInfo.LineNumber, + dwLineOffset + ); + } + else + { + xr_sprintf(formatBuff, _countof(formatBuff), " in %s line %u", sourceInfo.FileName, sourceInfo.LineNumber); + } + frameStr.append(formatBuff); + } + + return true; } bool xrDebug::InitializeSymbolEngine() { - if (!m_SymEngineInitialized) - { - DWORD dwOptions = SymGetOptions(); - SymSetOptions(dwOptions | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); - - if (SymInitialize(GetCurrentProcess(), nullptr, TRUE)) - { - m_SymEngineInitialized = true; - } - } - - return m_SymEngineInitialized; + if (!m_SymEngineInitialized) + { + DWORD dwOptions = SymGetOptions(); + SymSetOptions(dwOptions | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); + + if (SymInitialize(GetCurrentProcess(), nullptr, TRUE)) + { + m_SymEngineInitialized = true; + } + } + + return m_SymEngineInitialized; } void xrDebug::DeinitializeSymbolEngine(void) { - if (m_SymEngineInitialized) - { - SymCleanup(GetCurrentProcess()); + if (m_SymEngineInitialized) + { + SymCleanup(GetCurrentProcess()); - m_SymEngineInitialized = false; - } + m_SymEngineInitialized = false; + } } xr_vector xrDebug::BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesCount) { - SStringVec traceResult; - STACKFRAME stackFrame = { 0 }; - xr_string frameStr; + SStringVec traceResult; + STACKFRAME stackFrame = { 0 }; + xr_string frameStr; - if (!InitializeSymbolEngine()) - { - Msg("[xrDebug::BuildStackTrace]InitializeSymbolEngine failed with error: %d", GetLastError()); - return traceResult; - } + if (!InitializeSymbolEngine()) + { + Msg("[xrDebug::BuildStackTrace]InitializeSymbolEngine failed with error: %d", GetLastError()); + return traceResult; + } - traceResult.reserve(maxFramesCount); + traceResult.reserve(maxFramesCount); #if defined XR_X64 - stackFrame.AddrPC.Mode = AddrModeFlat; - stackFrame.AddrPC.Offset = threadCtx->Rip; - stackFrame.AddrStack.Mode = AddrModeFlat; - stackFrame.AddrStack.Offset = threadCtx->Rsp; - stackFrame.AddrFrame.Mode = AddrModeFlat; - stackFrame.AddrFrame.Offset = threadCtx->Rbp; + stackFrame.AddrPC.Mode = AddrModeFlat; + stackFrame.AddrPC.Offset = threadCtx->Rip; + stackFrame.AddrStack.Mode = AddrModeFlat; + stackFrame.AddrStack.Offset = threadCtx->Rsp; + stackFrame.AddrFrame.Mode = AddrModeFlat; + stackFrame.AddrFrame.Offset = threadCtx->Rbp; #elif defined XR_X86 - stackFrame.AddrPC.Mode = AddrModeFlat; - stackFrame.AddrPC.Offset = threadCtx->Eip; - stackFrame.AddrStack.Mode = AddrModeFlat; - stackFrame.AddrStack.Offset = threadCtx->Esp; - stackFrame.AddrFrame.Mode = AddrModeFlat; - stackFrame.AddrFrame.Offset = threadCtx->Ebp; + stackFrame.AddrPC.Mode = AddrModeFlat; + stackFrame.AddrPC.Offset = threadCtx->Eip; + stackFrame.AddrStack.Mode = AddrModeFlat; + stackFrame.AddrStack.Offset = threadCtx->Esp; + stackFrame.AddrFrame.Mode = AddrModeFlat; + stackFrame.AddrFrame.Offset = threadCtx->Ebp; #else # error CPU architecture is not supported. #endif - while ( - GetNextStackFrameSring(&stackFrame, threadCtx, frameStr) - && - traceResult.size() <= maxFramesCount - ) - { - traceResult.push_back(frameStr); - } + while ( + GetNextStackFrameString(&stackFrame, threadCtx, frameStr) + && + traceResult.size() <= maxFramesCount + ) + { + traceResult.push_back(frameStr); + } - DeinitializeSymbolEngine(); + DeinitializeSymbolEngine(); - return traceResult; + return traceResult; } SStringVec xrDebug::BuildStackTrace(u16 maxFramesCount) -{ - CONTEXT currentThreadCtx = { 0 }; +{ + CONTEXT currentThreadCtx = { 0 }; - RtlCaptureContext(¤tThreadCtx); /// GetThreadContext cann't be used on the current thread - currentThreadCtx.ContextFlags = CONTEXT_FULL; + RtlCaptureContext(¤tThreadCtx); /// GetThreadContext cann't be used on the current thread + currentThreadCtx.ContextFlags = CONTEXT_FULL; - return BuildStackTrace(¤tThreadCtx, maxFramesCount); + return BuildStackTrace(¤tThreadCtx, maxFramesCount); } void xrDebug::LogStackTrace(const char* header) { - SStringVec stackTrace = BuildStackTrace(); - Msg("%s", header); - for each (const auto& frame in stackTrace) - { - Msg("%s", frame.c_str()); - } + SStringVec stackTrace = BuildStackTrace(); + Msg("%s", header); + for(const auto& frame : stackTrace) + { + Msg("%s", frame.c_str()); + } } void xrDebug::GatherInfo(char* assertionInfo, const ErrorLocation& loc, const char* expr, const char* desc, @@ -585,7 +584,7 @@ LONG WINAPI xrDebug::UnhandledFilter(EXCEPTION_POINTERS* exPtrs) if (!ErrorAfterDialog && !strstr(GetCommandLine(), "-no_call_stack_assert")) { CONTEXT save = *exPtrs->ContextRecord; - xr_vector stackTrace = BuildStackTrace(exPtrs->ContextRecord, 1024); + xr_vector stackTrace = BuildStackTrace(exPtrs->ContextRecord, 1024); *exPtrs->ContextRecord = save; if (shared_str_initialized) Msg("stack trace:\n"); @@ -682,7 +681,7 @@ static void invalid_parameter_handler( line = __LINE__; xr_strcpy(mbFile, __FILE__); } - xrDebug::Fail(ignoreAlways, {mbFile, int(line), mbFunction}, mbExpression, "invalid parameter"); + xrDebug::Fail(ignoreAlways, { mbFile, int(line), mbFunction }, mbExpression, "invalid parameter"); } static void pure_call_handler() { handler_base("pure virtual function call"); } @@ -699,7 +698,7 @@ void xrDebug::OnThreadSpawn() #ifdef USE_BUG_TRAP BT_SetTerminate(); #else -// std::set_terminate(_terminate); + // std::set_terminate(_terminate); #endif _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); signal(SIGABRT, abort_handler); diff --git a/src/xrCore/xrDebug.h b/src/xrCore/xrDebug.h index cf2d4e67d62..9d38be3488a 100644 --- a/src/xrCore/xrDebug.h +++ b/src/xrCore/xrDebug.h @@ -35,13 +35,13 @@ class ErrorLocation class XRCORE_API xrDebug { public: - using OutOfMemoryCallbackFunc = void (*)(); - using CrashHandler = void (*)(); - using DialogHandler = void (*)(bool); + using OutOfMemoryCallbackFunc = void(*)(); + using CrashHandler = void(*)(); + using DialogHandler = void(*)(bool); using UnhandledExceptionFilter = LONG(WINAPI*)(EXCEPTION_POINTERS* exPtrs); private: - static const u16 MaxFramesCountDefault = 512; + static const u16 MaxFramesCountDefault = 512; static UnhandledExceptionFilter PrevFilter; static OutOfMemoryCallbackFunc OutOfMemoryCallback; @@ -62,7 +62,7 @@ class XRCORE_API xrDebug static DialogHandler GetDialogHandler() { return OnDialog; } static void SetDialogHandler(DialogHandler handler) { OnDialog = handler; } static const char* ErrorToString(long code); - static void SetBugReportFile(const char* fileName); + static void SetBugReportFile(const char* fileName); static void GatherInfo(char* assertionInfo, const ErrorLocation& loc, const char* expr, const char* desc, const char* arg1 = nullptr, const char* arg2 = nullptr); static void Fatal(const ErrorLocation& loc, const char* format, ...); @@ -74,11 +74,11 @@ class XRCORE_API xrDebug const char* arg1 = nullptr, const char* arg2 = nullptr); static void DoExit(const std::string& message); - /// - /// Note: DbgHelp is singlethreaded, so you must synchronize calls to these functions - /// - static void LogStackTrace(const char* header); - static xr_vector BuildStackTrace(u16 maxFramesCount = MaxFramesCountDefault); + /// + /// Note: DbgHelp is singlethreaded, so you must synchronize calls to these functions + /// + static void LogStackTrace(const char* header); + static xr_vector BuildStackTrace(u16 maxFramesCount = MaxFramesCountDefault); private: static void FormatLastError(char* buffer, const size_t& bufferSize); static void SetupExceptionHandler(const bool& dedicated); @@ -86,15 +86,15 @@ class XRCORE_API xrDebug static void WINAPI PreErrorHandler(INT_PTR); static void SaveMiniDump(EXCEPTION_POINTERS* exPtrs); - /// - /// Next members relates to stack tracing - /// - static bool m_SymEngineInitialized; + /// + /// Next members relates to stack tracing + /// + static bool m_SymEngineInitialized; - static xr_vector BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesCount); - static bool GetNextStackFrameSring(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string& frameStr); - static bool InitializeSymbolEngine(); - static void DeinitializeSymbolEngine(void); + static xr_vector BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesCount); + static bool GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string& frameStr); + static bool InitializeSymbolEngine(); + static void DeinitializeSymbolEngine(void); }; // for debug purposes only From b7a895545e41f02823b2df2e97d08be4075fb95b Mon Sep 17 00:00:00 2001 From: "Neo][" Date: Wed, 14 Mar 2018 15:07:39 +0500 Subject: [PATCH 3/6] Adds more fixes to follow coding convention --- src/xrCore/xrDebug.cpp | 43 +++++++----------------------------------- 1 file changed, 7 insertions(+), 36 deletions(-) diff --git a/src/xrCore/xrDebug.cpp b/src/xrCore/xrDebug.cpp index 595754804d3..52bdf480565 100644 --- a/src/xrCore/xrDebug.cpp +++ b/src/xrCore/xrDebug.cpp @@ -82,17 +82,8 @@ void xrDebug::SetBugReportFile(const char* fileName) { strcpy_s(BugReportFile, f bool xrDebug::GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string& frameStr) { - BOOL result = StackWalk( - MACHINE_TYPE, - GetCurrentProcess(), - GetCurrentThread(), - stackFrame, - threadCtx, - nullptr, - SymFunctionTableAccess, - SymGetModuleBase, - nullptr - ); + BOOL result = StackWalk(MACHINE_TYPE, GetCurrentProcess(), GetCurrentThread(), stackFrame, threadCtx, nullptr, + SymFunctionTableAccess, SymGetModuleBase, nullptr); if (result == FALSE || stackFrame->AddrPC.Offset == 0) { @@ -127,12 +118,7 @@ bool xrDebug::GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCt functionInfo->MaxNameLength = sizeof(arrSymBuffer) - sizeof(*functionInfo) + 1; DWORD_PTR dwFunctionOffset; - result = SymGetSymFromAddr( - GetCurrentProcess(), - stackFrame->AddrPC.Offset, - &dwFunctionOffset, - functionInfo - ); + result = SymGetSymFromAddr(GetCurrentProcess(), stackFrame->AddrPC.Offset, &dwFunctionOffset, functionInfo); if (result) { @@ -154,25 +140,14 @@ bool xrDebug::GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCt IMAGEHLP_LINE sourceInfo = { 0 }; sourceInfo.SizeOfStruct = sizeof(sourceInfo); - result = SymGetLineFromAddr( - GetCurrentProcess(), - stackFrame->AddrPC.Offset, - &dwLineOffset, - &sourceInfo - ); + result = SymGetLineFromAddr(GetCurrentProcess(), stackFrame->AddrPC.Offset, &dwLineOffset, &sourceInfo); if (result) { if (dwLineOffset) { - xr_sprintf( - formatBuff, - _countof(formatBuff), - " in %s line %u + %u byte(s)", - sourceInfo.FileName, - sourceInfo.LineNumber, - dwLineOffset - ); + xr_sprintf(formatBuff, _countof(formatBuff), " in %s line %u + %u byte(s)", sourceInfo.FileName, + sourceInfo.LineNumber, dwLineOffset); } else { @@ -242,11 +217,7 @@ xr_vector xrDebug::BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesC # error CPU architecture is not supported. #endif - while ( - GetNextStackFrameString(&stackFrame, threadCtx, frameStr) - && - traceResult.size() <= maxFramesCount - ) + while (GetNextStackFrameString(&stackFrame, threadCtx, frameStr) && traceResult.size() <= maxFramesCount) { traceResult.push_back(frameStr); } From a598ee076bfa23485402dcea9154def95f4880ef Mon Sep 17 00:00:00 2001 From: "Neo][" Date: Thu, 15 Mar 2018 10:26:04 +0500 Subject: [PATCH 4/6] Adds a synchronization to the stack tracing methods. --- src/xrCore/Threading/ScopeLock.h | 27 +++++++++++++++++++++++++++ src/xrCore/xrCore.vcxproj | 1 + src/xrCore/xrCore.vcxproj.filters | 3 +++ src/xrCore/xrDebug.cpp | 7 ++++++- src/xrCore/xrDebug.h | 6 +++--- 5 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 src/xrCore/Threading/ScopeLock.h diff --git a/src/xrCore/Threading/ScopeLock.h b/src/xrCore/Threading/ScopeLock.h new file mode 100644 index 00000000000..1ca548128cb --- /dev/null +++ b/src/xrCore/Threading/ScopeLock.h @@ -0,0 +1,27 @@ +#pragma once + +#include "Common/Noncopyable.hpp" +#include "Threading/Lock.hpp" +#include "xrDebug.h" + +class ScopeLock: Noncopyable +{ +public: + ScopeLock(Lock* SyncObject); + ~ScopeLock(); + +private: + Lock * m_SyncObject; +}; + +ScopeLock::ScopeLock(Lock* SyncObject): m_SyncObject(SyncObject) +{ + VERIFY(m_SyncObject); + + m_SyncObject->Enter(); +} + +ScopeLock::~ScopeLock() +{ + m_SyncObject->Leave(); +} diff --git a/src/xrCore/xrCore.vcxproj b/src/xrCore/xrCore.vcxproj index 8318e095b59..5fd13c37444 100644 --- a/src/xrCore/xrCore.vcxproj +++ b/src/xrCore/xrCore.vcxproj @@ -354,6 +354,7 @@ + diff --git a/src/xrCore/xrCore.vcxproj.filters b/src/xrCore/xrCore.vcxproj.filters index ba6f794daf8..2e16cbd915f 100644 --- a/src/xrCore/xrCore.vcxproj.filters +++ b/src/xrCore/xrCore.vcxproj.filters @@ -668,6 +668,9 @@ Memory + + Threading + diff --git a/src/xrCore/xrDebug.cpp b/src/xrCore/xrDebug.cpp index 52bdf480565..53d273dd8cd 100644 --- a/src/xrCore/xrDebug.cpp +++ b/src/xrCore/xrDebug.cpp @@ -4,7 +4,8 @@ #include "xrDebug.h" #include "os_clipboard.h" #include "Debug/dxerr.h" -#include "xrCore/Threading/Lock.hpp" +#include "Threading/ScopeLock.h" + #pragma warning(push) #pragma warning(disable : 4091) // 'typedef ': ignored on left of '' when no variable is declared #include "Debug/MiniDump.h" @@ -76,7 +77,9 @@ xrDebug::CrashHandler xrDebug::OnCrash = nullptr; xrDebug::DialogHandler xrDebug::OnDialog = nullptr; string_path xrDebug::BugReportFile; bool xrDebug::ErrorAfterDialog = false; + bool xrDebug::m_SymEngineInitialized = false; +Lock xrDebug::m_DbgHelpLock; void xrDebug::SetBugReportFile(const char* fileName) { strcpy_s(BugReportFile, fileName); } @@ -187,6 +190,8 @@ void xrDebug::DeinitializeSymbolEngine(void) xr_vector xrDebug::BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesCount) { + ScopeLock Lock(&m_DbgHelpLock); + SStringVec traceResult; STACKFRAME stackFrame = { 0 }; xr_string frameStr; diff --git a/src/xrCore/xrDebug.h b/src/xrCore/xrDebug.h index 9d38be3488a..42d986eed56 100644 --- a/src/xrCore/xrDebug.h +++ b/src/xrCore/xrDebug.h @@ -2,6 +2,8 @@ #include "xrCore/_types.h" #include "xrCommon/xr_string.h" #include "xrCommon/xr_vector.h" +#include "Threading/Lock.hpp" + #include #pragma warning(push) @@ -74,9 +76,6 @@ class XRCORE_API xrDebug const char* arg1 = nullptr, const char* arg2 = nullptr); static void DoExit(const std::string& message); - /// - /// Note: DbgHelp is singlethreaded, so you must synchronize calls to these functions - /// static void LogStackTrace(const char* header); static xr_vector BuildStackTrace(u16 maxFramesCount = MaxFramesCountDefault); private: @@ -90,6 +89,7 @@ class XRCORE_API xrDebug /// Next members relates to stack tracing /// static bool m_SymEngineInitialized; + static Lock m_DbgHelpLock; static xr_vector BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesCount); static bool GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string& frameStr); From d2536250eee0270d46f2c2abc6b1659b6b95adfd Mon Sep 17 00:00:00 2001 From: "Neo][" Date: Thu, 15 Mar 2018 13:47:28 +0500 Subject: [PATCH 5/6] Reformat sources --- src/.editorconfig | 5 ++- src/xrCore/Threading/ScopeLock.h | 14 +++--- src/xrCore/xrDebug.cpp | 74 ++++++++++++++++---------------- src/xrCore/xrDebug.h | 46 ++++++++++---------- 4 files changed, 71 insertions(+), 68 deletions(-) diff --git a/src/.editorconfig b/src/.editorconfig index 36fb7ba67c2..178814df73c 100644 --- a/src/.editorconfig +++ b/src/.editorconfig @@ -4,4 +4,7 @@ root = true # 4 space indentation [*.{cpp,h,hpp}] indent_style = space -indent_size = 4 \ No newline at end of file +indent_size = 4 + +# newline ending every file +insert_final_newline = true diff --git a/src/xrCore/Threading/ScopeLock.h b/src/xrCore/Threading/ScopeLock.h index 1ca548128cb..2594fc6ed57 100644 --- a/src/xrCore/Threading/ScopeLock.h +++ b/src/xrCore/Threading/ScopeLock.h @@ -4,24 +4,24 @@ #include "Threading/Lock.hpp" #include "xrDebug.h" -class ScopeLock: Noncopyable +class ScopeLock : Noncopyable { public: - ScopeLock(Lock* SyncObject); + ScopeLock(Lock *SyncObject); ~ScopeLock(); private: - Lock * m_SyncObject; + Lock *syncObject; }; -ScopeLock::ScopeLock(Lock* SyncObject): m_SyncObject(SyncObject) +ScopeLock::ScopeLock(Lock *SyncObject) : syncObject(SyncObject) { - VERIFY(m_SyncObject); + VERIFY(syncObject); - m_SyncObject->Enter(); + syncObject->Enter(); } ScopeLock::~ScopeLock() { - m_SyncObject->Leave(); + syncObject->Leave(); } diff --git a/src/xrCore/xrDebug.cpp b/src/xrCore/xrDebug.cpp index 53d273dd8cd..7a946b2b360 100644 --- a/src/xrCore/xrDebug.cpp +++ b/src/xrCore/xrDebug.cpp @@ -78,12 +78,12 @@ xrDebug::DialogHandler xrDebug::OnDialog = nullptr; string_path xrDebug::BugReportFile; bool xrDebug::ErrorAfterDialog = false; -bool xrDebug::m_SymEngineInitialized = false; -Lock xrDebug::m_DbgHelpLock; +bool xrDebug::symEngineInitialized = false; +Lock xrDebug::dbgHelpLock; -void xrDebug::SetBugReportFile(const char* fileName) { strcpy_s(BugReportFile, fileName); } +void xrDebug::SetBugReportFile(const char *fileName) { strcpy_s(BugReportFile, fileName); } -bool xrDebug::GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string& frameStr) +bool xrDebug::GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string &frameStr) { BOOL result = StackWalk(MACHINE_TYPE, GetCurrentProcess(), GetCurrentThread(), stackFrame, threadCtx, nullptr, SymFunctionTableAccess, SymGetModuleBase, nullptr); @@ -140,7 +140,7 @@ bool xrDebug::GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCt /// Source info /// DWORD dwLineOffset; - IMAGEHLP_LINE sourceInfo = { 0 }; + IMAGEHLP_LINE sourceInfo = {}; sourceInfo.SizeOfStruct = sizeof(sourceInfo); result = SymGetLineFromAddr(GetCurrentProcess(), stackFrame->AddrPC.Offset, &dwLineOffset, &sourceInfo); @@ -164,36 +164,36 @@ bool xrDebug::GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCt bool xrDebug::InitializeSymbolEngine() { - if (!m_SymEngineInitialized) + if (!symEngineInitialized) { DWORD dwOptions = SymGetOptions(); SymSetOptions(dwOptions | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); if (SymInitialize(GetCurrentProcess(), nullptr, TRUE)) { - m_SymEngineInitialized = true; + symEngineInitialized = true; } } - return m_SymEngineInitialized; + return symEngineInitialized; } void xrDebug::DeinitializeSymbolEngine(void) { - if (m_SymEngineInitialized) + if (symEngineInitialized) { SymCleanup(GetCurrentProcess()); - m_SymEngineInitialized = false; + symEngineInitialized = false; } } xr_vector xrDebug::BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesCount) { - ScopeLock Lock(&m_DbgHelpLock); + ScopeLock Lock(&dbgHelpLock); SStringVec traceResult; - STACKFRAME stackFrame = { 0 }; + STACKFRAME stackFrame = {}; xr_string frameStr; if (!InitializeSymbolEngine()) @@ -234,7 +234,7 @@ xr_vector xrDebug::BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesC SStringVec xrDebug::BuildStackTrace(u16 maxFramesCount) { - CONTEXT currentThreadCtx = { 0 }; + CONTEXT currentThreadCtx = {}; RtlCaptureContext(¤tThreadCtx); /// GetThreadContext cann't be used on the current thread currentThreadCtx.ContextFlags = CONTEXT_FULL; @@ -242,20 +242,20 @@ SStringVec xrDebug::BuildStackTrace(u16 maxFramesCount) return BuildStackTrace(¤tThreadCtx, maxFramesCount); } -void xrDebug::LogStackTrace(const char* header) +void xrDebug::LogStackTrace(const char *header) { SStringVec stackTrace = BuildStackTrace(); Msg("%s", header); - for(const auto& frame : stackTrace) + for (const auto &frame : stackTrace) { Msg("%s", frame.c_str()); } } -void xrDebug::GatherInfo(char* assertionInfo, const ErrorLocation& loc, const char* expr, const char* desc, - const char* arg1, const char* arg2) +void xrDebug::GatherInfo(char *assertionInfo, const ErrorLocation &loc, const char *expr, const char *desc, + const char *arg1, const char *arg2) { - char* buffer = assertionInfo; + char *buffer = assertionInfo; if (!expr) expr = ""; bool extendedDesc = desc && strchr(desc, '\n'); @@ -317,7 +317,7 @@ void xrDebug::GatherInfo(char* assertionInfo, const ErrorLocation& loc, const ch os_clipboard::copy_to_clipboard(assertionInfo); } -void xrDebug::Fatal(const ErrorLocation& loc, const char* format, ...) +void xrDebug::Fatal(const ErrorLocation &loc, const char *format, ...) { string1024 desc; va_list args; @@ -328,14 +328,14 @@ void xrDebug::Fatal(const ErrorLocation& loc, const char* format, ...) Fail(ignoreAlways, loc, nullptr, "fatal error", desc); } -void xrDebug::Fail( - bool& ignoreAlways, const ErrorLocation& loc, const char* expr, long hresult, const char* arg1, const char* arg2) +void xrDebug::Fail(bool &ignoreAlways, const ErrorLocation &loc, const char *expr, long hresult, const char *arg1, + const char *arg2) { Fail(ignoreAlways, loc, expr, xrDebug::ErrorToString(hresult), arg1, arg2); } -void xrDebug::Fail(bool& ignoreAlways, const ErrorLocation& loc, const char* expr, const char* desc, const char* arg1, - const char* arg2) +void xrDebug::Fail(bool &ignoreAlways, const ErrorLocation &loc, const char *expr, const char *desc, const char *arg1, + const char *arg2) { #ifdef PROFILE_CRITICAL_SECTIONS static Lock lock(MUTEX_PROFILE_ID(xrDebug::Backend)); @@ -393,13 +393,13 @@ void xrDebug::Fail(bool& ignoreAlways, const ErrorLocation& loc, const char* exp lock.Leave(); } -void xrDebug::Fail(bool& ignoreAlways, const ErrorLocation& loc, const char* expr, const std::string& desc, - const char* arg1, const char* arg2) +void xrDebug::Fail(bool &ignoreAlways, const ErrorLocation &loc, const char *expr, const std::string &desc, + const char *arg1, const char *arg2) { Fail(ignoreAlways, loc, expr, desc.c_str(), arg1, arg2); } -void xrDebug::DoExit(const std::string& message) +void xrDebug::DoExit(const std::string &message) { FlushLog(); MessageBox(NULL, message.c_str(), "Error", MB_OK | MB_ICONERROR | MB_SYSTEMMODAL); @@ -408,7 +408,7 @@ void xrDebug::DoExit(const std::string& message) LPCSTR xrDebug::ErrorToString(long code) { - const char* result = nullptr; + const char *result = nullptr; static string1024 descStorage; DXGetErrorDescription(code, descStorage, sizeof(descStorage)); if (!result) @@ -476,7 +476,7 @@ void WINAPI xrDebug::PreErrorHandler(INT_PTR) BT_SaveSnapshot(nullptr); } -void xrDebug::SetupExceptionHandler(const bool& dedicated) +void xrDebug::SetupExceptionHandler(const bool &dedicated) { // disable 'appname has stopped working' popup dialog UINT prevMode = SetErrorMode(SEM_NOGPFAULTERRORBOX); @@ -516,7 +516,7 @@ void xrDebug::SetupExceptionHandler(const bool& dedicated) #endif // USE_BUG_TRAP #ifdef USE_OWN_MINI_DUMP -void xrDebug::SaveMiniDump(EXCEPTION_POINTERS* exPtrs) +void xrDebug::SaveMiniDump(EXCEPTION_POINTERS *exPtrs) { string64 dateStr; timestamp(dateStr); @@ -537,7 +537,7 @@ void xrDebug::SaveMiniDump(EXCEPTION_POINTERS* exPtrs) } #endif -void xrDebug::FormatLastError(char* buffer, const size_t& bufferSize) +void xrDebug::FormatLastError(char *buffer, const size_t &bufferSize) { int lastErr = GetLastError(); if (lastErr == ERROR_SUCCESS) @@ -545,7 +545,7 @@ void xrDebug::FormatLastError(char* buffer, const size_t& bufferSize) *buffer = 0; return; } - void* msg = nullptr; + void *msg = nullptr; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, nullptr, lastErr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, nullptr); // XXX nitrocaster: check buffer overflow @@ -553,7 +553,7 @@ void xrDebug::FormatLastError(char* buffer, const size_t& bufferSize) LocalFree(msg); } -LONG WINAPI xrDebug::UnhandledFilter(EXCEPTION_POINTERS* exPtrs) +LONG WINAPI xrDebug::UnhandledFilter(EXCEPTION_POINTERS *exPtrs) { string256 errMsg; FormatLastError(errMsg, sizeof(errMsg)); @@ -628,14 +628,14 @@ void _terminate() } #endif // USE_BUG_TRAP -static void handler_base(const char* reason) +static void handler_base(const char *reason) { bool ignoreAlways = false; xrDebug::Fail(ignoreAlways, DEBUG_INFO, nullptr, reason, nullptr, nullptr); } -static void invalid_parameter_handler( - const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t reserved) +static void invalid_parameter_handler(const wchar_t *expression, const wchar_t *function, const wchar_t *file, + unsigned int line, uintptr_t reserved) { bool ignoreAlways = false; string4096 mbExpression; @@ -657,7 +657,7 @@ static void invalid_parameter_handler( line = __LINE__; xr_strcpy(mbFile, __FILE__); } - xrDebug::Fail(ignoreAlways, { mbFile, int(line), mbFunction }, mbExpression, "invalid parameter"); + xrDebug::Fail(ignoreAlways, {mbFile, int(line), mbFunction}, mbExpression, "invalid parameter"); } static void pure_call_handler() { handler_base("pure virtual function call"); } @@ -692,7 +692,7 @@ void xrDebug::OnThreadSpawn() #endif } -void xrDebug::Initialize(const bool& dedicated) +void xrDebug::Initialize(const bool &dedicated) { *BugReportFile = 0; OnThreadSpawn(); diff --git a/src/xrCore/xrDebug.h b/src/xrCore/xrDebug.h index 42d986eed56..94c39d7ddd6 100644 --- a/src/xrCore/xrDebug.h +++ b/src/xrCore/xrDebug.h @@ -18,14 +18,14 @@ class ErrorLocation int Line = -1; const char* Function = nullptr; - ErrorLocation(const char* file, int line, const char* function) + ErrorLocation(const char* file, int line, const char *function) { File = file; Line = line; Function = function; } - ErrorLocation& operator=(const ErrorLocation& rhs) + ErrorLocation& operator=(const ErrorLocation &rhs) { File = rhs.File; Line = rhs.Line; @@ -40,7 +40,7 @@ class XRCORE_API xrDebug using OutOfMemoryCallbackFunc = void(*)(); using CrashHandler = void(*)(); using DialogHandler = void(*)(bool); - using UnhandledExceptionFilter = LONG(WINAPI*)(EXCEPTION_POINTERS* exPtrs); + using UnhandledExceptionFilter = LONG(WINAPI*)(EXCEPTION_POINTERS *exPtrs); private: static const u16 MaxFramesCountDefault = 512; @@ -64,41 +64,41 @@ class XRCORE_API xrDebug static DialogHandler GetDialogHandler() { return OnDialog; } static void SetDialogHandler(DialogHandler handler) { OnDialog = handler; } static const char* ErrorToString(long code); - static void SetBugReportFile(const char* fileName); - static void GatherInfo(char* assertionInfo, const ErrorLocation& loc, const char* expr, const char* desc, - const char* arg1 = nullptr, const char* arg2 = nullptr); - static void Fatal(const ErrorLocation& loc, const char* format, ...); - static void Fail(bool& ignoreAlways, const ErrorLocation& loc, const char* expr, long hresult, - const char* arg1 = nullptr, const char* arg2 = nullptr); - static void Fail(bool& ignoreAlways, const ErrorLocation& loc, const char* expr, - const char* desc = "assertion failed", const char* arg1 = nullptr, const char* arg2 = nullptr); - static void Fail(bool& ignoreAlways, const ErrorLocation& loc, const char* expr, const std::string& desc, - const char* arg1 = nullptr, const char* arg2 = nullptr); - static void DoExit(const std::string& message); + static void SetBugReportFile(const char *fileName); + static void GatherInfo(char *assertionInfo, const ErrorLocation &loc, const char *expr, const char *desc, + const char *arg1 = nullptr, const char *arg2 = nullptr); + static void Fatal(const ErrorLocation &loc, const char *format, ...); + static void Fail(bool &ignoreAlways, const ErrorLocation &loc, const char *expr, long hresult, + const char *arg1 = nullptr, const char *arg2 = nullptr); + static void Fail(bool &ignoreAlways, const ErrorLocation &loc, const char *expr, + const char *desc = "assertion failed", const char *arg1 = nullptr, const char *arg2 = nullptr); + static void Fail(bool &ignoreAlways, const ErrorLocation &loc, const char *expr, const std::string &desc, + const char *arg1 = nullptr, const char *arg2 = nullptr); + static void DoExit(const std::string &message); - static void LogStackTrace(const char* header); + static void LogStackTrace(const char *header); static xr_vector BuildStackTrace(u16 maxFramesCount = MaxFramesCountDefault); private: - static void FormatLastError(char* buffer, const size_t& bufferSize); - static void SetupExceptionHandler(const bool& dedicated); - static LONG WINAPI UnhandledFilter(EXCEPTION_POINTERS* exPtrs); + static void FormatLastError(char *buffer, const size_t &bufferSize); + static void SetupExceptionHandler(const bool &dedicated); + static LONG WINAPI UnhandledFilter(EXCEPTION_POINTERS *exPtrs); static void WINAPI PreErrorHandler(INT_PTR); - static void SaveMiniDump(EXCEPTION_POINTERS* exPtrs); + static void SaveMiniDump(EXCEPTION_POINTERS *exPtrs); /// /// Next members relates to stack tracing /// - static bool m_SymEngineInitialized; - static Lock m_DbgHelpLock; + static bool symEngineInitialized; + static Lock dbgHelpLock; static xr_vector BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesCount); - static bool GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string& frameStr); + static bool GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string &frameStr); static bool InitializeSymbolEngine(); static void DeinitializeSymbolEngine(void); }; // for debug purposes only -inline std::string make_string(const char* format, ...) +inline std::string make_string(const char *format, ...) { va_list args; va_start(args, format); From 960882555784cfe77214bb61e1452651d268e152 Mon Sep 17 00:00:00 2001 From: "Neo][" Date: Thu, 15 Mar 2018 14:08:14 +0500 Subject: [PATCH 6/6] Reformat source 2 --- src/xrCore/xrDebug.h | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/xrCore/xrDebug.h b/src/xrCore/xrDebug.h index 94c39d7ddd6..7dbdb9de4d5 100644 --- a/src/xrCore/xrDebug.h +++ b/src/xrCore/xrDebug.h @@ -43,8 +43,6 @@ class XRCORE_API xrDebug using UnhandledExceptionFilter = LONG(WINAPI*)(EXCEPTION_POINTERS *exPtrs); private: - static const u16 MaxFramesCountDefault = 512; - static UnhandledExceptionFilter PrevFilter; static OutOfMemoryCallbackFunc OutOfMemoryCallback; static CrashHandler OnCrash; @@ -77,20 +75,15 @@ class XRCORE_API xrDebug static void DoExit(const std::string &message); static void LogStackTrace(const char *header); - static xr_vector BuildStackTrace(u16 maxFramesCount = MaxFramesCountDefault); + static xr_vector BuildStackTrace(u16 maxFramesCount = 512); private: + static bool symEngineInitialized; + static Lock dbgHelpLock; static void FormatLastError(char *buffer, const size_t &bufferSize); static void SetupExceptionHandler(const bool &dedicated); static LONG WINAPI UnhandledFilter(EXCEPTION_POINTERS *exPtrs); static void WINAPI PreErrorHandler(INT_PTR); - static void SaveMiniDump(EXCEPTION_POINTERS *exPtrs); - - /// - /// Next members relates to stack tracing - /// - static bool symEngineInitialized; - static Lock dbgHelpLock; - + static void SaveMiniDump(EXCEPTION_POINTERS *exPtrs); static xr_vector BuildStackTrace(PCONTEXT threadCtx, u16 maxFramesCount); static bool GetNextStackFrameString(LPSTACKFRAME stackFrame, PCONTEXT threadCtx, xr_string &frameStr); static bool InitializeSymbolEngine();