static void getStack(CONTEXT& context, char* out, int max_size) { BOOL result; HANDLE process; HANDLE thread; STACKFRAME64 stack; char symbol_mem[sizeof(IMAGEHLP_SYMBOL64) + 256]; IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)symbol_mem; DWORD64 displacement; char name[256]; copyString(out, max_size, "Crash callstack:\n"); memset(&stack, 0, sizeof(STACKFRAME64)); process = GetCurrentProcess(); thread = GetCurrentThread(); displacement = 0; DWORD machineType; #ifdef _WIN64 machineType = IMAGE_FILE_MACHINE_IA64; stack.AddrPC.Offset = context.Rip; stack.AddrPC.Mode = AddrModeFlat; stack.AddrStack.Offset = context.Rsp; stack.AddrStack.Mode = AddrModeFlat; stack.AddrFrame.Offset = context.Rbp; stack.AddrFrame.Mode = AddrModeFlat; #else machineType = IMAGE_FILE_MACHINE_I386; stack.AddrPC.Offset = context.Eip; stack.AddrPC.Mode = AddrModeFlat; stack.AddrStack.Offset = context.Esp; stack.AddrStack.Mode = AddrModeFlat; stack.AddrFrame.Offset = context.Ebp; stack.AddrFrame.Mode = AddrModeFlat; #endif do { result = StackWalk64(machineType, process, thread, &stack, &context, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL); symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); symbol->MaxNameLength = 255; SymGetSymFromAddr64(process, (ULONG64)stack.AddrPC.Offset, &displacement, symbol); UnDecorateSymbolName(symbol->Name, (PSTR)name, 256, UNDNAME_COMPLETE); catString(out, max_size, symbol->Name); catString(out, max_size, "\n"); } while (result); }
void PlatformStack::ProgramAddressToSymbolInfo(uint64 address, SymbolInfo& oSymbolInfo) { InitSysStack(); oSymbolInfo.Address = address; uint32 lastError = 0; HANDLE processHandle = GetCurrentProcess(); ansichar symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + SymbolInfo::MAX_NAME_LENGHT] = { 0 }; IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)symbolBuffer; symbol->SizeOfStruct = sizeof(symbolBuffer); symbol->MaxNameLength = SymbolInfo::MAX_NAME_LENGHT; if (SymGetSymFromAddr64(processHandle, address, nullptr, symbol)) { int32 offset = 0; while (symbol->Name[offset] < 32 || symbol->Name[offset] > 127) { offset++; } strncpy(oSymbolInfo.FunctionName, symbol->Name + offset, SymbolInfo::MAX_NAME_LENGHT); strncat(oSymbolInfo.FunctionName, "()", SymbolInfo::MAX_NAME_LENGHT); } else { lastError = GetLastError(); } IMAGEHLP_LINE64 imageHelpLine = { 0 }; imageHelpLine.SizeOfStruct = sizeof(imageHelpLine); if (SymGetLineFromAddr64(processHandle, address, (::DWORD *)&oSymbolInfo.SymbolDisplacement, &imageHelpLine)) { strncpy(oSymbolInfo.FileName, imageHelpLine.FileName, SymbolInfo::MAX_NAME_LENGHT); oSymbolInfo.LineNumber = imageHelpLine.LineNumber; } else { lastError = GetLastError(); } IMAGEHLP_MODULE64 imageHelpModule = { 0 }; imageHelpModule.SizeOfStruct = sizeof(imageHelpModule); if (SymGetModuleInfo64(processHandle, address, &imageHelpModule)) { strncpy(oSymbolInfo.ModuleName, imageHelpModule.ImageName, SymbolInfo::MAX_NAME_LENGHT); } else { lastError = GetLastError(); } }
void CallStack::getFuncInfo(LPVOID dwFunc, FuncInfo& info) { memset(szBuffer, 0, sizeof(szBuffer)); #ifdef WIN32 #ifdef X64 PIMAGEHLP_SYMBOL64 symbol = (PIMAGEHLP_SYMBOL64)szBuffer; symbol->SizeOfStruct = sizeof(szBuffer); symbol->MaxNameLength = sizeof(szBuffer) - sizeof(IMAGEHLP_SYMBOL64); DWORD64 dwDisplacement = 0; if (SymGetSymFromAddr64(hProcess, (DWORD)dwFunc, &dwDisplacement, symbol)) { strncpy(info.szFuncName, symbol->Name, min(sizeof(info.szFuncName) - 1, strlen(symbol->Name))); info.szFuncName[min(sizeof(info.szFuncName) - 1, strlen(symbol->Name))] = 0; } IMAGEHLP_LINE64 imageHelpLine; imageHelpLine.SizeOfStruct = sizeof(imageHelpLine); if (SymGetLineFromAddr64(hProcess, (DWORD)dwFunc, (PDWORD)&dwDisplacement, &imageHelpLine)) { strncpy(info.szFilePath, imageHelpLine.FileName, min(sizeof(info.szFilePath) - 1, strlen(imageHelpLine.FileName))); info.szFilePath[min(sizeof(info.szFilePath) - 1, strlen(imageHelpLine.FileName))] = 0; info.dwLineNumber = imageHelpLine.LineNumber; } #else PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL)szBuffer; symbol->SizeOfStruct = sizeof(szBuffer); symbol->MaxNameLength = sizeof(szBuffer) - sizeof(IMAGEHLP_SYMBOL); DWORD dwDisplacement = 0; if (SymGetSymFromAddr(hProcess, (DWORD)dwFunc, &dwDisplacement, symbol)) { strncpy(info.szFuncName, symbol->Name, min(sizeof(info.szFuncName) - 1, strlen(symbol->Name))); info.szFuncName[min(sizeof(info.szFuncName) - 1, strlen(symbol->Name))] = 0; } IMAGEHLP_LINE imageHelpLine; imageHelpLine.SizeOfStruct = sizeof(imageHelpLine); if (SymGetLineFromAddr(hProcess, (DWORD)dwFunc, &dwDisplacement, &imageHelpLine)) { strncpy(info.szFilePath, imageHelpLine.FileName, min(sizeof(info.szFilePath) - 1, strlen(imageHelpLine.FileName))); info.szFilePath[min(sizeof(info.szFilePath) - 1, strlen(imageHelpLine.FileName))] = 0; info.dwLineNumber = imageHelpLine.LineNumber; } #endif #endif }
// ------------------------------------------------------------------ bool win32_platform::get_backtrace_frame_info(void* frame, char* function, char* filename, int* line_number) { IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)malloc( sizeof(IMAGEHLP_SYMBOL64) + DEREFEREE_MAX_FUNCTION_LEN); symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); symbol->MaxNameLength = DEREFEREE_MAX_FUNCTION_LEN; memset((char*)symbol + sizeof(IMAGEHLP_SYMBOL64), 0, DEREFEREE_MAX_FUNCTION_LEN); DWORD64 displacement = 0; BOOL res = SymGetSymFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement, symbol); if(res) { strncpy(function, (char*)symbol->Name, DEREFEREE_MAX_FUNCTION_LEN - 1); IMAGEHLP_LINE64 line_info = { 0 }; line_info.SizeOfStruct = sizeof(line_info); DWORD displacement2 = 0; res = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64)frame, &displacement2, &line_info); if(res) { strncpy(filename, (char*)line_info.FileName, DEREFEREE_MAX_FILENAME_LEN - 1); *line_number = (int)line_info.LineNumber; } else { filename[0] = '\0'; *line_number = 0; } free(symbol); return true; } else { free(symbol); return false; } }
int KDumpModuleAnalyzer::GetModuleInfo(KDumpModuleInfo *pRetDumpModuleInfo) { int nResult = false; int nRetCode = false; #ifdef _DEBUG struct IMAGEHLP_SYMBOL64_EX : IMAGEHLP_SYMBOL64 { TCHAR _EX[MAX_PATH]; }; DWORD64 dwDisplacement; IMAGEHLP_SYMBOL64_EX Symbol; Symbol.MaxNameLength = sizeof(Symbol._EX) / sizeof(Symbol._EX[0]); nRetCode = SymGetSymFromAddr64(m_hProcess, m_Stackframe.AddrPC.Offset, &dwDisplacement, &Symbol); if (nRetCode) { #ifdef OPEN_LOG_AND_BREAK KLogPrintf("%s\t%d\t%x\n", Symbol.Name, 0, m_Stackframe.AddrPC.Offset); #endif printf("%s\t%d\t%x\n", Symbol.Name, 0, m_Stackframe.AddrPC.Offset); } #endif KG_PROCESS_ERROR(pRetDumpModuleInfo); memset(pRetDumpModuleInfo, 0, sizeof(KDumpModuleInfo)); pRetDumpModuleInfo->dwStackAddress = m_dwStackAddress; nRetCode = EnumerateLoadedModules64(m_hProcess, KDumpModuleAnalyzer::FindExceptionModule, (void *)pRetDumpModuleInfo); KG_PROCESS_ERROR(nRetCode);//EnumerateLoadedModules64 执行失败 KG_PROCESS_ERROR(pRetDumpModuleInfo->nFindDumpModuleFlag);//FindExceptionModule 没有查找到 #ifdef OPEN_LOG_AND_BREAK KLogPrintf( "Name:%s\tBase:%llp\tOffset:%llp\tStack:%llp", pRetDumpModuleInfo->szModuleName, pRetDumpModuleInfo->dwModuleBase, pRetDumpModuleInfo->dwStackAddress, m_dwStackAddress ); #endif nResult = true; Exit0: return nResult; }
char* LookupAddressSymbolName(DWORD64 dw64Address) { static bool bHasFailed = false; // for debugging purposes (so we only output the first time symbol lookup fails) if( dw64Address == 0 ) { return nullptr; } PIMAGEHLP_SYMBOL64 pSymbol; pSymbol = (PIMAGEHLP_SYMBOL64)SymbolBuffer; pSymbol->SizeOfStruct = sizeof(SymbolBuffer); pSymbol->MaxNameLength = MAX_SYM_NAME; DWORD64 SymbolDisplacement64 = 0; //NOTE: Symbols that contain "dynamic initializer for" are for static initializers and can be REALLY slow to load if( SymGetSymFromAddr64(hApplicationProcess, dw64Address, &SymbolDisplacement64, pSymbol) ) { char* p = pSymbol->Name; while( (*p < 32) || (*p > 127) ) // skip any strange characters at the beginning of the symbol name { p++; } return p; } else if( !bHasFailed ) // only output error message once (to prevent massive spam) { bHasFailed = true; DWORD error = GetLastError(); DebugLog("SymGetSymFromAddr64 failed: error = %d", error); } return nullptr; }
PRAGMA_ENABLE_OPTIMIZATION void FWindowsPlatformStackWalk::ProgramCounterToSymbolInfo( uint64 ProgramCounter, FProgramCounterSymbolInfo& out_SymbolInfo ) { // Initialize stack walking as it loads up symbol information which we require. InitStackWalking(); // Set the program counter. out_SymbolInfo.ProgramCounter = ProgramCounter; uint32 LastError = 0; HANDLE ProcessHandle = GetCurrentProcess(); // Initialize symbol. ANSICHAR SymbolBuffer[sizeof( IMAGEHLP_SYMBOL64 ) + FProgramCounterSymbolInfo::MAX_NAME_LENGHT] = {0}; IMAGEHLP_SYMBOL64* Symbol = (IMAGEHLP_SYMBOL64*)SymbolBuffer; Symbol->SizeOfStruct = sizeof(SymbolBuffer); Symbol->MaxNameLength = FProgramCounterSymbolInfo::MAX_NAME_LENGHT; // Get function name. if( SymGetSymFromAddr64( ProcessHandle, ProgramCounter, nullptr, Symbol ) ) { // Skip any funky chars in the beginning of a function name. int32 Offset = 0; while( Symbol->Name[Offset] < 32 || Symbol->Name[Offset] > 127 ) { Offset++; } // Write out function name. FCStringAnsi::Strncpy( out_SymbolInfo.FunctionName, Symbol->Name + Offset, FProgramCounterSymbolInfo::MAX_NAME_LENGHT ); FCStringAnsi::Strncat( out_SymbolInfo.FunctionName, "()", FProgramCounterSymbolInfo::MAX_NAME_LENGHT ); } else { // No symbol found for this address. LastError = GetLastError(); } // Get filename and line number. IMAGEHLP_LINE64 ImageHelpLine = {0}; ImageHelpLine.SizeOfStruct = sizeof( ImageHelpLine ); if( SymGetLineFromAddr64( ProcessHandle, ProgramCounter, (::DWORD *)&out_SymbolInfo.SymbolDisplacement, &ImageHelpLine ) ) { FCStringAnsi::Strncpy( out_SymbolInfo.Filename, ImageHelpLine.FileName, FProgramCounterSymbolInfo::MAX_NAME_LENGHT ); out_SymbolInfo.LineNumber = ImageHelpLine.LineNumber; } else { LastError = GetLastError(); } // Get module name. IMAGEHLP_MODULE64 ImageHelpModule = {0}; ImageHelpModule.SizeOfStruct = sizeof( ImageHelpModule ); if( SymGetModuleInfo64( ProcessHandle, ProgramCounter, &ImageHelpModule) ) { // Write out module information. FCStringAnsi::Strncpy( out_SymbolInfo.ModuleName, ImageHelpModule.ImageName, FProgramCounterSymbolInfo::MAX_NAME_LENGHT ); } else { LastError = GetLastError(); } }
void printStackTrace(MemoryAllocationRecord* rec) { const unsigned int bufferSize = 512; // Resolve the program counter to the corresponding function names. unsigned int pc; for (int i = 0; i < MAX_STACK_FRAMES; i++) { // Check to see if we are at the end of the stack trace. pc = rec->pc[i]; if (pc == 0) break; // Get the function name. unsigned char buffer[sizeof(IMAGEHLP_SYMBOL64) + bufferSize]; IMAGEHLP_SYMBOL64* symbol = (IMAGEHLP_SYMBOL64*)buffer; DWORD64 displacement; memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64) + bufferSize); symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); symbol->MaxNameLength = bufferSize; if (!SymGetSymFromAddr64(GetCurrentProcess(), pc, &displacement, symbol)) { gameplay::print("[memory] STACK TRACE: <unknown location>\n"); } else { symbol->Name[bufferSize - 1] = '\0'; // Check if we need to go further up the stack. if (strncmp(symbol->Name, "operator new", 12) == 0) { // In operator new or new[], keep going... } else { // Get the file and line number. if (pc != 0) { IMAGEHLP_LINE64 line; DWORD displacement; memset(&line, 0, sizeof(line)); line.SizeOfStruct = sizeof(line); if (!SymGetLineFromAddr64(GetCurrentProcess(), pc, &displacement, &line)) { gameplay::print("[memory] STACK TRACE: %s - <unknown file>:<unknown line number>\n", symbol->Name); } else { const char* file = strrchr(line.FileName, '\\'); if(!file) file = line.FileName; else file++; gameplay::print("[memory] STACK TRACE: %s - %s:%d\n", symbol->Name, file, line.LineNumber); } } } } } }
static std::list<stack_info> get_stack_list( void* bp, void* sp, void* ip, size_t max_depth, size_t offset, bool module, bool symbol, bool brief ) { QWORD trace[33]; CONTEXT context; ZeroMemory(&context, sizeof(context)); context.ContextFlags = CONTEXT_FULL; #ifdef _WIN64 context.Rbp = (DWORD64)bp; context.Rsp = (DWORD64)sp; context.Rip = (DWORD64)ip; #else context.Ebp = (DWORD)bp; context.Esp = (DWORD)sp; context.Eip = (DWORD)ip; #endif size_t depths = stack_walk(trace, max_depth, &context); std::list<stack_info> image_list; HANDLE hProcess = GetCurrentProcess(); for (size_t i = offset; i < depths; i++) { stack_info stack_result(brief); { DWORD symbolDisplacement = 0; IMAGEHLP_LINE64 imageHelpLine; imageHelpLine.SizeOfStruct = sizeof(imageHelpLine); if (SymGetLineFromAddr64(hProcess, trace[i], &symbolDisplacement, &imageHelpLine)) { stack_result.file_ = std::string(imageHelpLine.FileName, check_file_name(imageHelpLine.FileName)); std::memset(imageHelpLine.FileName, 0, stack_result.file_.size() + 1); stack_result.line_ = (int)imageHelpLine.LineNumber; } else { stack_result.line_ = -1; } } if (symbol) { static const int max_name_length = 1024; char symbolBf[sizeof(IMAGEHLP_SYMBOL64) + max_name_length] = { 0 }; PIMAGEHLP_SYMBOL64 symbol; DWORD64 symbolDisplacement64 = 0; symbol = (PIMAGEHLP_SYMBOL64)symbolBf; symbol->SizeOfStruct = sizeof(symbolBf); symbol->MaxNameLength = max_name_length; if (SymGetSymFromAddr64( hProcess, trace[i], &symbolDisplacement64, symbol) ) { stack_result.symbol_ = symbol->Name; } else { stack_result.symbol_ = "unknow..."; } } if (module) { IMAGEHLP_MODULE64 imageHelpModule; imageHelpModule.SizeOfStruct = sizeof(imageHelpModule); if (SymGetModuleInfo64(hProcess, trace[i], &imageHelpModule)) { stack_result.module_ = std::string(imageHelpModule.ImageName, check_file_name(imageHelpModule.ImageName)); std::memset(imageHelpModule.ImageName, 0, stack_result.module_.size() + 1); } } image_list.push_back(std::move(stack_result)); } return image_list; }
static LONG WINAPI handler(EXCEPTION_POINTERS* e) { const DWORD code = e->ExceptionRecord->ExceptionCode; SkDebugf("\nCaught exception %u", code); for (size_t i = 0; i < SK_ARRAY_COUNT(kExceptions); i++) { if (kExceptions[i].code == code) { SkDebugf(" %s", kExceptions[i].name); } } SkDebugf("\n"); // We need to run SymInitialize before doing any of the stack walking below. HANDLE hProcess = GetCurrentProcess(); SymInitialize(hProcess, 0, true); STACKFRAME64 frame; sk_bzero(&frame, sizeof(frame)); // Start frame off from the frame that triggered the exception. CONTEXT* c = e->ContextRecord; frame.AddrPC.Mode = AddrModeFlat; frame.AddrStack.Mode = AddrModeFlat; frame.AddrFrame.Mode = AddrModeFlat; #if defined(_X86_) frame.AddrPC.Offset = c->Eip; frame.AddrStack.Offset = c->Esp; frame.AddrFrame.Offset = c->Ebp; const DWORD machineType = IMAGE_FILE_MACHINE_I386; #elif defined(_AMD64_) frame.AddrPC.Offset = c->Rip; frame.AddrStack.Offset = c->Rsp; frame.AddrFrame.Offset = c->Rbp; const DWORD machineType = IMAGE_FILE_MACHINE_AMD64; #endif while (StackWalk64(machineType, GetCurrentProcess(), GetCurrentThread(), &frame, c, nullptr, SymFunctionTableAccess64, SymGetModuleBase64, nullptr)) { // Buffer to store symbol name in. static const int kMaxNameLength = 1024; uint8_t buffer[sizeof(IMAGEHLP_SYMBOL64) + kMaxNameLength]; sk_bzero(buffer, sizeof(buffer)); // We have to place IMAGEHLP_SYMBOL64 at the front, and fill in // how much space it can use. IMAGEHLP_SYMBOL64* symbol = reinterpret_cast<IMAGEHLP_SYMBOL64*>(&buffer); symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); symbol->MaxNameLength = kMaxNameLength - 1; // Translate the current PC into a symbol and byte offset from the symbol. DWORD64 offset; SymGetSymFromAddr64(hProcess, frame.AddrPC.Offset, &offset, symbol); SkDebugf("%s +%x\n", symbol->Name, offset); } // Exit NOW. Don't notify other threads, don't call anything registered with atexit(). _exit(1); // The compiler wants us to return something. This is what we'd do // if we didn't _exit(). return EXCEPTION_EXECUTE_HANDLER; }
std::vector<CallStackInfo> GetCallStack(const CONTEXT* pContext) { HANDLE hProcess = GetCurrentProcess(); SymInitialize(hProcess, NULL, TRUE); vector<CallStackInfo> arrCallStackInfo; CONTEXT c = *pContext; STACKFRAME64 sf; memset(&sf, 0, sizeof(STACKFRAME64)); DWORD dwImageType = IMAGE_FILE_MACHINE_I386; #ifdef _M_IX86 sf.AddrPC.Offset = c.Eip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Offset = c.Esp; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Offset = c.Ebp; sf.AddrFrame.Mode = AddrModeFlat; #elif _M_X64 dwImageType = IMAGE_FILE_MACHINE_AMD64; sf.AddrPC.Offset = c.Rip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrFrame.Offset = c.Rsp; sf.AddrFrame.Mode = AddrModeFlat; sf.AddrStack.Offset = c.Rsp; sf.AddrStack.Mode = AddrModeFlat; #elif _M_IA64 dwImageType = IMAGE_FILE_MACHINE_IA64; sf.AddrPC.Offset = c.StIIP; sf.AddrPC.Mode = AddrModeFlat; sf.AddrFrame.Offset = c.IntSp; sf.AddrFrame.Mode = AddrModeFlat; sf.AddrBStore.Offset = c.RsBSP; sf.AddrBStore.Mode = AddrModeFlat; sf.AddrStack.Offset = c.IntSp; sf.AddrStack.Mode = AddrModeFlat; #else #error "Platform not supported!" #endif HANDLE hThread = GetCurrentThread(); while (true) { if (!StackWalk64(dwImageType, hProcess, hThread, &sf, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) break; if (sf.AddrFrame.Offset == 0) break; CallStackInfo callstackinfo; strcpy_s(callstackinfo.MethodName, MAX_NAME_LENGTH, "N/A"); strcpy_s(callstackinfo.FileName, MAX_NAME_LENGTH, "N/A"); strcpy_s(callstackinfo.ModuleName, MAX_NAME_LENGTH, "N/A"); strcpy_s(callstackinfo.LineNumber, MAX_NAME_LENGTH, "N/A"); BYTE symbolBuffer[sizeof(IMAGEHLP_SYMBOL64) + MAX_NAME_LENGTH]; IMAGEHLP_SYMBOL64 *pSymbol = (IMAGEHLP_SYMBOL64*)symbolBuffer; memset(pSymbol, 0, sizeof(IMAGEHLP_SYMBOL64) + MAX_NAME_LENGTH); pSymbol->SizeOfStruct = sizeof(symbolBuffer); pSymbol->MaxNameLength = MAX_NAME_LENGTH; DWORD symDisplacement = 0; // 得到函数名 if (SymGetSymFromAddr64(hProcess, sf.AddrPC.Offset, NULL, pSymbol)) strcpy_s(callstackinfo.MethodName, MAX_NAME_LENGTH, pSymbol->Name); IMAGEHLP_LINE64 lineInfo; memset(&lineInfo, 0, sizeof(IMAGEHLP_LINE64)); lineInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE64); DWORD dwLineDisplacement; // 得到文件名和所在的代码行 if (SymGetLineFromAddr64(hProcess, sf.AddrPC.Offset, &dwLineDisplacement, &lineInfo)) { strcpy_s(callstackinfo.FileName, MAX_NAME_LENGTH, lineInfo.FileName); sprintf_s(callstackinfo.LineNumber, "%d", lineInfo.LineNumber); } IMAGEHLP_MODULE64 moduleInfo; memset(&moduleInfo, 0, sizeof(IMAGEHLP_MODULE64)); moduleInfo.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); // 得到模块名 if (SymGetModuleInfo64(hProcess, sf.AddrPC.Offset, &moduleInfo)) { strcpy_s(callstackinfo.ModuleName, MAX_NAME_LENGTH, moduleInfo.ModuleName); } arrCallStackInfo.push_back(callstackinfo); } SymCleanup(hProcess); return arrCallStackInfo; }
GCallStack::GCallStack(HANDLE hThread, CONTEXT& c) { if (!_bLockInit) // only init the single instance of the CRITICAL_SECTION 1 time for the many instances of GCallStack { InitializeCriticalSection(&_DbgHelpLock); _bLockInit = true; } DWORD imageType = IMAGE_FILE_MACHINE_I386; HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, GetCurrentProcessId()); int frameNum = 0; // counts walked frames int MAX_STACK_FRAMES = 7777; // in C# the maximum stack frames imposed by the language is 1000. Arbitrary limit to guarantee no condition of infinate walking in corrupted memory. DWORD offsetFromLine; // tells us line number in the source file #if defined(_LINUX64) || defined(_WIN64) || defined(_IOS) unsigned __int64 offsetFromSymbol; // tells us how far from the symbol we were #else DWORD offsetFromSymbol; // tells us how far from the symbol we were #endif DWORD symOptions; // symbol handler settings IMAGEHLP_SYMBOL *pSym = (IMAGEHLP_SYMBOL *) malloc( IMGSYMLEN + MAXNAMELEN ); GString strStackName(MAXNAMELEN + 512); // undecorated method/function name + Source file and line number IMAGEHLP_MODULE Module; IMAGEHLP_LINE Line; STACKFRAME64 s; // in/out stackframe memset( &s, '\0', sizeof s ); // note: converted code from [std::string symSearchPath] to [GString symSearchPath] so it will compile with the _UNICODE build flag - 8/18/2014 GString symSearchPath; #ifdef _UNICODE wchar_t *tt = 0, *p; tt = new wchar_t[TTBUFLEN]; #else char *tt = 0, *p; tt = new char[TTBUFLEN]; #endif // build symbol search path from: symSearchPath = ""; // current directory if (GetCurrentDirectory(TTBUFLEN, tt)) symSearchPath << tt << "; "; // dir with executable if ( GetModuleFileName( 0, tt, TTBUFLEN ) ) { #ifdef _UNICODE for (p = tt + wcslen(tt) - 1; p >= tt; --p) #else for (p = tt + strlen(tt) - 1; p >= tt; --p) // VC6 does not have a _tcsclen() and we still support VC6 #endif { // locate the rightmost path separator if ( *p == '\\' || *p == '/' || *p == ':' ) break; } // if we found one, p is pointing at it; if not, tt only contains an exe name (no path), and p points before its first byte if ( p != tt ) // path sep found? { if ( *p == ':' ) // we leave colons in place ++ p; *p = '\0'; // eliminate the exe name and last path sep symSearchPath << tt << "; "; } } // environment variable _NT_SYMBOL_PATH GString g("_NT_SYMBOL_PATH"); if (GetEnvironmentVariable(g, tt, TTBUFLEN)) symSearchPath << tt << "; "; // environment variable _NT_ALTERNATE_SYMBOL_PATH g = "_NT_ALTERNATE_SYMBOL_PATH"; if (GetEnvironmentVariable(g, tt, TTBUFLEN)) symSearchPath << tt << "; "; // environment variable SYSTEMROOT g = "SYSTEMROOT"; if (GetEnvironmentVariable(g, tt, TTBUFLEN)) symSearchPath << tt << "; "; if ( symSearchPath.size() > 0 ) // if we added anything, we have a trailing semicolon symSearchPath = symSearchPath.substr( 0, symSearchPath.size() - 1 ); // 8/20/2014 note: In older Windows API's SymInitialize()'s 2nd argument was not defined as "const char *", it was only "char *" // Although "const" was not defined, the API call is "const" in behavior. In newer versions of the Windows API this has been fixed. // In newer versions - SymInitialize's 2nd argument may resolve to either "const char *" OR "const wchar_t *", and in those builds the // GString has a default conversion to the correct string type, however in the older build configurations, GString does not (and should not) // know how to resolve to a "char *" by default, so in that case the preprocessor directive isolates the code needed to convert to "char *" #if defined(_MSC_VER) && _MSC_VER <= 1200 if (!SymInitialize(hProcess, symSearchPath.Buf(), false)) // symSearchPath == (char *) #else if (!SymInitialize(hProcess, symSearchPath, true)) // symSearchPath == (const char *) --OR-- (const wchar_t *) depending on the _UNICODE preprocessor definition #endif { goto tagCleanUp; } symOptions = SymGetOptions(); symOptions |= SYMOPT_LOAD_LINES; symOptions &= ~SYMOPT_UNDNAME; SymSetOptions( symOptions ); enumAndLoadModuleSymbols( hProcess, GetCurrentProcessId() ); // init STACKFRAME for first call, definitions found in ImageHlp.h #ifdef _M_IX86 imageType = IMAGE_FILE_MACHINE_I386; s.AddrPC.Offset = c.Eip; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = c.Ebp; s.AddrFrame.Mode = AddrModeFlat; s.AddrStack.Offset = c.Esp; s.AddrStack.Mode = AddrModeFlat; #elif _M_X64 imageType = IMAGE_FILE_MACHINE_AMD64; s.AddrPC.Offset = c.Rip; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = c.Rsp; s.AddrFrame.Mode = AddrModeFlat; s.AddrStack.Offset = c.Rsp; s.AddrStack.Mode = AddrModeFlat; #elif _M_IA64 imageType = IMAGE_FILE_MACHINE_IA64; s.AddrPC.Offset = c.StIIP; s.AddrPC.Mode = AddrModeFlat; s.AddrFrame.Offset = c.IntSp; s.AddrFrame.Mode = AddrModeFlat; s.AddrBStore.Offset = c.RsBSP; s.AddrBStore.Mode = AddrModeFlat; s.AddrStack.Offset = c.IntSp; s.AddrStack.Mode = AddrModeFlat; #endif memset( pSym, '\0', IMGSYMLEN + MAXNAMELEN ); pSym->SizeOfStruct = IMGSYMLEN; pSym->MaxNameLength = MAXNAMELEN; memset( &Line, '\0', sizeof Line ); Line.SizeOfStruct = sizeof Line; memset( &Module, '\0', sizeof Module ); Module.SizeOfStruct = sizeof Module; offsetFromSymbol = 0; // DbgHelp is single threaded, so acquire a lock. EnterCriticalSection(&_DbgHelpLock); while ( frameNum < MAX_STACK_FRAMES ) { // get next stack frame (StackWalk(), SymFunctionTableAccess(), SymGetModuleBase()) // if this returns ERROR_INVALID_ADDRESS (487) or ERROR_NOACCESS (998), you can // assume that either you are done, or that the stack is so hosed that the next deeper frame could not be found. #ifdef _WIN64 if (!StackWalk64(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL)) #else if (!StackWalk(imageType, hProcess, hThread, &s, &c, NULL, SymFunctionTableAccess, SymGetModuleBase, NULL)) #endif break; // Maybe it failed, maybe we have finished walking the stack if ( s.AddrPC.Offset != 0 ) { // Most likely a valid stack rame // show procedure info if ( ! SymGetSymFromAddr64( hProcess, s.AddrPC.Offset, &offsetFromSymbol, pSym ) ) { break; } else { // UnDecorateSymbolName() to get the Class::Method or function() name in tyhe callstack strStackName.Empty(); UnDecorateSymbolName(pSym->Name, strStackName._str, MAXNAMELEN, UNDNAME_COMPLETE); strStackName.SetLength(strlen(strStackName._str)); // SymGetLineFromAddr() to get the source.cpp and the line number IMAGEHLP_LINE64 Line; if (SymGetLineFromAddr64(hProcess, s.AddrPC.Offset, &offsetFromLine, &Line) != FALSE) { GString g(Line.FileName); // Line.FileName conains the "c:\Full\Path\TO\Source.cpp" // Builds string "Foo::Bar[Source.cpp]@777" strStackName << "[" << g.StartingAt(g.ReverseFind("\\") + 1) << "]@" << Line.LineNumber; } // add the GString to the GStringList, do not add frame 0 because it will always be GException::GSeception where we divided by 0 if (frameNum > 0) _stk += strStackName; } } else { // base reached SetLastError(0); break; } ++frameNum; } LeaveCriticalSection(&_DbgHelpLock); // de-init symbol handler etc. (SymCleanup()) SymCleanup( hProcess ); free( pSym ); tagCleanUp:; delete [] tt; CloseHandle(hProcess); }
void PrintBacktrace(PCONTEXT context) { HANDLE hProcess = GetCurrentProcess(); HANDLE hThread = GetCurrentThread(); char appDir[MAX_PATH + 1]; GetModuleFileName(nullptr, appDir, sizeof(appDir)); char* end = strrchr(appDir, PATH_SEPARATOR); if (end) *end = '\0'; SymSetOptions(SymGetOptions() | SYMOPT_LOAD_LINES | SYMOPT_FAIL_CRITICAL_ERRORS); if (!SymInitialize(hProcess, appDir, TRUE)) { warn("Could not obtain detailed exception information: SymInitialize failed"); return; } const int MAX_NAMELEN = 1024; IMAGEHLP_SYMBOL64* sym = (IMAGEHLP_SYMBOL64 *) malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_NAMELEN); memset(sym, 0, sizeof(IMAGEHLP_SYMBOL64) + MAX_NAMELEN); sym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); sym->MaxNameLength = MAX_NAMELEN; IMAGEHLP_LINE64 ilLine; memset(&ilLine, 0, sizeof(ilLine)); ilLine.SizeOfStruct = sizeof(ilLine); STACKFRAME64 sfStackFrame; memset(&sfStackFrame, 0, sizeof(sfStackFrame)); DWORD imageType; #ifdef _M_IX86 imageType = IMAGE_FILE_MACHINE_I386; sfStackFrame.AddrPC.Offset = context->Eip; sfStackFrame.AddrPC.Mode = AddrModeFlat; sfStackFrame.AddrFrame.Offset = context->Ebp; sfStackFrame.AddrFrame.Mode = AddrModeFlat; sfStackFrame.AddrStack.Offset = context->Esp; sfStackFrame.AddrStack.Mode = AddrModeFlat; #elif _M_X64 imageType = IMAGE_FILE_MACHINE_AMD64; sfStackFrame.AddrPC.Offset = context->Rip; sfStackFrame.AddrPC.Mode = AddrModeFlat; sfStackFrame.AddrFrame.Offset = context->Rsp; sfStackFrame.AddrFrame.Mode = AddrModeFlat; sfStackFrame.AddrStack.Offset = context->Rsp; sfStackFrame.AddrStack.Mode = AddrModeFlat; #else warn("Could not obtain detailed exception information: platform not supported"); return; #endif for (int frameNum = 0; ; frameNum++) { if (frameNum > 1000) { warn("Endless stack, abort tracing"); return; } if (!StackWalk64(imageType, hProcess, hThread, &sfStackFrame, context, nullptr, SymFunctionTableAccess64, SymGetModuleBase64, nullptr)) { warn("Could not obtain detailed exception information: StackWalk64 failed"); return; } DWORD64 dwAddr = sfStackFrame.AddrPC.Offset; BString<1024> symName; BString<1024> srcFileName; int lineNumber = 0; DWORD64 dwSymbolDisplacement; if (SymGetSymFromAddr64(hProcess, dwAddr, &dwSymbolDisplacement, sym)) { UnDecorateSymbolName(sym->Name, symName, symName.Capacity(), UNDNAME_COMPLETE); symName[sizeof(symName) - 1] = '\0'; } else { symName = "<symbol not available>"; } DWORD dwLineDisplacement; if (SymGetLineFromAddr64(hProcess, dwAddr, &dwLineDisplacement, &ilLine)) { lineNumber = ilLine.LineNumber; char* useFileName = ilLine.FileName; char* root = strstr(useFileName, "\\daemon\\"); if (root) { useFileName = root; } srcFileName = useFileName; } else { srcFileName = "<filename not available>"; } info("%s (%i) : %s", *srcFileName, lineNumber, *symName); if (sfStackFrame.AddrReturn.Offset == 0) { break; } } }
int diag_backtrace(diag_output_t *o, diag_backtrace_param_t *p, diag_context_t *c) { int cur = 0, count; STACKFRAME64 stackframe; CONTEXT context; HANDLE process = GetCurrentProcess(); HANDLE thread = GetCurrentThread(); DWORD bytes_written; if (c) { context = *c->context; } else { RtlCaptureContext(&context); } if (p->backtrace_count && p->backtrace_count < DIAG_BT_LIMIT) { count = p->backtrace_count; } else { count = DIAG_BT_LIMIT; } memset(&stackframe, 0, sizeof stackframe); stackframe.AddrPC.Mode = stackframe.AddrFrame.Mode = stackframe.AddrStack.Mode = AddrModeFlat; #ifdef DIAG_BITS_64 stackframe.AddrPC.Offset = context.Rip; stackframe.AddrFrame.Offset = context.Rbp; stackframe.AddrStack.Offset = context.Rsp; #else stackframe.AddrPC.Offset = context.Eip; stackframe.AddrFrame.Offset = context.Ebp; stackframe.AddrStack.Offset = context.Esp; #endif if (!p->symbols_initialized) { SymInitialize(process, NULL, TRUE); } while (StackWalk64( #ifdef DIAG_BITS_64 IMAGE_FILE_MACHINE_AMD64, #else IMAGE_FILE_MACHINE_I386, #endif process, thread, &stackframe, &context, NULL, /* ReadMemoryRoutine */ SymFunctionTableAccess64, /* FunctionTableAccessRoutine */ SymGetModuleBase64, /* GetModuleBaseRoutine */ NULL) /* TranslateAddress */ == TRUE) { char symbol_buffer[128] = {0}; IMAGEHLP_SYMBOL64 *symbol = (IMAGEHLP_SYMBOL64 *)&symbol_buffer; DWORD64 ignored; const char *function; const char *offset; char address_buf[20], offset_buf[20]; char buf[128]; char *outch = buf; char *lastoutch = buf + sizeof buf - 1; if (cur + 1 > count) { /* avoid loop on corrupted chain, respect caller's wishes */ break; } symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); symbol->MaxNameLength = sizeof(symbol_buffer) - sizeof(IMAGEHLP_SYMBOL64); ignored = 0; if (SymGetSymFromAddr64(process, stackframe.AddrPC.Offset, &ignored, symbol) != TRUE) { function = NULL; offset = NULL; } else { function = symbol->Name; add_int(offset_buf, offset_buf + sizeof offset_buf - 1, stackframe.AddrPC.Offset - symbol->Address, 16); offset = offset_buf; } add_int(address_buf, address_buf + sizeof address_buf - 1, stackframe.AddrPC.Offset, 16); if (function && !strcmp(function, "diag_backtrace")) { /* filter outselves out */ continue; } cur++; /* gonna keep this frame, so count it */ output_frame(outch, lastoutch, p->backtrace_fields, NULL, /* no module path */ NULL, /* no module */ function, offset, address_buf); if (o->output_mode == DIAG_CALL_FN) { o->output_fn(o->user_data, buf); } else { WriteFile(o->outfile, buf, strlen(buf), &bytes_written, NULL); WriteFile(o->outfile, "\r\n", 2, &bytes_written, NULL); } } return 0; }
const char* MemoryManager::GetCallerForAllocation(AllocHeader* pAllocation) { #ifdef USE_STACKTRACE const size_t cnBufferSize=512; char szFile[cnBufferSize]; char szFunc[cnBufferSize]; unsigned int nLine; static char szBuff[cnBufferSize*3]; strcpy(szFile,"??"); nLine=0; DWORD64 nPC; for(int i=0;i<AllocHeader::cnMaxStackFrames;++i) { nPC=pAllocation->nPC[i]; if(nPC==0) break; unsigned char byBuffer[sizeof(IMAGEHLP_SYMBOL64)+cnBufferSize]; IMAGEHLP_SYMBOL64* pSymbol=(IMAGEHLP_SYMBOL64*)byBuffer; DWORD64 dwDisplacement; memset(pSymbol,0,sizeof(IMAGEHLP_SYMBOL64)+cnBufferSize); pSymbol->SizeOfStruct=sizeof(IMAGEHLP_SYMBOL64); pSymbol->MaxNameLength=cnBufferSize; if(!SymGetSymFromAddr64(GetCurrentProcess(),nPC,&dwDisplacement,pSymbol)) strcpy(szFunc,"??"); else { pSymbol->Name[cnBufferSize-1]='\0'; if(strncmp(pSymbol->Name,"MemMgr::",8)==0) { // In MemMgr,keep going... } else if(strncmp(pSymbol->Name,"operator new",12)==0) { // In operator new or new[],keep going... } else if(strncmp(pSymbol->Name,"std::",5)==0) { // In STL code,keep going... } else { // Found the allocator (Or near to it) strcpy(szFunc,pSymbol->Name); break; } } } if(nPC!=0) { IMAGEHLP_LINE64 theLine; DWORD dwDisplacement; memset(&theLine,0,sizeof(theLine)); theLine.SizeOfStruct=sizeof(theLine); if(!SymGetLineFromAddr64(GetCurrentProcess(),nPC,&dwDisplacement,&theLine)) { strcpy(szFile,"??"); nLine=0; } else { const char* pszFile=strrchr(theLine.FileName,'\\'); if(!pszFile) pszFile=theLine.FileName; else ++pszFile; strncpy(szFile,pszFile,cnBufferSize); nLine=theLine.LineNumber; } } sprintf(szBuff,"%s:%d (%s)",szFile,nLine,szFunc); return szBuff; #else UNREFERENCED_PARAMETER(pAllocation); return "Stack trace unavailable"; #endif }
bool ll_get_stack_trace(std::vector<std::string>& lines) { const S32 MAX_STACK_DEPTH = 32; const S32 STRING_NAME_LENGTH = 200; const S32 FRAME_SKIP = 2; static BOOL symbolsLoaded = false; static BOOL firstCall = true; HANDLE hProc = GetCurrentProcess(); // load the symbols if they're not loaded if(!symbolsLoaded && firstCall) { symbolsLoaded = SymInitialize(hProc, NULL, true); firstCall = false; } // if loaded, get the call stack if(symbolsLoaded) { // create the frames to hold the addresses void* frames[MAX_STACK_DEPTH]; memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH); S32 depth = 0; // get the addresses depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL); IMAGEHLP_LINE64 line; memset(&line, 0, sizeof(IMAGEHLP_LINE64)); line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); // create something to hold address info PIMAGEHLP_SYMBOL64 pSym; pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); pSym->MaxNameLength = STRING_NAME_LENGTH; pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); // get address info for each address frame // and store for(S32 i=0; i < depth; i++) { std::stringstream stack_line; BOOL ret; DWORD64 addr = (DWORD64)frames[i]; ret = SymGetSymFromAddr64(hProc, addr, 0, pSym); if(ret) { stack_line << pSym->Name << " "; } DWORD dummy; ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line); if(ret) { std::string file_name = line.FileName; std::string::size_type index = file_name.rfind("\\"); stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber; } lines.push_back(stack_line.str()); } free(pSym); // TODO: figure out a way to cleanup symbol loading // Not hugely necessary, however. //SymCleanup(hProc); return true; } else { lines.push_back("Stack Trace Failed. PDB symbol info not loaded"); } return false; }
int StackTrace::GetSymbolInfo(Address address, char* symbol, int maxSymbolLen) { if (!InitSymbols()) return 0; // Start with address. int charsAdded = _snprintf_s(symbol, maxSymbolLen, _TRUNCATE, "%p ", address); symbol += charsAdded; maxSymbolLen -= charsAdded; if (maxSymbolLen < 0) return charsAdded; const DWORD64 address64 = (DWORD64)address; // Module name IMAGEHLP_MODULE64 moduleInfo; ZeroMemory(&moduleInfo, sizeof(moduleInfo)); moduleInfo.SizeOfStruct = sizeof(moduleInfo); const HANDLE hCurrentProcess = GetCurrentProcess(); if (SymGetModuleInfo64(hCurrentProcess, address64, &moduleInfo)) { char moduleName[_MAX_PATH + 1]; GetFileFromPath(moduleInfo.ImageName, moduleName, _MAX_PATH); const int moduleLen = (int)strlen(moduleName); strncpy_s(symbol, maxSymbolLen, moduleName, _TRUNCATE); symbol += moduleLen; charsAdded += moduleLen; maxSymbolLen -= moduleLen; } if (maxSymbolLen <= 0) return charsAdded; // Symbol name ULONG64 symbolBuffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)] = { 0 }; IMAGEHLP_SYMBOL64* symbolInfo = reinterpret_cast<IMAGEHLP_SYMBOL64*>(symbolBuffer); symbolInfo->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); symbolInfo->MaxNameLength = MAX_SYM_NAME; DWORD64 disp(0); if (SymGetSymFromAddr64(hCurrentProcess, address64, &disp, symbolInfo)) { const int symbolChars = _snprintf_s(symbol, maxSymbolLen, _TRUNCATE, " %s + 0x%X", symbolInfo->Name, disp); symbol += symbolChars; maxSymbolLen -= symbolChars; charsAdded += symbolChars; } if (maxSymbolLen <= 0) return charsAdded; // File + line DWORD displacementLine; IMAGEHLP_LINE64 lineInfo; ZeroMemory(&lineInfo, sizeof(lineInfo)); lineInfo.SizeOfStruct = sizeof(lineInfo); if (SymGetLineFromAddr64(hCurrentProcess, address64, &displacementLine, &lineInfo)) { char fileName[_MAX_PATH + 1]; GetFileFromPath(lineInfo.FileName, fileName, _MAX_PATH); int fileLineChars(0); if (displacementLine > 0) { fileLineChars = _snprintf_s(symbol, maxSymbolLen, _TRUNCATE, " %s(%d+%04d byte(s))", fileName, lineInfo.LineNumber, displacementLine); } else { fileLineChars = _snprintf_s(symbol, maxSymbolLen, _TRUNCATE, " %s(%d)", fileName, lineInfo.LineNumber); } symbol += fileLineChars; maxSymbolLen -= fileLineChars; charsAdded += fileLineChars; } return charsAdded; }
std::vector<CL_String> CL_System::get_stack_frames_text(void **frames, int num_frames) { #ifdef WIN32 static CL_Mutex mutex; CL_MutexSection mutex_lock(&mutex); BOOL result = SymInitialize(GetCurrentProcess(), NULL, TRUE); if (!result) return std::vector<CL_String>(); std::vector<CL_String> backtrace_text; for (unsigned short i = 0; i < num_frames; i++) { unsigned char buffer[sizeof(IMAGEHLP_SYMBOL64) + 128]; IMAGEHLP_SYMBOL64 *symbol64 = reinterpret_cast<IMAGEHLP_SYMBOL64*>(buffer); memset(symbol64, 0, sizeof(IMAGEHLP_SYMBOL64) + 128); symbol64->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); symbol64->MaxNameLength = 128; DWORD64 displacement = 0; BOOL result = SymGetSymFromAddr64(GetCurrentProcess(), (DWORD64) frames[i], &displacement, symbol64); if (result) { IMAGEHLP_LINE64 line64; DWORD displacement = 0; memset(&line64, 0, sizeof(IMAGEHLP_LINE64)); line64.SizeOfStruct = sizeof(IMAGEHLP_LINE64); result = SymGetLineFromAddr64(GetCurrentProcess(), (DWORD64) frames[i], &displacement, &line64); if (result) { backtrace_text.push_back( cl_format( "%1 (%2, line %3)", CL_StringHelp::local8_to_text(symbol64->Name), CL_StringHelp::local8_to_text(line64.FileName), (int) line64.LineNumber)); } else { backtrace_text.push_back(symbol64->Name); } } } SymCleanup(GetCurrentProcess()); return backtrace_text; #elif !defined(__APPLE__) char **strings; strings = backtrace_symbols(frames, num_frames); if (!strings) { return std::vector<CL_String>(); } std::vector<CL_String> backtrace_text; for (int cnt = 0; cnt < num_frames; cnt++) { // Decode the strings char *ptr = strings[cnt]; char *filename = ptr; const char *function = ""; // Find function name while(*ptr) { if (*ptr=='(') // Found function name { *(ptr++) = 0; function = ptr; break; } ptr++; } // Find offset if (function[0]) // Only if function was found { while(*ptr) { if (*ptr=='+') // Found function offset { *(ptr++) = 0; break; } if (*ptr==')') // Not found function offset, but found, end of function { *(ptr++) = 0; break; } ptr++; } } int status; char *new_function = abi::__cxa_demangle(function, 0, 0, &status); if (new_function) // Was correctly decoded { function = new_function; } backtrace_text.push_back( cl_format("%1 (%2)", function, filename)); if (new_function) { free(new_function); } } free (strings); return backtrace_text; #else return std::vector<CL_String>(); #endif }
/** * Find symbol by address (nearest). * * @returns VBox status. * @param pVM VM handle. * @param Address Address. * @param poffDisplacement Where to store the symbol displacement from Address. * @param pSymbol Where to store the symbol info. */ VMMR3DECL(int) DBGFR3SymbolByAddr(PVM pVM, RTGCUINTPTR Address, PRTGCINTPTR poffDisplacement, PDBGFSYMBOL pSymbol) { /* * Lazy init. */ if (!pVM->dbgf.s.fSymInited) { int rc = dbgfR3SymLazyInit(pVM); if (RT_FAILURE(rc)) return rc; } /* * Look it up. */ #ifdef HAVE_DBGHELP char achBuffer[sizeof(IMAGEHLP_SYMBOL64) + DBGF_SYMBOL_NAME_LENGTH * sizeof(TCHAR) + sizeof(ULONG64)]; PIMAGEHLP_SYMBOL64 pSym = (PIMAGEHLP_SYMBOL64)&achBuffer[0]; pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); pSym->MaxNameLength = DBGF_SYMBOL_NAME_LENGTH; if (SymGetSymFromAddr64(pVM, Address, (PDWORD64)poffDisplacement, pSym)) { pSymbol->Value = (RTGCUINTPTR)pSym->Address; pSymbol->cb = pSym->Size; pSymbol->fFlags = pSym->Flags; strcpy(pSymbol->szName, pSym->Name); return VINF_SUCCESS; } //return win32Error(pVM); #else PDBGFSYM pSym = dbgfR3SymbolGetAddr(pVM, Address); if (pSym) { pSymbol->Value = pSym->Core.Key; pSymbol->cb = pSym->Core.KeyLast - pSym->Core.Key + 1; pSymbol->fFlags = 0; pSymbol->szName[0] = '\0'; strncat(pSymbol->szName, pSym->szName, sizeof(pSymbol->szName) - 1); if (poffDisplacement) *poffDisplacement = Address - pSymbol->Value; return VINF_SUCCESS; } #endif /* * Try PDM. */ if (MMHyperIsInsideArea(pVM, Address)) { char szModName[64]; RTRCPTR RCPtrMod; char szNearSym1[260]; RTRCPTR RCPtrNearSym1; char szNearSym2[260]; RTRCPTR RCPtrNearSym2; int rc = PDMR3LdrQueryRCModFromPC(pVM, Address, &szModName[0], sizeof(szModName), &RCPtrMod, &szNearSym1[0], sizeof(szNearSym1), &RCPtrNearSym1, &szNearSym2[0], sizeof(szNearSym2), &RCPtrNearSym2); if (RT_SUCCESS(rc) && szNearSym1[0]) { pSymbol->Value = RCPtrNearSym1; pSymbol->cb = RCPtrNearSym2 > RCPtrNearSym1 ? RCPtrNearSym2 - RCPtrNearSym1 : 0; pSymbol->fFlags = 0; pSymbol->szName[0] = '\0'; strncat(pSymbol->szName, szNearSym1, sizeof(pSymbol->szName) - 1); if (poffDisplacement) *poffDisplacement = Address - pSymbol->Value; return VINF_SUCCESS; } } return VERR_SYMBOL_NOT_FOUND; }