Example #1
0
        internal static bool GetStaticField(ClrHeap heap, ClrType type, GetMemberBinder binder, out object result)
        {
            result = null;
            bool           success = false;
            ClrStaticField field   = null;

            StringComparison compare = binder.IgnoreCase ? StringComparison.CurrentCultureIgnoreCase : StringComparison.CurrentCulture;

            foreach (var inst in type.StaticFields)
            {
                if (inst.Name.Equals(binder.Name, compare))
                {
                    field = inst;
                    break;
                }
            }

            if (field != null)
            {
                result  = new StaticVariableValueWrapper(heap, field);
                success = true;
            }

            return(success);
        }
        public static ClrObject GetStaticFldValue(this ClrRuntime runtime, [NotNull] ClrType clrType,
                                                  [NotNull] string fieldName)
        {
            Assert.ArgumentNotNull(clrType, "typeName");
            Assert.ArgumentNotNullOrEmpty(fieldName, "fieldName");

            ClrStaticField fld = clrType.GetStaticFieldByName(fieldName);

            if (fld == null)
            {
                throw new MissingFieldException(clrType.Name, fieldName);
            }

            var domains = runtime.AppDomains.ToArray();

            if ((domains == null) || (domains.Length == 0))
            {
                throw new ArgumentException("No domains are found inside runtime!");
            }

            ulong?resultAddress = (from domain in domains
                                   where !string.IsNullOrWhiteSpace(domain.Name)
                                   where !domain.Name.Contains("Default") && fld.IsInitialized(domain)
                                   select(ulong?) fld.GetValue(domain)).FirstOrDefault();

            return(resultAddress.HasValue ? (new ClrObject(resultAddress.Value, clrType.Heap))
        : ClrObject.NullObject);
        }
Example #3
0
        public void AsEnumTest()
        {
            using DataTarget dt      = TestTargets.Types.LoadFullDump();
            using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();

            ClrModule typesModule = runtime.GetModule(ModuleName);
            ClrType   type        = typesModule.GetTypeByName("Types");

            ClrStaticField field = type.GetStaticFieldByName("s_enum");

            Assert.True(field.Type.IsEnum);

            ClrEnum clrEnum = field.Type.AsEnum();

            Assert.NotNull(clrEnum);

            string[] propertyNames = clrEnum.GetEnumNames().ToArray();
            Assert.NotEmpty(propertyNames);
            Assert.Contains(nameof(FileAccess.Read), propertyNames);
            Assert.Contains(nameof(FileAccess.Write), propertyNames);
            Assert.Contains(nameof(FileAccess.ReadWrite), propertyNames);

            Assert.Equal(ClrElementType.Int32, clrEnum.ElementType);

            Assert.Equal(FileAccess.Read, clrEnum.GetEnumValue <FileAccess>(nameof(FileAccess.Read)));
            Assert.Equal(FileAccess.Write, clrEnum.GetEnumValue <FileAccess>(nameof(FileAccess.Write)));
            Assert.Equal(FileAccess.ReadWrite, clrEnum.GetEnumValue <FileAccess>(nameof(FileAccess.ReadWrite)));
        }
Example #4
0
        public void IntegerObjectClrType()
        {
            using DataTarget dt      = TestTargets.Types.LoadFullDump();
            using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();
            ClrHeap      heap   = runtime.Heap;
            ClrAppDomain domain = runtime.AppDomains.Single();

            ClrModule      module    = runtime.GetModule(ModuleName);
            ClrType        typesType = module.GetTypeByName("Types");
            ClrStaticField field     = typesType.GetStaticFieldByName("s_i");

            ClrObject obj = field.ReadObject(domain);

            Assert.False(obj.IsNull);

            ClrType type = obj.Type;

            Assert.NotNull(type);

            Assert.True(type.IsPrimitive);
            Assert.False(type.IsObjectReference);
            Assert.True(type.IsValueType);

            var fds = obj.Type.Fields;

            Assert.True(obj.IsBoxedValue);
            int value = obj.ReadBoxedValue <int>();

            Assert.Equal(42, value);

            Assert.Contains(obj.Address, heap.EnumerateObjects().Select(a => a.Address));
        }
Example #5
0
        public static ClrObject GetStaticObjectValue(this ClrType mainType, string fieldName)
        {
            ClrStaticField field = mainType.GetStaticFieldByName(fieldName);
            ulong          obj   = (ulong)field.GetValue(field.Type.Heap.Runtime.AppDomains.Single());

            return(new ClrObject(obj, mainType.Heap.GetObjectType(obj)));
        }
Example #6
0
        private int GetClrTypeStaticField(Tuple <int, string> input)
        {
            int            clrTypeId      = input.Item1;
            string         fieldName      = input.Item2;
            ClrType        clrType        = clrTypesCache[clrTypeId];
            ClrStaticField clrStaticField = clrType.GetStaticFieldByName(fieldName);

            return(GetClrTypeId(clrStaticField?.Type));
        }
        public StaticField(ClrRuntime runtime, string typee, string name)
        {
            Domain = runtime.AppDomains.First();
            ClrHeap heap = runtime.GetHeap();
            ClrType type = heap.GetTypeByName(typee);

            Field = type.GetStaticFieldByName(name);
            Heap  = runtime.GetHeap();
        }
Example #8
0
        private ulong GetClrStaticFieldAddress(Tuple <int, string, int> input)
        {
            int            clrTypeId      = input.Item1;
            string         fieldName      = input.Item2;
            int            clrAppDomainId = input.Item3;
            ClrType        clrType        = clrTypesCache[clrTypeId];
            ClrStaticField clrStaticField = clrType.GetStaticFieldByName(fieldName);
            ClrAppDomain   clrAppDomain   = clrType.Module.Runtime.AppDomains.First(ad => ad.Id == clrAppDomainId);

            return(clrStaticField.GetAddress(clrAppDomain));
        }
Example #9
0
 public NetFrameworkClrDriver(ClrRuntime runtime) : base(runtime)
 {
     typeTimerQueue      = heap.GetTypeByName("System.Threading.TimerQueue");
     fieldSQueue         = typeTimerQueue.GetStaticFieldByName("s_queue");
     fieldTimers         = typeTimerQueue.GetFieldByName("m_timers");
     typeTimerQueueTimer = heap.GetTypeByName("System.Threading.TimerQueueTimer");
     fieldNext           = typeTimerQueueTimer.GetFieldByName("m_next");
     fieldState          = typeTimerQueueTimer.GetFieldByName("m_state");
     typeMoveNextRunner  = heap.GetTypeByName("System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner");
     fieldStateMachine   = typeMoveNextRunner.GetFieldByName("m_stateMachine");
 }
 /// <summary>
 ///     Initializes a new instance of the <see cref="ClrStaticFieldAdapter" /> class.
 /// </summary>
 /// <param name="converter">Converter to use</param>
 /// <param name="staticField">The static field.</param>
 /// <exception cref="ArgumentNullException">staticField</exception>
 /// <inheritdoc />
 public ClrStaticFieldAdapter(IConverter converter, ClrStaticField staticField) : base(converter)
 {
     StaticField       = staticField ?? throw new ArgumentNullException(nameof(staticField));
     HasDefaultValue   = StaticField.HasDefaultValue;
     HasSimpleValue    = StaticField.HasSimpleValue;
     IsInternal        = StaticField.IsInternal;
     IsObjectReference = StaticField.IsObjectReference;
     IsPrimitive       = StaticField.IsPrimitive;
     IsPrivate         = StaticField.IsPrivate;
     IsProtected       = StaticField.IsProtected;
     IsPublic          = StaticField.IsPublic;
     IsValueClass      = StaticField.IsValueClass;
     Name   = StaticField.Name;
     Offset = StaticField.Offset;
     Size   = StaticField.Size;
     Token  = StaticField.Token;
 }
Example #11
0
        public void StringEmptyIsObtainableTest()
        {
            using DataTarget dt      = TestTargets.Types.LoadFullDump();
            using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();
            ClrHeap heap = runtime.Heap;

            ClrType stringType = heap.StringType;

            Assert.NotNull(stringType);

            ClrStaticField empty = stringType.GetStaticFieldByName("Empty");

            Assert.NotNull(empty);

            string value = empty.ReadString(runtime.AppDomains.Single());

            Assert.Equal(string.Empty, value);
        }
Example #12
0
        private IEnumerable <ThreadPoolItem> EnumerateLocalThreadPoolItemsInNetFramework(ClrModule mscorlib)
        {
            // look into the local stealing queues in each thread TLS
            // hopefully, they are all stored in static (one per app domain) instance
            // of ThreadPoolWorkQueue.SparseArray<ThreadPoolWorkQueue.WorkStealingQueue>
            //
            var queueType = mscorlib.GetTypeByName("System.Threading.ThreadPoolWorkQueue");

            if (queueType == null)
            {
                yield break;
            }

            ClrStaticField threadQueuesField = queueType.GetStaticFieldByName("allThreadQueues");

            if (threadQueuesField == null)
            {
                yield break;
            }

            foreach (ClrAppDomain domain in _clr.AppDomains)
            {
                var threadQueue = threadQueuesField.ReadObject(domain);
                if (!threadQueue.IsValid)
                {
                    continue;
                }

                var sparseArray = threadQueue.ReadObjectField("m_array").AsArray();
                for (int current = 0; current < sparseArray.Length; current++)
                {
                    var stealingQueue = sparseArray.GetObjectValue(current);
                    if (!stealingQueue.IsValid)
                    {
                        continue;
                    }

                    foreach (var item in EnumerateThreadPoolStealingQueue(stealingQueue))
                    {
                        yield return(item);
                    }
                }
            }
        }
Example #13
0
        // The ThreadPool is keeping track of the pending work items into two different areas:
        // - a global queue: stored by ThreadPoolWorkQueue instances of the ThreadPoolGlobals.workQueue static field
        // - several per thread (TLS) local queues: stored in SparseArray<ThreadPoolWorkQueue+WorkStealingQueue> linked from ThreadPoolWorkQueue.allThreadQueues static fields
        // both are using arrays of Task or QueueUserWorkItemCallback
        //
        // NOTE: don't show other thread pool related topics such as timer callbacks or wait objects
        //
        private IEnumerable <ThreadPoolItem> EnumerateGlobalThreadPoolItemsInNetFramework(ClrModule mscorlib)
        {
            ClrType queueType = mscorlib.GetTypeByName("System.Threading.ThreadPoolGlobals");

            if (queueType == null)
            {
                yield break;
            }

            ClrStaticField workQueueField = queueType.GetStaticFieldByName("workQueue");

            if (workQueueField == null)
            {
                yield break;
            }

            // the CLR keeps one static instance per application domain
            foreach (var appDomain in _clr.AppDomains)
            {
                var workQueue = workQueueField.ReadObject(appDomain);
                if (!workQueue.IsValid)
                {
                    continue;
                }

                // should be  System.Threading.ThreadPoolWorkQueue
                var workQueueType = workQueue.Type;
                if (workQueueType == null)
                {
                    continue;
                }
                if (string.CompareOrdinal(workQueueType.Name, "System.Threading.ThreadPoolWorkQueue") != 0)
                {
                    continue;
                }

                foreach (var item in EnumerateThreadPoolWorkQueue(workQueue))
                {
                    yield return(item);
                }
            }
        }
Example #14
0
        public void ComponentTypeEventuallyFilledTest()
        {
            // https://github.com/microsoft/clrmd/issues/108
            // Ensure that a previously created type with a erronous null ComponentType eventually
            // gets its ComponentType set.

            using DataTarget dt      = TestTargets.Types.LoadFullDump();
            using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();

            ClrType        fooType = runtime.GetModule(ModuleName).GetTypeByName("Types");
            ClrStaticField cq      = fooType.GetStaticFieldByName("s_cq");

            Assert.NotNull(cq);

            ClrInstanceField m_head         = cq.Type.GetFieldByName("m_head");
            ClrInstanceField m_array        = m_head.Type.GetFieldByName("m_array");
            bool             hasSimpleValue = m_array.HasSimpleValue;
            ClrElementType   elementType    = m_array.ElementType;
            ClrType          componentType  = m_array.Type.ComponentType;

            // If this assert fails, remove the test.  This value is null because currently CLR's
            // debugging layer doesn't tell us the component type of an array.  If we eventually
            // fix that issue, we would return a non-null m_array.Type.ComponentType, causing
            // this test to fail but the underlying issue would be fixed.
            Assert.Null(componentType);

            ClrObject m_arrayObj = cq.ReadObject().GetObjectField("m_head").GetObjectField("m_array");

            // Ensure we are looking at the same ClrType
            if (dt.CacheOptions.CacheTypes)
            {
                Assert.Same(m_array.Type, m_arrayObj.Type);
            }
            else
            {
                Assert.Equal(m_array.Type, m_arrayObj.Type);
            }

            // Assert that we eventually filled in ComponentType after we got a real object for the type
            Assert.NotNull(m_arrayObj.Type.ComponentType);
        }
Example #15
0
        public CacheFieldInfo(ClrStaticField Field, int FieldIndex)
        {
            IsStatic       = true;
            IsThreadStatic = false;

            TypeName       = GetFieldTypeName(Field.Type);
            Name           = AdjustFieldName(Field.Name);
            MethodTable    = HeapStatItem.GetMTOfType(Field.Type);
            Offset         = Field.Offset;
            Token          = Field.Type == null ? 0 : Field.Type.MetadataToken;
            Module         = Field.Type == null || Field.Type.Module == null ? 0 : Field.Type.Module.ImageBase;
            Assembly       = Field.Type == null || Field.Type.Module == null ? 0 : Field.Type.Module.AssemblyId;
            BackField      = Field;
            Size           = Field.Size;
            CorElementType = (int)Field.ElementType;
            IsArray        = Field.Type == null ? false : Field.Type.IsArray;
            IsValueType    = Field.Type == null ? false : Field.Type.IsValueClass || Field.Type.IsPrimitive;
            IsGeneric      = Field.Type == null ? true : Field.Type.Name.Contains('<') && Field.Type.Name.Contains('>') && Field.Type.Name[0] != '<';
            Index          = FieldIndex;
            IsEnum         = Field.Type == null ? false : Field.Type.IsEnum;
            IsString       = Field.Type == null ? false : Field.Type.IsString;
        }
Example #16
0
        public IEnumerable <ObjectInfo> EnumerateManagedWorkItems()
        {
            ClrStaticField workQueueField = ClrMdUtils.GetCorlib(runtime).GetTypeByName("System.Threading.ThreadPoolGlobals")?.GetStaticFieldByName("workQueue");

            if (workQueueField != null)
            {
                object workQueueValue = workQueueField.GetValue(domain);
                ulong  workQueueRef   = (workQueueValue == null) ? 0L : (ulong)workQueueValue;
                if (workQueueRef != 0)
                {
                    ClrType workQueueType = heap.GetObjectType(workQueueRef);                   // should be System.Threading.ThreadPoolWorkQueue
                    if (workQueueType?.Name == "System.Threading.ThreadPoolWorkQueue")
                    {
                        foreach (var item in EnumerateThreadPoolWorkQueue(workQueueRef))
                        {
                            yield return(new ObjectInfo {
                                Address = item, Type = heap.GetObjectType(item)
                            });
                        }
                    }
                }
            }
        }
Example #17
0
        public void IntegerObjectClrType()
        {
            using (DataTarget dt = TestTargets.Types.LoadFullDump())
            {
                ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();
                ClrHeap    heap    = runtime.Heap;

                ClrStaticField field = runtime.GetModule("types.exe").GetTypeByName("Types").GetStaticFieldByName("s_i");

                ulong   addr = (ulong)field.GetValue(runtime.AppDomains.Single());
                ClrType type = heap.GetObjectType(addr);
                Assert.True(type.IsPrimitive);
                Assert.False(type.IsObjectReference);
                Assert.False(type.IsValueClass);

                object value = type.GetValue(addr);
                Assert.Equal("42", value.ToString());
                Assert.IsType <int>(value);
                Assert.Equal(42, (int)value);

                Assert.Contains(addr, heap.EnumerateObjectAddresses());
            }
        }
Example #18
0
        public void TestStaticFieldModifiers()
        {
            using DataTarget dt      = TestTargets.NestedTypes.LoadFullDump();
            using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();

            ClrModule module  = runtime.GetModule(TypeTests.NestedTypesModuleName);
            ClrType   program = module.GetTypeByName("Program");

            ClrStaticField publicField = program.GetStaticFieldByName("s_publicField");

            Assert.True(publicField.IsPublic);

            ClrStaticField privateField = program.GetStaticFieldByName("s_privateField");

            Assert.True(privateField.IsPrivate);

            ClrStaticField internalField = program.GetStaticFieldByName("s_internalField");

            Assert.True(internalField.IsInternal);

            ClrStaticField protectedField = program.GetStaticFieldByName("s_protectedField");

            Assert.True(protectedField.IsProtected);
        }
Example #19
0
 public MDStaticField(ClrStaticField field)
 {
     m_field = field;
 }
Example #20
0
 public StaticVariableValueWrapper(ClrHeap heap, ClrStaticField field)
 {
     m_heap  = heap;
     m_field = field;
 }
Example #21
0
        public IEnumerable <TimerInfo> EnumerateTimers()
        {
            // the implementation is different between .NET Framework/.NET Core 2.*, and .NET Core 3.0+
            // - the former is relying on a single static TimerQueue.s_queue
            // - the latter uses an array of TimerQueue (static TimerQueue.Instances field)
            // each queue refers to TimerQueueTimer linked list via its m_timers or _shortTimers/_longTimers fields
            var timerQueueType = GetMscorlib().GetTypeByName("System.Threading.TimerQueue");

            if (timerQueueType == null)
            {
                yield break;
            }

            // .NET Core case
            ClrStaticField instancesField = timerQueueType.GetStaticFieldByName("<Instances>k__BackingField");

            if (instancesField != null)
            {
                // until the ClrMD bug to get static field value is fixed, iterate on each object of the heap
                // to find each TimerQueue and iterate on (slower but it works)
                foreach (var obj in _heap.EnumerateObjects())
                {
                    var objType = obj.Type;
                    if (objType == null)
                    {
                        continue;
                    }
                    if (objType == _heap.FreeType)
                    {
                        continue;
                    }
                    if (string.Compare(objType.Name, "System.Threading.TimerQueue", StringComparison.Ordinal) != 0)
                    {
                        continue;
                    }

                    // m_timers is the start of the linked list of TimerQueueTimer in pre 3.0
                    var timersField = objType.GetFieldByName("m_timers");
                    if (timersField != null)
                    {
                        var currentTimerQueueTimer = obj.ReadObjectField("m_timers");
                        foreach (var timer in GetTimers(currentTimerQueueTimer, false))
                        {
                            yield return(timer);
                        }
                    }
                    else
                    {
                        // get short timers
                        timersField = objType.GetFieldByName("_shortTimers");
                        if (timersField == null)
                        {
                            throw new InvalidOperationException("Missing _shortTimers field. Check the .NET Core version implementation of TimerQueue.");
                        }

                        var currentTimerQueueTimer = obj.ReadObjectField("_shortTimers");
                        foreach (var timer in GetTimers(currentTimerQueueTimer, true))
                        {
                            timer.IsShort = true;
                            yield return(timer);
                        }

                        // get long timers
                        currentTimerQueueTimer = obj.ReadObjectField("_longTimers");
                        foreach (var timer in GetTimers(currentTimerQueueTimer, true))
                        {
                            timer.IsShort = false;
                            yield return(timer);
                        }
                    }
                }
            }
            else
            {
                // .NET Framework implementation
                var instanceField = timerQueueType.GetStaticFieldByName("s_queue");
                if (instanceField == null)
                {
                    yield break;
                }

                foreach (var domain in _clr.AppDomains)
                {
                    var timerQueue = instanceField.ReadObject(domain);
                    if ((timerQueue.IsNull) || (!timerQueue.IsValid))
                    {
                        continue;
                    }

                    // m_timers is the start of the list of TimerQueueTimer
                    var currentTimerQueueTimer = timerQueue.ReadObjectField("m_timers");
                    foreach (var timer in GetTimers(currentTimerQueueTimer, false))
                    {
                        yield return(timer);
                    }
                }
            }
        }
Example #22
0
        private IEnumerable <ulong> EnumerateManagedThreadpoolObjects()
        {
            _heap = _runtime.GetHeap();

            ClrModule mscorlib = GetMscorlib();

            if (mscorlib != null)
            {
                ClrType queueType = mscorlib.GetTypeByName("System.Threading.ThreadPoolGlobals");
                if (queueType != null)
                {
                    ClrStaticField workQueueField = queueType.GetStaticFieldByName("workQueue");
                    if (workQueueField != null)
                    {
                        foreach (var appDomain in _runtime.AppDomains)
                        {
                            object  workQueueValue = workQueueField.GetValue(appDomain);
                            ulong   workQueue      = workQueueValue == null ? 0L : (ulong)workQueueValue;
                            ClrType workQueueType  = _heap.GetObjectType(workQueue);

                            if (workQueue == 0 || workQueueType == null)
                            {
                                continue;
                            }

                            ulong   queueHead;
                            ClrType queueHeadType;
                            do
                            {
                                if (!GetFieldObject(workQueueType, workQueue, "queueHead", out queueHeadType, out queueHead))
                                {
                                    break;
                                }

                                ulong   nodes;
                                ClrType nodesType;
                                if (GetFieldObject(queueHeadType, queueHead, "nodes", out nodesType, out nodes) && nodesType.IsArray)
                                {
                                    int len = nodesType.GetArrayLength(nodes);
                                    for (int i = 0; i < len; ++i)
                                    {
                                        ulong addr = (ulong)nodesType.GetArrayElementValue(nodes, i);
                                        if (addr != 0)
                                        {
                                            yield return(addr);
                                        }
                                    }
                                }

                                if (!GetFieldObject(queueHeadType, queueHead, "Next", out queueHeadType, out queueHead))
                                {
                                    break;
                                }
                            } while (queueHead != 0);
                        }
                    }
                }


                queueType = mscorlib.GetTypeByName("System.Threading.ThreadPoolWorkQueue");
                if (queueType != null)
                {
                    ClrStaticField threadQueuesField = queueType.GetStaticFieldByName("allThreadQueues");
                    if (threadQueuesField != null)
                    {
                        foreach (ClrAppDomain domain in _runtime.AppDomains)
                        {
                            ulong?threadQueue = (ulong?)threadQueuesField.GetValue(domain);
                            if (!threadQueue.HasValue || threadQueue.Value == 0)
                            {
                                continue;
                            }

                            ClrType threadQueueType = _heap.GetObjectType(threadQueue.Value);
                            if (threadQueueType == null)
                            {
                                continue;
                            }

                            ulong   outerArray     = 0;
                            ClrType outerArrayType = null;
                            if (!GetFieldObject(threadQueueType, threadQueue.Value, "m_array", out outerArrayType, out outerArray) || !outerArrayType.IsArray)
                            {
                                continue;
                            }

                            int outerLen = outerArrayType.GetArrayLength(outerArray);
                            for (int i = 0; i < outerLen; ++i)
                            {
                                ulong entry = (ulong)outerArrayType.GetArrayElementValue(outerArray, i);
                                if (entry == 0)
                                {
                                    continue;
                                }

                                ClrType entryType = _heap.GetObjectType(entry);
                                if (entryType == null)
                                {
                                    continue;
                                }

                                ulong   array;
                                ClrType arrayType;
                                if (!GetFieldObject(entryType, entry, "m_array", out arrayType, out array) || !arrayType.IsArray)
                                {
                                    continue;
                                }

                                int len = arrayType.GetArrayLength(array);
                                for (int j = 0; j < len; ++j)
                                {
                                    ulong addr = (ulong)arrayType.GetArrayElementValue(array, i);
                                    if (addr != 0)
                                    {
                                        yield return(addr);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Example #23
0
        public static ClrObject GetStaticObjectValue(this ClrType mainType, string fieldName)
        {
            ClrStaticField field = mainType.GetStaticFieldByName(fieldName);

            return(field.ReadObject());
        }
Example #24
0
        public IEnumerable <TimerInfo> EnumerateTimers()
        {
            // the implementation is different between .NET Framework/.NET Core 2.0 and .NET Core 2.1+
            // - the former is relying on a single static TimerQueue.s_queue
            // - the latter uses an array of TimerQueue (static TimerQueue.Instances field)
            // each queue refers to TimerQueueTimer linked list via its m_timers field
            //
            var timerQueueType = GetMscorlib().GetTypeByName("System.Threading.TimerQueue");

            if (timerQueueType == null)
            {
                yield break;
            }

            // .NET Core 2.1+ case
            ClrStaticField instancesField = timerQueueType.GetStaticFieldByName("<Instances>k__BackingField");

            if (instancesField != null)
            {
                // until the ClrMD bug to get static field value is fixed, iterate on each object of the heap
                // to find each TimerQueue and iterate on (slower but it works)
                foreach (var obj in _heap.EnumerateObjects())
                {
                    var objType = obj.Type;
                    if (objType == null)
                    {
                        continue;
                    }
                    if (objType == _heap.FreeType)
                    {
                        continue;
                    }
                    if (string.Compare(objType.Name, "System.Threading.TimerQueue", StringComparison.Ordinal) != 0)
                    {
                        continue;
                    }

                    // m_timers is the start of the linked list of TimerQueueTimer
                    var currentTimerQueueTimer = obj.ReadObjectField("m_timers");

                    // iterate on each TimerQueueTimer in the linked list
                    while (currentTimerQueueTimer.Address != 0)
                    {
                        var ti = GetTimerInfo(currentTimerQueueTimer);

                        if (ti == null)
                        {
                            continue;
                        }

                        yield return(ti);

                        currentTimerQueueTimer = currentTimerQueueTimer.ReadObjectField("m_next");
                    }
                }
            }
            else
            {
                // .NET Framework implementation
                var instanceField = timerQueueType.GetStaticFieldByName("s_queue");
                if (instanceField == null)
                {
                    yield break;
                }

                foreach (var domain in _clr.AppDomains)
                {
                    var timerQueue = instanceField.ReadObject(domain);
                    if ((timerQueue.IsNull) || (!timerQueue.IsValid))
                    {
                        continue;
                    }

                    // m_timers is the start of the list of TimerQueueTimer
                    var currentTimerQueueTimer = timerQueue.ReadObjectField("m_timers");

                    while (currentTimerQueueTimer.IsValid)
                    {
                        var ti = GetTimerInfo(currentTimerQueueTimer);
                        if (ti == null)
                        {
                            continue;
                        }

                        yield return(ti);

                        currentTimerQueueTimer = currentTimerQueueTimer.ReadObjectField("m_next");
                    }
                }
            }
        }
Example #25
0
        public void RunDone()
        {
            _workItems     = new Dictionary <string, WorkInfo>();
            _workItemCount = 0;
            _tasks         = new Dictionary <string, WorkInfo>();
            _taskCount     = 0;

            ClrMDHelper helper = new ClrMDHelper(_host.Session.Clr);

            // The ThreadPool is keeping track of the pending work items into two different areas:
            // - a global queue: stored by ThreadPoolWorkQueue instances of the ThreadPoolGlobals.workQueue static field
            // - several per thread (TLS) local queues: stored in SparseArray<ThreadPoolWorkQueue+WorkStealingQueue> linked from ThreadPoolWorkQueue.allThreadQueues static fields
            // both are using arrays of Task or QueueUserWorkItemCallback
            //
            // NOTE: don't show other thread pool related topics such as timer callbacks or wait objects
            //
            try
            {
                var heap = _host.Session.Clr.Heap;
                var clr  = _host.Session.Clr;

                _host.WriteLine("global work item queue________________________________");
                // look for the ThreadPoolGlobals.workQueue static field
                ClrModule mscorlib = helper.GetMscorlib();
                if (mscorlib == null)
                {
                    return;
                }

                ClrType queueType = mscorlib.GetTypeByName("System.Threading.ThreadPoolGlobals");
                if (queueType == null)
                {
                    return;
                }

                ClrStaticField workQueueField = queueType.GetStaticFieldByName("workQueue");
                if (workQueueField == null)
                {
                    return;
                }

                // the CLR keeps one static instance per application domain
                foreach (var appDomain in clr.AppDomains)
                {
                    object workQueueValue = workQueueField.GetValue(appDomain);
                    ulong  workQueueRef   = (workQueueValue == null) ? 0L : (ulong)workQueueValue;
                    if (workQueueRef == 0)
                    {
                        continue;
                    }

                    // should be  System.Threading.ThreadPoolWorkQueue
                    ClrType workQueueType = heap.GetObjectType(workQueueRef);
                    if (workQueueType == null)
                    {
                        continue;
                    }
                    if (workQueueType.Name != "System.Threading.ThreadPoolWorkQueue")
                    {
                        continue;
                    }

                    if (!DumpThreadPoolWorkQueue(workQueueType, workQueueRef))
                    {
                        _host.WriteLine("Impossible to dump thread pool work queue @ 0x" + workQueueRef.ToString("X"));
                    }
                }



                // look into the local stealing queues in each thread TLS
                // hopefully, they are all stored in static (one per app domain) instance
                // of ThreadPoolWorkQueue.SparseArray<ThreadPoolWorkQueue.WorkStealingQueue>
                //
                _host.WriteLine("\r\nlocal per thread work items_____________________________________");
                try
                {
                    queueType = mscorlib.GetTypeByName("System.Threading.ThreadPoolWorkQueue");
                    if (queueType == null)
                    {
                        return;
                    }

                    ClrStaticField threadQueuesField = queueType.GetStaticFieldByName("allThreadQueues");
                    if (threadQueuesField == null)
                    {
                        return;
                    }

                    foreach (ClrAppDomain domain in clr.AppDomains)
                    {
                        ulong?threadQueue = (ulong?)threadQueuesField.GetValue(domain);
                        if (!threadQueue.HasValue || threadQueue.Value == 0)
                        {
                            continue;
                        }

                        ClrType threadQueueType = heap.GetObjectType(threadQueue.Value);
                        if (threadQueueType == null)
                        {
                            continue;
                        }

                        var sparseArrayRef = _host.Session.GetFieldValue(threadQueue.Value, "m_array");
                        _host.Session.ForEach((ulong)sparseArrayRef, stealingQueue =>
                        {
                            if (stealingQueue != 0)
                            {
                                var arrayRef = _host.Session.GetFieldValue(stealingQueue, "m_array");
                                DumpThreadPoolWorkItems((ulong)arrayRef);
                            }
                        });
                    }
                }
                finally
                {
                    // provide a summary sorted by count
                    // tasks first if any
                    if (_tasks.Values.Count > 0)
                    {
                        foreach (var item in _tasks.Values.OrderBy(wi => wi.Count))
                        {
                            _host.WriteLine(string.Format(" {0,4} Task  {1}", item.Count.ToString(), item.Name));
                        }
                        _host.WriteLine(" ----");
                        _host.WriteLine(string.Format(" {0,4}\r\n", _taskCount.ToString()));
                    }

                    // then QueueUserWorkItem next if any
                    if (_workItems.Values.Count > 0)
                    {
                        foreach (var item in _workItems.Values.OrderBy(wi => wi.Count))
                        {
                            _host.WriteLine(string.Format(" {0,4} Work  {1}", item.Count.ToString(), item.Name));
                        }
                        _host.WriteLine(" ----");
                        _host.WriteLine(string.Format(" {0,4}\r\n", _workItemCount.ToString()));
                    }

                    var threadPool = _host.Session.Clr.ThreadPool;
                    _host.WriteLine(string.Format(
                                        "\r\nCPU = {0}% for {1} threads (#idle = {2} + #running = {3} | #dead = {4} | #max = {5})",
                                        threadPool.CpuUtilization.ToString(),
                                        threadPool.TotalThreads.ToString(),
                                        threadPool.IdleThreads.ToString(),
                                        threadPool.RunningThreads.ToString(),
                                        _host.Session.Clr.Threads.Count(t => t.IsThreadpoolWorker && !t.IsThreadpoolCompletionPort && !t.IsAlive && !t.IsThreadpoolGate && !t.IsThreadpoolTimer && !t.IsThreadpoolWait).ToString(),
                                        threadPool.MaxThreads.ToString()
                                        ));

                    // show the running worker threads
                    DumpRunningThreadpoolThreads(helper);
                }
            }
            catch (Exception x)
            {
                _host.WriteLine(x.Message);
            }
        }
Example #26
0
        private static IEnumerable <TimerInfo> EnumerateTimers(ClrRuntime clr)
        {
            var timerQueueType = Utils.GetMscorlib(clr).GetTypeByName("System.Threading.TimerQueue");

            if (timerQueueType == null)
            {
                yield break;
            }

            ClrStaticField instanceField = timerQueueType.GetStaticFieldByName("s_queue");

            if (instanceField == null)
            {
                yield break;
            }

            var heap = clr.Heap;

            foreach (ClrAppDomain domain in clr.AppDomains)
            {
                ulong?timerQueue = (ulong?)instanceField.GetValue(domain);
                if (!timerQueue.HasValue || timerQueue.Value == 0)
                {
                    continue;
                }

                ClrType t = heap.GetObjectType(timerQueue.Value);
                if (t == null)
                {
                    continue;
                }

                // m_timers is the start of the list of TimerQueueTimer
                var currentPointer = Utils.GetFieldValue(heap, timerQueue.Value, "m_timers");

                while ((currentPointer != null) && (((ulong)currentPointer) != 0))
                {
                    // currentPointer points to a TimerQueueTimer instance
                    ulong currentTimerQueueTimerRef = (ulong)currentPointer;

                    TimerInfo ti = new TimerInfo()
                    {
                        TimerQueueTimerAddress = currentTimerQueueTimerRef
                    };

                    var val = Utils.GetFieldValue(heap, currentTimerQueueTimerRef, "m_dueTime");
                    ti.DueTime       = (uint)val;
                    val              = Utils.GetFieldValue(heap, currentTimerQueueTimerRef, "m_period");
                    ti.Period        = (uint)val;
                    val              = Utils.GetFieldValue(heap, currentTimerQueueTimerRef, "m_canceled");
                    ti.Cancelled     = (bool)val;
                    val              = Utils.GetFieldValue(heap, currentTimerQueueTimerRef, "m_state");
                    ti.StateTypeName = "";
                    if (val == null)
                    {
                        ti.StateAddress = 0;
                    }
                    else
                    {
                        ti.StateAddress = (ulong)val;
                        var stateType = heap.GetObjectType(ti.StateAddress);
                        if (stateType != null)
                        {
                            ti.StateTypeName = stateType.Name;
                        }
                    }

                    // decypher the callback details
                    val = Utils.GetFieldValue(heap, currentTimerQueueTimerRef, "m_timerCallback");
                    if (val != null)
                    {
                        ulong elementAddress = (ulong)val;
                        if (elementAddress == 0)
                        {
                            continue;
                        }

                        var elementType = heap.GetObjectType(elementAddress);
                        if (elementType != null)
                        {
                            if (elementType.Name == "System.Threading.TimerCallback")
                            {
                                ti.MethodName = Utils.BuildTimerCallbackMethodName(clr, heap, elementAddress);
                            }
                            else
                            {
                                ti.MethodName = "<" + elementType.Name + ">";
                            }
                        }
                        else
                        {
                            ti.MethodName = "{no callback type?}";
                        }
                    }
                    else
                    {
                        ti.MethodName = "???";
                    }

                    yield return(ti);

                    currentPointer = Utils.GetFieldValue(heap, currentTimerQueueTimerRef, "m_next");
                }
            }
        }