Пример #1
0
 IEnumerator IEnumerable.GetEnumerator()
 {
     MDbgThread[] ret = new MDbgThread[m_items.Count];
     m_items.Values.CopyTo(ret, 0);
     Array.Sort(ret);
     return(ret.GetEnumerator());
 }
Пример #2
0
        public static ThreadSnapshot GetThreadSnapshot(MDbgThread thread)
        {
            var snapshot = new ThreadSnapshot();

            snapshot.Id = thread.Id;

            long creation = 0, exit = 0, kernel = 0, user = 0;

            try {
                GetThreadTimes(thread.CorThread.Handle, out creation, out exit, out kernel, out user);
            }
            catch (Exception ex) {
                Console.WriteLine(" Exception on GetThreadTimes for thread ID {0} : {1}", thread.Id, ex);
            }

            snapshot.KernelTime = kernel;
            snapshot.UserTime = user;
            snapshot.StackTrace = new List<string>();

            foreach (MDbgFrame frame in thread.Frames) {
                try {
                    snapshot.StackTrace.Add(frame.Function.FullName);
                } catch {
                    // no frame, so ignore
                }
            }

            return snapshot;
        }
Пример #3
0
        // Update list w/ current callstack. Return an array of FramePair representing the callstack.
        // Run on worker thread.
        static FramePair[] GetFrameList(MDbgThread thread)
        {
            // Populate listbox with frames.
            MDbgFrame f = thread.BottomFrame;
            MDbgFrame af = thread.HaveCurrentFrame ? thread.CurrentFrame : null;
            
            System.Collections.ArrayList l = new System.Collections.ArrayList();

            int i = 0;
            int depth = 20;
            bool verboseOutput = true;

            while (f != null && (depth == 0 || i < depth))
            {
                string line;
                if (f.IsInfoOnly)
                {
                    line = string.Format(CultureInfo.InvariantCulture, "[{0}]", f.ToString());
                }
                else
                {
                    string frameDescription =  "<unknown>";
                    try
                    {
                        // Get IP info.
                        uint ipNative;
                        uint ipIL;
                        CorDebugMappingResult result;
                        f.CorFrame.GetNativeIP(out ipNative);
                        f.CorFrame.GetIP(out ipIL, out result);
                        string frameLocation = String.Format(CultureInfo.InvariantCulture, " N=0x{0:x}, IL=0x{1:x} ({2})", 
                            ipNative, ipIL, result.ToString());


                        // This may actually do a ton of work, including evaluating parameters.
                        frameDescription = f.ToString(verboseOutput ? "v" : null) + frameLocation;
                    }
                    catch (System.Runtime.InteropServices.COMException)
                    {
                        if (f.Function != null)
                        {
                            frameDescription = f.Function.FullName;
                        }                        
                    }

                    line = string.Format(CultureInfo.InvariantCulture, "{0}{1}. {2}", f.Equals(af) ? "*" : " ", i, frameDescription);
                    ++i;
                }
                l.Add(new FramePair(f, line));
                f = f.NextUp;
            }
            if (f != null && depth != 0) // means we still have some frames to show....
            {
                l.Add(new FramePair(null,
                    string.Format(CultureInfo.InvariantCulture, "displayed only first {0} frames. For more frames use -c switch", depth)
                    ));
            }

            return (FramePair[]) l.ToArray(typeof(FramePair));
        }
Пример #4
0
        /// <summary>
        /// Unwind unmanaged frames within an native chain.
        /// </summary>
        /// <param name="thread">thread containing an unmanged frame</param>
        /// <param name="context">context containing the current context of the stack frame</param>
        /// <param name="endValue">address of the next managed frame</param>
        /// <returns>enumeration of MDbgFrames for the native frames</returns>
        /// <remarks>ICorDebug stackwalking only unwinds managed chains.
        /// A derived class can override this function to provide native stacktracing.</remarks>
        protected virtual IEnumerable <MDbgFrame> UnwindNativeFrames(MDbgThread thread, INativeContext context, long endValue)
        {
            // Base class can't unwind unmanaged chains.
            // A derived class can override and provide native stack unwinding.
            // Use:
            // 1) chain.RegisterSet to get the starting context.
            // 2) chain.GetStackRange(out start, out end);   to get the stackrange to unwind to
            // 3) a native unwinder (such as DbgHelp.dll) to actually do the native stack unwinding.

            yield break;
        }
Пример #5
0
        // Update list w/ current callstack
        public void RefreshCallstack(MDbgThread thread)
        {
            ListBox.ObjectCollection list = this.listBoxCallstack.Items;
            list.Clear();

            // Set Title.
            this.Text = "Callstack on Thread #" + thread.Number + " (tid=" + thread.Id + ")";

            // Populate listbox with frames.
            MDbgFrame f = thread.BottomFrame;
            MDbgFrame af = thread.HaveCurrentFrame ? thread.CurrentFrame : null;

            int i = 0;
            int depth = 20;
            bool verboseOutput = true;

            while (f != null && (depth == 0 || i < depth))
            {
                string line;
                if (f.IsInfoOnly)
                {
                    line = string.Format(CultureInfo.InvariantCulture, "[{0}]", f.ToString());
                }
                else
                {
                    string frameDescription =  "<unknown>";
                    try
                    {
                        // This may actually do a ton of work, including evaluating parameters.
                        frameDescription = f.ToString(verboseOutput ? "v" : null);
                    }
                    catch (System.Runtime.InteropServices.COMException)
                    {
                        if (f.Function != null)
                        {
                            frameDescription = f.Function.FullName;
                        }                        
                    }

                    line = string.Format(CultureInfo.InvariantCulture, "{0}{1}. {2}", f.Equals(af) ? "*" : " ", i, frameDescription);
                    ++i;
                }
                AddItem(line, f);
                f = f.NextUp;
            }
            if (f != null && depth != 0) // means we still have some frames to show....
            {
                AddItem(
                    string.Format(CultureInfo.InvariantCulture, "displayed only first {0} frames. For more frames use -c switch", depth), 
                    null);
            }
        }
Пример #6
0
        public IEnumerable <MDbgFrame> EnumerateFrames(MDbgThread thread)
        {
            IMDbgFrameFactory factory;

            if (thread.CorThread.IsV3)
            {
                factory = new MDbgV3FrameFactory();
                return(factory.EnumerateFrames(thread));
            }
            else
            {
                factory = new MDbgV2FrameFactory();
                return(factory.EnumerateFrames(thread));
            }
        }
Пример #7
0
        /// <summary>
        /// Creates a new V2 StackWalker.
        /// </summary>
        /// <param name="thread">a thread object associated with the stackwalker</param>
        /// <returns>object implementing MDbgStackWalker interface</returns>
        public IEnumerable <MDbgFrame> EnumerateFrames(MDbgThread thread)
        {
            // To do stackwalking using V2 ICorDebug, we enumerate through the chains,
            // and then enumerate each frame in every chain

            CorChain chain = null;

            try
            {
                chain = thread.CorThread.ActiveChain;
            }
            catch (System.Runtime.InteropServices.COMException ce)
            {
                // Sometimes we cannot get the callstack.  For example, the thread
                // may not be scheduled yet (CORDBG_E_THREAD_NOT_SCHEDULED),
                // or the debuggee 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);
            }

            while (chain != null)
            {
                if (chain.IsManaged)
                {
                    // Enumerate managed frames
                    // A chain may have 0 managed frames.
                    CorFrame f = chain.ActiveFrame;
                    while (f != null)
                    {
                        MDbgFrame frame = new MDbgILFrame(thread, f);
                        f = f.Caller;
                        yield return(frame);
                    }
                }
                else
                {
                    // ICorDebug doesn't unwind unmanaged frames. Need to let a native-debug component handle that.
                    foreach (MDbgFrame frame in UnwindNativeFrames(thread, chain))
                    {
                        yield return(frame);
                    }
                }

                // Move to next chain
                chain = chain.Caller;
            }
        }
Пример #8
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);
            }
        }
Пример #9
0
        /// <summary>
        /// Gets the MDbgThread with the given ThreadId.
        /// </summary>
        /// <param name="threadId">The ThreadId to look up.</param>
        /// <returns>The MDbgThread.</returns>
        public MDbgThread GetThreadFromThreadId(int threadId)
        {
            // This sometimes fails because we're looking for a thread don't recognize.
            // Need to offer lazy create semantics here.
            MDbgThread te = (MDbgThread)m_items[threadId];

            if (te == null)
            {
                CorThread t = m_process.CorProcess.GetThread(threadId);
                if (t != null)
                {
                    Register(t);
                    te = (MDbgThread)m_items[threadId];
                }
            }
            return(te);
        }
Пример #10
0
 internal void UnRegister(CorThread t)
 {
     m_items.Remove(t.Id);
     if (m_active != null &&
         m_active.CorThread.Id == t.Id)
     {
         m_active = null;
     }
 }
Пример #11
0
 internal MDbgILFrame(MDbgThread thread, CorFrame frame)
     : base(thread)
 {
     Debug.Assert(frame != null);
     m_frame = frame;
 }
Пример #12
0
        private static void InternalWhereCommand(MDbgThread thread, int depth, bool verboseOutput)
        {
            Debug.Assert(thread != null);

            WriteOutput("Thread [#:" + g_threadNickNames.GetThreadName(thread) + "]");

            MDbgFrame af = thread.HaveCurrentFrame ? thread.CurrentFrame : null;
            MDbgFrame f = thread.BottomFrame;
            int i = 0;
            while (f != null && (depth == 0 || i < depth))
            {
                string line;
                if (f.IsInfoOnly)
                {
                    if (!ShowInternalFrames)
                    {
                        // in cases when we don't want to show internal frames, we'll skip them
                        f = f.NextUp;
                        continue;
                    }
                    line = string.Format(CultureInfo.InvariantCulture, "    {0}", f.ToString());
                }
                else
                {
                    string frameDescription = f.ToString(verboseOutput ? "v" : null);
                    line = string.Format(CultureInfo.InvariantCulture, "{0}{1}. {2}", f.Equals(af) ? "*" : " ", i, frameDescription);
                    ++i;
                }
                WriteOutput(line);
                f = f.NextUp;
            }
            if (f != null && depth != 0) // means we still have some frames to show....
            {
                WriteOutput(string.Format(CultureInfo.InvariantCulture, "displayed only first {0} frames. For more frames use -c switch", depth));
            }
        }
Пример #13
0
 internal void Clear()
 {
     m_items.Clear();
     m_active = null;
     m_freeThreadNumber = 0;
 }
Пример #14
0
 public string GetThreadName(MDbgThread thread)
 {
     Debug.Assert(thread != null);
     if (thread == null)
     {
         throw new ArgumentException();
     }
     string nick = GetNickNameFromThreadNumber(thread.Number);
     if (nick.Length == 0)
     {
         // no nick name
         return thread.Number.ToString(CultureInfo.InvariantCulture);
     }
     else
     {
         return nick;
     }
 }
Пример #15
0
        private static string GetThreadStateDescriptionString(MDbgThread thread)
        {
            CorThread t = thread.CorThread;
            StringBuilder debuggerState = new StringBuilder();
            StringBuilder clientState = new StringBuilder();

            if (t.DebugState == CorDebugThreadState.THREAD_SUSPEND)
                debuggerState.Append("(SUSPENDED)");

            try
            {
                CorDebugUserState userState = t.UserState;

                if ((userState & CorDebugUserState.USER_SUSPENDED) != 0)
                    clientState.Append("user suspended");

                if ((userState & CorDebugUserState.USER_WAIT_SLEEP_JOIN) != 0)
                {
                    if (clientState.Length > 0)
                        clientState.Append(", ");
                    clientState.Append("waiting");
                }
            }
            catch (System.Runtime.InteropServices.COMException e)
            {
                if (e.ErrorCode != (int)HResult.CORDBG_E_BAD_THREAD_STATE)
                    throw;

                clientState.Append("in bad thread state");
            }

            StringBuilder result = debuggerState;
            if (clientState.Length > 0)
            {
                if (result.Length > 0)
                    result.Append(" ");
                result.Append("[").Append(clientState.ToString()).Append("]");
            }
            return result.ToString();
        }
Пример #16
0
 /// <summary> From time to time the thread may be in invalid state. </summary>
 public static bool CheckValidState(MDbgThread th)
 {
     try
     {
         th.CorThread.UserState.ToString();
         return true;
     }
     catch (COMException e)
     {
         // The state of the thread is invalid.
         if ((uint)e.ErrorCode == 0x8013132D)
         {
             return false;
         }
     }
     return true;
 }
Пример #17
0
        public static StackSample GetThreadStacks(MDbgThread t, bool withArgs = false, bool originFirst = false)
        {
            //Console.WriteLine("Callstack for Thread {0}", t.Id.ToString());
            StackSample sample = new StackSample { ThreadId = t.Id, Time = DateTime.Now };
            MDbgFrame[] frames = new MDbgFrame[0];
            try
            {
                frames = t.Frames.ToArray();
            }
            catch (Exception ex)
            {
                DebuggerUtils.HandleExceptionSilently(ex);
            }

            foreach (MDbgFrame f in frames)
            {
                try
                {
                    string frame = GetFrameString(f, withArgs).Trim();
                    if (string.IsNullOrWhiteSpace(frame))
                        frame = "[Missing frame]";

                    if (originFirst)
                        sample.CallStack.Insert(0, frame);
                    else
                        sample.CallStack.Add(frame);
                }
                catch (Exception ex)
                {
                    DebuggerUtils.HandleExceptionSilently(ex);
                }
            }

            return sample;
        }
Пример #18
0
 public IEnumerable<MDbgFrame> EnumerateFrames(MDbgThread thread)
 {
     IMDbgFrameFactory factory;
     if (thread.CorThread.IsV3)
     {
         factory = new MDbgV3FrameFactory();
         return factory.EnumerateFrames(thread);
     }
     else
     {
         factory = new MDbgV2FrameFactory();
         return factory.EnumerateFrames(thread);
     }
 }
Пример #19
0
 internal void SetActiveThread(CorThread thread)
 {
     if (thread == null)
     {
         m_active = null;
     }
     else
     {
         m_active = GetThreadFromThreadId(thread.Id);
     }
     lock (this.m_process)
     {
         m_frameFactory.InvalidateStackWalkers(); // @TODO can this line be removed???
     }
 }
Пример #20
0
        /// <summary>
        /// Unwind unmanaged frames within an native chain.
        /// </summary>
        /// <param name="thread">thread containing an unmanged frame</param>
        /// <param name="context">context containing the current context of the stack frame</param>
        /// <param name="endValue">address of the next managed frame</param>
        /// <returns>enumeration of MDbgFrames for the native frames</returns>
        /// <remarks>ICorDebug stackwalking only unwinds managed chains. 
        /// A derived class can override this function to provide native stacktracing.</remarks>
        protected virtual IEnumerable<MDbgFrame> UnwindNativeFrames(MDbgThread thread, INativeContext context, long endValue)
        {
            // Base class can't unwind unmanaged chains. 
            // A derived class can override and provide native stack unwinding.
            // Use:
            // 1) chain.RegisterSet to get the starting context.
            // 2) chain.GetStackRange(out start, out end);   to get the stackrange to unwind to
            // 3) a native unwinder (such as DbgHelp.dll) to actually do the native stack unwinding.

            yield break;
        }
Пример #21
0
 /// <summary>
 /// Creates a frame cache for the given thread
 /// </summary>
 /// <param name="frames">Enumeration of frames</param>
 /// <param name="thread">Thread associated the the stack walker</param>
 public FrameCache(IEnumerable<MDbgFrame> frames, MDbgThread thread)
 {
     m_frameEnum = frames.GetEnumerator();
     m_thread = thread;
 }
Пример #22
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;
            }
        }
Пример #23
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;
        }
Пример #24
0
        private static ExceptionInfo GetExceptionInfo(MDbgThread activeThread, MDbgValue ex)
        {
            ExceptionInfo exinfo = new ExceptionInfo();
            exinfo.ExType = ex.TypeName;
            exinfo.Function = (ex.GetField("_exceptionMethodString").IsNull ? null : ex.GetField("_exceptionMethodString").ToString());
            exinfo.Message = (ex.GetField("_message").IsNull ? null : ex.GetField("_message").GetStringValue(false));
            exinfo.Source = (ex.GetField("_source").IsNull ? null : ex.GetField("_source").ToString());

            //StringBuilder sbCallstack = new StringBuilder();
            //try
            //{
            //    if (activeThread != null)
            //        activeThread.Frames.ToList().ForEach(f => sbCallstack.AppendLine(f.ToString()));
            //}
            //catch (Exception ex1)
            //{
            //    DebuggerUtils.HandleExceptionSilently(ex1);
            //}
            exinfo.Callstack = DebuggerUtils.GetThreadStacks(activeThread, true).ToString();
            return exinfo;
        }
Пример #25
0
 /// <summary>
 /// Creates a new stack walker object.
 /// </summary>
 /// <param name="factory">FrameFactory owning this walker</param>
 /// <param name="thread">Thread associated with the stackwalker</param>
 public MDbgV2StackWalker(MDbgFrameFactoryBase factory, MDbgThread thread)
     : base(factory, thread)
 {
 }
Пример #26
0
        private static string GetStringFromException(MDbgThread activeThread, MDbgValue ex)
        {
            ExceptionInfo exinfo = GetExceptionInfo(activeThread, ex);

            StringBuilder retVal = new StringBuilder();
            string exceptionType = exinfo.ExType;
            if (!string.IsNullOrWhiteSpace(exinfo.Function))
            {
                retVal.AppendLine("at function: " + exinfo.Function);
            }

            if (!string.IsNullOrWhiteSpace(exinfo.Message))
            {
                retVal.AppendLine("Message: " + exinfo.Message);
            }

            if (!string.IsNullOrWhiteSpace(exinfo.Source))
            {
                retVal.AppendLine("in source file: " + exinfo.Source);
            }

            if (!string.IsNullOrWhiteSpace(exinfo.Callstack))
            {
                retVal.AppendLine("Callstack: " + exinfo.Callstack);
            }

            return retVal.ToString();
        }
Пример #27
0
            public void SetThreadNickName(string nickName, MDbgThread thread)
            {
                Debug.Assert(thread != null);
                if (thread == null) throw new ArgumentException();
                {
                    NickNamesHash.Remove(GetNickNameFromThreadNumber(thread.Number)); // remove old nick-name, if any
                }
                if (nickName == null || nickName.Length == 0)
                {
                    return; // we just want to remove nickname
                }

                if (IsNumber(nickName))
                {
                    throw new MDbgShellException("invalid nickname");
                }

                if (NickNamesHash.ContainsKey(nickName))
                {
                    throw new MDbgShellException("nickname already exists");
                }
                NickNamesHash.Add(nickName, Debugger.Processes.Active.Threads.Active.Number);
            }
Пример #28
0
        private string PrintObject(int indentLevel, CorObjectValue ov, int expandDepth, bool canDoFunceval)
        {
            Debug.Assert(expandDepth >= 0);

            bool fNeedToResumeThreads = true;

            // Print generics-aware type.
            string name = InternalUtil.PrintCorType(this.m_process, ov.ExactType);

            StringBuilder txt = new StringBuilder();

            txt.Append(name);

            if (expandDepth > 0)
            {
                // we gather the field info of the class before we do
                // funceval since funceval requires running the debugger process
                // and this in turn can cause GC and invalidate our references.
                StringBuilder expandedDescription = new StringBuilder();
                if (IsComplexType)
                {
                    foreach (MDbgValue v in GetFields())
                    {
                        expandedDescription.Append("\n").Append(IndentedString(indentLevel + 1, v.Name)).
                        Append("=").Append(IndentedBlock(indentLevel + 2,
                                                         v.GetStringValue(expandDepth - 1, false)));
                    }
                }

                // if the value we're printing is a nullable type that has no value (is null), we can't do a func eval
                // to get its value, since it will be boxed as a null pointer. We already have the information we need, so
                // we'll just take care of it now. Note that ToString() for null-valued nullable types just prints the
                // empty string.

                // bool hasValue = (bool)(GetField("hasValue").CorValue.CastToGenericValue().GetValue());

                if (IsNullableType(ov.ExactType) && !(bool)(GetField("hasValue").CorValue.CastToGenericValue().GetValue()))
                {
                    txt.Append(" < >");
                }

                else if (ov.IsValueClass && canDoFunceval)
                // we could display even values for real Objects, but we will just show
                // "description" for valueclasses.
                {
                    CorClass          cls      = ov.ExactType.Class;
                    CorMetadataImport importer = m_process.Modules.Lookup(cls.Module).Importer;
                    MetadataType      mdType   = importer.GetType(cls.Token) as MetadataType;

                    if (mdType.ReallyIsEnum)
                    {
                        txt.AppendFormat(" <{0}>", InternalGetEnumString(ov, mdType));
                    }
                    else if (m_process.IsRunning)
                    {
                        txt.Append(" <N/A during run>");
                    }
                    else
                    {
                        MDbgThread activeThread = m_process.Threads.Active;

                        CorValue     thisValue;
                        CorHeapValue hv = ov.CastToHeapValue();
                        if (hv != null)
                        {
                            // we need to pass reference value.
                            CorHandleValue handle = hv.CreateHandle(CorDebugHandleType.HANDLE_WEAK_TRACK_RESURRECTION);
                            thisValue = handle;
                        }
                        else
                        {
                            thisValue = ov;
                        }

                        try
                        {
                            CorEval eval = m_process.Threads.Active.CorThread.CreateEval();
                            m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_SUSPEND,
                                                                         activeThread.CorThread);

                            MDbgFunction toStringFunc = m_process.ResolveFunctionName(null, "System.Object", "ToString",
                                                                                      thisValue.ExactType.Class.Module.Assembly.AppDomain)[0];

                            Debug.Assert(toStringFunc != null); // we should be always able to resolve ToString function.

                            eval.CallFunction(toStringFunc.CorFunction, new CorValue[] { thisValue });
                            m_process.Go();
                            do
                            {
                                m_process.StopEvent.WaitOne();
                                if (m_process.StopReason is EvalCompleteStopReason)
                                {
                                    CorValue cv = eval.Result;
                                    Debug.Assert(cv != null);
                                    MDbgValue mv      = new MDbgValue(m_process, cv);
                                    string    valName = mv.GetStringValue(0);

                                    // just purely for esthetical reasons we 'discard' "
                                    if (valName.StartsWith("\"") && valName.EndsWith("\""))
                                    {
                                        valName = valName.Substring(1, valName.Length - 2);
                                    }

                                    txt.Append(" <").Append(valName).Append(">");
                                    break;
                                }
                                if ((m_process.StopReason is ProcessExitedStopReason) ||
                                    (m_process.StopReason is EvalExceptionStopReason))
                                {
                                    txt.Append(" <N/A cannot evaluate>");
                                    break;
                                }
                                // hitting bp or whatever should not matter -- we need to ignore it
                                m_process.Go();
                            }while (true);
                        }
                        catch (COMException e)
                        {
                            // Ignore cannot copy a VC class error - Can't copy a VC with object refs in it.
                            if (e.ErrorCode != (int)HResult.CORDBG_E_OBJECT_IS_NOT_COPYABLE_VALUE_CLASS)
                            {
                                throw;
                            }
                        }
                        catch (System.NotImplementedException)
                        {
                            fNeedToResumeThreads = false;
                        }
                        finally
                        {
                            if (fNeedToResumeThreads)
                            {
                                // we need to resume all the threads that we have suspended no matter what.
                                m_process.CorProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_RUN,
                                                                             activeThread.CorThread);
                            }
                        }
                    }
                }
                txt.Append(expandedDescription.ToString());
            }
            return(txt.ToString());
        }
Пример #29
0
        // Helper to set the debug state and ignore certain errors. 
        // Throws on error.
        static void SetDebugStateWrapper(MDbgThread t, CorDebugThreadState newState, bool showWarnings)
        {
            if ((newState == CorDebugThreadState.THREAD_SUSPEND) &&
                ((t.CorThread.UserState & CorDebugUserState.USER_UNSAFE_POINT) != 0))
            {
                // Hard-suspending a thread while the thread is not at GC-safe point is bad.
                // If the users resumes a process and the GC triggers, the GC suspension logic
                // will not be able to suspend because it will wait forever on the thread that
                // is not at the GC safe point.  However, in this scenario, a debugger can always 
                // async-break and resume the suspended thread to avoid a live lock.  So we just
                // issue a warning here.
                if (showWarnings)
                {
                    WriteOutput("Warning: You are suspending Thread " + t.Number + " at an unsafe spot.");
                    WriteOutput("Until you resume this thread, the process may block if a garbage collection occurs.");
                    WriteOutput("To unblock the process, you need to asynchronously break the process (e.g. Ctrl-C) and resume the thread.");
                }
            }

            try
            {
                t.CorThread.DebugState = newState;
            }
            catch (System.Runtime.InteropServices.COMException e)
            {
                if (e.ErrorCode == (int)HResult.CORDBG_E_BAD_THREAD_STATE) // CORDBG_E_BAD_THREAD_STATE
                {
                    if (showWarnings)
                    {
                        WriteOutput(MDbgOutputConstants.Ignore, "Warning: Thread " + t.Number + " can't be set to " + newState);
                    }
                    return;   // thread is unavailable, ignore it
                }
                throw; // let error propogate up.
            }
        }
Пример #30
0
 /// <summary>
 /// Create a new instance of the ThreadCreatedStopReason class.
 /// </summary>
 /// <param name="thread">The thread that has been created.</param>
 public ThreadCreatedStopReason(MDbgThread thread)
 {
     Debug.Assert(thread != null);
     m_thread = thread;
 }
Пример #31
0
 IEnumerator IEnumerable.GetEnumerator()
 {
     MDbgThread[] ret = new MDbgThread[m_items.Count];
     m_items.Values.CopyTo(ret, 0);
     Array.Sort(ret);
     return ret.GetEnumerator();
 }
Пример #32
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);
        }
Пример #33
0
 internal void SetActiveThread(CorThread thread)
 {
     if (thread == null)
     {
         m_active = null;
     }
     else
     {
         m_active = GetThreadFromThreadId(thread.Id);
     }
     InvalidateAllStacks();
 }
Пример #34
0
 internal MDbgILFrame(MDbgThread thread, CorFrame frame)
     : base(thread)
 {
     Debug.Assert(frame != null);
     m_frame = frame;
 }
Пример #35
0
 /// <summary>
 /// Creates an instance of class MDbgFramebase.
 /// </summary>
 /// <param name="thread"></param>
 protected MDbgFrameBase(MDbgThread thread)
 {
     Debug.Assert(thread != null);
     m_thread = thread;
 }
Пример #36
0
 /// <summary>
 /// Creates a new V2 StackWalker.
 /// </summary>
 /// <param name="thread">a thread object associated with the stackwalker</param>
 /// <returns>object implementing MDbgStackWalker interface</returns>
 override public IMDbgStackWalker CreateStackWalker(MDbgThread thread)
 {
     return(new MDbgV2StackWalker(this, thread));
 }
Пример #37
0
 /// <summary>
 /// Creates a new stack walker object.
 /// </summary>
 /// <param name="factory">FrameFactory owning this walker</param>
 /// <param name="thread">Thread associated with the stackwalker</param>
 public MDbgV2StackWalker(MDbgFrameFactoryBase factory, MDbgThread thread)
     : base(factory, thread)
 {
 }
Пример #38
0
 /// <summary>
 /// Create a new instance of the ThreadCreatedStopReason class.
 /// </summary>
 /// <param name="thread">The thread that has been created.</param>
 public ThreadCreatedStopReason(MDbgThread thread)
 {
     Debug.Assert(thread != null);
     m_thread = thread;
 }
Пример #39
0
 /// <summary>
 /// Creates an instance of class MDbgFramebase.
 /// </summary>
 /// <param name="thread"></param>
 protected MDbgFrameBase(MDbgThread thread)
 {
     Debug.Assert(thread != null);
     m_thread = thread;
 }
Пример #40
0
        /// <summary>
        /// Creates a new V2 StackWalker.
        /// </summary>
        /// <param name="thread">a thread object associated with the stackwalker</param>
        /// <returns>object implementing MDbgStackWalker interface</returns>
        public IEnumerable<MDbgFrame> EnumerateFrames(MDbgThread thread)
        {
            // To do stackwalking using V2 ICorDebug, we enumerate through the chains, 
            // and then enumerate each frame in every chain

            CorChain chain = null;
            try
            {
                chain = thread.CorThread.ActiveChain;
            }
            catch (System.Runtime.InteropServices.COMException ce)
            {
                // Sometimes we cannot get the callstack.  For example, the thread
                // may not be scheduled yet (CORDBG_E_THREAD_NOT_SCHEDULED),
                // or the debuggee 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);
            }

            while (chain != null)
            {
                if (chain.IsManaged)
                {
                    // Enumerate managed frames
                    // A chain may have 0 managed frames.
                    CorFrame f = chain.ActiveFrame;
                    while (f != null)
                    {
                        MDbgFrame frame = new MDbgILFrame(thread, f);
                        f = f.Caller;
                        yield return frame;
                    }
                }
                else
                {
                    // ICorDebug doesn't unwind unmanaged frames. Need to let a native-debug component handle that.
                    foreach (MDbgFrame frame in UnwindNativeFrames(thread, chain))
                    {
                        yield return frame;
                    }
                }

                // Move to next chain
                chain = chain.Caller;
            }

        }
Пример #41
0
        /// <summary>
        /// Gets an array of strings containing information about each level of the call stack.
        /// </summary>
        /// <param name="thread">The thread to get the call stack from</param>
        /// <returns>An array of strings containing information about each level of the call stack.</returns>
        private string[] GetStackTrace(MDbgThread thread)
        {
            List<string> stackTrace = new List<string>();

            MDbgFrame af = thread.HaveCurrentFrame ? thread.CurrentFrame : null;
            MDbgFrame f = thread.BottomFrame;
            int i = 0;
            while (f != null)
            {
                if (f.IsInfoOnly)
                {
                    f = f.NextUp;
                    continue;
                }

                string functionName = f.Function.FullName;
                int sourceLine = -1;
                if (f.SourcePosition != null)
                    sourceLine = f.SourcePosition.Line;
                string line
                    = string.Format(CultureInfo.InvariantCulture,
                    "{0}{1}. {2}:{3}",
                        f.Equals(af) ? "*" : " ",
                        i,
                        functionName,
                        sourceLine == -1 ? "" : sourceLine.ToString()
                    );
                stackTrace.Add(line);
                f = f.NextUp;
                ++i;
            }

            return stackTrace.ToArray();
        }
Пример #42
0
 /// <summary>
 /// Creates a stack walker and associates the walker with the frame factory and a thread.
 /// </summary>
 /// <param name="factory">FrameFactory that created the stackwalker</param>
 /// <param name="thread">Thread associated the the stack walker</param>
 protected MDbgStackWalkerBase(MDbgFrameFactoryBase factory, MDbgThread thread)
 {
     m_thread           = thread;
     m_factory          = factory;
     m_logicalStopClock = factory.m_logicalStopClock;
 }
Пример #43
0
        public static ThreadSnapshot GetThreadSnapshot(MDbgThread thread)
        {
            var snapshot = new ThreadSnapshot();

            snapshot.Id = thread.Id;

            long creation, exit, kernel, user;
            GetThreadTimes(thread.CorThread.Handle, out creation, out exit, out kernel, out user);

            snapshot.KernelTime = kernel;
            snapshot.UserTime = user;
            snapshot.StackTrace = new List<string>();

            foreach (MDbgFrame frame in thread.Frames) {
                try {
                    snapshot.StackTrace.Add(frame.Function.FullName);
                } catch {
                    // no frame, so ignore
                }
            }

            return snapshot;
        }
Пример #44
0
 /// <summary>
 /// Creates a new StackWalker.
 /// </summary>
 /// <param name="thread">a thread object associated with the stackwalker</param>
 /// <returns>object implementing MDbgStackWalker interface</returns>
 public abstract IMDbgStackWalker CreateStackWalker(MDbgThread thread);
Пример #45
0
 /// <summary>
 /// Creates a frame cache for the given thread
 /// </summary>
 /// <param name="frames">Enumeration of frames</param>
 /// <param name="thread">Thread associated the the stack walker</param>
 public FrameCache(IEnumerable <MDbgFrame> frames, MDbgThread thread)
 {
     m_frameEnum = frames.GetEnumerator();
     m_thread    = thread;
 }
Пример #46
0
 /// <summary>
 /// Creates a new V2 StackWalker.
 /// </summary>
 /// <param name="thread">a thread object associated with the stackwalker</param>
 /// <returns>object implementing MDbgStackWalker interface</returns>
 public override IMDbgStackWalker CreateStackWalker(MDbgThread thread)
 {
     return new MDbgV2StackWalker(this, thread);
 }