public ulong SkipAllocationContext(ClrSegment seg, ulong obj, ulong mt, Action <ulong, ulong, int, int, uint>?callback) { if (seg is null) { throw new ArgumentNullException(nameof(seg)); } if (seg.IsLargeObjectSegment) { return(obj); } uint minObjSize = (uint)IntPtr.Size * 3; while (AllocationContext.TryGetValue(obj, out ulong nextObj)) { nextObj += Align(minObjSize, seg.IsLargeObjectSegment); if (obj >= nextObj || obj >= seg.End) { return(0); } // Only if there's data corruption: if (obj >= nextObj || obj >= seg.End) { callback?.Invoke(obj, mt, int.MinValue + 2, -1, 0); return(0); } obj = nextObj; } return(obj); }
private static void CheckSegments(ClrHeap heap) { foreach (ClrSegment seg in heap.Segments) { Assert.NotEqual(0ul, seg.Start); Assert.NotEqual(0ul, seg.End); Assert.True(seg.Start <= seg.End); Assert.True(seg.Start < seg.CommittedEnd); Assert.True(seg.CommittedEnd < seg.ReservedEnd); if (!seg.IsEphemeralSegment) { Assert.Equal(0ul, seg.Gen0Length); Assert.Equal(0ul, seg.Gen1Length); } int count = 0; foreach (ulong obj in seg.EnumerateObjects()) { ClrSegment curr = heap.GetSegmentByAddress(obj); Assert.Same(seg, curr); count++; } Assert.True(count >= 1); } }
public void SegmentEnumeration() { // Simply test that we can enumerate the heap. using DataTarget dt = TestTargets.Types.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrHeap heap = runtime.Heap; ClrObject[] objs = heap.EnumerateObjects().ToArray(); // Enumerating each segment and then each object on each segment should produce // the same enumeration as ClrHeap.EnumerateObjects(). int index = 0; foreach (ClrSegment seg in heap.Segments) { foreach (ClrObject obj in seg.EnumerateObjects()) { Assert.Equal(objs[index], obj); index++; } } ClrSegment large = heap.Segments.Single(s => s.IsLargeObjectSegment); large.EnumerateObjects().ToArray(); Assert.Equal(objs.Length, index); }
public void StringEmptyTest() { using DataTarget dt = TestTargets.Types.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrType strType = runtime.Heap.StringType; var statics = strType.StaticFields; ulong valueSlot = Assert.Single(statics).GetAddress(runtime.AppDomains[0]); Assert.NotEqual(0ul, valueSlot); ulong address = dt.DataReader.ReadPointer(valueSlot); Assert.NotEqual(0ul, address); ClrObject obj = runtime.Heap.GetObject(address); Assert.True(obj.Type.IsString); string strValue = obj.AsString(); Assert.Equal("", strValue); ClrSegment seg = runtime.Heap.GetSegmentByAddress(valueSlot); Assert.NotNull(seg); ulong prev = seg.GetPreviousObjectAddress(valueSlot); Assert.NotEqual(0ul, prev); ClrObject staticsArray = runtime.Heap.GetObject(prev); Assert.True(staticsArray.IsValid); Assert.True(staticsArray.IsArray); }
public ulong SkipAllocationContext(ClrSegment seg, ulong address) { if (seg is null) { throw new ArgumentNullException(nameof(seg)); } if (seg.IsLargeObjectSegment) { return(address); } uint minObjSize = (uint)IntPtr.Size * 3; while (AllocationContexts.TryGetValue(address, out ulong nextObj)) { nextObj += Align(minObjSize, seg.IsLargeObjectSegment); if (address >= nextObj || address >= seg.End) { return(0); } // Only if there's data corruption: if (address >= nextObj || address >= seg.End) { return(0); } address = nextObj; } return(address); }
/// <summary> /// Gets the LOH size and the object summary in the LOH /// </summary> /// <param name="minTotalSize">The min size that we will be filtering on.</param> /// <returns>List with ClrType's Name, Count of Object of ClrType and total size of that type</returns> private IEnumerable <(string type, int count, long size)> GetLOHStats() { ClrSegment lohSegment = Runtime.Heap.Segments.Where(s => s.IsLargeObjectSegment).First(); IEnumerable <ClrObject> objects = lohSegment.EnumerateObjects(); var stats = GetStats(objects); return(stats.Select(s => (type: s.type.Name, count: s.objects.Count(), s.size))); }
public ClrStackInteriorRoot(ClrSegment seg, ulong address, ulong objAddr, ClrStackFrame stackFrame, bool pinned) { _segment = seg; ObjectPointer = objAddr; Address = address; StackFrame = stackFrame; IsPinned = pinned; }
public SegmentInfo(ClrSegment segment) { _segment = segment; Number = _segment.ProcessorAffinity; IsEphemeral = _segment.IsEphemeral; IsLoh = _segment.IsLarge; IsGen2 = !(IsEphemeral || IsLoh); ComputeGenerations(segment); }
private static void WalkSegment(ClrSegment seg) { foreach (ClrObject obj in seg.EnumerateObjects().Take(2048)) { foreach (ClrReference reference in obj.EnumerateReferencesWithFields(carefully: false, considerDependantHandles: true)) { _ = reference.Object; } } }
private bool TryGetSegmentMemoryRange(ClrSegment segment, GCGeneration generation, out ulong start, out ulong end) { start = 0; end = 0; switch (generation) { case GCGeneration.Generation0: if (segment.IsEphemeralSegment) { start = segment.Generation0.Start; end = segment.Generation0.End; } return(start != end); case GCGeneration.Generation1: if (segment.IsEphemeralSegment) { start = segment.Generation1.Start; end = segment.Generation1.End; } return(start != end); case GCGeneration.Generation2: if (!(segment.IsLargeObjectSegment || segment.IsPinnedObjectSegment)) { start = segment.Generation2.Start; end = segment.Generation2.End; } return(start != end); case GCGeneration.LargeObjectHeap: if (segment.IsLargeObjectSegment) { start = segment.Start; end = segment.End; } return(start != end); case GCGeneration.PinnedObjectHeap: if (segment.IsPinnedObjectSegment) { start = segment.Start; end = segment.End; } return(start != end); default: return(false); } }
private void CheckSorted(IReadOnlyList <ClrSegment> segments) { ClrSegment last = null; foreach (ClrSegment seg in segments) { if (last != null) { Assert.True(last.Start < seg.Start); } last = seg; } }
private void CheckSorted(ImmutableArray <ClrSegment> segments) { ClrSegment last = null; foreach (ClrSegment seg in segments) { if (last != null) { Assert.True(last.Start < seg.Start); } last = seg; } }
private static int?GenerationOf(ClrHeap heap, ClrObject obj) { ClrSegment segment = heap.GetSegmentByAddress(obj.Address); if (segment == null) { // This happen if the object is no longer live return(null); } else { return(segment.GetGeneration(obj)); } }
public override ClrSegment?GetSegmentByAddress(ulong objRef) { VolatileHeapData data = GetHeapData(); ImmutableArray <ClrSegment> segments = data.Segments; if (segments.Length == 0) { return(null); } if (segments[0].FirstObjectAddress <= objRef && objRef < segments[segments.Length - 1].End) { // Start the segment search where you where last int prevIndex = data.LastSegmentIndex; int curIdx = prevIndex; for (; ;) { ClrSegment segment = segments[curIdx]; unchecked { long offsetInSegment = (long)(objRef - segment.Start); if (offsetInSegment >= 0) { long intOffsetInSegment = offsetInSegment; if (intOffsetInSegment < (long)segment.Length) { data.LastSegmentIndex = curIdx; return(segment); } } } // Get the next segment loop until you come back to where you started. curIdx++; if (curIdx >= segments.Length) { curIdx = 0; } if (curIdx == prevIndex) { break; } } } return(null); }
private void ComputeGenerations(ClrSegment segment) { _generations = new List <GenerationInSegment>(); if (segment.IsLarge) { _generations.Add( new GenerationInSegment() { Generation = 3, Start = segment.Gen2Start, End = segment.Gen2Start + segment.Gen2Length, Length = segment.Gen2Length } ); } else if (segment.IsEphemeral) { _generations.Add( new GenerationInSegment() { Generation = 0, Start = segment.Gen0Start, End = segment.Gen0Start + segment.Gen0Length, Length = segment.Gen0Length } ); _generations.Add( new GenerationInSegment() { Generation = 1, Start = segment.Gen1Start, End = segment.Gen1Start + segment.Gen1Length, Length = segment.Gen1Length } ); _generations.Add( new GenerationInSegment() { Generation = 2, Start = segment.Gen2Start, End = segment.Gen2Start + segment.Gen2Length, Length = segment.Gen2Length } ); } }
private static void CheckSegments(ClrHeap heap) { foreach (ClrSegment seg in heap.Segments) { Assert.NotEqual(0ul, seg.Start); Assert.NotEqual(0ul, seg.End); Assert.True(seg.Start <= seg.End); Assert.True(seg.Start < seg.CommittedMemory.End); Assert.True(seg.CommittedMemory.End < seg.ReservedMemory.End); Assert.False(seg.CommittedMemory.Overlaps(seg.ReservedMemory)); Assert.True(seg.CommittedMemory.Contains(seg.ObjectRange)); if (seg.Generation0.Length > 0) { Assert.True(seg.ObjectRange.Contains(seg.Generation0)); } if (seg.Generation1.Length > 0) { Assert.True(seg.ObjectRange.Contains(seg.Generation1)); } if (seg.Generation2.Length > 0) { Assert.True(seg.ObjectRange.Contains(seg.Generation2)); } if (!seg.IsEphemeralSegment) { Assert.Equal(0ul, seg.Generation0.Length); Assert.Equal(0ul, seg.Generation1.Length); } int count = 0; foreach (ulong obj in seg.EnumerateObjects()) { ClrSegment curr = heap.GetSegmentByAddress(obj); Assert.Same(seg, curr); count++; } Assert.True(count >= 1); } }
public static void SetGenerationStats(ClrSegment clrSeg, ulong addr, ulong size, int[] cnts, ulong[] sizes) { addr = Utils.RealAddress(addr); if (clrSeg.IsLarge) { cnts[0] += 1; sizes[0] += size; } else { var gen = clrSeg.GetGeneration(addr); if (gen >= 0) { cnts[gen] += 1; sizes[gen] += size; } } }
/// <summary> /// Initializes a new instance of the <see cref="ClrSegmentAdapter" /> class. /// </summary> /// <param name="segment">The segment.</param> /// <exception cref="ArgumentNullException">segment</exception> /// <inheritdoc /> public ClrSegmentAdapter(IConverter converter, ClrSegment segment) : base(converter) { Segment = segment ?? throw new ArgumentNullException(nameof(segment)); CommittedEnd = Segment.CommittedEnd; End = Segment.End; FirstObject = Segment.FirstObject; Gen0Length = Segment.Gen0Length; Gen0Start = Segment.Gen0Start; Gen1Length = Segment.Gen1Length; Gen1Start = Segment.Gen1Start; Gen2Length = Segment.Gen2Length; Gen2Start = Segment.Gen2Start; IsEphemeral = Segment.IsEphemeral; IsLarge = Segment.IsLarge; Length = Segment.Length; ProcessorAffinity = Segment.ProcessorAffinity; ReservedEnd = Segment.ReservedEnd; Start = Segment.Start; }
public ClrtSegment(ClrSegment seg, ulong firstAddr, ulong lastAddr, int firstNdx, int endNdx) { CommittedEnd = seg.CommittedEnd; ReservedEnd = seg.ReservedEnd; Start = seg.Start; End = seg.End; Gen0Start = seg.Gen0Start; Gen0Length = seg.Gen0Length; Gen1Start = seg.Gen1Start; Gen1Length = seg.Gen1Length; Gen2Start = seg.Gen2Start; Gen2Length = seg.Gen2Length; FirstObject = seg.FirstObject; ProcessorAffinity = seg.ProcessorAffinity; Ephemeral = seg.IsEphemeral; Large = seg.IsLarge; FirstAddress = firstAddr; LastAddress = lastAddr; FirstIndex = firstNdx; EndIndex = endNdx; }
public void AllocationContextLocation() { // Simply test that we can enumerate the heap. using DataTarget dt = TestTargets.Types.LoadFullDump(); using ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime(); ClrHeap heap = runtime.Heap; // Ensure that we never find objects within allocation contexts. MemoryRange[] allocationContexts = heap.EnumerateAllocationContexts().ToArray(); Assert.NotEmpty(allocationContexts); foreach (MemoryRange ac in allocationContexts) { Assert.True(ac.Length > 0); ClrSegment seg = heap.GetSegmentByAddress(ac.Start); Assert.NotNull(seg); Assert.Same(seg, heap.GetSegmentByAddress(ac.End - 1)); Assert.True(seg.ObjectRange.Contains(ac)); } }
public static IEnumerable <ulong> EnumerateObjectAddresses(this ClrSegment segment, Func <ClrType, bool> predicate) { var address = segment.FirstObjectAddress; while (address != 0 && address < segment.CommittedMemory.End) { if (predicate != null) { var type = segment.Heap.GetObjectType(address); if (predicate(type)) { yield return(address); } } else { yield return(address); } address = segment.GetNextObjectAddress(address); } }
private static void CheckSegments(ClrHeap heap) { foreach (ClrSegment seg in heap.Segments) { Assert.AreNotEqual(0ul, seg.Start); Assert.AreNotEqual(0ul, seg.End); Assert.IsTrue(seg.Start <= seg.End); Assert.IsTrue(seg.Start < seg.CommittedEnd); Assert.IsTrue(seg.CommittedEnd < seg.ReservedEnd); if (!seg.IsEphemeral) { Assert.AreEqual(0ul, seg.Gen0Length); Assert.AreEqual(0ul, seg.Gen1Length); } foreach (ulong obj in seg.EnumerateObjectAddresses()) { ClrSegment curr = heap.GetSegmentByAddress(obj); Assert.AreSame(seg, curr); } } }
public ObjectSegmentEnum(ClrSegment seg) { m_seg = seg; m_obj = seg.FirstObject; }
public SegmentInformation(ClrSegment segment) => this.segment = segment;
public MDSegment(ClrSegment seg) { m_seg = seg; }