//============================================================================== String SystemStats::getStackBacktrace() { String result; #if JUCE_ANDROID || JUCE_MINGW jassertfalse; // sorry, not implemented yet! #elif JUCE_WINDOWS HANDLE process = GetCurrentProcess(); SymInitialize (process, nullptr, TRUE); void* stack[128]; int frames = (int) CaptureStackBackTrace (0, numElementsInArray (stack), stack, nullptr); HeapBlock<SYMBOL_INFO> symbol; symbol.calloc (sizeof (SYMBOL_INFO) + 256, 1); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof (SYMBOL_INFO); for (int i = 0; i < frames; ++i) { DWORD64 displacement = 0; if (SymFromAddr (process, (DWORD64) stack[i], &displacement, symbol)) { result << i << ": "; IMAGEHLP_MODULE64 moduleInfo; zerostruct (moduleInfo); moduleInfo.SizeOfStruct = sizeof (moduleInfo); if (::SymGetModuleInfo64 (process, symbol->ModBase, &moduleInfo)) result << moduleInfo.ModuleName << ": "; result << symbol->Name << " + 0x" << String::toHexString ((int64) displacement) << newLine; } } #else void* stack[128]; int frames = backtrace (stack, numElementsInArray (stack)); char** frameStrings = backtrace_symbols (stack, frames); for (int i = 0; i < frames; ++i) result << frameStrings[i] << newLine; ::free (frameStrings); #endif return result; }
void print_backtrace(char* out, int len, int max_depth) { typedef USHORT (*RtlCaptureStackBackTrace_t)( __in ULONG FramesToSkip, __in ULONG FramesToCapture, __out PVOID *BackTrace, __out_opt PULONG BackTraceHash); static RtlCaptureStackBackTrace_t RtlCaptureStackBackTrace = 0; if (RtlCaptureStackBackTrace == 0) { // we don't actually have to free this library, everyone has it loaded HMODULE lib = LoadLibrary(TEXT("kernel32.dll")); RtlCaptureStackBackTrace = (RtlCaptureStackBackTrace_t)GetProcAddress(lib, "RtlCaptureStackBackTrace"); if (RtlCaptureStackBackTrace == 0) { out[0] = 0; return; } } int i; void* stack[50]; int size = CaptureStackBackTrace(0, 50, stack, 0); SYMBOL_INFO* symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR), 1); symbol->MaxNameLen = MAX_SYM_NAME; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); HANDLE p = GetCurrentProcess(); static bool sym_initialized = false; if (!sym_initialized) { sym_initialized = true; SymInitialize(p, NULL, true); } for (i = 0; i < size && len > 0; ++i) { int ret; if (SymFromAddr(p, uintptr_t(stack[i]), 0, symbol)) ret = libed2k::snprintf(out, len, "%d: %s\n", i, symbol->Name); else ret = libed2k::snprintf(out, len, "%d: <unknown>\n", i); out += ret; len -= ret; if (i == max_depth && max_depth > 0) break; } free(symbol); }
LIBXSMM_API #if defined(_WIN32) /*TODO: no inline*/ #elif defined(__GNUC__) /*LIBXSMM_ATTRIBUTE(noinline)*/ #endif unsigned int libxsmm_backtrace(void* buffer[], unsigned int size) { #if defined(_WIN32) || defined(__CYGWIN__) return CaptureStackBackTrace(0, size, buffer, NULL); #else return (unsigned int)backtrace(buffer, (int)size); #endif }
const std::string PXL_stack_trace(int num_traces) { #if defined(_DEBUG) uint32 i; DWORD* stacks = new DWORD[num_traces]; uint16 frames_captured; SYMBOL_INFO* symbol; HANDLE process; process = GetCurrentProcess(); SymInitialize(process, NULL, TRUE); frames_captured = CaptureStackBackTrace(0, num_traces, (PVOID*)stacks, NULL); //needs to be allocated on heap symbol = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); symbol->MaxNameLen = 192; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); IMAGEHLP_LINE line; DWORD disp; std::string output = ""; char* char_output = new char[255]; for (i = 0; i < frames_captured; i++) { SymFromAddr(process, stacks[i], NULL, symbol); SymGetLineFromAddr(process, stacks[i], &disp, &line); //convert file name to string and remove everything in the string before src or include std::string file_name = line.FileName; int id; if ((id = file_name.rfind("src")) != -1) { file_name = file_name.substr(id + 4, file_name.length()); } else if ((id = file_name.rfind("include")) != -1) { file_name = file_name.substr(id, file_name.length()); } if (id != -1) { sprintf(char_output, "%i: %s (%s, line %i)\n", frames_captured - i - 1, symbol->Name, file_name.c_str(), line.LineNumber); output += char_output; } } delete symbol; delete[] stacks; return output; #endif return ""; }
void printBacktrace(std::ostream * os) { if(os == 0) os = &std::cout; const int SIZE = 100; const int NAME_SIZE = 256; #if defined(_WIN32) HANDLE process = GetCurrentProcess(); SymSetOptions(SYMOPT_LOAD_LINES); SymInitialize(process, NULL, TRUE); void * stack[SIZE]; unsigned short frames = CaptureStackBackTrace(0, SIZE, stack, NULL); SYMBOL_INFO * symbol = (SYMBOL_INFO * )calloc(sizeof(SYMBOL_INFO) + NAME_SIZE * sizeof(char), 1); symbol->MaxNameLen = NAME_SIZE; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); for(unsigned short i = 0; i < frames; i++ ) { SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); IMAGEHLP_LINE64 line; line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); DWORD dwDisplacement; if(!strstr(symbol->Name, __FUNCTION__) && !strstr(symbol->Name,"pgr::debugCallback") && SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &dwDisplacement, &line)) { *os << symbol->Name << "():" << line.LineNumber << std::endl; } if(strcmp(symbol->Name, "main") == 0) break; } free(symbol); #elif defined(__linux__) int j; void *buffer[SIZE]; char **strings; int nptrs = backtrace(buffer, SIZE); strings = backtrace_symbols(buffer, nptrs); if(strings == NULL) { *os << "error in backtrace_symbols" << std::endl; return; } for (j = 0; j < nptrs; j++) *os << strings[j] << std::endl; free(strings); #else *os << "backtrace not supported on this platform" << std::endl; #endif }
std::string Exception::btCallStack(const int maxCalls) { std::ostringstream btStream; #ifdef FL_UNIX int bufferSize = maxCalls; void* buffer[bufferSize]; int backtraceSize = backtrace(buffer, bufferSize); char **btSymbols = backtrace_symbols(buffer, backtraceSize); if (btSymbols == NULL) { btStream << "[backtrace error] no symbols could be retrieved"; } else { if (backtraceSize == 0) btStream << "[backtrace is empty]"; for (int i = 0; i < backtraceSize; ++i) { btStream << btSymbols[i] << "\n"; } } free(btSymbols); /** * WINDOWS: */ #elif defined FL_WINDOWS (void) maxCalls; //Can't allocate an with non-constant size in Windows const int bufferSize = 30; void* buffer[bufferSize]; SymInitialize(GetCurrentProcess(), NULL, TRUE); int backtraceSize = CaptureStackBackTrace(0, bufferSize, buffer, NULL); SYMBOL_INFO* btSymbol = (SYMBOL_INFO *) calloc(sizeof ( SYMBOL_INFO) + 256 * sizeof ( char), 1); btSymbol->MaxNameLen = 255; btSymbol->SizeOfStruct = sizeof ( SYMBOL_INFO); if (not btSymbol) { btStream << "[backtrace error] no symbols could be retrieved"; } else { if (backtraceSize == 0) btStream << "[backtrace is empty]"; for (int i = 0; i < backtraceSize; ++i) { SymFromAddr(GetCurrentProcess(), (DWORD64) (buffer[ i ]), 0, btSymbol); btStream << (backtraceSize - i - 1) << ": " << btSymbol->Name << " at 0x" << btSymbol->Address << "\n"; } } free(btSymbol); #else btStream << "[backtrace error] backtrace not implemented for your operating system"; #endif return btStream.str(); }
static bool GetStackWalk(std::string &outWalk) { #ifdef USE_STACK_WALKER StackWalkerToString x(outWalk); x.ShowCallstack(); #else // // http://blog.aaronballman.com/2011/04/generating-a-stack-crawl/ // // Set up the symbol options so that we can gather information from the current // executable's PDB files, as well as the Microsoft symbol servers. We also want // to undecorate the symbol names we're returned. If you want, you can add other // symbol servers or paths via a semi-colon separated list in SymInitialized. ::SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_UNDNAME); if(!::SymInitialize(::GetCurrentProcess(), "http://msdl.microsoft.com/download/symbols", TRUE)) return false; // Capture up to 25 stack frames from the current call stack. We're going to // skip the first stack frame returned because that's the GetStackWalk function // itself, which we don't care about. PVOID addrs[ 400 ] = { 0 }; USHORT frames = CaptureStackBackTrace(1, 400, addrs, nullptr); for(USHORT i = 0; i < frames; i++) { // Allocate a buffer large enough to hold the symbol information on the stack and get // a pointer to the buffer. We also have to set the size of the symbol structure itself // and the number of bytes reserved for the name. ULONG64 buffer[(sizeof(SYMBOL_INFO) + 1024 + sizeof(ULONG64) - 1) / sizeof(ULONG64) ] = { 0 }; SYMBOL_INFO *info = (SYMBOL_INFO *)buffer; info->SizeOfStruct = sizeof(SYMBOL_INFO); info->MaxNameLen = 1024; // Attempt to get information about the symbol and add it to our output parameter. DWORD64 displacement = 0; if(::SymFromAddr(::GetCurrentProcess(), (DWORD64)addrs[ i ], &displacement, info)) { outWalk.append(info->Name, info->NameLen); outWalk.append("\n"); } } ::SymCleanup(::GetCurrentProcess()); #endif return true; }
void JKG_AssertFunction(char *file, int linenum, const char *expression) { // This is different from the Win32 version of assert in that it dumps a stack crawl. Highly useful. DWORD stack[MAX_JKG_ASSERT_STACK_CRAWL]; fileHandle_t f; //MessageBeep(MB_ICONERROR); // BEEP memset(stack, 0, sizeof(DWORD)*MAX_JKG_ASSERT_STACK_CRAWL); CaptureStackBackTrace(0, MAX_JKG_ASSERT_STACK_CRAWL, (PVOID *)stack, NULL); // K, next we create an assert log trap_FS_FOpenFile(JKG_Asset_GetAssertlogName(), &f, FS_WRITE); JKG_WriteToAssertLogEasy( "========================================\r\n" " Jedi Knight Galaxies Assertion Failure \r\n" "========================================\r\n\r\n", &f); JKG_WriteToAssertLogEasy(va("Version: %s (Windows)\r\n", GAMEVERSION), &f); JKG_WriteToAssertLogEasy(va("Side: Server-side\r\n"), &f); JKG_WriteToAssertLogEasy(va("Build Date/Time: %s %s\r\n", __DATE__, __TIME__), &f); JKG_WriteToAssertLogEasy("\r\n\r\n", &f); JKG_WriteToAssertLogEasy("Assertion Failure!\r\n", &f); JKG_WriteToAssertLogEasy(va("File: %s\r\n", file), &f); JKG_WriteToAssertLogEasy(va("Line: %i\r\n", linenum), &f); JKG_WriteToAssertLogEasy(va("Expression: %s\r\n\r\n", expression), &f); JKG_WriteToAssertLogEasy( "========================================\r\n" " Stack Crawl \r\n" "========================================\r\n", &f); JKG_WriteStackCrawl(&f, stack); JKG_WriteToAssertLogEasy( "========================================\r\n" " Module Information \r\n" "========================================\r\n", &f); JKG_Assert_ListModules(&f); trap_FS_FCloseFile(f); SymCleanup(GetCurrentProcess()); }
void logvisorAbort() { unsigned int i; void* stack[100]; unsigned short frames; SYMBOL_INFO* symbol; HANDLE process; process = GetCurrentProcess(); SymInitialize(process, NULL, TRUE); frames = CaptureStackBackTrace(0, 100, stack, NULL); symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); for (i = 0; i < frames; i++) { SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); fprintf(stderr, "%i: %s - 0x%0llX", frames - i - 1, symbol->Name, symbol->Address); DWORD dwDisplacement; IMAGEHLP_LINE64 line; SymSetOptions(SYMOPT_LOAD_LINES); line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); if (SymGetLineFromAddr64(process, (DWORD64)(stack[i]), &dwDisplacement, &line)) { // SymGetLineFromAddr64 returned success fprintf(stderr, " LINE %d\n", line.LineNumber); } else { fprintf(stderr, "\n"); } } fflush(stderr); free(symbol); // If you caught one of the above signals, it is likely you just // want to quit your program right now. system("PAUSE"); exit(1); }
QString CrashHandler::getStacktrace() { #ifdef _WIN32 unsigned int i; void * stack[ 100 ]; unsigned short frames; SYMBOL_INFO * symbol; HANDLE process; process = GetCurrentProcess(); SymInitialize( process, NULL, TRUE ); frames = CaptureStackBackTrace( 0, 100, stack, NULL ); symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 ); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof( SYMBOL_INFO ); QString bkTrace(""); for( i = 0; i < frames; i++ ) { char buf[500]; SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol ); sprintf(buf, "%i: %s - 0x%0llx\n", frames - i - 1, symbol->Name, symbol->Address ); bkTrace += buf; } return bkTrace; #elif __linux__ void *array[400]; size_t size; char **strings; size = backtrace(array, 10); strings = backtrace_symbols(array, size); QString bkTrace(""); for(int j = 0; j < size; j++) bkTrace += QString(strings[j])+"\n"; return bkTrace; #else return QString(""); #endif }
void capture() { const ULONG framesToSkip = 0; const ULONG framesToCapture = 64; void* backTrace[framesToCapture] {}; ULONG backTraceHash = 0; const USHORT nFrame = CaptureStackBackTrace( framesToSkip , framesToCapture , backTrace , &backTraceHash ); for(USHORT iFrame = 0; iFrame < nFrame; ++iFrame) { printf("[%3d] = %p\n", iFrame, backTrace[iFrame]); } printf("backTraceHash = %08x\n", backTraceHash); }
void BaseException::CreateStacktrace() { std::stringstream ss; #ifdef _MSC_VER void *stack[60]; USHORT frames = CaptureStackBackTrace(3, MAX_STACK_FRAMES, stack, NULL); HANDLE process = GetCurrentProcess(); if (SymInitialize(process, NULL, TRUE) == FALSE) { *_stacktrace = "Could not generate stack trace"; return; } size_t symbolLength = sizeof(SYMBOL_INFO) + (MAX_FUNCTION_NAME_LENGTH - 1) * sizeof(TCHAR); SYMBOL_INFO *symbol = (SYMBOL_INFO *)malloc(symbolLength); ZeroMemory(symbol, symbolLength); symbol->MaxNameLen = MAX_FUNCTION_NAME_LENGTH; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); DWORD displacement; IMAGEHLP_LINE64 line; ZeroMemory(&line, sizeof(IMAGEHLP_LINE64)); line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); for (int i = 0; i < frames; ++i) { DWORD64 address = (DWORD64)(stack[i]); SymFromAddr(process, address, NULL, symbol); if (SymGetLineFromAddr64(process, address, &displacement, &line)) { ss << "\tat " << symbol->Name; ss << " in " << line.FileName; ss << ":" << line.LineNumber; ss << "(address: 0x"; ss << std::setfill('0') << std::setw(sizeof(ULONG64) * 2) << std::hex; ss << symbol->Address << std::dec << ")" << std::endl; } else { ss << "\tat " << symbol->Name << "(address: 0x"; ss << std::setfill('0') << std::setw(sizeof(ULONG64) * 2) << std::hex; ss << symbol->Address << ")" << std::endl; } } SymCleanup(process); free(symbol); *_stacktrace = ss.str(); #else *_stacktrace = "Not implemented"; #endif }
static void print_backtrace(FILE *f) { static bool initialised = false; static HANDLE process; unsigned int frames; void *ip[MAX_STACK_FRAMES]; SYMBOL_INFO *sym; if (!initialised) { process = GetCurrentProcess(); SymInitialize(process, NULL, true); initialised = true; } if (!process) { fprintf(f, "Failed to get process for backtrace\n"); return; } sym = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + MAX_SYMBOL_LENGTH * (sizeof(char)), 1); if (!sym) { fprintf(f, "Failed to allocate symbol info for backtrace\n"); return; } sym->MaxNameLen = MAX_SYMBOL_LENGTH; sym->SizeOfStruct = sizeof(SYMBOL_INFO); /* Skip 2 frames (print_backtrace and the LogError function itself) */ frames = CaptureStackBackTrace(2, MAX_STACK_FRAMES, ip, NULL); for (unsigned int frame = 0; frame < frames; frame++) { SymFromAddr(process, (DWORD64)(ip[frame]), 0, sym); fprintf(f, " 0x%p %s+0x%Ix\n", ip[frame], sym->Name, (uintptr_t)ip[frame] - (uintptr_t)sym->Address); } free(sym); }
void crash_handler::create_log_file_for_hockey_app(EXCEPTION_POINTERS* /* pExcPtrs */) { const int max_stack_trace_depth = 48; void *stack[max_stack_trace_depth]; USHORT count = CaptureStackBackTrace(0, max_stack_trace_depth, stack, NULL); std::stringstream stack_trace_stream; for (USHORT c = 0; c < count; c++) { stack_trace_stream << stack[c] << ";"; } std::string stack_trace = stack_trace_stream.str(); std::wstring log_name = get_report_log_path(); time_t now = time(0); std::stringstream log_stream; // TODO (*) : use real info about app log_stream << "Package: " << product_bundle << std::endl; log_stream << "Version: " << VERSION_INFO_STR << std::endl; log_stream << "OS: " << get_os_version() << std::endl; log_stream << "Manufacturer: MS" << std::endl; log_stream << "Model: " << tools::version_info().get_version() << std::endl; char str[26]; ctime_s(str, sizeof str, &now); log_stream << "Date: " << str << std::endl; log_stream << stack_trace << std::endl; auto log_text = log_stream.str(); DWORD dwWritten; HANDLE handleFile (CreateFile(log_name.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0)); // https://msdn.microsoft.com/ru-ru/library/windows/desktop/5fc6ft2t(v=vs.80).aspx if(handleFile == INVALID_HANDLE_VALUE) { return; } CHandle hFile(handleFile); WriteFile(hFile, log_text.c_str(), log_text.size(), &dwWritten, 0); }
int backtrace(void **array, int framesToCapture) { int frames = 0; #ifdef _M_X64 frames = CaptureStackBackTrace(framesToSkip, framesToCapture, backTrace, nullptr); #else __try { void **frame = 0; __asm { mov frame, ebp } while (frame && frames < framesToCapture) { array[frames] = frame[1]; frames++; frame = (void **) frame[0]; } } __except (1 /*EXCEPTION_EXECUTE_HANDLER*/) { } #endif return frames; }
//------------------------------------------------------------------------ Callstack* AllocateCallstack(uint skipFrames) { void* stack[MAX_DEPTH]; //Getting from the calling function (0 is this function) to the number you want to capture uint32_t frames = CaptureStackBackTrace(1 + skipFrames, MAX_DEPTH, stack, NULL); ++gCallstackCount; size_t size = sizeof(Callstack) + sizeof(void*) * frames; void* bufferDataBegin = malloc(size); Callstack* callstack = new(bufferDataBegin) Callstack(); byte* frameDataFront = (byte*)bufferDataBegin + sizeof(Callstack); callstack->frames = (void**)frameDataFront; callstack->frameCount = frames; memcpy(callstack->frames, stack, sizeof(void*) * frames); return callstack; }
void StackDump(int level) { unsigned int i; void * stack[ 100 ]; unsigned short frames; SYMBOL_INFO * symbol; HANDLE process; level = std::min(100, level); if (level <= 0) return; process = GetCurrentProcess(); SymSetOptions(SYMOPT_LOAD_LINES); SymInitialize( process, NULL, TRUE ); frames = CaptureStackBackTrace( 0, level, stack, NULL ); symbol = ( SYMBOL_INFO * )calloc( sizeof( SYMBOL_INFO ) + 256 * sizeof( char ), 1 ); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof( SYMBOL_INFO ); std::cerr << "C++ stack dump:\n"; for( i = 0; i < frames; i++ ) { SymFromAddr( process, ( DWORD64 )( stack[ i ] ), 0, symbol ); DWORD dwDisplacement; IMAGEHLP_LINE64 line; line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); if (!strstr(symbol->Name,"debug::") && SymGetLineFromAddr64(process, ( DWORD64 )( stack[ i ] ), &dwDisplacement, &line)) { std::cerr << "function: " << symbol->Name << " - line: " << line.LineNumber << "\n"; } if (0 == strcmp(symbol->Name,"main")) break; } free( symbol ); }
// Requires DbgHelp.dll/dbghelp.lib static void dumpExceptions() { unsigned int i; void *stack[ 100 ]; unsigned short frames; SYMBOL_INFO *symbol; HANDLE process; process = GetCurrentProcess(); SymInitialize(process, NULL, TRUE); frames = CaptureStackBackTrace(0, 100, stack, NULL); symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1 ); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); for( i = 0; i < frames; i++ ) { SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); printf("%i: %s - 0x%0X\n", frames-i-1, symbol->Name, symbol->Address); } free(symbol); #endif }
// PD_TRACE_DECLARE_FUNCTION ( SDB_OSSWS, "ossWalkStack" ) UINT32 ossWalkStack( UINT32 framesToSkip, UINT32 framesRequested, void ** ppInstruction ) { PD_TRACE_ENTRY ( SDB_OSSWS ); UINT32 numFrames, framesOnStk ; framesOnStk = 0 ; if ( NULL != ppInstruction ) { numFrames = framesRequested ; if ( OSS_MAX_BACKTRACE_FRAMES_SUPPORTED <= ( framesToSkip + numFrames ) ) { numFrames = OSS_MAX_BACKTRACE_FRAMES_SUPPORTED - framesToSkip -1 ; } framesOnStk = CaptureStackBackTrace( framesToSkip, numFrames, ppInstruction, NULL ) ; } PD_TRACE_EXIT ( SDB_OSSWS ); return framesOnStk ; }
/*memory ownership to the caller*/ static void store_backtrace(char *s_backtrace) { void *stack[STACK_PRINT_SIZE]; size_t i, frames, bt_idx = 0; SYMBOL_INFO *symbol; HANDLE process; process = GetCurrentProcess(); SymInitialize(process, NULL, TRUE); symbol = (SYMBOL_INFO*)_alloca(sizeof(SYMBOL_INFO) + SYMBOL_MAX_SIZE); symbol->MaxNameLen = SYMBOL_MAX_SIZE-1; symbol->SizeOfStruct = sizeof(SYMBOL_INFO); frames = CaptureStackBackTrace(STACK_FIRST_IDX, STACK_PRINT_SIZE, stack, NULL); for (i=0; i<frames; i++) { int len; int bt_len; char *symbol_name = "unresolved"; SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); if (symbol->Name) symbol_name = (char*)symbol->Name; bt_len = (int) strlen(symbol_name) + 10; if (bt_idx + bt_len > STACK_PRINT_SIZE*SYMBOL_MAX_SIZE) { gf_memory_log(GF_MEMORY_WARNING, "[MemoryInfo] Not enough space to hold backtrace - truncating\n"); break; } len = _snprintf(s_backtrace+bt_idx, SYMBOL_MAX_SIZE-1, "\t%02u 0x%I64X %s", (unsigned int) (frames-i-1), symbol->Address, symbol_name); if (len<0) len = SYMBOL_MAX_SIZE-1; s_backtrace[bt_idx+len]='\n'; bt_idx += (len+1); } assert(bt_idx < STACK_PRINT_SIZE*SYMBOL_MAX_SIZE); s_backtrace[bt_idx-1] = '\0'; }
void print_stack_trace(out_stream_t *out, int signum) { handle_t process = GetCurrentProcess(); if (!SymRefreshModuleList(process)) { out_stream_printf(out, "Error refreshing module list: %i", GetLastError()); return; } out_stream_printf(out, "# Received condition %i\n", signum); // Capture the stack trace. static const size_t kMaxStackSize = 32; void *backtrace[kMaxStackSize]; size_t frame_count = CaptureStackBackTrace(0, kMaxStackSize, backtrace, NULL); // Scan through the trace one frame at a time, resolving symbols as we go. static const size_t kMaxNameLength = 128; static const size_t kSymbolInfoSize = sizeof(SYMBOL_INFO) + (kMaxNameLength * sizeof(char_t)); // A SYMBOL_INFO is variable size so we stack allocate a blob of memory and // cast it rather than stack allocate the info directly. uint8_t symbol_info_bytes[kSymbolInfoSize]; ZeroMemory(symbol_info_bytes, kSymbolInfoSize); SYMBOL_INFO *info = reinterpret_cast<SYMBOL_INFO*>(symbol_info_bytes); // This isn't strictly true, it's symbol_info_bytes, but SymFromAddr requires // it to have this value. info->SizeOfStruct = sizeof(SYMBOL_INFO); info->MaxNameLen = kMaxNameLength; for (size_t i = 0; i < frame_count; i++) { void *addr = backtrace[i]; DWORD64 addr64 = reinterpret_cast<DWORD64>(addr); if (SymFromAddr(process, addr64, 0, info)) { out_stream_printf(out, "# - 0x%p: %s\n", addr, info->Name); } else { out_stream_printf(out, "# - 0x%p\n", addr); } } }
LPVOID getCtrlRoutine() { LPVOID ctrlRoutine; // CtrlRoutine --> MyHandle --> getCtrlRoutine // set the CaptureStackBackTrace's first param to 2 to ingore the MyHandler and getCtrlRoutine calls. // should disable complier optimization on Release version. USHORT count = CaptureStackBackTrace((ULONG) 2, (ULONG) 1, &ctrlRoutine, NULL); if (count != 1) { _tprintf(__T("CaptureStackBackTrace error\n")); goto error; } HANDLE hProcess = GetCurrentProcess(); if (!SymInitialize(hProcess, NULL, TRUE)) { RETVAL rv; _HandleLastError(rv, __T("SymInitialize")); } ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME*sizeof(TCHAR) + sizeof(ULONG64)-1)/sizeof(ULONG64)]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO) buffer; pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; LPVOID funcCtrlRoutine = NULL; DWORD64 dwDisplacement = 0; if(!SymFromAddr(hProcess, (DWORD64) ctrlRoutine, &dwDisplacement, pSymbol)) { RETVAL rv; _HandleLastError(rv, __T("SymFromAddr")); } funcCtrlRoutine = reinterpret_cast<LPVOID>(pSymbol->Address); SymCleanup(hProcess); return funcCtrlRoutine; error: return NULL; }
size_t backtrace(void **frames, size_t n_frames) { // Skip the first three frames; they're always going to show // w_log, log_stack_trace and backtrace return CaptureStackBackTrace(3, (DWORD)n_frames, frames, NULL); }
void printTrace() { SymInitialize(GetCurrentProcess(), NULL, TRUE); UINT32 maxframes = 62; UINT_PTR myFrames[62]; ZeroMemory(myFrames, sizeof(UINT_PTR) * maxframes); ULONG BackTraceHash; maxframes = CaptureStackBackTrace(0, maxframes, reinterpret_cast<PVOID*>(myFrames), &BackTraceHash); const UINT_PTR* pFrame = myFrames; const size_t frameSize = maxframes; UINT32 startIndex = 0; int unresolvedFunctionsCount = 0; IMAGEHLP_LINE sourceInfo = { 0 }; sourceInfo.SizeOfStruct = sizeof(IMAGEHLP_LINE); // Use static here to increase performance, and avoid heap allocs. // It's thread safe because of g_heapMapLock lock. static char stack_line[1024] = ""; bool isPrevFrameInternal = false; DWORD NumChars = 0; const size_t max_line_length = 512; const int resolvedCapacity = 62 * max_line_length; const size_t allocedBytes = resolvedCapacity * sizeof(char); char resolved[resolvedCapacity]; if (resolved) { ZeroMemory(resolved, allocedBytes); } HANDLE hProcess = GetCurrentProcess(); int resolvedLength = 0; // Iterate through each frame in the call stack. for (UINT32 frame = 0; frame < frameSize; frame++) { if (pFrame[frame] == 0) break; // Try to get the source file and line number associated with // this program counter address. SIZE_T programCounter = pFrame[frame]; DWORD64 displacement64; BYTE symbolBuffer[sizeof(SYMBOL_INFO) + 256 * sizeof(char)]; LPCSTR functionName = getFunctionName(programCounter, displacement64, (SYMBOL_INFO*)&symbolBuffer); // It turns out that calls to SymGetLineFromAddrW64 may free the very memory we are scrutinizing here // in this method. If this is the case, m_Resolved will be null after SymGetLineFromAddrW64 returns. // When that happens there is nothing we can do except crash. DWORD displacement = 0; BOOL foundline = SymGetLineFromAddr(hProcess, programCounter, &displacement, &sourceInfo); bool isFrameInternal = false; // show one allocation function for context if (NumChars > 0 && !isFrameInternal && isPrevFrameInternal) { resolvedLength += NumChars; if (resolved) { strncat_s(resolved, resolvedCapacity, stack_line, NumChars); } } isPrevFrameInternal = isFrameInternal; if (!foundline) displacement = (DWORD)displacement64; NumChars = resolveFunction(programCounter, foundline ? &sourceInfo : NULL, displacement, functionName, stack_line, _countof(stack_line)); if (NumChars > 0 && !isFrameInternal) { resolvedLength += NumChars; if (resolved) { strncat_s(resolved, resolvedCapacity, stack_line, NumChars); } } } // end for loop printLog(resolved); SymCleanup(GetCurrentProcess()); return; }
//============================================================================== std::vector <std::string> getStackBacktrace() { std::vector <std::string> result; #if BEAST_ANDROID || BEAST_MINGW || BEAST_BSD assert(false); // sorry, not implemented yet! #elif BEAST_WINDOWS HANDLE process = GetCurrentProcess(); SymInitialize (process, nullptr, TRUE); void* stack[128]; int frames = (int) CaptureStackBackTrace (0, std::distance(std::begin(stack), std::end(stack)), stack, nullptr); // Allow symbols that are up to 1024 characters long. std::size_t constexpr nameLength = 1024; alignas(SYMBOL_INFO) unsigned char symbuf[ sizeof(SYMBOL_INFO) + nameLength * sizeof(SYMBOL_INFO::Name)]; auto symbol = reinterpret_cast<SYMBOL_INFO*>(symbuf); for (int i = 0; i < frames; ++i) { DWORD64 displacement = 0; std::memset (symbol, 0, sizeof(symbuf)); symbol->SizeOfStruct = sizeof(SYMBOL_INFO); symbol->MaxNameLen = nameLength; if (SymFromAddr (process, (DWORD64)stack[i], &displacement, symbol)) { std::string frame; frame.append (std::to_string (i) + ": "); IMAGEHLP_MODULE64 moduleInfo { sizeof(moduleInfo) }; if (::SymGetModuleInfo64 (process, symbol->ModBase, &moduleInfo)) { frame.append (moduleInfo.ModuleName); frame.append (": "); } frame.append (symbol->Name); if (displacement) { frame.append ("+"); frame.append (std::to_string (displacement)); } result.push_back (frame); } } #else void* stack[128]; int frames = backtrace (stack, std::distance(std::begin(stack), std::end(stack))); std::unique_ptr<char*[], decltype(std::free)*> frame { backtrace_symbols (stack, frames), std::free }; for (int i = 0; i < frames; ++i) result.push_back (frame[i]); #endif return result; }
void StackWalker::walk( xsize skip, Visitor *visit) { (void)skip; (void)visit; #if X_ENABLE_STACK_WALKING struct Utils { static void doVisit(Visitor *visit, xsize i, void *pcOffset) { visit->visit(i, pcOffset); } }; enum { BlockCaptureSize = 16, MaxSymbols = 128, }; #if defined(X_WIN) xsize position = skip + 1; const xsize start = position; void *frames[BlockCaptureSize]; xuint16 captured = 0; do { captured = CaptureStackBackTrace((DWORD)position, BlockCaptureSize, frames, 0); for(xsize i = 0; i < captured; ++i) { Utils::doVisit(visit, position + i - start, frames[i]); } position += captured; } while(captured == BlockCaptureSize); #elif defined(X_OSX) void *frames[MaxSymbols]; int captured = backtrace(frames, MaxSymbols); if (captured <= 0 || (xsize)captured > X_ARRAY_COUNT(frames)) { return; } for(xsize i = 0; i < (xsize)captured; ++i) { Utils::doVisit(visit, i, frames[skip+i]); } #else (void)skip; (void)visit; #endif #endif }
void mrpt::system::getCallStackBackTrace(TCallStackBackTrace& out_bt) { out_bt.backtrace_levels.clear(); const unsigned int framesToSkip = 1; // skip *this* function from the backtrace const unsigned int framesToCapture = 64; #ifdef _WIN32 void* backTrace[framesToCapture]{}; SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); const HANDLE hProcess = GetCurrentProcess(); if (!SymInitialize( hProcess, nullptr /* UserSearchPath */, TRUE /*fInvadeProcess*/)) { std::cerr << "[mrpt::system::getCallStackBackTrace] Error in SymInitialize()!" << std::endl; return; } char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; const USHORT nFrames = CaptureStackBackTrace( framesToSkip, framesToCapture, backTrace, nullptr); for (unsigned int i = 0; i < nFrames; i++) { TCallStackEntry cse; cse.address = backTrace[i]; if (!SymFromAddr(hProcess, (DWORD64)cse.address, nullptr, pSymbol)) { cse.symbolName = "???"; cse.symbolNameOriginal = "???"; out_bt.backtrace_levels.emplace_back(cse); continue; } SYMBOL_INFO& si = *pSymbol; cse.symbolNameOriginal = si.Name; char undecorated_name[1024]; if (!UnDecorateSymbolName( si.Name, undecorated_name, sizeof(undecorated_name), UNDNAME_COMPLETE)) { cse.symbolName = cse.symbolNameOriginal; } else { cse.symbolName = std::string(undecorated_name); } out_bt.backtrace_levels.emplace_back(cse); } #else // Based on: https://gist.github.com/fmela/591333 void* callstack[framesToCapture]; const int nMaxFrames = sizeof(callstack) / sizeof(callstack[0]); int nFrames = ::backtrace(callstack, nMaxFrames); char** symbols = ::backtrace_symbols(callstack, nFrames); for (int i = (int)framesToSkip; i < nFrames; i++) { TCallStackEntry cse; cse.address = callstack[i]; Dl_info info; if (dladdr(callstack[i], &info) && info.dli_sname) { char* demangled = nullptr; int status = -1; if (info.dli_sname[0] == '_') { demangled = abi::__cxa_demangle( info.dli_sname, nullptr, nullptr, &status); } cse.symbolNameOriginal = info.dli_sname == nullptr ? symbols[i] : info.dli_sname; cse.symbolName = status == 0 ? std::string(demangled) : cse.symbolNameOriginal; free(demangled); } out_bt.backtrace_levels.emplace_back(cse); } free(symbols); #endif }
// PD_TRACE_DECLARE_FUNCTION ( SDB_OSSWKSEX, "ossWalkStackEx" ) UINT32 ossWalkStackEx( LPEXCEPTION_POINTERS lpEP, UINT32 framesToSkip, UINT32 framesRequested , void ** ppInstruction ) { PD_TRACE_ENTRY ( SDB_OSSWKSEX ); HANDLE hProcess = GetCurrentProcess() ; HANDLE hThread = GetCurrentThread() ; STACKFRAME64 stackFrame = { 0 } ; CONTEXT cContext = { 0 } ; PCONTEXT pContext = &cContext ; BOOLEAN bSuccess = true ; UINT32 numFrames, framesOnStk ; framesOnStk = 0 ; if ( NULL != ppInstruction ) { numFrames = framesRequested ; if ( OSS_MAX_BACKTRACE_FRAMES_SUPPORTED <= ( framesToSkip + numFrames ) ) { numFrames = OSS_MAX_BACKTRACE_FRAMES_SUPPORTED - framesToSkip -1 ; } if ( NULL == lpEP ) { framesOnStk = CaptureStackBackTrace( framesToSkip, numFrames, ppInstruction, NULL ) ; } else { #ifndef _WIN64 stackFrame.AddrPC.Offset = lpEP->ContextRecord->Eip ; stackFrame.AddrPC.Mode = AddrModeFlat ; stackFrame.AddrStack.Offset = lpEP->ContextRecord->Esp ; stackFrame.AddrStack.Mode = AddrModeFlat ; stackFrame.AddrFrame.Offset = lpEP->ContextRecord->Ebp ; stackFrame.AddrFrame.Mode = AddrModeFlat ; ossMemcpy( pContext, lpEP->ContextRecord, sizeof( CONTEXT ) ) ; #else RtlCaptureContext( pContext ) ; #endif bSuccess = true ; WaitForSingleObject( ossGetSysMutexHandle( _StackWalk64 ), INFINITE ) ; while ( bSuccess && framesOnStk < numFrames ) { bSuccess = StackWalk64( OSS_THIS_IMAGE_MACHINE_TYPE, hProcess, hThread, &stackFrame, pContext, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL ) ; if ( bSuccess ) { ppInstruction[ framesOnStk ] = (void*)stackFrame.AddrPC.Offset ; } else { ppInstruction[ framesOnStk ] = 0 ; } framesOnStk++ ; } ReleaseMutex ( ossGetSysMutexHandle( _StackWalk64 ) ) ; } } PD_TRACE_EXIT ( SDB_OSSWKSEX ); return framesOnStk ; }
static void dumpBacktrace( unsigned int depth ) { if ( depth == 0 ) depth = 20; #if (defined(linux) && !defined(ANDROID)) || defined(__FreeBSD__) int stderr_fd = -1; if ( access( "/usr/bin/c++filt", X_OK ) < 0 ) { myPrint( "Stacktrace (c++filt NOT FOUND):\n" ); } else { int fd[2]; if ( pipe( fd ) == 0 && fork() == 0 ) { close( STDIN_FILENO ); // close stdin // stdin from pipe if ( dup( fd[0] ) != STDIN_FILENO ) { QgsDebugMsg( "dup to stdin failed" ); } close( fd[1] ); // close writing end execl( "/usr/bin/c++filt", "c++filt", ( char * ) 0 ); perror( "could not start c++filt" ); exit( 1 ); } myPrint( "Stacktrace (piped through c++filt):\n" ); stderr_fd = dup( STDERR_FILENO ); close( fd[0] ); // close reading end close( STDERR_FILENO ); // close stderr // stderr to pipe if ( dup( fd[1] ) != STDERR_FILENO ) { QgsDebugMsg( "dup to stderr failed" ); } close( fd[1] ); // close duped pipe } void **buffer = new void *[ depth ]; int nptrs = backtrace( buffer, depth ); backtrace_symbols_fd( buffer, nptrs, STDERR_FILENO ); delete [] buffer; if ( stderr_fd >= 0 ) { int status; close( STDERR_FILENO ); if ( dup( stderr_fd ) != STDERR_FILENO ) { QgsDebugMsg( "dup to stderr failed" ); } close( stderr_fd ); wait( &status ); } #elif defined(Q_OS_WIN) void **buffer = new void *[ depth ]; SymSetOptions( SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_UNDNAME ); SymInitialize( GetCurrentProcess(), "http://msdl.microsoft.com/download/symbols", TRUE ); unsigned short nFrames = CaptureStackBackTrace( 1, depth, buffer, NULL ); SYMBOL_INFO *symbol = ( SYMBOL_INFO * ) qgsMalloc( sizeof( SYMBOL_INFO ) + 256 ); symbol->MaxNameLen = 255; symbol->SizeOfStruct = sizeof( SYMBOL_INFO ); for ( int i = 0; i < nFrames; i++ ) { SymFromAddr( GetCurrentProcess(), ( DWORD64 )( buffer[ i ] ), 0, symbol ); symbol->Name[ 255 ] = 0; myPrint( "%d: %s [%x]\n", i, symbol->Name, symbol->Address ); } qgsFree( symbol ); #endif }
void* winpr_backtrace(DWORD size) { #if defined(HAVE_EXECINFO_H) t_execinfo* data = calloc(1, sizeof(t_execinfo)); if (!data) return NULL; data->buffer = calloc(size, sizeof(void*)); if (!data->buffer) { free(data); return NULL; } data->max = size; data->used = backtrace(data->buffer, size); return data; #elif defined(ANDROID) t_corkscrew_data* data = calloc(1, sizeof(t_corkscrew_data)); if (!data) return NULL; data->buffer = calloc(size, sizeof(backtrace_frame_t)); if (!data->buffer) { free(data); return NULL; } pthread_once(&initialized, load_library); data->max = size; data->used = fkt->unwind_backtrace(data->buffer, 0, size); return data; #elif defined(_WIN32) || defined(_WIN64) HANDLE process = GetCurrentProcess(); t_win_stack* data = calloc(1, sizeof(t_win_stack)); if (!data) return NULL; data->max = size; data->stack = calloc(data->max, sizeof(PVOID)); if (!data->stack) { free(data); return NULL; } SymInitialize(process, NULL, TRUE); data->used = CaptureStackBackTrace(2, size, data->stack, NULL); return data; #else LOGF(support_msg); return NULL; #endif }