public List<UnifiedStackFrame> GetStackTraceFromContext(uint? threadIndex, CONTEXT? context) { ThreadInformation threadInfo = GetThreadInfo(threadIndex); List<UnifiedStackFrame> unifiedStackTrace = new List<UnifiedStackFrame>(); List<UnifiedStackFrame> nativeStackTrace = GetNativeStackTrace( threadIndex.HasValue ? (uint?)threadInfo.EngineThreadId : null, context); if (threadInfo.IsManagedThread) { List<UnifiedStackFrame> managedStackTrace = GetManagedStackTrace(threadInfo.ManagedThread); int managedFrame = 0; for (int nativeFrame = 0; nativeFrame < nativeStackTrace.Count; ++nativeFrame) { bool found = false; for (int temp = managedFrame; temp < managedStackTrace.Count; ++temp) { if (nativeStackTrace[nativeFrame].InstructionPointer == managedStackTrace[temp].InstructionPointer) { managedStackTrace[temp].LinkedStackFrame = nativeStackTrace[nativeFrame]; unifiedStackTrace.Add(managedStackTrace[temp]); managedFrame = temp + 1; found = true; break; } else if (managedFrame > 0) { // We have already seen at least one managed frame, and we're about // to skip a managed frame because we didn't find a matching native // frame. In this case, add the managed frame into the stack anyway. unifiedStackTrace.Add(managedStackTrace[temp]); managedFrame = temp + 1; found = true; break; } } // We didn't find a matching managed frame, so add the native frame directly. if (!found) unifiedStackTrace.Add(nativeStackTrace[nativeFrame]); } } else { return nativeStackTrace; } return unifiedStackTrace; }
private List<UnifiedStackFrame> GetNativeStackTrace(uint? engineThreadId, CONTEXT? context) { if (engineThreadId.HasValue) Util.VerifyHr(((IDebugSystemObjects)_debugClient).SetCurrentThreadId(engineThreadId.Value)); DEBUG_STACK_FRAME[] stackFrames = new DEBUG_STACK_FRAME[200]; uint framesFilled; if (context.HasValue) { int ctxSize = Marshal.SizeOf(context); IntPtr ctxPtr = Marshal.AllocHGlobal(ctxSize); IntPtr frameCtxsPtr = Marshal.AllocHGlobal(ctxSize * stackFrames.Length); try { Marshal.StructureToPtr(context, ctxPtr, false); Util.VerifyHr(((IDebugControl4)_debugClient).GetContextStackTrace( ctxPtr, (uint)ctxSize, stackFrames, stackFrames.Length, frameCtxsPtr, (uint)(stackFrames.Length * ctxSize), (uint)ctxSize, out framesFilled)); } finally { Marshal.FreeHGlobal(ctxPtr); Marshal.FreeHGlobal(frameCtxsPtr); } } else { Util.VerifyHr(((IDebugControl)_debugClient).GetStackTrace( 0, 0, 0, stackFrames, stackFrames.Length, out framesFilled)); } List<UnifiedStackFrame> stackTrace = new List<UnifiedStackFrame>(); for (uint i = 0; i < framesFilled; ++i) { stackTrace.Add(new UnifiedStackFrame(stackFrames[i], (IDebugSymbols2)_debugClient)); } return stackTrace; }