public ClrtRoot(ClrRoot root, int typeId, int nameId) { ulong raddr = root.Address; ulong obj = root.Object; Address = raddr == 0UL ? 0UL : Utils.SetRooted(raddr); Object = (raddr == 0UL) ? obj : Utils.SetRooted(root.Object); TypeId = typeId; NameId = nameId; DomainId = root.AppDomain != null ? root.AppDomain.Id : Constants.InvalidIndex; OsThreadId = root.Thread != null ? root.Thread.OSThreadId : Constants.InvalidThreadId; ManagedThreadId = root.Thread != null ? root.Thread.ManagedThreadId : Constants.InvalidIndex;; int traits = (int)Convert(root.Kind); if (root.IsInterior) { traits |= (int)Kinds.Interior; } if (root.IsPinned) { traits |= (int)Kinds.Pinned; } if (root.IsPossibleFalsePositive) { traits |= (int)Kinds.PossibleFalsePositive; } RootKind = (Kinds)traits; }
public ClrtRoot(ClrRoot root, int typeId, int nameId, int domainId, uint osthreadId, int managedThrdId) { Address = root.Address; Object = root.Object; TypeId = typeId; NameId = nameId; DomainId = domainId; OsThreadId = osthreadId; ManagedThreadId = managedThrdId; int traits = (int)Convert(root.Kind); if (root.IsInterior) { traits |= (int)Kinds.Interior; } if (root.IsPinned) { traits |= (int)Kinds.Pinned; } if (root.IsPossibleFalsePositive) { traits |= (int)Kinds.PossibleFalsePositive; } RootKind = (Kinds)traits; }
public SimplifiedRoot(ClrRoot root) { Address = root.Address; Object = root.Object; Kind = root.Kind; DisplayText = root.BetterToString(); }
public ValuePointer(ClrRoot r, ClrHeap heap) { // r.Address is the memory location of the root, not the thing it points to r.Type.Heap.ReadPointer(r.Address, out Address); Type = r.Type; Heap = heap; }
public static string BetterToString(this ClrRoot root) { if (root.Kind == GCRootKind.LocalVar && root.Thread != null) { return(String.Format("{0} thread {1}", root.Name, root.Thread.ManagedThreadId)); } return(root.Name); }
public IClrObject ReadGCRoot(ClrRoot root) { if (root.Address == 0) { return(null); } return(ReadFromNotNullAddress(root.Type, root.Object)); }
/// <summary> /// Initializes a new instance of the <see cref="ClrRootAdapter" /> class. /// </summary> /// <param name="root">The root.</param> /// <exception cref="ArgumentNullException">root</exception> /// <inheritdoc /> public ClrRootAdapter(IConverter converter, ClrRoot root) : base(converter) { Root = root ?? throw new ArgumentNullException(nameof(root)); Address = Root.Address; IsInterior = Root.IsInterior; IsPinned = Root.IsPinned; IsPossibleFalsePositive = Root.IsPossibleFalsePositive; Name = Root.Name; Object = Root.Object; }
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]); } }
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.Contains("s_foo", staticRoot.Name); var arr = fooRoots.Where(r => r.Kind == GCRootKind.LocalVar).ToArray(); ClrRoot[] localVarRoots = fooRoots.Where(r => r.Kind == GCRootKind.LocalVar).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 (ClrRoot localVarRoot in localVarRoots) { Assert.True(low <= localVarRoot.Address && localVarRoot.Address <= high); } } }
private Node TryFindPathToTarget(ClrRoot root) { ClrType type = _heap.GetObjectType(root.Object); if (type == null) { return(null); } List <ulong> refList = new List <ulong>(); List <int> offsetList = new List <int>(); Node curr = new Node(root.Object, type); while (curr != null) { if (curr.Children == null) { refList.Clear(); offsetList.Clear(); curr.Type.EnumerateRefsOfObject(curr.Object, (child, offset) => { if (child != 0) { refList.Add(child); offsetList.Add(offset); } }); curr.Children = refList.ToArray(); curr.Offsets = offsetList.ToArray(); } else { if (curr.Curr < curr.Children.Length) { ulong nextObj = curr.Children[curr.Curr]; int offset = curr.Offsets[curr.Curr]; curr.Curr++; if (_visitedObjects.Contains(nextObj)) { continue; } _visitedObjects.Add(nextObj); Node next = null; if (_targets.TryGetValue(nextObj, out next)) { curr.Next = next; next.Prev = curr; next.Offset = offset; while (curr.Prev != null) { _targets[curr.Object] = curr; curr = curr.Prev; } _targets[curr.Object] = curr; return(curr); } type = _heap.GetObjectType(nextObj); if (type != null && type.ContainsPointers) { curr = new Node(nextObj, type, curr); curr.Offset = offset; } } else { curr = curr.Prev; if (curr != null) { curr.Next = null; } } } } return(null); }
public StackInstanceInformation(ClrDump clrDump, ClrRoot clrRoot) { ClrDump = clrDump; ClrRoot = clrRoot; }
public ClrRootsInformation(ClrDump clrDump, ClrRoot clrRoot) { ClrDump = clrDump; ClrRoot = clrRoot; }
public MDRoot(ClrRoot root) { m_root = root; }
private Node FindPathToTarget(Dump dump, ClrRoot root, HashSet <ulong> considered, Dictionary <ulong, Node> targets) { var type = dump.Heap.GetObjectType(root.Object); if (type == null) { return(null); } var refList = new List <ulong>(); var offsetList = new List <int>(); var curr = new Node(root.Object, type); while (curr != null) { if (curr.Children == null) { refList.Clear(); offsetList.Clear(); curr.Type.EnumerateRefsOfObject(curr.Object, (child, offset) => { if (child != 0) { refList.Add(child); offsetList.Add(offset); } }); curr.Children = refList.ToArray(); curr.Offsets = offsetList.ToArray(); } else { if (curr.Curr < curr.Children.Length) { ulong nextObj = curr.Children[curr.Curr]; int offset = curr.Offsets[curr.Curr]; curr.Curr++; if (considered.Contains(nextObj)) { continue; } considered.Add(nextObj); Node next = null; if (targets.TryGetValue(nextObj, out next)) { curr.Next = next; next.Prev = curr; next.Offset = offset; while (curr.Prev != null) { targets[curr.Object] = curr; curr = curr.Prev; } targets[curr.Object] = curr; return(curr); } type = dump.Heap.GetObjectType(nextObj); if (type != null && type.ContainsPointers) { curr = new Node(nextObj, type, curr); curr.Offset = offset; } } else { curr = curr.Prev; if (curr != null) { curr.Next = null; } } } } return(null); }
private static Dictionary <ulong, List <ulong> > PathToGcRoots(ClrHeap heap, ulong objRef, ClrRoot root) { const int maxSteps = 65536; var sourceNode = new ObjectGraphNode(objRef, heap.GetObjectType(objRef).Name); var considered = new HashSet <ulong>(); var gcRootNodes = new HashSet <ulong>(); var count = 0; var eval = new Stack <ObjectGraphNode>(); eval.Push(sourceNode); while (eval.Count > 0) { var node = eval.Pop(); if (considered.Contains(node.ObjRef)) { continue; } considered.Add(node.ObjRef); if (gcRootsByRef.ContainsKey(node.ObjRef)) { gcRootNodes.Add(node.ObjRef); continue; } var type = heap.GetObjectType(node.ObjRef); if (type == null) { continue; } count++; if (count >= maxSteps) { return(null); } type.EnumerateRefsOfObject(node.ObjRef, (child, offset) => { if (child != 0 && !considered.Contains(child)) { var typeName = heap.GetObjectType(child).Name; eval.Push(new ObjectGraphNode(child, typeName)); } }); } return(null); }