Beispiel #1
0
        public void ArrayReferenceEnumeration()
        {
            using (DataTarget dt = TestTargets.Types.LoadFullDump())
            {
                ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();
                ClrHeap    heap    = runtime.Heap;

                ClrAppDomain domain = runtime.AppDomains.Single();

                ClrModule typesModule = runtime.GetModule("types.exe");
                ClrType   type        = heap.GetTypeByName("Types");


                ulong s_array = (ulong)type.GetStaticFieldByName("s_array").GetValue(domain);
                ulong s_one   = (ulong)type.GetStaticFieldByName("s_one").GetValue(domain);
                ulong s_two   = (ulong)type.GetStaticFieldByName("s_two").GetValue(domain);
                ulong s_three = (ulong)type.GetStaticFieldByName("s_three").GetValue(domain);

                ClrType arrayType = heap.GetObjectType(s_array);

                List <ulong> objs = new List <ulong>();
                arrayType.EnumerateRefsOfObject(s_array, (obj, offs) => objs.Add(obj));

                // We do not guarantee the order in which these are enumerated.
                Assert.Equal(3, objs.Count);
                Assert.Contains(s_one, objs);
                Assert.Contains(s_two, objs);
                Assert.Contains(s_three, objs);
            }
        }
Beispiel #2
0
        private static ulong ObjSize(ClrHeap heap, ulong address)
        {
            Stack <ulong> eval = new Stack <ulong>();

            // ObjectSet is memory-efficient HashSet<ulong>
            ObjectSet considered = new ObjectSet(heap);
            ulong     size       = 0;

            eval.Push(address);
            while (eval.Count > 0)
            {
                address = eval.Pop();
                if (considered.Contains(address))
                {
                    continue;
                }
                considered.Add(address);
                ClrType type = heap.GetObjectType(address);
                if (type == null) // Heap-corruption :(
                {
                    continue;
                }
                size += type.GetSize(address);
                type.EnumerateRefsOfObject(address, (child, _) =>
                {
                    if (child != 0 && !considered.Contains(child))
                    {
                        eval.Push(child);
                    }
                });
            }
            return(size);
        }
Beispiel #3
0
        /// <summary>
        /// Taken from https://github.com/Microsoft/dotnetsamples/blob/master/Microsoft.Diagnostics.Runtime/CLRMD/docs/WalkingTheHeap.md
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="count"></param>
        /// <param name="size"></param>
        static protected void GetObjSize(ClrHeap heap, ulong obj, ObjectSet farReachingParents, out uint count, out ulong size)
        {
            // Evaluation stack
            Stack <ulong> eval = new Stack <ulong>();

            // To make sure we don't count the same object twice, we'll keep a set of all objects
            // we've seen before.  Note the ObjectSet here is basically just "HashSet<ulong>".
            // However, HashSet<ulong> is *extremely* memory inefficient.  So we use our own to
            // avoid OOMs.
            ObjectSet considered = new ObjectSet(heap);

            count = 0;
            size  = 0;
            eval.Push(obj);

            while (eval.Count > 0)
            {
                // Pop an object, ignore it if we've seen it before.
                obj = eval.Pop();
                if (farReachingParents.Contains(obj))
                {
                    continue;
                }

                if (considered.Contains(obj))
                {
                    continue;
                }

                considered.Add(obj);

                // Grab the type. We will only get null here in the case of heap corruption.
                ClrType type = heap.GetObjectType(obj);
                if (type == null)
                {
                    continue;
                }

                count++;
                size += type.GetSize(obj);

                // Now enumerate all objects that this object points to, add them to the
                // evaluation stack if we haven't seen them before.
                type.EnumerateRefsOfObject(obj, delegate(ulong child, int offset)
                {
                    if (child != 0 && !considered.Contains(child) && !farReachingParents.Contains(child))
                    {
                        eval.Push(child);
                    }
                });
            }
        }
Beispiel #4
0
        private void StoreData(CancellationToken token)
        {
            BeginUpdate();
            Dictionary <ClrType, ClrTypeStats> stats = new Dictionary <ClrType, ClrTypeStats>();

            foreach (var address in ClrDump.Heap.EnumerateObjectAddresses())
            {
                ClrType type = ClrDump.Heap.GetObjectType(address);
                if (type == null)
                {
                    continue;
                }
                ulong size = type.GetSize(address);

                ClrTypeStats stat;
                if (!stats.TryGetValue(type, out stat))
                {
                    stat        = new ClrTypeStats(stats.Count, type);
                    stats[type] = stat;
                }

                stat.Inc(size);
                InsertInstances(stat.Id, address);

                type.EnumerateRefsOfObject(address, delegate(ulong child, int offset)
                {
                    InsertReferences(child, address);
                });

                n++;
                if (n % 1024 * 64 == 0)
                {
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }
                    ClrDump.MessageBus.Status(GetStats());
                }
            }


            ClrDump.MessageBus.Log(this, "Inserting type stats...");
            foreach (var stat in stats.Values)
            {
                InsertTypeStat(stat);
            }

            EndUpdate();
            ClrDump.MessageBus.Status("Cache Initialized.", StatusType.EndTask);
        }
        /// <summary>
        ///   Gets all object references
        /// </summary>
        /// <param name="currentObjPoi">Objects whose references are checked</param>
        /// <param name="visitedObjects">Already checked objects</param>
        /// <param name="objCountByType">Keeping track of type distribution</param>
        /// <param name="heap"></param>
        private void EnumerateRootReferences(
            ulong currentObjPoi,
            HashSet <ulong> visitedObjects,
            IDictionary <string, HashSet <ulong> > objCountByType,
            ClrHeap heap)
        {
            // Empty pointer is passed or we have already checked the object
            if ((currentObjPoi == 0) || visitedObjects.Contains(currentObjPoi))
            {
                return;
            }

            // Mark that we have processed the node
            visitedObjects.Add(currentObjPoi);

            // Get object type
            ClrType type = heap.GetObjectType(currentObjPoi);

            if (type == null)
            {
                return; // Cannot do anything
            }

            if (objCountByType.ContainsKey(type.Name))
            {
                objCountByType[type.Name].Add(currentObjPoi);
            }
            else
            {
                objCountByType[type.Name] = new HashSet <ulong>
                {
                    currentObjPoi
                };
            }

            type.EnumerateRefsOfObject(currentObjPoi, delegate(ulong arg1, int i)
            {
                if (visitedObjects.Contains(arg1))
                {
                    return;
                }

                this.EnumerateRootReferences(arg1, visitedObjects, objCountByType, heap);
            });
        }
Beispiel #6
0
        public void EnumerateReferences(ulong objRef, out IMDReferenceEnum ppEnum)
        {
            List <MD_Reference> refs = new List <MD_Reference>();

            m_type.EnumerateRefsOfObject(objRef, delegate(ulong child, int offset)
            {
                if (child != 0)
                {
                    MD_Reference r = new MD_Reference();
                    r.address      = child;
                    r.offset       = offset;
                    refs.Add(r);
                }
            });


            ppEnum = new ReferenceEnum(refs);
        }
        private void GetObjSize(ClrHeap heap, ulong obj, out uint count, out ulong size)
        {
            // Evaluation stack
            var eval = new Stack <ulong>();

            // To make sure we don't count the same object twice, we'll keep a set of all objects
            // we've seen before.
            var considered = new HashSet <ulong>();

            count = 0;
            size  = 0;
            eval.Push(obj);

            while (eval.Count > 0)
            {
                // Pop an object, ignore it if we've seen it before.
                obj = eval.Pop();
                if (!considered.Add(obj))
                {
                    continue;
                }

                // Grab the type. We will only get null here in the case of heap corruption.
                ClrType type = heap.GetObjectType(obj);
                if (type == null)
                {
                    continue;
                }

                count++;
                size += type.GetSize(obj);

                // Now enumerate all objects that this object points to, add them to the
                // evaluation stack if we haven't seen them before.
                type.EnumerateRefsOfObject(obj, (child, offset) =>
                {
                    if (child != 0 && !considered.Contains(child))
                    {
                        eval.Push(child);
                    }
                });
            }
        }
        private void GetRefChainFromRootToObject(ulong objPtr, Stack <ulong> refChain, HashSet <ulong> visited)
        {
            _token.ThrowIfCancellationRequested();
            if (_found)
            {
                return;
            }

            var currentObj = refChain.Peek();

            if (!visited.Add(currentObj))
            {
                return;
            }

            if (currentObj == objPtr)
            {
                _found = true;
                return;
            }

            ClrType type = _heap.GetObjectType(currentObj);

            type?.EnumerateRefsOfObject(currentObj, (innerObj, fieldOffset) =>
            {
                if (innerObj == 0 || visited.Contains(innerObj))
                {
                    return;
                }
                refChain.Push(innerObj);
                GetRefChainFromRootToObject(objPtr, refChain, visited);
                if (_found)
                {
                    return;
                }
                refChain.Pop();
            });
        }
Beispiel #9
0
        public override void EnumerateRefsOfObject(ulong objRef, Action <ulong, int> action)
        {
            ClrType realType = DesktopHeap.GetObjectType(objRef);

            realType.EnumerateRefsOfObject(objRef, action);
        }
Beispiel #10
0
 /// <summary>
 ///     EnumeationRefsOfObject will call 'action' once for each object reference inside 'objRef'.
 ///     'action' is passed the address of the outgoing refernece as well as an integer that
 ///     represents the field offset.  While often this is the physical offset of the outgoing
 ///     refernece, abstractly is simply something that can be given to GetFieldForOffset to
 ///     return the field information for that object reference
 /// </summary>
 /// <param name="objRef">The object reference.</param>
 /// <param name="action">The action.</param>
 public void EnumerateRefsOfObject(ulong objRef, Action <ulong, int> action)
 {
     ClrType.EnumerateRefsOfObject(objRef, action);
 }
Beispiel #11
0
        private static (uint, ulong) PopulateReferencedObjects(ClrHeap heap, ClrObjectModel clrObjModel)
        {
            // Evaluation stack
            var eval = new Stack <ulong>();
            var addressToClrObjectModel = new Dictionary <ulong, ClrObjectModel>
            {
                { clrObjModel.Address, clrObjModel }
            };
            // To make sure we don't count the same object twice, we'll keep a set of all objects
            // we've seen before.  Note the ObjectSet here is basically just "HashSet<ulong>".
            // However, HashSet<ulong> is *extremely* memory inefficient.  So we use our own to
            // avoid OOMs.
            var   currentObj = clrObjModel.Address;
            var   considered = new ObjectSet(heap);
            uint  count      = 0;
            ulong size       = 0;

            eval.Push(currentObj);

            while (eval.Count > 0)
            {
                // Pop an object, ignore it if we've seen it before.
                currentObj = eval.Pop();
                if (considered.Contains(currentObj))
                {
                    continue;
                }

                considered.Add(currentObj);

                // Grab the type. We will only get null here in the case of heap corruption.
                ClrType type = heap.GetObjectType(currentObj);
                if (type == null)
                {
                    continue;
                }

                count++;
                size += type.GetSize(currentObj);

                // Now enumerate all objects that this object points to, add them to the
                // evaluation stack if we haven't seen them before.
                type.EnumerateRefsOfObject(currentObj, delegate(ulong child, int offset)
                {
                    if (child != 0 && !considered.Contains(child))
                    {
                        var childObj = heap.GetObject(child);
                        ClrObjectModel childClrModel = null;
                        if (addressToClrObjectModel.ContainsKey(childObj))
                        {
                            childClrModel = addressToClrObjectModel[childObj];
                        }
                        else
                        {
                            childClrModel = new ClrObjectModel
                            {
                                TypeName          = childObj.Type.Name,
                                Address           = childObj,
                                ReferencedObjects = new List <ClrObjectModel>(),
                            };
                            addressToClrObjectModel[currentObj] = childClrModel;
                        }

                        addressToClrObjectModel[currentObj].ReferencedObjects.Add(childClrModel);
                        eval.Push(child);
                    }
                });
            }

            return(count, size);
        }