Ejemplo n.º 1
0
 public SimplifiedRoot(ClrRoot root)
 {
     Address     = root.Address;
     Object      = root.Object;
     Kind        = root.Kind;
     DisplayText = root.BetterToString();
 }
Ejemplo n.º 2
0
 public HandleRoot(ulong addr, ulong obj, ClrType type, HandleType hndType, GCRootKind kind, ClrAppDomain domain)
 {
     _name   = Enum.GetName(typeof(HandleType), hndType) + " handle";
     Address = addr;
     Object  = obj;
     _kind   = kind;
     _type   = type;
     _domain = domain;
 }
Ejemplo n.º 3
0
        }                                  // For deserialization

        internal ICorDebugGCHeapRoot(string name, GCRootKind kind, Address heapReference, Address addressOfRoot, ICorDebugGCHeapType type, string appDomainName)
        {
            m_kind          = kind;
            m_name          = name;
            m_type          = type;
            m_heapReference = heapReference;
            m_addressOfRoot = addressOfRoot;
            m_appDomain     = new ICorDebugAD(appDomainName);
        }
Ejemplo n.º 4
0
 public HandleRoot(ulong addr, ulong obj, ClrType type, HandleType handleType, GCRootKind kind, ClrAppDomain domain)
 {
     Address    = addr;
     Object     = obj;
     Kind       = kind;
     Type       = type;
     HandleType = handleType;
     AppDomain  = domain;
 }
Ejemplo n.º 5
0
        public KeyValuePair <ulong, ulong>[] GetAddressObjectPairsUnordered(GCRootKind kind)
        {
            var ary = GetItems(kind);

            if (ary.Length < 1)
            {
                return(Utils.EmptyArray <KeyValuePair <ulong, ulong> > .Value);
            }
            KeyValuePair <ulong, ulong>[] addrs = new KeyValuePair <ulong, ulong> [ary.Length];
            for (int i = 0, icnt = ary.Length; i < icnt; ++i)
            {
                addrs[i] = new KeyValuePair <ulong, ulong>(ary[i].Address, ary[i].Object);
            }
            return(addrs);
        }
Ejemplo n.º 6
0
        public ulong[] GetObjects(GCRootKind kind)
        {
            var ary = GetItems(kind);

            if (ary.Length < 1)
            {
                return(Utils.EmptyArray <ulong> .Value);
            }
            ulong[] addrs = new ulong[ary.Length];
            for (int i = 0, icnt = ary.Length; i < icnt; ++i)
            {
                addrs[i] = ary[i].Object;
            }
            Array.Sort(addrs, new Utils.AddressComparison());
            return(addrs);
        }
Ejemplo n.º 7
0
        private ClrRoot GetHandleRoot(ClrHandle handle)
        {
            GCRootKind kind = GCRootKind.Strong;

            switch (handle.HandleType)
            {
            case HandleType.Pinned:
                kind = GCRootKind.Pinning;
                break;

            case HandleType.AsyncPinned:
                kind = GCRootKind.AsyncPinning;
                break;
            }

            return(new HandleRoot(handle.Address, handle.Object, handle.Type, handle.HandleType, kind, handle.AppDomain));
        }
Ejemplo n.º 8
0
        private void Init(Address addr, Address obj, Address dependentTarget, ClrType type, int hndType, ClrAppDomain domain, string name)
        {
            HandleType htype = (HandleType)hndType;

            switch (htype)
            {
            case HandleType.AsyncPinned:
                m_kind = GCRootKind.AsyncPinning;
                break;

            case HandleType.Pinned:
                m_kind = GCRootKind.Pinning;
                break;

            case HandleType.WeakShort:
            case HandleType.WeakLong:
                m_kind = GCRootKind.Weak;
                break;

            default:
                m_kind = GCRootKind.Strong;
                break;
            }

            Address     = addr;
            m_name      = name;
            m_type      = type;
            m_appDomain = domain;

            if (htype == HandleType.Dependent && dependentTarget != 0)
            {
                Object = dependentTarget;
            }
            else
            {
                Object = obj;
            }
        }
Ejemplo n.º 9
0
 private static string KindString(this GCRootKind kind)
 {
     switch (kind)
     {
         case GCRootKind.StaticVar:
             return "StaticVar";
         case GCRootKind.Finalizer:
             return "Finalizer";
         case GCRootKind.Pinning:
             return "Pinning";
         case GCRootKind.AsyncPinning:
             return "AsyncPinning";
         case GCRootKind.LocalVar:
             return "LocalVar";
         case GCRootKind.ThreadStaticVar:
             return "ThreadStaticVar";
         case GCRootKind.Strong:
             return "Strong";
         case GCRootKind.Weak:
             return "Weak";
         default:
             return "Unknown";
     }
 }
Ejemplo n.º 10
0
        private void Init(Address addr, Address obj, Address dependentTarget, ClrType type, int hndType, ClrAppDomain domain, string name)
        {
            HandleType htype = (HandleType)hndType;
            switch (htype)
            {
                case HandleType.AsyncPinned:
                    _kind = GCRootKind.AsyncPinning;
                    break;

                case HandleType.Pinned:
                    _kind = GCRootKind.Pinning;
                    break;

                case HandleType.WeakShort:
                case HandleType.WeakLong:
                    _kind = GCRootKind.Weak;
                    break;

                default:
                    _kind = GCRootKind.Strong;
                    break;
            }

            Address = addr;
            _name = name;
            _type = type;
            _appDomain = domain;

            if (htype == HandleType.Dependent && dependentTarget != 0)
                Object = dependentTarget;
            else
                Object = obj;
        }
    /// <summary>
    /// Sets up the callbacks needed to do a heap dump (work need before processing the events()
    /// </summary>
    internal void SetupCallbacks(MemoryGraph memoryGraph, TraceEventDispatcher source, string processNameOrId = null, double startTimeRelativeMSec = 0)
    {
        m_graph            = memoryGraph;
        m_typeID2TypeIndex = new Dictionary <Address, NodeTypeIndex>(1000);
        m_moduleID2Name    = new Dictionary <Address, string>(16);
        m_arrayNametoIndex = new Dictionary <string, NodeTypeIndex>(32);
        m_objectToRCW      = new Dictionary <Address, RCWInfo>(100);
        m_nodeBlocks       = new Queue <GCBulkNodeTraceData>();
        m_edgeBlocks       = new Queue <GCBulkEdgeTraceData>();
        m_typeBlocks       = new Queue <GCBulkTypeTraceData>();
        m_staticVarBlocks  = new Queue <GCBulkRootStaticVarTraceData>();
        m_ccwBlocks        = new Queue <GCBulkRootCCWTraceData>();
        m_typeIntern       = new Dictionary <string, NodeTypeIndex>();
        m_root             = new MemoryNodeBuilder(m_graph, "[.NET Roots]");
        m_typeStorage      = m_graph.AllocTypeNodeStorage();

        // We also keep track of the loaded modules in the target process just in case it is a project N scenario.
        // (Not play for play but it is small).
        m_modules = new Dictionary <Address, Module>(32);

        m_ignoreEvents    = true;
        m_ignoreUntilMSec = startTimeRelativeMSec;

        m_processId = 0;        // defaults to a wildcard.
        if (processNameOrId != null)
        {
            if (!int.TryParse(processNameOrId, out m_processId))
            {
                m_processId   = -1;     // an illegal value.
                m_processName = processNameOrId;
            }
        }

        // Remember the module IDs too.
        Action <ModuleLoadUnloadTraceData> moduleCallback = delegate(ModuleLoadUnloadTraceData data)
        {
            if (data.ProcessID != m_processId)
            {
                return;
            }

            if (!m_moduleID2Name.ContainsKey((Address)data.ModuleID))
            {
                m_moduleID2Name[(Address)data.ModuleID] = data.ModuleILPath;
            }

            m_log.WriteLine("Found Module {0} ID 0x{1:x}", data.ModuleILFileName, (Address)data.ModuleID);
        };

        source.Clr.AddCallbackForEvents <ModuleLoadUnloadTraceData>(moduleCallback); // Get module events for clr provider
        // TODO should not be needed if we use CAPTURE_STATE when collecting.
        var clrRundown = new ClrRundownTraceEventParser(source);

        clrRundown.AddCallbackForEvents <ModuleLoadUnloadTraceData>(moduleCallback); // and its rundown provider.

        DbgIDRSDSTraceData lastDbgData = null;
        var symbolParser = new SymbolTraceEventParser(source);

        symbolParser.ImageIDDbgID_RSDS += delegate(DbgIDRSDSTraceData data)
        {
            if (data.ProcessID != m_processId)
            {
                return;
            }

            lastDbgData = (DbgIDRSDSTraceData)data.Clone();
        };

        source.Kernel.ImageGroup += delegate(ImageLoadTraceData data)
        {
            if (m_processId == 0)
            {
                return;
            }

            if (data.ProcessID != m_processId)
            {
                return;
            }

            Module module = new Module(data.ImageBase);
            module.Path      = data.FileName;
            module.Size      = data.ImageSize;
            module.BuildTime = data.BuildTime;
            if (lastDbgData != null && data.TimeStampRelativeMSec == lastDbgData.TimeStampRelativeMSec)
            {
                module.PdbGuid = lastDbgData.GuidSig;
                module.PdbAge  = lastDbgData.Age;
                module.PdbName = lastDbgData.PdbFileName;
            }
            m_modules[module.ImageBase] = module;
        };

        // TODO this does not work in the circular case
        source.Kernel.ProcessGroup += delegate(ProcessTraceData data)
        {
            if (0 <= m_processId || m_processName == null)
            {
                return;
            }

            if (string.Compare(data.ProcessName, processNameOrId, StringComparison.OrdinalIgnoreCase) == 0)
            {
                m_log.WriteLine("Found process id {0} for process Name {1}", processNameOrId, data.ProcessName);
                m_processId = data.ProcessID;
            }
            else
            {
                m_log.WriteLine("Found process {0} but does not match {1}", data.ProcessName, processNameOrId);
            }
        };

        source.Clr.GCStart += delegate(GCStartTraceData data)
        {
            // If this GC is not part of a heap dump, ignore it.
            // TODO FIX NOW if (data.ClientSequenceNumber == 0)
            //     return;

            if (data.TimeStampRelativeMSec < m_ignoreUntilMSec)
            {
                return;
            }

            if (m_processId == 0)
            {
                m_processId = data.ProcessID;
                m_log.WriteLine("Process wildcard selects process id {0}", m_processId);
            }
            if (data.ProcessID != m_processId)
            {
                m_log.WriteLine("GC Start found but Process ID {0} != {1} desired ID", data.ProcessID, m_processId);
                return;
            }

            if (!IsProjectN && data.ProviderGuid == ClrTraceEventParser.NativeProviderGuid)
            {
                IsProjectN = true;
            }

            if (data.Depth < 2 || data.Type != GCType.NonConcurrentGC)
            {
                m_log.WriteLine("GC Start found but not a Foreground Gen 2 GC");
                return;
            }

            if (data.Reason != GCReason.Induced)
            {
                m_log.WriteLine("GC Start not induced. Skipping.");
                return;
            }

            if (!m_seenStart)
            {
                m_gcID = data.Count;
                m_log.WriteLine("Found a Gen2 Induced non-background GC Start at {0:n3} msec GC Count {1}", data.TimeStampRelativeMSec, m_gcID);
                m_ignoreEvents      = false;
                m_seenStart         = true;
                memoryGraph.Is64Bit = (data.PointerSize == 8);
            }
        };



        source.Clr.GCStop += delegate(GCEndTraceData data)
        {
            if (m_ignoreEvents || data.ProcessID != m_processId)
            {
                return;
            }

            if (data.Count == m_gcID)
            {
                m_log.WriteLine("Found a GC Stop at {0:n3} for GC {1}, ignoring events from now on.", data.TimeStampRelativeMSec, m_gcID);
                m_ignoreEvents = true;

                if (m_nodeBlocks.Count == 0 && m_typeBlocks.Count == 0 && m_edgeBlocks.Count == 0)
                {
                    m_log.WriteLine("Found no node events, looking for another GC");
                    m_seenStart = false;
                    return;
                }

                // TODO we have to continue processing to get the module rundown events.
                // If we could be sure to get these early, we could optimized this.
                // source.StopProcessing();
            }
            else
            {
                m_log.WriteLine("Found a GC Stop at {0:n3} but id {1} != {2} Target ID", data.TimeStampRelativeMSec, data.Count, m_gcID);
            }
        };

        source.Clr.TypeBulkType += delegate(GCBulkTypeTraceData data)
        {
            // Don't check m_ignoreEvents here, as BulkType events can be emitted by other events...such as the GC allocation event.
            // This means that when setting m_processId to 0 in the command line may still lose type events.
            if (data.ProcessID != m_processId)
            {
                return;
            }

            m_typeBlocks.Enqueue((GCBulkTypeTraceData)data.Clone());
        };

        source.Clr.GCBulkNode += delegate(GCBulkNodeTraceData data)
        {
            if (m_ignoreEvents || data.ProcessID != m_processId)
            {
                return;
            }

            m_nodeBlocks.Enqueue((GCBulkNodeTraceData)data.Clone());
        };

        source.Clr.GCBulkEdge += delegate(GCBulkEdgeTraceData data)
        {
            if (m_ignoreEvents || data.ProcessID != m_processId)
            {
                return;
            }

            m_edgeBlocks.Enqueue((GCBulkEdgeTraceData)data.Clone());
        };

        source.Clr.GCBulkRootEdge += delegate(GCBulkRootEdgeTraceData data)
        {
            if (m_ignoreEvents || data.ProcessID != m_processId)
            {
                return;
            }

            MemoryNodeBuilder staticRoot = m_root.FindOrCreateChild("[static vars]");
            for (int i = 0; i < data.Count; i++)
            {
                var value = data.Values(i);
                var flags = value.GCRootFlag;
                if ((flags & GCRootFlags.WeakRef) == 0)     // ignore weak references. they are not roots.
                {
                    GCRootKind        kind = value.GCRootKind;
                    MemoryNodeBuilder root = m_root;
                    string            name;
                    if (kind == GCRootKind.Stack)
                    {
                        name = "[local vars]";
                    }
                    else
                    {
                        root = m_root.FindOrCreateChild("[other roots]");

                        if ((flags & GCRootFlags.RefCounted) != 0)
                        {
                            name = "[COM/WinRT Objects]";
                        }
                        else if (kind == GCRootKind.Finalizer)
                        {
                            name = "[finalizer Handles]";
                        }
                        else if (kind == GCRootKind.Handle)
                        {
                            if (flags == GCRootFlags.Pinning)
                            {
                                name = "[pinning Handles]";
                            }
                            else
                            {
                                name = "[strong Handles]";
                            }
                        }
                        else
                        {
                            name = "[other Handles]";
                        }

                        // Remember the root for later processing.
                        if (value.RootedNodeAddress != 0)
                        {
                            Address gcRootId = value.GCRootID;
                            if (gcRootId != 0 && IsProjectN)
                            {
                                Module gcRootModule = GetModuleForAddress(gcRootId);
                                if (gcRootModule != null)
                                {
                                    var staticRva     = (int)(gcRootId - gcRootModule.ImageBase);
                                    var staticTypeIdx = m_graph.CreateType(staticRva, gcRootModule, 0, " (static var)");
                                    var staticNodeIdx = m_graph.CreateNode();
                                    m_children.Clear();
                                    m_children.Add(m_graph.GetNodeIndex(value.RootedNodeAddress));
                                    m_graph.SetNode(staticNodeIdx, staticTypeIdx, 0, m_children);
                                    staticRoot.AddChild(staticNodeIdx);
                                    Trace.WriteLine("Got Static 0x" + gcRootId.ToString("x") + " pointing at 0x" + value.RootedNodeAddress.ToString("x") + " kind " + value.GCRootKind + " flags " + value.GCRootFlag);
                                    continue;
                                }
                            }

                            Trace.WriteLine("Got GC Root 0x" + gcRootId.ToString("x") + " pointing at 0x" + value.RootedNodeAddress.ToString("x") + " kind " + value.GCRootKind + " flags " + value.GCRootFlag);
                        }
                    }

                    root = root.FindOrCreateChild(name);
                    Address objId = value.RootedNodeAddress;
                    root.AddChild(m_graph.GetNodeIndex(objId));
                }
            }
        };

        source.Clr.GCBulkRCW += delegate(GCBulkRCWTraceData data)
        {
            if (m_ignoreEvents || data.ProcessID != m_processId)
            {
                return;
            }

            for (int i = 0; i < data.Count; i++)
            {
                GCBulkRCWValues comInfo = data.Values(i);
                m_objectToRCW[comInfo.ObjectID] = new RCWInfo(comInfo);
            }
        };

        source.Clr.GCBulkRootCCW += delegate(GCBulkRootCCWTraceData data)
        {
            if (m_ignoreEvents || data.ProcessID != m_processId)
            {
                return;
            }

            m_ccwBlocks.Enqueue((GCBulkRootCCWTraceData)data.Clone());
        };

        source.Clr.GCBulkRootStaticVar += delegate(GCBulkRootStaticVarTraceData data)
        {
            if (m_ignoreEvents || data.ProcessID != m_processId)
            {
                return;
            }

            m_staticVarBlocks.Enqueue((GCBulkRootStaticVarTraceData)data.Clone());
        };

        source.Clr.GCBulkRootConditionalWeakTableElementEdge += delegate(GCBulkRootConditionalWeakTableElementEdgeTraceData data)
        {
            if (m_ignoreEvents || data.ProcessID != m_processId)
            {
                return;
            }

            var otherRoots       = m_root.FindOrCreateChild("[other roots]");
            var dependentHandles = otherRoots.FindOrCreateChild("[Dependent Handles]");
            for (int i = 0; i < data.Count; i++)
            {
                var value = data.Values(i);
                // TODO fix this so that they you see this as an arc from source to target.
                // The target is alive only if the source ID (which is a weak handle) is alive (non-zero)
                if (value.GCKeyNodeID != 0)
                {
                    dependentHandles.AddChild(m_graph.GetNodeIndex(value.GCValueNodeID));
                }
            }
        };

        source.Clr.GCGenerationRange += delegate(GCGenerationRangeTraceData data)
        {
            if (m_ignoreEvents || data.ProcessID != m_processId)
            {
                return;
            }

            if (m_dotNetHeapInfo == null)
            {
                return;
            }

            // We want the 'after' ranges so we wait
            if (m_nodeBlocks.Count == 0)
            {
                return;
            }

            Address start = data.RangeStart;
            Address end   = start + data.RangeUsedLength;

            if (m_dotNetHeapInfo.Segments == null)
            {
                m_dotNetHeapInfo.Segments = new List <GCHeapDumpSegment>();
            }

            GCHeapDumpSegment segment = new GCHeapDumpSegment();
            segment.Start = start;
            segment.End   = end;

            switch (data.Generation)
            {
            case 0:
                segment.Gen0End = end;
                break;

            case 1:
                segment.Gen1End = end;
                break;

            case 2:
                segment.Gen2End = end;
                break;

            case 3:
                segment.Gen3End = end;
                break;

            default:
                throw new Exception("Invalid generation in GCGenerationRangeTraceData");
            }
            m_dotNetHeapInfo.Segments.Add(segment);
        };
    }
Ejemplo n.º 12
0
 public static Kinds Convert(GCRootKind kind)
 {
     return((Kinds)(1 << (4 + (int)kind)));
 }
Ejemplo n.º 13
0
 public ClrtRoot[] GetItems(GCRootKind kind)
 {
     return(_roots[(int)kind] == null ? Utils.EmptyArray <ClrtRoot> .Value : _roots[(int)kind]);
 }
Ejemplo n.º 14
0
 public SimplifiedRoot(ClrRoot root)
 {
     Address = root.Address;
     Object = root.Object;
     Kind = root.Kind;
     DisplayText = root.BetterToString();
 }