Пример #1
0
        /// <summary>
        /// We want to be able to interleave native and internal frames together and also minimize the exposure of internal frames.
        /// This method takes the internal frame cache and interleaves them with the native frames returned from UnwindNativeFrames.  In this
        /// case, this function will merely return all of the internal frames since the interop extension isn't loaded.
        /// <param name="thread">current thread that we're creating the stackwalker on</param>
        /// <param name="internalFrameCache">the internal frame cache</param>
        /// <param name="nativeFrames">native frames returned from UnwindNativeFrames</param>
        /// <returns>enumeration of the interleaved internal and native MDbgFrames</returns>
        /// </summary>
        protected virtual IEnumerable <MDbgFrame> StitchInternalFrames(MDbgThread thread, IEnumerator <CorFrame> internalFrameCache, IEnumerable <MDbgFrame> nativeFrames)
        {
            if (internalFrameCache == null)
            {
                yield break;
            }

            MDbgFrame mf = null;

            // iterate through the internal frames
            internalFrameCache.Reset();
            while (internalFrameCache.MoveNext())
            {
                mf = thread.LookupFrame(internalFrameCache.Current);
                yield return(mf);
            }
        }
Пример #2
0
        /// <summary>
        /// We want to be able to interleave native and internal frames together and also minimize the exposure of internal frames.
        /// This method takes the internal frame cache and interleaves them with the native frames returned from UnwindNativeFrames.  In this
        /// case, this function will merely return all of the internal frames since the interop extension isn't loaded.
        /// <param name="thread">current thread that we're creating the stackwalker on</param>
        /// <param name="internalFrameCache">the internal frame cache</param>
        /// <param name="nativeFrames">native frames returned from UnwindNativeFrames</param>
        /// <returns>enumeration of the interleaved internal and native MDbgFrames</returns>
        /// </summary>
        protected virtual IEnumerable<MDbgFrame> StitchInternalFrames(MDbgThread thread, IEnumerator<CorFrame> internalFrameCache, IEnumerable<MDbgFrame> nativeFrames)
        {
            if (internalFrameCache == null)
            {
                yield break;
            }

            MDbgFrame mf = null;

            // iterate through the internal frames
            internalFrameCache.Reset();
            while (internalFrameCache.MoveNext())
            {
                mf = thread.LookupFrame(internalFrameCache.Current);
                yield return mf;
            }
        }
Пример #3
0
        public IEnumerable <MDbgFrame> EnumerateFrames(MDbgThread thread)
        {
            MDbgFrame               frameToReturn = null;
            long                    pEndVal = Int64.MinValue;
            CorStackWalk            m_v3StackWalk = thread.CorThread.CreateStackWalk(CorStackWalkType.ExtendedV3StackWalk);
            INativeContext          ctxUnmanagedChain = null, currentCtx = null;
            IEnumerable <MDbgFrame> nFrames;
            List <CorFrame>         iFrameCache = new List <CorFrame>(); //storage cache for internal frames

            // we need to call MoveNext() to make the enumerator valid
            while ((m_v3StackWalk != null) && (m_v3StackWalk.MoveNext()))
            {
                CorFrame frame = m_v3StackWalk.Current;

                if (frame != null)
                {
                    // If we get a RuntimeUnwindableFrame, then the stackwalker is also stopped at a native
                    // stack frame, but it's a native stack frame which requires special unwinding help from
                    // the runtime. When a debugger gets a RuntimeUnwindableFrame, it should use the runtime
                    // to unwind, but it has to do inspection on its own. It can call
                    // ICorDebugStackWalk::GetContext() to retrieve the context of the native stack frame.
                    if (frame.FrameType != CorFrameType.RuntimeUnwindableFrame)
                    {
                        // check for an internal frame...if the internal frame happens to come after the last
                        // managed frame, any call to GetContext() will assert
                        if (frame.FrameType != CorFrameType.InternalFrame)
                        {
                            // we need to store the CONTEXT when we're at a managed frame, if there's an internal frame
                            // after this, then we'll need this CONTEXT
                            currentCtx = m_v3StackWalk.GetContext();
                        }
                        else if ((frame.FrameType == CorFrameType.InternalFrame) && (ctxUnmanagedChain != null))
                        {
                            // we need to check to see if this internal frame could have been sandwiched between
                            // native frames, this will be the case if ctxUnmanagedChain is not null

                            // we need to store ALL internal frames until we hit the next managed frame
                            iFrameCache.Add(frame);
                            continue;
                        }
                        // else we'll use the 'stored' currentCtx if we're at an InternalFrame

                        pEndVal = Int64.MaxValue;
                        if (currentCtx != null)
                        {
                            pEndVal = currentCtx.StackPointer.ToInt64();
                        }

                        //check to see if we have native frames to unwind
                        nFrames = UnwindNativeFrames(thread, ctxUnmanagedChain, pEndVal);

                        foreach (MDbgFrame fr in StitchInternalFrames(thread, iFrameCache.GetEnumerator(), nFrames))
                        {
                            yield return(fr);
                        }

                        //clear out the CONTEXT and native frame cache
                        ctxUnmanagedChain = null;
                        nFrames           = null;
                        iFrameCache.Clear();

                        //return the managed frame
                        frameToReturn = thread.LookupFrame(frame);
                        yield return(frameToReturn);
                    }
                    else
                    {
                        continue;
                    }
                }
                // If we don't get a frame, then the stackwalker is stopped at a native stack frame.
                else
                {
                    // we've hit a native frame, we need to store the CONTEXT
                    ctxUnmanagedChain = m_v3StackWalk.GetContext();

                    //we need to invalidate the currentCtx since it won't be valid on the next loop iteration
                    currentCtx = null;
                }
            } //end while

            // we may have native frames at the end of the stack
            nFrames = UnwindNativeFrames(thread, ctxUnmanagedChain, Int64.MaxValue);


            foreach (MDbgFrame frame in StitchInternalFrames(thread, iFrameCache.GetEnumerator(), nFrames))
            {
                yield return(frame);
            }

            nFrames           = null;
            ctxUnmanagedChain = null;

            // End of stackwalk. Return null as sentinel.
            yield return(null);
        }
Пример #4
0
        public IEnumerable<MDbgFrame> EnumerateFrames(MDbgThread thread)
        {
            MDbgFrame frameToReturn = null;
            long pEndVal = Int64.MinValue;
            CorStackWalk m_v3StackWalk = thread.CorThread.CreateStackWalk(CorStackWalkType.ExtendedV3StackWalk);
            INativeContext ctxUnmanagedChain = null, currentCtx = null;
            IEnumerable<MDbgFrame> nFrames;
            List<CorFrame> iFrameCache = new List<CorFrame>(); //storage cache for internal frames

            // we need to call MoveNext() to make the enumerator valid
            while ((m_v3StackWalk != null) && (m_v3StackWalk.MoveNext()))
            {
                CorFrame frame = m_v3StackWalk.Current;

                if (frame != null)
                {
                    // If we get a RuntimeUnwindableFrame, then the stackwalker is also stopped at a native
                    // stack frame, but it's a native stack frame which requires special unwinding help from
                    // the runtime. When a debugger gets a RuntimeUnwindableFrame, it should use the runtime
                    // to unwind, but it has to do inspection on its own. It can call
                    // ICorDebugStackWalk::GetContext() to retrieve the context of the native stack frame.
                    if (frame.FrameType != CorFrameType.RuntimeUnwindableFrame)
                    {

                        // check for an internal frame...if the internal frame happens to come after the last
                        // managed frame, any call to GetContext() will assert
                        if (frame.FrameType != CorFrameType.InternalFrame)
                        {
                            // we need to store the CONTEXT when we're at a managed frame, if there's an internal frame
                            // after this, then we'll need this CONTEXT
                            currentCtx = m_v3StackWalk.GetContext();
                        }
                        else if ((frame.FrameType == CorFrameType.InternalFrame) && (ctxUnmanagedChain != null))
                        {
                            // we need to check to see if this internal frame could have been sandwiched between
                            // native frames, this will be the case if ctxUnmanagedChain is not null

                            // we need to store ALL internal frames until we hit the next managed frame
                            iFrameCache.Add(frame);
                            continue;
                        }
                        // else we'll use the 'stored' currentCtx if we're at an InternalFrame

                        pEndVal = Int64.MaxValue;
                        if (currentCtx != null)
                        {
                            pEndVal = currentCtx.StackPointer.ToInt64();
                        }

                        //check to see if we have native frames to unwind
                        nFrames = UnwindNativeFrames(thread, ctxUnmanagedChain, pEndVal);

                        foreach (MDbgFrame fr in StitchInternalFrames(thread,iFrameCache.GetEnumerator(),nFrames))
                        {
                            yield return fr;
                        }

                        //clear out the CONTEXT and native frame cache
                        ctxUnmanagedChain = null;
                        nFrames = null;
                        iFrameCache.Clear();

                        //return the managed frame
                        frameToReturn = thread.LookupFrame(frame);
                        yield return frameToReturn;
                    }
                    else
                    {
                        continue;
                    }

                }
                // If we don't get a frame, then the stackwalker is stopped at a native stack frame.
                else
                {
                    // we've hit a native frame, we need to store the CONTEXT
                    ctxUnmanagedChain = m_v3StackWalk.GetContext();

                    //we need to invalidate the currentCtx since it won't be valid on the next loop iteration
                    currentCtx = null;
                }

            } //end while

            // we may have native frames at the end of the stack
            nFrames = UnwindNativeFrames(thread, ctxUnmanagedChain, Int64.MaxValue);

           
            foreach (MDbgFrame frame in StitchInternalFrames(thread, iFrameCache.GetEnumerator(), nFrames))
            {
                yield return frame;
            }

            nFrames = null;
            ctxUnmanagedChain = null;

            // End of stackwalk. Return null as sentinel.
            yield return null;
        }