/// <summary>
        /// Enumerates objects that are either located in thread stack (f.e. structures), or mentioned there by pointer (reference types).
        /// </summary>
        /// <param name="thread">A thread to have stack inspected.</param>
        /// <returns>A stream of non-duplicated objects that match criterias.</returns>
        public virtual IEnumerable <ClrObject> Enumerate(ClrThread thread)
        {
            if (thread == null)
            {
                yield break;
            }

            var clrRoots  = thread.EnumerateStackObjects(this.IncludePossiblyDead);
            var processed = new HashSet <ulong>();

            var heap = thread.Runtime.GetHeap();

            foreach (var root in clrRoots)
            {
                var clrObject = new ClrObject(root.Object, heap);

                if (processed.Contains(clrObject.Address))
                {
                    continue;
                }

                if (this.ShouldSkip(clrObject, thread))
                {
                    continue;
                }

                if (processed.Add(clrObject.Address))
                {
                    yield return(clrObject);
                }
            }
        }
예제 #2
0
        public static List <StackFrameInfo> GetDetailedStackTrace(this ClrThread thread)
        {
            List <StackFrameInfo> stackframes = new List <StackFrameInfo>();

            List <ClrRoot> stackObjects = thread.EnumerateStackObjects().ToList();

            ulong lastAddress = 0;

            foreach (ClrStackFrame frame in thread.StackTrace)
            {
                ClrStackFrame     f = frame;
                List <ClrDynamic> objectsInFrame = stackObjects
                                                   .Where(o => o.Address > lastAddress && o.Address <= f.StackPointer)
                                                   .OrderBy(o => o.Address)
                                                   .Select(o => ClrMDSession.Current.Heap.GetDynamicObject(o.Object))
                                                   .ToList();

                stackframes.Add(new StackFrameInfo
                {
                    Function = f.DisplayString,
                    Objects  = objectsInFrame
                });

                lastAddress = f.StackPointer;
            }

            return(stackframes);
        }
예제 #3
0
        private string GetFrameInformation(ClrThread thread, ClrStackFrame frame, ClrStackFrame firstFrame)
        {
            // get the method call from the given frame
            string info           = "";
            var    sourceLocation = frame.GetFileAndLineNumber();

            if (sourceLocation == null)
            {
                info = frame.DisplayString;
            }
            else  // it seems that GetFileAndLineNumber() does not work --> need to figure out what is the other ClrMD API to dig into the symbols
            {
                info = frame.DisplayString + "[" + sourceLocation.FilePath + ", Line " + sourceLocation.LineNumber.ToString() + "]";
            }

            // look for locking information
            if (firstFrame.Method.Name.Contains("Wait") || (firstFrame.Method.Name == "Enter") && (firstFrame.Method.Type.Name == "System.Threading.Monitor"))
            {
                // special case for MonitorEnter --> not a WaitHandle to wait on
                bool isMonitorEnter = (firstFrame.Method.Name == "Enter") && (firstFrame.Method.Type.Name == "System.Threading.Monitor");

                info = info + "\r\n                             => " + firstFrame.Method.Type.Name + "." + firstFrame.Method.Name;

                // look for object used as lock
                int maxStackObjects = 10;
                foreach (var so in thread.EnumerateStackObjects(true))
                {
                    if (so == null)
                    {
                        continue;
                    }

                    var type = so.Type;
                    if (so.Type == null)
                    {
                        continue;
                    }

                    string typeName = so.Type.Name;
                    if (typeName.Contains("WaitHandle") || isMonitorEnter)
                    {
                        info = info + string.Format("({0} = 0x{1:X16})\r\n", typeName, so.Object);
                        break;
                    }
                    else
                    {
                    }

                    maxStackObjects--;
                    if (maxStackObjects == 0)
                    {
                        break;
                    }
                }
            }

            return(info);
        }
예제 #4
0
        public void NullValueOkTest()
        {
            ClrThread  clrThread = Thread.Current.FindClrThread();
            StackFrame frame     = clrThread.ClrStackTrace.Frames.Where(f => f.FunctionNameWithoutModule.StartsWith("Program.Main(")).Single();
            Variable   fooObject = frame.Locals["containsnullref"];

            Assert.AreEqual(42, (int)fooObject.GetField("SetValue").GetField("i"));
            Assert.IsTrue(fooObject.GetField("NullValue").IsNullPointer());
            Assert.IsTrue(clrThread.EnumerateStackObjects().Contains(fooObject));
        }
예제 #5
0
        public void PrimitiveVariableConversionTest()
        {
            ClrThread  clrThread = Thread.Current.FindClrThread();
            StackFrame frame;

            foreach (var f in clrThread.ClrStackTrace.Frames)
            {
                foreach (var variable in f.Locals)
                {
                    System.Console.WriteLine(" {2} = ({0}) {1:X}", variable.GetCodeType(), variable.GetPointerAddress(), variable.GetName());
                }
            }

            foreach (Variable variable in clrThread.EnumerateStackObjects())
            {
                System.Console.WriteLine("   ({0}) {1:X}", variable.GetCodeType(), variable.GetPointerAddress());
            }

            frame = clrThread.ClrStackTrace.Frames.Where(f => f.FunctionNameWithoutModule.StartsWith("Program.Inner(")).Single();
            Assert.IsTrue((bool)frame.Locals["b"]);
            Assert.AreEqual('c', (char)frame.Locals["c"]);
            Assert.AreEqual("hello world", new ClrString(frame.Locals["s"]).Text);
            Assert.AreEqual(42, (int)frame.Locals["st"].GetField("i"));
            Assert.IsTrue(clrThread.EnumerateStackObjects().Contains(frame.Locals["s"]));

            frame = clrThread.ClrStackTrace.Frames.Where(f => f.FunctionNameWithoutModule.StartsWith("Program.Middle(")).Single();
            Assert.AreEqual(0x42, (byte)frame.Locals["b"]);
            Assert.AreEqual(0x43, (sbyte)frame.Locals["sb"]);
            Assert.AreEqual(0x4242, (short)frame.Locals["sh"]);
            Assert.AreEqual(0x4243, (ushort)frame.Locals["ush"]);
            Assert.AreEqual(0x42424242, (int)frame.Locals["i"]);
            Assert.AreEqual(0x42424243u, (uint)frame.Locals["ui"]);

            frame = clrThread.ClrStackTrace.Frames.Where(f => f.FunctionNameWithoutModule.StartsWith("Program.Outer(")).Single();
            Assert.AreEqual(42.0f, (float)frame.Locals["f"]);
            Assert.AreEqual(43.0, (double)frame.Locals["d"]);
            Assert.AreEqual((ulong)0x42424242, (ulong)frame.Locals["ptr"]);
            Assert.AreEqual((ulong)0x43434343, (ulong)frame.Locals["uptr"]);
        }
예제 #6
0
        private IEnumerable <Tuple <ulong, int> > EnumerateClrThreadStackObjects(ClrThread clrThread)
        {
            foreach (ClrRoot root in clrThread.EnumerateStackObjects())
            {
                if (root.Type.IsFree || root.Type.Module == null)
                {
                    continue;
                }

                int   clrTypeId = GetClrTypeId(root.Type);
                ulong address   = root.Address;

                yield return(Tuple.Create(address, clrTypeId));
            }
        }
예제 #7
0
        private string GetFrameInformation(ClrThread thread, ClrStackFrame frame, ClrStackFrame firstFrame)
        {
            // get the method call from the given frame
            string info = frame.DisplayString;

            // look for locking information
            if (firstFrame.Method.Name.Contains("Wait") || (firstFrame.Method.Name == "Enter") && (firstFrame.Method.Type.Name == "System.Threading.Monitor"))
            {
                // special case for MonitorEnter --> not a WaitHandle to wait on
                bool isMonitorEnter = (firstFrame.Method.Name == "Enter") && (firstFrame.Method.Type.Name == "System.Threading.Monitor");

                info = info + "\r\n                             => " + firstFrame.Method.Type.Name + "." + firstFrame.Method.Name;

                // look for object used as lock
                int maxStackObjects = 10;
                foreach (var so in thread.EnumerateStackObjects(true))
                {
                    if (so == null)
                    {
                        continue;
                    }

                    var type = so.Type;
                    if (so.Type == null)
                    {
                        continue;
                    }

                    string typeName = so.Type.Name;
                    if (typeName.Contains("WaitHandle") || isMonitorEnter)
                    {
                        info = info + string.Format("({0} = 0x{1:X16})\r\n", typeName, so.Object);
                        break;
                    }
                    else
                    {
                    }

                    maxStackObjects--;
                    if (maxStackObjects == 0)
                    {
                        break;
                    }
                }
            }

            return(info);
        }
예제 #8
0
        /// <summary>
        /// Enumerates the GC references (objects) on the stack.
        /// </summary>
        public IEnumerable <Variable> EnumerateStackObjects()
        {
            CLR.ClrMdProvider provider = ((ClrMdRuntime)Runtime).Provider;

            foreach (Microsoft.Diagnostics.Runtime.ClrRoot root in ClrThread.EnumerateStackObjects())
            {
                if (root.Type.IsFree || root.Type.Module == null)
                {
                    continue;
                }

                Variable field = Variable.CreateNoCast(Process.FromClrType(provider.FromClrType(root.Type)), root.Address);

                yield return(Variable.UpcastClrVariable(field));
            }
        }
예제 #9
0
        public void ObjectFieldTest()
        {
            ClrThread  clrThread = Thread.Current.FindClrThread();
            StackFrame frame     = clrThread.ClrStackTrace.Frames.Where(f => f.FunctionNameWithoutModule.StartsWith("Program.Main(")).Single();
            Variable   foo       = frame.Locals["foo"];

            Assert.IsTrue(clrThread.EnumerateStackObjects().Contains(foo));
            Assert.AreEqual(42, (int)foo.GetField("i"));
            Assert.AreEqual(0x42u, (uint)foo.GetField("ui"));
            Assert.AreEqual("string", new ClrString(foo.GetField("s")).Text);
            Assert.AreEqual(true, (bool)foo.GetField("b"));
            Assert.AreEqual(4.2f, (float)foo.GetField("f"));
            Assert.AreEqual(8.4, (double)foo.GetField("d"));
            Assert.AreEqual('c', (char)foo.GetField("c"));
            Assert.AreEqual(0x12, (byte)foo.GetField("by"));
            Assert.AreEqual((sbyte)0x13, (sbyte)foo.GetField("sby"));
            Assert.AreEqual((short)0x4242, (short)foo.GetField("sh"));
            Assert.AreEqual((ushort)0x4343, (ushort)foo.GetField("ush"));
            Assert.AreEqual(0x424242ul, (ulong)foo.GetField("ulng"));
            Assert.AreEqual(0x434343L, (long)foo.GetField("lng"));
        }
예제 #10
0
 /// <summary>
 ///     Enumerates the GC references (objects) on the stack.  This is equivalent to
 ///     EnumerateStackObjects(true).
 /// </summary>
 /// <returns>An enumeration of GC references on the stack as the GC sees them.</returns>
 /// <inheritdoc />
 public IEnumerable <IClrRoot> EnumerateStackObjects() =>
 Thread.EnumerateStackObjects().Select(Converter.Convert);