void wxStackWalker::ProcessFrames(size_t skip) { wxStackFrame frames[MAX_FRAMES]; if (!ms_symbols || !m_depth) return; // we have 3 more "intermediate" frames which the calling code doesn't know // about, account for them skip += 3; // call addr2line only once since this call may be very slow // (it has to load in memory the entire EXE of this app which may be quite // big, especially if it contains debug info and is compiled statically!) int towalk = InitFrames(frames, m_depth - skip, &ms_addresses[skip], &ms_symbols[skip]); // now do user-defined operations on each frame for ( int n = 0; n < towalk - (int)skip; n++ ) OnStackFrame(frames[n]); }
void wxStackWalker::ProcessFrames(size_t skip) { wxStackFrame frames[MAX_FRAMES]; if (!ms_symbols || !m_depth) return; // we are another level down from Walk(), so adjust the number of stack // frames to skip accordingly skip += 1; // call addr2line only once since this call may be very slow // (it has to load in memory the entire EXE of this app which may be quite // big, especially if it contains debug info and is compiled statically!) int numFrames = InitFrames(frames, m_depth - skip, &ms_addresses[skip], &ms_symbols[skip]); // now do user-defined operations on each frame for ( int n = 0; n < numFrames; n++ ) OnStackFrame(frames[n]); }
void wxStackWalker::WalkFrom(const CONTEXT *pCtx, size_t skip) { #if wxUSE_THREADS // wxDbgHelpDLL has its own mutex locks for some critical functions, but really it // should have locks on ALL its functions. So until it gets fixed, we'll use a // mutex here for stackframe walking. --air wxMutexLocker lock(s_mtx_StackWalker); #endif if ( !wxDbgHelpDLL::Init() ) { // don't log a user-visible error message here because the stack trace // is only needed for debugging/diagnostics anyhow and we shouldn't // confuse the user by complaining that we couldn't generate it wxLogDebug(_T("Failed to get stack backtrace: %s"), wxDbgHelpDLL::GetErrorMessage().c_str()); return; } // according to MSDN, the first parameter should be just a unique value and // not process handle (although the parameter is prototyped as "HANDLE // hProcess") and actually it advises to use the process id and not handle // for Win9x, but then we need to use the same value in StackWalk() call // below which should be a real handle... so this is what we use const HANDLE hProcess = ::GetCurrentProcess(); if ( !wxDbgHelpDLL::RefreshModuleList(hProcess) ) return; CONTEXT ctx = *pCtx; // will be modified by StackWalk() DWORD dwMachineType; // initialize the initial frame: currently we can do it for x86 only STACKFRAME sf; wxZeroMemory(sf); #ifdef _M_IX86 sf.AddrPC.Offset = ctx.Eip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Offset = ctx.Esp; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Offset = ctx.Ebp; sf.AddrFrame.Mode = AddrModeFlat; dwMachineType = IMAGE_FILE_MACHINE_I386; #else #error "Need to initialize STACKFRAME on non x86" #endif // _M_IX86 // iterate over all stack frames (but stop after 200 to avoid entering // infinite loop if the stack is corrupted) for ( size_t nLevel = 0; nLevel < 200; nLevel++ ) { // get the next stack frame if ( !wxDbgHelpDLL::StackWalk ( dwMachineType, hProcess, ::GetCurrentThread(), &sf, &ctx, NULL, // read memory function (default) wxDbgHelpDLL::SymFunctionTableAccess, wxDbgHelpDLL::SymGetModuleBase, NULL // address translator for 16 bit ) ) { if ( ::GetLastError() ) wxDbgHelpDLL::LogError(_T("StackWalk")); break; } // don't show this frame itself in the output if ( nLevel >= skip ) { wxStackFrame frame(nLevel - skip, (void *)sf.AddrPC.Offset, sf.AddrFrame.Offset); OnStackFrame(frame); } } // this results in crashes inside ntdll.dll when called from // exception handler ... #if 0 if ( !wxDbgHelpDLL::SymCleanup(hProcess) ) { wxDbgHelpDLL::LogError(_T("SymCleanup")); } #endif }
void wxStackWalker::WalkFrom(const CONTEXT *pCtx, size_t skip) { if ( !wxDbgHelpDLL::Init() ) { wxLogError(_("Failed to get stack backtrace:\n%s"), wxDbgHelpDLL::GetErrorMessage().c_str()); return; } // according to MSDN, the first parameter should be just a unique value and // not process handle (although the parameter is prototyped as "HANDLE // hProcess") and actually it advises to use the process id and not handle // for Win9x, but then we need to use the same value in StackWalk() call // below which should be a real handle... so this is what we use const HANDLE hProcess = ::GetCurrentProcess(); if ( !wxDbgHelpDLL::SymInitialize ( hProcess, NULL, // use default symbol search path TRUE // load symbols for all loaded modules ) ) { wxDbgHelpDLL::LogError(_T("SymInitialize")); return; } CONTEXT ctx = *pCtx; // will be modified by StackWalk() DWORD dwMachineType; // initialize the initial frame: currently we can do it for x86 only STACKFRAME sf; wxZeroMemory(sf); #ifdef _M_IX86 sf.AddrPC.Offset = ctx.Eip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Offset = ctx.Esp; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Offset = ctx.Ebp; sf.AddrFrame.Mode = AddrModeFlat; dwMachineType = IMAGE_FILE_MACHINE_I386; #else #error "Need to initialize STACKFRAME on non x86" #endif // _M_IX86 // iterate over all stack frames for ( size_t nLevel = 0; ; nLevel++ ) { // get the next stack frame if ( !wxDbgHelpDLL::StackWalk ( dwMachineType, hProcess, ::GetCurrentThread(), &sf, &ctx, NULL, // read memory function (default) wxDbgHelpDLL::SymFunctionTableAccess, wxDbgHelpDLL::SymGetModuleBase, NULL // address translator for 16 bit ) ) { if ( ::GetLastError() ) wxDbgHelpDLL::LogError(_T("StackWalk")); break; } // don't show this frame itself in the output if ( nLevel >= skip ) { wxStackFrame frame(nLevel - skip, (void *)sf.AddrPC.Offset, sf.AddrFrame.Offset); OnStackFrame(frame); } } // this results in crashes inside ntdll.dll when called from // exception handler ... #if 0 if ( !wxDbgHelpDLL::SymCleanup(hProcess) ) { wxDbgHelpDLL::LogError(_T("SymCleanup")); } #endif }
void wxStackWalker::WalkFrom(const CONTEXT *pCtx, size_t skip, size_t maxDepth) { if ( !wxDbgHelpDLL::Init() ) { // don't log a user-visible error message here because the stack trace // is only needed for debugging/diagnostics anyhow and we shouldn't // confuse the user by complaining that we couldn't generate it wxLogDebug(wxT("Failed to get stack backtrace: %s"), wxDbgHelpDLL::GetErrorMessage().c_str()); return; } // according to MSDN, the first parameter should be just a unique value and // not process handle (although the parameter is prototyped as "HANDLE // hProcess") and actually it advises to use the process id and not handle // for Win9x, but then we need to use the same value in StackWalk() call // below which should be a real handle... so this is what we use const HANDLE hProcess = ::GetCurrentProcess(); if ( !wxDbgHelpDLL::SymInitialize ( hProcess, NULL, // use default symbol search path TRUE // load symbols for all loaded modules ) ) { wxDbgHelpDLL::LogError(wxT("SymInitialize")); return; } CONTEXT ctx = *pCtx; // will be modified by StackWalk() DWORD dwMachineType; // initialize the initial frame: currently we can do it for x86 only STACKFRAME sf; wxZeroMemory(sf); #if defined(_M_AMD64) sf.AddrPC.Offset = ctx.Rip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Offset = ctx.Rsp; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Offset = ctx.Rbp; sf.AddrFrame.Mode = AddrModeFlat; dwMachineType = IMAGE_FILE_MACHINE_AMD64; #elif defined(_M_IX86) sf.AddrPC.Offset = ctx.Eip; sf.AddrPC.Mode = AddrModeFlat; sf.AddrStack.Offset = ctx.Esp; sf.AddrStack.Mode = AddrModeFlat; sf.AddrFrame.Offset = ctx.Ebp; sf.AddrFrame.Mode = AddrModeFlat; dwMachineType = IMAGE_FILE_MACHINE_I386; #else #error "Need to initialize STACKFRAME on non x86" #endif // _M_IX86 // iterate over all stack frames for ( size_t nLevel = 0; nLevel < maxDepth; nLevel++ ) { // get the next stack frame if ( !wxDbgHelpDLL::StackWalk ( dwMachineType, hProcess, ::GetCurrentThread(), &sf, &ctx, NULL, // read memory function (default) wxDbgHelpDLL::SymFunctionTableAccess, wxDbgHelpDLL::SymGetModuleBase, NULL // address translator for 16 bit ) ) { if ( ::GetLastError() ) wxDbgHelpDLL::LogError(wxT("StackWalk")); break; } // don't show this frame itself in the output if ( nLevel >= skip ) { wxStackFrame frame(nLevel - skip, wxUIntToPtr(sf.AddrPC.Offset), sf.AddrFrame.Offset); OnStackFrame(frame); } } if ( !wxDbgHelpDLL::SymCleanup(hProcess) ) { wxDbgHelpDLL::LogError(wxT("SymCleanup")); } }