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; } } }
CString FileSystem::GetLastErrorMessage() { BString<1024> msg; strerror_r(errno, msg, msg.Capacity()); return *msg; }