/// <summary> /// Sadly this is a bit subtle. We only want to scan the GC heap once, the read of /// the heap only happens when we write during serialization of the heap data. However /// until we do this we don't have the types, and we need the types to initialize the /// roots. Thus we have to pospone the creation of the roots as long as possible /// (after serialization of the GC data), so it all works out. /// </summary> private void InitRoots() { // We should only be calling this when the data is coming from a live process. Debug.Assert(m_process5 != null); // TODO FIX NOW REMOVE Console.WriteLines Console.WriteLine("Initializing roots"); // We need to look up the types by name create a temporary dication to do this. // TODO FIX NOW we can have collisions (it happens with generics right now). var types = new Dictionary <string, ICorDebugGCHeapType>(); foreach (var type in m_types) { types[type.Name] = type; } var roots = new List <ICorDebugGCHeapRoot>(); ICorDebugGCReferenceEnum refEnum; m_process5.EnumerateGCReferences(0, out refEnum); uint fetched; COR_GC_REFERENCE[] corRoots = new COR_GC_REFERENCE[256]; StringBuilder buffer = new StringBuilder(1024); for (; ;) { refEnum.Next(256, corRoots, out fetched); if (fetched == 0) { break; } for (int i = 0; i < fetched; i++) { roots.Add(new ICorDebugGCHeapRoot(ref corRoots[i], this, buffer)); } } m_roots = roots.ToArray(); //Console.WriteLine("Root count = {0}", m_roots.Length); }
internal ICorDebugGCHeapRoot(ref COR_GC_REFERENCE root, ICorDebugGCHeap heap, StringBuilder buffer) { Address address; Address objRef = 0; root.Location.GetAddress(out address); m_addressOfRoot = address; string adName = ""; if (root.Domain != null) { uint nameSize; root.Domain.GetName((uint)buffer.Capacity, out nameSize, buffer); adName = buffer.ToString(); } m_appDomain = new ICorDebugAD(adName); var asRef = root.Location as ICorDebugReferenceValue; if (asRef != null) { asRef.GetValue(out objRef); m_heapReference = objRef; } else if (root.Location != null) { root.Location.GetAddress(out objRef); m_heapReference = objRef; } else { Console.WriteLine("ERROR! could not fetch value from root 0x{0:x}", address); } Debug.Assert(Object == 0 || heap.IsInHeap(Object)); m_type = null; if (root.Type == CorGCReferenceType.CorHandleStrong) { m_kind = GCRootKind.Strong; m_name = "Strong Handle"; } else if (root.Type == CorGCReferenceType.CorHandleStrongPinning) { m_kind = GCRootKind.Pinning; m_name = "Pinning Handle"; } else if (root.Type == CorGCReferenceType.CorHandleWeakShort) { m_kind = GCRootKind.Weak; m_name = "Weak Handle"; } else if (root.Type == CorGCReferenceType.CorReferenceStack) { m_kind = GCRootKind.LocalVar; m_name = "Local Variable"; } else if (root.Type == CorGCReferenceType.CorReferenceFinalizer) { m_kind = GCRootKind.Finalizer; m_name = "Finalization"; } else if (root.Type == CorGCReferenceType.CorHandleStrongAsyncPinned) { m_kind = GCRootKind.AsyncPinning; m_name = "Async Pinning"; } else { m_kind = GCRootKind.Strong; // TODO FIX NOW complete the enumeration. m_name = "Other Handle"; } }