Пример #1
0
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]);
}
Пример #2
0
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]);
}
Пример #3
0
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
}
Пример #4
0
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
}
Пример #5
0
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"));
    }
}