/// <summary> /// Finds the leaf-most frame in the stack. /// </summary> /// <returns>the top-most frame in the stack</returns> protected MDbgFrame ReturnLeafFrame() { MDbgFrame leafFrame = null; CorChain c = null; try { c = Thread.CorThread.ActiveChain; } catch (COMException ce) { // Sometimes we cannot get the callstack. For example, the thread // may not be scheduled yet (CORDBG_E_THREAD_NOT_SCHEDULED), // or the CLR may be corrupt (CORDBG_E_BAD_THREAD_STATE). // In either case, we'll ignore the problem and return an empty callstack. // Debug.Assert(ce.ErrorCode == (int) HResult.CORDBG_E_BAD_THREAD_STATE || // ce.ErrorCode == (int) HResult.CORDBG_E_THREAD_NOT_SCHEDULED); DI.log.error("intenal MDbg error: Debug.Assert(ce.ErrorCode == (int) HResult.CORDBG_E_BAD_THREAD_STATE || ce.ErrorCode == (int) HResult.CORDBG_E_THREAD_NOT_SCHEDULED);"); DI.log.ex(ce); } if (c != null) { if (!c.IsManaged) { leafFrame = FillAndGetLeafFrameFromNativeChain(c); } if (leafFrame == null) { // if we still have no frame, we'll get one from the managed code. while (c != null && (!c.IsManaged || (c.IsManaged && c.ActiveFrame == null)) ) { c = c.Caller; } if (c == null) { leafFrame = null; } else { Debug.Assert(c != null && c.IsManaged); leafFrame = new MDbgILFrame(Thread, c.ActiveFrame); } } } else { leafFrame = null; } return(leafFrame); }
/// <summary> /// Finds the leaf-most frame in the stack. /// </summary> /// <returns>the top-most frame in the stack</returns> protected MDbgFrame ReturnLeafFrame() { MDbgFrame leafFrame = null; CorChain c = null; try { c = Thread.CorThread.ActiveChain; } catch (COMException ce) { // Sometimes we cannot get the callstack. For example, the thread // may not be scheduled yet (CORDBG_E_THREAD_NOT_SCHEDULED), // or the CLR may be corrupt (CORDBG_E_BAD_THREAD_STATE). // In either case, we'll ignore the problem and return an empty callstack. // Debug.Assert(ce.ErrorCode == (int) HResult.CORDBG_E_BAD_THREAD_STATE || // ce.ErrorCode == (int) HResult.CORDBG_E_THREAD_NOT_SCHEDULED); DI.log.error("intenal MDbg error: Debug.Assert(ce.ErrorCode == (int) HResult.CORDBG_E_BAD_THREAD_STATE || ce.ErrorCode == (int) HResult.CORDBG_E_THREAD_NOT_SCHEDULED);"); DI.log.ex(ce); } if (c != null) { if (! c.IsManaged) { leafFrame = FillAndGetLeafFrameFromNativeChain(c); } if (leafFrame == null) { // if we still have no frame, we'll get one from the managed code. while (c != null && (!c.IsManaged || (c.IsManaged && c.ActiveFrame == null)) ) { c = c.Caller; } if (c == null) { leafFrame = null; } else { Debug.Assert(c != null && c.IsManaged); leafFrame = new MDbgILFrame(Thread, c.ActiveFrame); } } } else { leafFrame = null; } return leafFrame; }
/// <summary> /// A function that returns the new MdbgFrame. The function is expected to be overriden by derived implementations. /// </summary> /// <param name="index">0 based index from top of the stack</param> /// <returns>frame from the stack</returns> protected override MDbgFrame GetFrameImpl(int index) { if (index < FrameCache.Count) { return FrameCache[index]; } MDbgFrame frameToReturn; if (index == 0) { // special case the first frame frameToReturn = ReturnLeafFrame(); } else { // use recursion... MDbgFrame prevFrame = GetFrameImpl(index - 1); if (prevFrame == null) throw new ArgumentException(); frameToReturn = GetFrameCaller(prevFrame); if (frameToReturn == null) { // we need to get the next frame from the following chain CorChain chain = GetFrameChain(prevFrame); Debug.Assert(chain != null); // 1. find next chain while (true) { chain = chain.Caller; if (chain == null) { break; } if (chain.IsManaged) { CorFrame f = chain.ActiveFrame; if (f != null) { frameToReturn = new MDbgILFrame(Thread, f); break; } } else { frameToReturn = FillAndGetLeafFrameFromNativeChain(chain); if (frameToReturn != null) { break; } } } } } // store and return frameToReturn if (frameToReturn != null) { Debug.Assert(FrameCache.Count >= index); if (FrameCache.Count == index) { FrameCache.Add(frameToReturn); } else { Debug.Assert(FrameCache[index] == frameToReturn, "List of frames pre-filled with incorrect frame"); } } return frameToReturn; }
/// <summary> /// A function that returns the new MdbgFrame. The function is expected to be overriden by derived implementations. /// </summary> /// <param name="index">0 based index from top of the stack</param> /// <returns>frame from the stack</returns> protected override MDbgFrame GetFrameImpl(int index) { if (index < FrameCache.Count) { return(FrameCache[index]); } MDbgFrame frameToReturn; if (index == 0) { // special case the first frame frameToReturn = ReturnLeafFrame(); } else { // use recursion... MDbgFrame prevFrame = GetFrameImpl(index - 1); if (prevFrame == null) { throw new ArgumentException(); } frameToReturn = GetFrameCaller(prevFrame); if (frameToReturn == null) { // we need to get the next frame from the following chain CorChain chain = GetFrameChain(prevFrame); Debug.Assert(chain != null); // 1. find next chain while (true) { chain = chain.Caller; if (chain == null) { break; } if (chain.IsManaged) { CorFrame f = chain.ActiveFrame; if (f != null) { frameToReturn = new MDbgILFrame(Thread, f); break; } } else { frameToReturn = FillAndGetLeafFrameFromNativeChain(chain); if (frameToReturn != null) { break; } } } } } // store and return frameToReturn if (frameToReturn != null) { Debug.Assert(FrameCache.Count >= index); if (FrameCache.Count == index) { FrameCache.Add(frameToReturn); } else { Debug.Assert(FrameCache[index] == frameToReturn, "List of frames pre-filled with incorrect frame"); } } return(frameToReturn); }