问题描述
|
我正在尝试使用StackWalk64在x64进程上遍历包含托管帧和本机帧的调用堆栈。一切正常,直到第一个或第二个受管帧为止,之后StackWalk64无法找出该帧的返回地址并失败。
我正在使用SymFunctionTableAccess64进行函数表访问回调,并且符号处理程序已使用SymInitialize()进行了初始化。我需要在dbghelp中执行一些魔术操作,以使其正确地遍历托管帧吗?
失败的示例调用栈:
UnmanagedFrame1
UnmanagedFrame2
UnmanagedFrame3
ManagedFrame1 <----- (StackWalk64 fails after this frame)
ManagedFrame2
UnmanagedFrame4
UnmanagedFrame5
ntdll!RtlUserThreadStart
注意:这个问题不是关于如何将托管帧解析为符号/方法名称/等,我只是想遍历整个堆栈,而不考虑符号解析/等。
同样,IDebugControl4 :: GetContextStackTrace可以正常工作,但是DbgEng使用自定义函数表回调,并且不只是委托给SymFunctionTableAccess64。我怀疑问题是CLR使用RtlInstallFunctionTableCallback安装回调函数表(指向mscordacwks),而SymFunctionTableAccess64不够聪明,无法遵循该表。
我花了一些时间尝试编写一个自定义函数表访问回调以遍历函数表链并在mscordacwks中调用该回调,但是它非常粗略,实际上并没有真正起作用。
解决方法
SOS调试器扩展是否有帮助?它提供了从
windbg
到ѭ9from完全按照您希望的方式移动堆栈的功能。
或者,在.NET Framework 2.0中使用探查器堆栈遍历:基础知识和超越可能有用。