Example #1
0
        public void VariableRootTest()
        {
            // Test to make sure that a specific static and local variable exist.

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

            IEnumerable <IClrRoot> fooRoots = from root in heap.EnumerateRoots()
                                              where root.Object.Type.Name == "Foo"
                                              select root;

            IClrRoot[] localVarRoots = fooRoots.Where(r => r.RootKind == ClrRootKind.Stack).ToArray();

            ClrThread     thread = runtime.GetMainThread();
            ClrStackFrame main   = thread.GetFrame("Main");
            ClrStackFrame inner  = thread.GetFrame("Inner");

            ulong low  = thread.StackBase;
            ulong high = thread.StackLimit;

            // Account for different platform stack direction.
            if (low > high)
            {
                ulong tmp = low;
                low  = high;
                high = tmp;
            }

            foreach (IClrRoot localVarRoot in localVarRoots)
            {
                Assert.True(low <= localVarRoot.Address && localVarRoot.Address <= high);
            }
        }
Example #2
0
        public bool Build(int chunkSize, string indexFileName, bool enumerateAllRoots)
        {
            if (chunkSize < 256 || chunkSize > 1048576 || chunkSize % 16 != 0)
            {
                _context.WriteErrorLine("Chunk size must be between 256 bytes and 1MB, and must be a multiple of 16.");
                return(false);
            }

            _chunkSize             = chunkSize;
            _staticRootsEnumerated = enumerateAllRoots;
            Measure(() =>
            {
                _allRoots = (from root in _heap.EnumerateRoots(enumerateStatics: enumerateAllRoots)
                             select new SimplifiedRoot(root)).ToList();
            }, "Enumerating roots");

            // Build an index of N-byte chunks in all heap segments. The index is from chunk-id (int?) to
            // the first non-free object in the chunk (not to start of the chunk, which could be in the middle
            // of an object). If a chunk is completely empty or doesn't contain the start of any object, it
            // doesn't have an id.
            Measure(BuildChunks, "Building chunks");

            // Traverse all object relationships on the heap from roots. For each chunk, specify which other
            // chunks contain references to objects in that chunk. When traversing this information, we need to
            // keep in mind that roots can also contain references to objects in the chunk -- we don't store this
            // information again because it's very easy to obtain by enumerating the roots. This decision can be
            // changed if root enumeration turns out to be slow when there are many roots.
            // Note that only live objects are being enumerated. For dead objects, it's not interesting to ask who
            // has a reference to the object -- because the referencing object is also dead.
            Measure(BuildChunkIndex, "Building chunk index");

            DisplayStatistics();

            if (!String.IsNullOrEmpty(indexFileName))
            {
                Measure(() => Save(indexFileName), "Saving index to disk");
            }
            else
            {
                _context.WriteWarningLine("You did not specify a file name, so the index will be stored only in memory. " +
                                          "If you plan to perform further analysis in another session, it is recommended that you store " +
                                          "the index to disk and later load it using the !lhi command.");
            }

            return(true);
        }
Example #3
0
        private void CalculateTypeStatisticsPhase2(ClrHeap heap, Regex typesToReportStatisticsOnRegex, HashSet <ulong> markedObjects, TypeStatistics typeStatistics)
        {
            typeStatistics.MemoryProfilingStopwatch.Start();

            HashSet <ulong>   visitedObjects = new HashSet <ulong>();
            Queue <ClrObject> objectQueue    = new Queue <ClrObject>();

            // Start with exclusive = inclusive and walk the heap from roots looking for objects to subtract from this number.
            typeStatistics.ExclusiveRetainedBytes = typeStatistics.InclusiveRetainedBytes;

            foreach (ClrRoot root in heap.EnumerateRoots())
            {
                // Interested only in roots outside of our marked inclusive graph.
                if (!markedObjects.Contains(root.Object))
                {
                    ClrObject rootObj = heap.GetObject(root.Object);
                    objectQueue.Enqueue(rootObj);
                    visitedObjects.Add(root.Object);

                    while (objectQueue.Count > 0)
                    {
                        ClrObject obj = objectQueue.Dequeue();
                        if (obj.IsNull || obj.Type == null)
                        {
                            continue;
                        }

                        // We stop the walk when we see an object of a type we are reporting statistics on.
                        if (!typesToReportStatisticsOnRegex.IsMatch(obj.Type.Name))
                        {
                            if (markedObjects.Contains(obj.Address))
                            {
                                // Not an object of a type we are reporting statistics on but it is part of the inclusive object graph.
                                // This means that it must not be reported in the exclusive bytes.
                                typeStatistics.ExclusiveRetainedBytes -= obj.Size;
                                markedObjects.Remove(obj.Address);
                            }

                            // Follow all references.
                            foreach (var reference in obj.EnumerateObjectReferences())
                            {
                                if (!reference.IsNull && !visitedObjects.Contains(reference.Address))
                                {
                                    visitedObjects.Add(reference.Address);
                                    objectQueue.Enqueue(reference);
                                }
                            }
                        }
                    }
                }
            }

            typeStatistics.MemoryProfilingStopwatch.Stop();
        }
        private void FindAliveObjects([CanBeNull] ClrHeap heap)
        {
            if (heap == null)
            {
                return;
            }

            foreach (ClrRoot clrRoot in heap.EnumerateRoots())
            {
                this.EnumerateRootReferences(clrRoot.Object, this.AliveObjectAdresses, this.AliveObjectsByType, heap);
            }
        }
Example #5
0
            public IEnumerable <IClrObject> ExploreFromRoots()
            {
                var reader = new ClrObjectReader();

                foreach (var root in heap.EnumerateRoots())
                {
                    if (root.Object == 0)
                    {
                        continue;
                    }
                    if (!visited.Add(root.Object))
                    {
                        continue;
                    }
                    if (root.Kind == GCRootKind.Finalizer)
                    {
                        continue;
                    }
                    if (root.Address == 0)
                    {
                        continue;
                    }
                    if (!reader.IsValidObjectType(root.Type))
                    {
                        continue;
                    }

                    yield return(reader.ReadGCRoot(root));

                    CollectChildren(root.Type, root.Object);
                }

                while (pending.Count > 0)
                {
                    var address = pending.Pop();
                    if (!visited.Add(address))
                    {
                        continue;
                    }
                    var type = heap.GetObjectType(address);
                    if (!reader.IsValidObjectType(type))
                    {
                        continue;
                    }

                    yield return(reader.ReadFromAddress(type, address));

                    CollectChildren(type, address);
                }
            }
Example #6
0
        public void EnumerateMethodTableTest()
        {
            using (DataTarget dt = TestTargets.AppDomains.LoadFullDump())
            {
                ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();
                ClrHeap    heap    = runtime.Heap;

                ulong[] fooObjects = (from obj in heap.EnumerateObjectAddresses()
                                      let t = heap.GetObjectType(obj)
                                              where t.Name == "Foo"
                                              select obj).ToArray();

                // There are exactly two Foo objects in the process, one in each app domain.
                // They will have different method tables.
                Assert.Equal(2, fooObjects.Length);


                ClrType fooType = heap.GetObjectType(fooObjects[0]);
                Assert.NotSame(fooType, heap.GetObjectType(fooObjects[1]));


                ClrRoot appDomainsFoo = (from root in heap.EnumerateRoots(true)
                                         where root.Kind == GCRootKind.StaticVar && root.Type == fooType
                                         select root).Single();

                ulong   nestedExceptionFoo     = fooObjects.Where(obj => obj != appDomainsFoo.Object).Single();
                ClrType nestedExceptionFooType = heap.GetObjectType(nestedExceptionFoo);

                Assert.NotSame(nestedExceptionFooType, appDomainsFoo.Type);

                ulong nestedExceptionFooMethodTable = dt.DataReader.ReadPointerUnsafe(nestedExceptionFoo);
                ulong appDomainsFooMethodTable      = dt.DataReader.ReadPointerUnsafe(appDomainsFoo.Object);

                // These are in different domains and should have different type handles:
                Assert.NotEqual(nestedExceptionFooMethodTable, appDomainsFooMethodTable);

                // The MethodTable returned by ClrType should always be the method table that lives in the "first"
                // AppDomain (in order of ClrAppDomain.Id).
                Assert.Equal(appDomainsFooMethodTable, fooType.MethodTable);

                // Ensure that we enumerate two type handles and that they match the method tables we have above.
                ulong[] methodTableEnumeration = fooType.EnumerateMethodTables().ToArray();
                Assert.Equal(2, methodTableEnumeration.Length);

                // These also need to be enumerated in ClrAppDomain.Id order
                Assert.Equal(appDomainsFooMethodTable, methodTableEnumeration[0]);
                Assert.Equal(nestedExceptionFooMethodTable, methodTableEnumeration[1]);
            }
        }
Example #7
0
        public IEnumerable <DotNetObject> EnumerateObjects()
        {
            var roots   = new List <DotNetObject>();
            var visited = new HashSet <ulong>();

            foreach (var root in heap.EnumerateRoots())
            {
                heap.EnumerateObjectAddresses();
                if (root?.Type == null || root.Name == null)
                {
                    continue;
                }

                var    name = root.Name;
                string prefix;
                if ((prefix = ClrGlobals.ExcludePrefix.FirstOrDefault(p => name.StartsWith(p, StringComparison.InvariantCultureIgnoreCase))) != null)
                {
                    name = name.Substring(prefix.Length);
                }
                if (ClrGlobals.ExcludeRootNamespaces.Any(n => name.StartsWith(n, StringComparison.InvariantCultureIgnoreCase)))
                {
                    continue;
                }

                if (ClrGlobals.ExcludeNames.Any(n => name.StartsWith(n, StringComparison.InvariantCultureIgnoreCase)))
                {
                    continue;
                }

                var dot = name.LastIndexOf('.');
                if (dot != -1)
                {
                    name = name.Substring(dot + 1);
                }

                if (!visited.Add(root.Object))
                {
                    continue;
                }

                var obj = new DotNetObject(root.Object, root.Type, name);
                roots.Add(obj);

                RecursiveEnumerateObjects(visited, obj, obj.Reference, obj.Type);
            }

            return(roots);
        }
Example #8
0
        public static ulong[] GetRootAddresses(ClrHeap heap)
        {
            var roots = heap.EnumerateRoots(true);
            var dct   = new Dictionary <ulong, ulong>();

            foreach (var root in roots)
            {
                ulong rootAddr = root.Address;
                ulong objAddr  = root.Object;
                if (rootAddr != 0Ul)
                {
                    rootAddr = Utils.SetRooted(root.Address);
                    ulong addr;
                    if (dct.TryGetValue(root.Address, out addr))
                    {
                        dct[root.Address] = rootAddr | addr;
                    }
                    else
                    {
                        dct.Add(root.Address, rootAddr);
                    }
                }
                if (objAddr != 0UL)
                {
                    if (root.Kind == GCRootKind.Finalizer)
                    {
                        objAddr = Utils.SetAsFinalizer(root.Object);
                    }
                    objAddr = Utils.SetRooted(objAddr);
                    ulong addr;
                    if (dct.TryGetValue(root.Object, out addr))
                    {
                        dct[root.Object] = addr | objAddr;
                    }
                    else
                    {
                        dct.Add(root.Object, objAddr);
                    }
                }
            }

            var addrAry = dct.Values.ToArray();
            var cmp     = new Utils.AddressCmpAcs();

            Array.Sort(addrAry, cmp);
            return(addrAry);
        }
Example #9
0
        private static List <ClrRoot> FillRootDictionary(ClrHeap heap)
        {
            List <ClrRoot> roots = new List <ClrRoot>(heap.EnumerateRoots());

            foreach (var root in roots)
            {
                List <ClrRoot> list;
                if (!m_rootDict.TryGetValue(root.Object, out list))
                {
                    list = new List <ClrRoot>();
                    m_rootDict[root.Object] = list;
                }

                list.Add(root);
            }
            return(roots);
        }
Example #10
0
        public void VariableRootTest()
        {
            // Test to make sure that a specific static and local variable exist.

            using (DataTarget dt = TestTargets.Types.LoadFullDump())
            {
                ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();
                ClrHeap    heap    = runtime.Heap;
                heap.StackwalkPolicy = ClrRootStackwalkPolicy.Exact;

                var fooRoots = from root in heap.EnumerateRoots()
                               where root.Type.Name == "Foo"
                               select root;

                ClrRoot staticRoot = fooRoots.Where(r => r.Kind == GCRootKind.StaticVar).Single();
                Assert.IsTrue(staticRoot.Name.Contains("s_foo"));

                var     arr          = fooRoots.Where(r => r.Kind == GCRootKind.LocalVar).ToArray();
                ClrRoot localVarRoot = fooRoots.Where(r => r.Kind == GCRootKind.LocalVar).Single();

                ClrThread     thread = runtime.GetMainThread();
                ClrStackFrame main   = thread.GetFrame("Main");
                ClrStackFrame inner  = thread.GetFrame("Inner");

                ulong low  = thread.StackBase;
                ulong high = thread.StackLimit;

                // Account for different platform stack direction.
                if (low > high)
                {
                    ulong tmp = low;
                    low  = high;
                    high = tmp;
                }


                Assert.IsTrue(low <= localVarRoot.Address && localVarRoot.Address <= high);
            }
        }
Example #11
0
        public void Execute(ClrHeap heap)
        {
            //var rootNames = new HashSet<string>();
            //rootNames.Add("Strong handle");
            //rootNames.Add("Pinned handle");
            //rootNames.Add("SizedRef handle");
            //rootNames.Add("AsyncPinned handle");
            //rootNames.Add("RefCount handle");
            //rootNames.Add("finalization handle");
            //rootNames.Add("local var");

            //foreach (var rootName in rootNames)
            //{
            var dict = new Dictionary <string, ulong>();

            foreach (var root in heap.EnumerateRoots())
            {
                //if (root.Name == rootName)
                //{
                if (dict.ContainsKey(root.Name))
                {
                    dict[root.Name]++;
                }
                else
                {
                    dict[root.Name] = 1;
                }
                //}
            }

            //File.WriteAllLines($"{rootName}.txt", dict.Select(pair => pair.ToString()));
            //}

            foreach (var keyValuePair in dict.OrderBy(x => x.Value))
            {
                Console.WriteLine(keyValuePair);
            }
        }
Example #12
0
        /// <summary>
        /// Enumerates all objects reachable from GC roots in the given heap. Each object is returned exactly once.
        /// </summary>
        private IEnumerable <ClrObject> EnumerateRootedObjects(ClrHeap heap)
        {
            HashSet <ulong>   visitedObjects = new HashSet <ulong>();
            Queue <ClrObject> objectQueue    = new Queue <ClrObject>();

            foreach (ClrRoot root in heap.EnumerateRoots())
            {
                if (!visitedObjects.Contains(root.Object))
                {
                    ClrObject rootObj = heap.GetObject(root.Object);
                    objectQueue.Enqueue(rootObj);
                    visitedObjects.Add(root.Object);
                    if (rootObj.Type != null)
                    {
                        yield return(rootObj);
                    }

                    while (objectQueue.Count > 0)
                    {
                        ClrObject obj = objectQueue.Dequeue();
                        if (obj.IsNull || obj.Type == null)
                        {
                            continue;
                        }
                        // Follow all references.
                        foreach (var reference in obj.EnumerateObjectReferences())
                        {
                            if (!reference.IsNull && !visitedObjects.Contains(reference.Address))
                            {
                                objectQueue.Enqueue(reference);
                                visitedObjects.Add(reference.Address);
                                yield return(reference);
                            }
                        }
                    }
                }
            }
        }
Example #13
0
        /// <summary>
        /// See http://stackoverflow.com/questions/35268695/what-is-the-clrmd-equivalent-to-dumpheap-live
        /// </summary>
        /// <param name="heap"></param>
        /// <returns></returns>
        private static ObjectSet GetLiveObjects(ClrHeap heap)
        {
            ObjectSet     considered = new ObjectSet(heap);
            Stack <ulong> eval       = new Stack <ulong>();

            foreach (var root in heap.EnumerateRoots())
            {
                eval.Push(root.Object);
            }

            while (eval.Count > 0)
            {
                ulong obj = eval.Pop();
                if (considered.Contains(obj))
                {
                    continue;
                }

                considered.Add(obj);

                var type = heap.GetObjectType(obj);
                if (type == null)  // Only if heap corruption
                {
                    continue;
                }

                type.EnumerateRefsOfObjectCarefully(obj, delegate(ulong child, int offset)
                {
                    if (child != 0 && !considered.Contains(child))
                    {
                        eval.Push(child);
                    }
                });
            }

            return(considered);
        }
Example #14
0
 /// <summary>
 ///     Enumerate the roots of the process.  (That is, all objects which keep other objects alive.)
 ///     Equivalent to EnumerateRoots(true).
 /// </summary>
 /// <returns>IEnumerable&lt;IClrRoot&gt;.</returns>
 /// <inheritdoc />
 public IEnumerable <IClrRoot> EnumerateRoots() => Heap.EnumerateRoots().Select(Converter.Convert);
Example #15
0
        private static void DumpRetention(DataTarget dataTarget, ClrInfo clrVersion, ClrRuntime runtime, ClrAppDomain appDomain, ClrHeap heap, string targetType)
        {
            var graph = new Graph();

            Console.WriteLine("## What's the retention path of the {0} object?", targetType);
            Console.WriteLine("");
            foreach (var ptr in heap.EnumerateObjectAddresses())
            {
                var type = heap.GetObjectType(ptr);
                if (type == null || type.Name != targetType)
                {
                    continue;
                }

                // Enumerate roots and try to find the current object
                var stack = new Stack <ulong>();
                foreach (var root in heap.EnumerateRoots())
                {
                    stack.Clear();
                    stack.Push(root.Object);
                    if (GetPathToObject(heap, ptr, stack, new HashSet <ulong>()))
                    {
                        // Print retention path
                        var depth           = 0;
                        var previousAddress = (ulong)0;
                        foreach (var address in stack)
                        {
                            var t = heap.GetObjectType(address);
                            if (t == null)
                            {
                                continue;
                            }

                            Console.WriteLine("{0} {1} - {2} - {3} bytes", new string('+', depth++), address, t.Name, t.GetSize(address));

                            graph.AddNode(address.ToString()).LabelText = $"{t.Name} ({address})";
                            if (previousAddress > 0 && !graph.Edges.Any(e => e.Source == previousAddress.ToString() && e.Target == address.ToString()))
                            {
                                graph.AddEdge(previousAddress.ToString(), address.ToString());
                            }
                            previousAddress = address;
                        }

                        Console.WriteLine();
                    }
                }
            }

            Console.ReadLine();

            // Render graph
            var width    = 1600;
            var renderer = new GraphRenderer(graph);

            renderer.CalculateLayout();
            var bitmap = new Bitmap(width, (int)(graph.Height * (width / graph.Width)), PixelFormat.Format32bppRgb);

            renderer.Render(bitmap);
            bitmap.Save("test.png");
            Process.Start("test.png");
        }
Example #16
0
        public HeapIndex(ClrHeap heap)
        {
            // Evaluation stack
            Stack <ulong> eval = new Stack <ulong>();

            _roots            = new ObjectSet(heap);
            _walkableFromRoot = new ObjectSet(heap);

            foreach (var clrRoot in heap.EnumerateRoots())
            {
                _roots.Add(clrRoot.Object);
                eval.Push(clrRoot.Object);
            }

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

                _walkableFromRoot.Add(address);

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

                // Now enumerate all objects that this object points to, add them to the
                // evaluation stack if we haven't seen them before.
                if (type.IsArray)
                {
                    EnumerateArrayElements(address);
                }
                else
                {
                    EnumerateFields(type, address);
                }
            }

            void EnumerateArrayElements(ulong address)
            {
                var obj           = heap.GetObject(address);
                var array         = obj.AsArray();
                var componentType = ((ClrmdArrayType)array.Type).ComponentType;

                if (componentType.IsObjectReference)
                {
                    foreach (var arrayElement in ArrayProxy.EnumerateObjectItems(array))
                    {
                        if (!arrayElement.IsNull)
                        {
                            AddReference(address, arrayElement.Address);
                            eval.Push(arrayElement.Address);
                        }
                    }
                }
                else
                {
                    // throw new NotSupportedException($"Enumerating array of {componentType} type is not supported");
                }
            }

            void EnumerateFields(ClrType?type, ulong address)
            {
                foreach (var instanceField in type.Fields)
                {
                    if (instanceField.IsObjectReference)
                    {
                        var fieldObject = instanceField.ReadObject(address, false);
                        if (!fieldObject.IsNull)
                        {
                            AddReference(address, fieldObject.Address);
                            eval.Push(fieldObject.Address);
                        }
                    }
                }
            }
        }
Example #17
0
 public void EnumerateRoots(out IMDRootEnum ppEnum)
 {
     ppEnum = new MDRootEnum(new List <ClrRoot>(m_heap.EnumerateRoots()));
 }
Example #18
0
        public static ReferenceGraph Build(ClrHeap heap, HashSet <ulong> targetAddresses, CancellationToken token = default)
        {
            var graph = new ReferenceGraph();

            var seen = new ObjectSet(heap);

            var stack = new HeapWalkStack();

            var nodeByAddress = new Dictionary <ulong, ReferenceGraphNode>();

            var chainCache = new Dictionary <(uint metadataToken, int fieldOffset), List <FieldReference> >();

            // For each root
            foreach (var root in heap.EnumerateRoots(enumerateStatics: true))
            {
                stack.Clear();

                if (root.Type == null)
                {
                    // This happens, though not sure why
                    continue;
                }

                stack.Push(new ClrObjectReference(-1, root.Object, root.Type));

                while (!stack.IsEmpty)
                {
                    token.ThrowIfCancellationRequested();

                    ref var top = ref stack.Peek();

                    if (top.Enumerator.MoveNext())
                    {
                        var o = top.Enumerator.Current;

                        if (targetAddresses.Contains(o.Address))
                        {
                            // Found a match
                            stack.Push(o);

                            // Ensure our stack's root is registered with the graph
                            ref var rootLevel = ref stack[0];
                            if (rootLevel.GraphNode == null)
                            {
                                var rootNode = new RootGraphNode(root);
                                nodeByAddress[root.Object] = rootNode;
                                rootLevel.GraphNode        = rootNode;
                                graph.Roots.Add(rootNode);
                            }

                            // Build path through graph for the current stack
                            // Skip the first node as it's always non-null
                            for (var i = 1; i < stack.Count; i++)
                            {
                                ref var level = ref stack[i];

                                // Ensure all levels have a graph node object
                                if (level.GraphNode == null)
                                {
                                    if (!nodeByAddress.TryGetValue(level.Reference.Address, out var node))
                                    {
                                        node = new ReferenceGraphNode(level.Reference.Object);
                                        nodeByAddress[level.Reference.Address] = node;

                                        if (i == stack.Count - 1)
                                        {
                                            graph.TargetSet.Add(node);
                                        }
                                    }

                                    level.GraphNode = node;

                                    ref var levelBefore = ref stack[i - 1];

                                    var referenceChain = GetChain(levelBefore.GraphNode.Object.Type, level.Reference);

                                    level.GraphNode.Referrers.Add((node: levelBefore.GraphNode, referenceChain, fieldOffset: level.Reference.FieldOffset));
//                                    levelBefore.GraphNode.References.Add((node: level.GraphNode, referenceChain));
                                }
                            }

                            stack.Pop();
                        }
Example #19
0
        public static ValueTuple <ulong[], int, int> GetFlaggedRoots(ClrHeap heap, string[] typeNames, StringIdDct strIds, string rootPath, out string error)
        {
            error = null;
            try
            {
                Dictionary <ulong, ulong> dct      = new Dictionary <ulong, ulong>(1024 * 512);
                List <ClrtRoot>[]         ourRoots = new List <ClrtRoot> [(int)GCRootKind.Max + 1];
                for (int i = 0, icnt = (int)GCRootKind.Max + 1; i < icnt; ++i)
                {
                    ourRoots[i] = new List <ClrtRoot>(256);
                }
                var roots = heap.EnumerateRoots(true);
                //ulong savedAddr;
                int finalizerCount = 0;
                int rootCount      = 0;
                foreach (var root in roots)
                {
                    ulong rootAddr        = root.Address;
                    ulong objAddr         = root.Object;
                    ulong flaggedRootAddr = rootAddr;
                    ulong flaggedObjAddr  = objAddr;

                    int    typeId;
                    string typeName;
                    if (root.Type == null)
                    {
                        var clrType = heap.GetObjectType(objAddr);
                        typeName = clrType == null ? Constants.UnknownName : clrType.Name;
                    }
                    else
                    {
                        typeName = root.Type.Name;
                    }

                    typeId = Array.BinarySearch(typeNames, typeName, StringComparer.Ordinal);
                    if (typeId < 0)
                    {
                        typeId = Constants.InvalidIndex;
                    }
                    string rootName = root.Name == null ? Constants.UnknownName : root.Name;

                    var nameId   = strIds.JustGetId(rootName);
                    var clrtRoot = new ClrtRoot(root, typeId, nameId);
                    ourRoots[(int)root.Kind].Add(clrtRoot);

                    switch (root.Kind)
                    {
                    case GCRootKind.Finalizer:
                        ++finalizerCount;
                        if (objAddr != 0UL)
                        {
                            flaggedObjAddr = Utils.SetAsFinalizer(flaggedObjAddr);
                        }
                        if (rootAddr != 0UL)
                        {
                            flaggedRootAddr = Utils.SetAsFinalizer(flaggedRootAddr);
                        }
                        break;

                    case GCRootKind.LocalVar:
                        if (objAddr != 0UL)
                        {
                            flaggedObjAddr = Utils.SetAsLocal(flaggedObjAddr);
                        }
                        if (rootAddr != 0UL)
                        {
                            flaggedRootAddr = Utils.SetAsLocal(flaggedRootAddr);
                        }
                        break;

                    default:
                        ++rootCount;
                        flaggedObjAddr = Utils.SetAsRoot(flaggedObjAddr);
                        if (objAddr != 0UL)
                        {
                            flaggedObjAddr = Utils.SetAsRoot(flaggedObjAddr);
                        }
                        if (rootAddr != 0UL)
                        {
                            flaggedRootAddr = Utils.SetAsRoot(flaggedRootAddr);
                        }
                        break;
                    }
                    SetFlaggedAddress(dct, objAddr, flaggedObjAddr);
                    SetFlaggedAddress(dct, rootAddr, flaggedRootAddr);
                }

                var rootCmp = new ClrtRootObjCmp();
                for (int i = 0, icnt = (int)GCRootKind.Max + 1; i < icnt; ++i)
                {
                    ourRoots[i].Sort(rootCmp);
                }

                Save(rootPath, ourRoots, out error);

                ulong[] rootAddrs = dct.Values.ToArray();
                Utils.SortAddresses(rootAddrs);
                return(rootAddrs, rootCount, finalizerCount);
            }
            catch (Exception ex)
            {
                error = Utils.GetExceptionErrorString(ex);
                return(null, 0, 0);
            }
        }
Example #20
0
        // TODO JRD -- delete later
        public static ClrtRoots GetRoots(ClrHeap heap, ulong[] instances, int[] types, StringIdAsyncDct idDct)
        {
            var rootDct            = new SortedDictionary <ulong, List <ClrtRoot> >();
            var finalizeQue        = new List <ulong>(1024 * 1024);
            var finalizeQueInstIds = new List <int>(1024 * 1024);

            List <ClrRoot>  lstNotFoundObject = new List <ClrRoot>();
            List <ClrtRoot> lstRoots          = new List <ClrtRoot>(1024 * 64);

            foreach (var root in heap.EnumerateRoots())
            {
                var rootObj = root.Object;
                if (root.Kind == GCRootKind.Finalizer)
                {
                    finalizeQue.Add(rootObj);
                    var obj = Array.BinarySearch(instances, rootObj);
                    if (obj < 0)
                    {
                        obj = Constants.InvalidIndex;
                    }
                    finalizeQueInstIds.Add(obj);
                    continue;
                }
                var             rootAddr = root.Address;
                List <ClrtRoot> lst;
                if (rootDct.TryGetValue(rootAddr, out lst))
                {
                    int i     = 0;
                    int icnt  = lst.Count;
                    var rkind = root.Kind;
                    for (; i < icnt; ++i)
                    {
                        if (rootObj == lst[i].Object && rkind == ClrtRoot.GetGCRootKind(lst[i].RootKind))
                        {
                            break;
                        }
                    }
                    if (i == icnt)
                    {
                        var rname   = root.Name ?? Constants.NullName;
                        var rnameId = idDct.JustGetId(rname);
                        var obj     = Array.BinarySearch(instances, rootObj);
                        if (obj < 0)
                        {
                            lstNotFoundObject.Add(root);
                        }
                        var typeId   = obj < 0 ? Constants.InvalidIndex : types[obj];
                        var clrtRoot = new ClrtRoot(root, typeId, rnameId, Constants.InvalidIndex, Constants.InvalidThreadId, Constants.InvalidIndex);
                        lst.Add(clrtRoot);
                        lstRoots.Add(clrtRoot);
                    }
                }
                else
                {
                    var rname   = root.Name ?? Constants.NullName;
                    var rnameId = idDct.JustGetId(rname);
                    var obj     = Array.BinarySearch(instances, rootObj);
                    if (obj < 0)
                    {
                        lstNotFoundObject.Add(root);
                    }
                    var typeId   = obj < 0 ? Constants.InvalidIndex : types[obj];
                    var clrtRoot = new ClrtRoot(root, typeId, rnameId, Constants.InvalidIndex, Constants.InvalidThreadId, Constants.InvalidIndex);
                    rootDct.Add(rootAddr, new List <ClrtRoot>()
                    {
                        clrtRoot
                    });
                    lstRoots.Add(clrtRoot);
                }
            }

            var rootAry = lstRoots.ToArray();

            lstRoots.Clear();
            lstRoots = null;
            ulong[] sortedObjs;
            int[]   kindOffsets;
            int[]   objMap;
            ulong[] sortedAddrs;
            int[]   addrMap;
            SortRoots(rootAry, out kindOffsets, out sortedAddrs, out addrMap, out sortedObjs, out objMap);

            var finQueAry        = finalizeQue.ToArray();
            var finQueInstIdsAry = finalizeQueInstIds.ToArray();

            Array.Sort(finQueAry, finQueInstIdsAry);

            return(new ClrtRoots(rootAry, kindOffsets, sortedAddrs, addrMap, sortedObjs, objMap, finQueAry, finQueInstIdsAry));
        }
Example #21
0
        public static ValueTuple <ulong[], ulong[]> SetupRootAddresses(int rtm, ClrHeap heap, string[] typeNames, StringIdDct strIds, DumpFileMoniker fileMoniker, out string error)
        {
            error = null;
            try
            {
                var roots   = heap.EnumerateRoots(true);
                var objSet  = new HashSet <ulong>(new Utils.AddressEqualityComparer());
                var finlSet = new HashSet <ulong>(new Utils.AddressEqualityComparer());
                List <ClrtRoot>[] ourRoots = new List <ClrtRoot> [(int)GCRootKind.Max + 1];
                for (int i = 0, icnt = (int)GCRootKind.Max + 1; i < icnt; ++i)
                {
                    ourRoots[i] = new List <ClrtRoot>(256);
                }

                foreach (var root in roots)
                {
                    ulong  rootAddr = root.Address;
                    ulong  objAddr  = root.Object;
                    int    typeId;
                    string typeName;
                    if (root.Type == null)
                    {
                        var clrType = heap.GetObjectType(objAddr);
                        typeName = clrType == null ? Constants.UnknownName : clrType.Name;
                    }
                    else
                    {
                        typeName = root.Type.Name;
                    }

                    typeId = Array.BinarySearch(typeNames, typeName, StringComparer.Ordinal);
                    if (typeId < 0)
                    {
                        typeId = Constants.InvalidIndex;
                    }
                    string rootName = root.Name == null ? Constants.UnknownName : root.Name;

                    var nameId   = strIds.JustGetId(rootName);
                    var clrtRoot = new ClrtRoot(root, typeId, nameId);

                    ourRoots[(int)root.Kind].Add(clrtRoot);

                    if (objAddr != 0UL)
                    {
                        if (root.Kind == GCRootKind.Finalizer)
                        {
                            objAddr = Utils.SetAsFinalizer(objAddr);
                            finlSet.Add(objAddr);
                        }
                        else
                        {
                            objAddr = Utils.SetRooted(objAddr);
                            objSet.Add(objAddr);
                        }
                    }
                    if (rootAddr != 0UL)
                    {
                        if (root.Kind == GCRootKind.Finalizer)
                        {
                            rootAddr = Utils.SetAsFinalizer(rootAddr);
                            finlSet.Add(rootAddr);
                        }
                        else
                        {
                            rootAddr = Utils.SetRooted(rootAddr);
                            objSet.Add(rootAddr);
                        }
                    }
                }

                // root infos TODO JRD -- Fix this
                //
                var rootCmp = new ClrtRootObjCmp();
                for (int i = 0, icnt = (int)GCRootKind.Max + 1; i < icnt; ++i)
                {
                    ourRoots[i].Sort(rootCmp);
                }

                // unique addresses
                //
                var addrAry = objSet.ToArray();
                Array.Sort(addrAry, new Utils.AddressComparison());

                var finlAry = finlSet.ToArray();
                Array.Sort(finlAry, new Utils.AddressComparison());

                if (!ClrtRootInfo.Save(rtm, ourRoots, fileMoniker, out error))
                {
                    return(new ValueTuple <ulong[], ulong[]>(null, null));
                }
                return(new ValueTuple <ulong[], ulong[]>(addrAry, finlAry));
            }
            catch (Exception ex)
            {
                error = Utils.GetExceptionErrorString(ex);
                return(new ValueTuple <ulong[], ulong[]>(null, null));
            }
        }