Debugging StackWalk64()返回单个帧
当尝试获取某个进程的线程的调用堆栈时,我总是得到一个相同的帧,尽管它肯定有更多帧(至少5帧) StackWalk64()在第一次调用时始终成功-返回具有以下内容的帧:Debugging StackWalk64()返回单个帧,debugging,winapi,dbghelp,Debugging,Winapi,Dbghelp,当尝试获取某个进程的线程的调用堆栈时,我总是得到一个相同的帧,尽管它肯定有更多帧(至少5帧) StackWalk64()在第一次调用时始终成功-返回具有以下内容的帧: AddrPC.Offset = 18446744072850558156 但是,在第二次调用时,它立即失败,错误id为998-error_NOACCESS(正如MSDN所说,此错误可能不是因为此调用) 此外,尝试使用SymFromAddr()将此地址解析为其符号名失败,错误为126-error\u MOD\u NOT\u(在成功
AddrPC.Offset = 18446744072850558156
但是,在第二次调用时,它立即失败,错误id为998-error_NOACCESS(正如MSDN所说,此错误可能不是因为此调用)
此外,尝试使用SymFromAddr()将此地址解析为其符号名失败,错误为126-error\u MOD\u NOT\u(在成功的symminitialize(m\u processHandler,NULL,TRUE)调用之后)
代码如下:
#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
#ifdef_M_IX86
//
//禁用全局优化并忽略由
//内联汇编。
//
#pragma优化(“g”,关闭)
#pragma警告(推送)
#杂注警告(禁用:4748)
#恩迪夫
bool EchoProfiler::getThreadStackTrace(uuu在句柄中的h_u线程,uuu在向量和帧之间)
{
语境与语境;
if(GetThreadContext(h_线程,&threadContext)==0)
{
cout溶液:
我错过了上下文结构必须正确初始化的部分。
添加以下内容解决了我的问题:
memset(&threadContext, 0, sizeof(CONTEXT));
threadContext.ContextFlags = CONTEXT_FULL;
感谢什么是targetProcessHandler以及它是如何初始化的?使用HANDLE targetProcessHandler=OpenProcess(PROCESS\u ALL\u ACCESS,false,pId)初始化
为什么在这里禁用优化,Hagay?看起来你这样做是完全正确的,但是为什么,它是必需的?如果我没有在我的应用程序中禁用优化,我会得到不正确的堆栈。我在堆栈打印机应用程序的输出中看到的函数地址更少。你知道原因是什么吗?