Question

When trying to obtain the call stack of a thread of some process, I always get a single same frame, although it is for sure has more (at least 5 frames).

StackWalk64() always succeeds on the first call - return a frame with:

AddrPC.Offset = 18446744072850558156

But, immediately on the second call it fails with error id 998-ERROR_NOACCESS (it might be that this error is not because of this call, as MSDN says).

Moreover, trying to resolve this address into its symbol name with SymFromAddr() fails with error 126-ERROR_MOD_NOT_FOUND (after successful SymInitialize(m_processHandler,NULL,TRUE) call).

Here is the code:

#ifdef _M_IX86
  //
  // Disable global optimization and ignore /GS waning caused by
  // inline assembly.
  //
  #pragma optimize( "g", off )
  #pragma warning( push )
  #pragma warning( disable : 4748 )
#endif

bool EchoProfiler::getThreadStackTrace(__in HANDLE h_thread, __out vector<DWORD64> &framesVec)
{
CONTEXT threadContext;
if (GetThreadContext(h_thread, &threadContext) == 0)
{
    cout << "Error: GetThreadContext() failed with error ID " << GetLastError() << endl;
    return false;
}

//initialize stack frame
DWORD MachineType;
STACKFRAME64 StackFrame;
ZeroMemory( &StackFrame, sizeof( STACKFRAME64 ) );

MachineType                 = IMAGE_FILE_MACHINE_I386;
StackFrame.AddrPC.Offset    = threadContext.Eip;
StackFrame.AddrPC.Mode      = AddrModeFlat;
StackFrame.AddrFrame.Offset = threadContext.Ebp;
StackFrame.AddrFrame.Mode   = AddrModeFlat;
StackFrame.AddrStack.Offset = threadContext.Esp;
StackFrame.AddrStack.Mode   = AddrModeFlat;

PVOID contextRec = (MachineType == IMAGE_FILE_MACHINE_I386) ? NULL : &threadContext;
int i=0;
// enumerate all the frames in the stack
for (i=1 ; ; i++)
{
    if (StackWalk64( MachineType, targetProcessHandler, h_thread, &StackFrame,
        contextRec, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL ) == false)
    {
        // in case it failed or we have finished walking the stack.
        cout << "Error: StackWalk64() failed with error ID " << GetLastError() << endl;
        i--;
        break;
        // return false;
    }

    if ( StackFrame.AddrPC.Offset != 0 )
    {
        // Valid frame.
        cout << "Frame #" << i << " address - " << StackFrame.AddrPC.Offset << endl;
        framesVec.push_back(StackFrame.AddrPC.Offset);
    }
    else
    {
        // Base reached.
        break;
    }
}

//cout << "StackWalk64 found " << i << " stack frames:" << endl;
//i = 1;
//for (FramesConstItr itr=framesVec.begin() ; itr != framesVec.end() ; itr++ , i++)
//  cout << i << " - " << *itr << endl;

return true;
}

#ifdef _M_IX86
  #pragma warning( pop )
  #pragma optimize( "g", on )
#endif

what could it be?

Was it helpful?

Solution

Solution:

I missed the part said that the context structure must be initialize properly. Adding the following solved my problem:

memset(&threadContext, 0, sizeof(CONTEXT));
threadContext.ContextFlags = CONTEXT_FULL;

Thanks

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top