1 #include "[Callstack.h]"2 #include <string>3 4 #if defined(WIN32) && defined(_MSC_VER) && !defined(WIN8RT)5 6 #include "../Math/InclWindows.h"7 #include <DbgHelp.h>8 9 #pragma comment(lib, "dbghelp.lib")10 11 static std::string GetSymbolName(void *address, HANDLE hProcess)12 {13 14 DWORD64 dwDisplacement = 0;15 DWORD64 dwAddress = (DWORD64)address;16 17 static char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];18 PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;19 20 pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);21 pSymbol->MaxNameLen = MAX_SYM_NAME;22 23 if (SymFromAddr(hProcess, dwAddress, &dwDisplacement, pSymbol))24 {25 26 IMAGEHLP_LINE64 line = {};27 line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);28 if (SymGetLineFromAddr64(hProcess, dwAddress, (PDWORD)&dwDisplacement, &line))29 {30 31 char str[128];32 sprintf(str, ":%u: ", line.LineNumber);33 return std::string(line.FileName) + str + pSymbol->Name;34 }35 else36 {37 38 39 40 return pSymbol->Name;41 }42 }43 else44 {45 46 47 48 return std::string();49 }50 }51 52 #ifdef _M_IX8653 #pragma warning(push)54 #pragma warning(disable : 4740) // warning C4740: flow in or out of inline asm code suppresses global optimization55 #endif56 57 std::string [NOINLINE] [GetCallstack](const char *indent, const char *ignoreFilter)58 {59 static bool symInitialized = false;60 61 HANDLE currentProcess = GetCurrentProcess();62 HANDLE currentThread = GetCurrentThread();63 64 if (!symInitialized)65 {66 SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);67 SymInitialize(currentProcess, NULL, TRUE);68 symInitialized = true;69 }70 71 CONTEXT context = {};72 STACKFRAME64 stack = {};73 74 #ifdef _M_IX8675 context.ContextFlags = CONTEXT_CONTROL;76 _asm {77 call x78 x: pop eax79 mov context.Eip, eax80 mov context.Ebp, ebp81 mov context.Esp, esp82 }83 #else84 RtlCaptureContext(&context);85 #endif86 87 stack.AddrPC.Mode = AddrModeFlat;88 stack.AddrStack.Mode = AddrModeFlat;89 stack.AddrFrame.Mode = AddrModeFlat;90 91 #ifdef _M_X6492 93 stack.AddrPC.Offset = context.Rip;94 stack.AddrStack.Offset = context.Rsp;95 stack.AddrFrame.Offset = context.Rbp;96 const DWORD machineType = IMAGE_FILE_MACHINE_AMD64;97 #else98 stack.AddrPC.Offset = context.Eip;99 stack.AddrStack.Offset = context.Esp;100 stack.AddrFrame.Offset = context.Ebp;101 const DWORD machineType = IMAGE_FILE_MACHINE_I386;102 #endif103 const PVOID contextRecord = &context;104 105 std::string callstack;106 for(int i = 0; i < 128; ++i)107 {108 BOOL result = StackWalk64(machineType, currentProcess, currentThread, &stack, contextRecord, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL);109 if (!result)110 break;111 112 std::string symbolName = GetSymbolName((void*)stack.AddrPC.Offset, currentProcess);113 if (symbolName.find(" GetCallstack") == symbolName.length() - strlen(" GetCallstack"))114 continue;115 if (!ignoreFilter || symbolName.find(ignoreFilter) == symbolName.npos)116 {117 if (!symbolName.empty())118 {119 callstack += indent;120 callstack += symbolName;121 callstack += '\n';122 }123 ignoreFilter = 0;124 }125 if (symbolName.find(" main") == symbolName.length() - strlen(" main"))126 break;127 if (stack.AddrReturn.Offset == 0)128 break;129 }130 return callstack;131 }132 133 #ifdef _M_IX86134 #pragma warning(pop)135 #endif136 137 #elif defined(__APPLE__) || defined(LINUX)138 139 #include <stdlib.h>140 #include <execinfo.h>141 #include <string.h>142 143 std::string [NOINLINE] [GetCallstack](const char *indent, const char *ignoreFilter)144 {145 const int N = 128;146 void *callstack[N];147 int n = backtrace(callstack, N);148 char **strs = backtrace_symbols(callstack, n);149 std::string stack;150 for(int i = 0; i < n; ++i)151 {152 if (strstr(strs[i], "_Z12GetCallstackPK") != 0)153 continue;154 if (!ignoreFilter || strstr(strs[i], ignoreFilter) != 0)155 {156 stack += indent;157 stack += strs[i];158 stack += '\n';159 }160 }161 free(strs);162 return stack;163 }164 165 #else166 167 std::string [GetCallstack](const char *indent, const char *ignoreFilter)168 {169 170 return std::string();171 }172 173 #endif Go back to previous page