Beispiel #1
0
        public void GetObjectField_WhenTypeHasFieldWithName_FindsField(ClrHeap heap, ClrType objectType, ClrInstanceField clrField, ulong clrObj, ulong fieldAddress, ulong fieldValue, string fieldName)
        {
            // Arrange
            heap.GetObjectType(Arg.Is <ulong>(address => address == clrObj || address == fieldValue)).Returns(objectType);

            objectType.GetFieldByName(fieldName).Returns(clrField);
            clrField.IsObjectReference.Returns(true);
            objectType.Heap.Returns(heap);

            clrField.GetAddress(clrObj).Returns(fieldAddress);

            heap.ReadPointer(fieldAddress, out var whatever)
            .Returns
                (call =>
            {
                call[1] = fieldValue;
                return(true);
            });

            // Act
            var fieldFoundByName = new ClrObject(clrObj, objectType).GetObjectField(fieldName);

            // Assert
            fieldFoundByName.Address.Should().Be(fieldValue);
        }
Beispiel #2
0
        public void RootCallback(IntPtr ptr, ulong addr, ulong obj, int hndType, uint refCount, int strong)
        {
            bool isDependent = hndType == (int)HandleType.Dependent;

            if ((isDependent && m_dependentSupport) || strong != 0)
            {
                if (Roots == null)
                {
                    Roots = new List <ClrRoot>(128);
                }

                string name = Enum.GetName(typeof(HandleType), hndType) + " handle";
                if (isDependent)
                {
                    ulong dependentTarget = obj;
                    if (!m_heap.ReadPointer(addr, out obj))
                    {
                        obj = 0;
                    }

                    ClrType type = m_heap.GetObjectType(obj);
                    Roots.Add(new RhHandleRoot(addr, obj, dependentTarget, type, hndType, m_domain, name));
                }
                else
                {
                    ClrType type = m_heap.GetObjectType(obj);
                    Roots.Add(new RhHandleRoot(addr, obj, type, hndType, m_domain, name));
                }
            }
        }
Beispiel #3
0
        protected virtual ClrObject[] ExecuteFallbackLogic(ClrObject clrObject)
        {
            int length;

            if (this.IsEmptyArray(clrObject, out length))
            {
                return(new ClrObject[0]);
            }

            var res = new ClrObject[length];

            ClrHeap heap        = clrObject.Type.Heap;
            int     pointerSize = heap.PointerSize;

            ulong arrayStart = this.CalculateArrayStart(clrObject, pointerSize);

            var isValueType = clrObject.Type.ComponentType.IsValueClass;

            var shiftSize = isValueType
        ? clrObject.Type.ComponentType.ElementSize
        : pointerSize;

            ulong dataReadPosition = arrayStart;

            for (int i = 0; i < length; i++)
            {
                dataReadPosition += (ulong)shiftSize;

                ulong     elemAddress;
                ClrObject clrObj;
                if (!isValueType)
                {
                    heap.ReadPointer(dataReadPosition, out elemAddress);
                    if (elemAddress == default(ulong))
                    {
                        continue;
                    }
                    clrObj = new ClrObject(elemAddress, clrObject.Type.Heap);
                }
                else
                {
                    clrObj = new ClrObject(dataReadPosition, clrObject.Type.Heap);
                }

                // object val = elemType.GetValue(elemAddress);
                // if (val == default(object) )
                // continue;
                // TODO: think should we skip object without type ?
                if (clrObj.Type == null)
                {
                    continue;
                }
                res[i] = clrObj;
            }

            return(res);
        }
Beispiel #4
0
        /// <summary>
        /// Returns only referenced objects that do not contain further pointers,
        /// and referenced arrays of objects that do not contain further pointers.
        /// This provides a fast estimate of the amount of memory that is likely
        /// only retained by the target object.
        /// </summary>
        public static IEnumerable <Tuple <ulong, ClrType> > FlatSubgraphOf(this ClrHeap heap, ulong objPtr)
        {
            var type = heap.GetObjectType(objPtr);

            if (type == null || type.IsFree || String.IsNullOrEmpty(type.Name))
            {
                yield break;
            }

            yield return(new Tuple <ulong, ClrType>(objPtr, type));

            List <Tuple <ulong, ClrType> > results = new List <Tuple <ulong, ClrType> >();

            type.EnumerateRefsOfObject(objPtr, (inner, offset) =>
            {
                var innerType = heap.GetObjectType(inner);

                if (innerType == null || innerType.IsFree)
                {
                    return;
                }
                if (innerType.IsArray &&
                    (innerType.ComponentType == null || innerType.ComponentType.ContainsPointers))
                {
                    return;
                }
                if (!innerType.IsArray && innerType.ContainsPointers)
                {
                    return;
                }

                results.Add(new Tuple <ulong, ClrType>(inner, innerType));

                // Value type instances are sized along with the containing array.
                if (innerType.IsArray && innerType.ElementType != ClrElementType.Struct)
                {
                    var arraySize = innerType.GetArrayLength(inner);
                    for (int i = 0; i < arraySize; ++i)
                    {
                        var address = innerType.GetArrayElementAddress(inner, i);
                        ulong value;
                        if (heap.ReadPointer(address, out value))
                        {
                            results.Add(new Tuple <ulong, ClrType>(
                                            value, innerType.ComponentType));
                        }
                    }
                }
            });

            foreach (var result in results)
            {
                yield return(result);
            }
        }
Beispiel #5
0
        public void GetObjectField_WhenHeapWasUnableToReadPointer_ThrowsMemoryReadException([Frozen] ClrHeap heap, [Frozen] ClrType objectType, ClrObject clrObject, ClrInstanceField clrField, ulong corruptedFieldPointer)
        {
            // Arrange
            clrField.IsObjectReference.Returns(true);
            clrField.GetAddress(clrObject.Address).Returns(corruptedFieldPointer);

            heap.ReadPointer(corruptedFieldPointer, out var whatever).Returns(false);

            // Act
            Action locateObjectFromValueTypeField = () => clrObject.GetObjectField(clrField.Name);

            // Assert
            locateObjectFromValueTypeField.Should().Throw <MemoryReadException>();
        }
Beispiel #6
0
        public void Can_cast_to_string()
        {
            var proxy = GetProxy <ClassWithStringField>();

            ClrType type = proxy.GetClrType();

            var address = type.GetFieldByName("Value").GetAddress((ulong)proxy);

            ulong stringAddress;

            _heap.ReadPointer(address, out stringAddress);

            Assert.AreEqual("OK", (string)_heap.GetProxy(stringAddress));
        }
Beispiel #7
0
        static protected TypeInstance GetObjectReference(ClrHeap heap, ulong objAddress, ClrType type, string fieldName, bool bInner = false)
        {
            var fieldType = type.GetFieldByName(fieldName);

            if (fieldType == null)
            {
                throw new ArgumentException(String.Format("Field {0} not found in type {1}", fieldName, type.Name));
            }
            ulong objAdr = fieldType.GetAddress(objAddress, bInner);

            if (!heap.ReadPointer(objAdr, out objAdr))
            {
                throw new InvalidOperationException(String.Format("Could not read from address 0x{0:X} which was field {1} in type {2}. Object Address: 0x:{3:X}", objAddress, fieldName, type.Name, objAddress));
            }
            return(new TypeInstance(objAdr, heap.GetObjectType(objAdr)));
        }
Beispiel #8
0
        public void GetObjectField_WhenTypeHasFieldWithName_FindsField([Frozen] ClrHeap heap, [Frozen] ClrType objectType, ClrObject source, ClrInstanceField clrField, ulong fieldAddress, ClrObject target)
        {
            // Arrange
            clrField.IsObjectReference.Returns(true);
            clrField.GetAddress(source.Address).Returns(fieldAddress);

            heap.ReadPointer(fieldAddress, out var whatever)
            .Returns(call =>
            {
                call[1] = target.Address;
                return(true);
            });

            // Act
            var fieldFoundByName = source.GetObjectField(clrField.Name);

            // Assert
            fieldFoundByName.Address.Should().Be(target);
        }
Beispiel #9
0
        public void GetObjectField_WhenFieldFound_ReturnsField([Frozen] ClrHeap heap, ClrObject target, [Frozen] ClrType structType, ClrValueClass someStruct, ClrInstanceField structReferenceField, ulong fieldAddress)
        {
            // Arrange
            structReferenceField.IsObjectReference.Returns(true);
            structReferenceField.GetAddress(someStruct.Address, Arg.Any <bool>()).Returns(fieldAddress);

            heap.ReadPointer(fieldAddress, out var whatever)
            .Returns(call =>
            {
                call[1] = target.Address;
                return(true);
            });

            // Act
            var structRefFieldTarget = someStruct.GetObjectField(structReferenceField.Name);

            // Assert
            structRefFieldTarget.Should().Be(target);
        }
Beispiel #10
0
        public void GetObjectField_WhenHeapWasUnableToReadPointer_ThrowsMemoryReadException(ClrHeap heap, ClrType objectType, ClrInstanceField clrField, ulong clrObj, ulong corruptedFieldPointer, string fieldName)
        {
            // Arrange
            heap.GetObjectType(clrObj).Returns(objectType);

            objectType.GetFieldByName(fieldName).Returns(clrField);
            clrField.IsObjectReference.Returns(true);
            objectType.Heap.Returns(heap);

            clrField.GetAddress(clrObj).Returns(corruptedFieldPointer);

            heap.ReadPointer(corruptedFieldPointer, out var whatever).Returns(false);

            // Act
            Action locateObjectFromValueTypeField = () => new ClrObject(clrObj, objectType).GetObjectField(fieldName);

            // Assert
            locateObjectFromValueTypeField.Should().Throw <MemoryReadException>();
        }
        public void GetFieldFrom_WhenStructureHasReferenceField_ReturnsField([Frozen] ClrHeap heap, ClrObject target, [Frozen] ClrType structType, ClrValueClass rawStruct, ClrInstanceField structReferenceField, ulong fieldAddress)
        {
            // Arrange
            IAddressableTypedEntity entity = rawStruct;

            structReferenceField.IsObjectReference.Returns(true);
            structReferenceField.GetAddress(entity.Address, Arg.Any <bool>()).Returns(fieldAddress);

            heap.ReadPointer(fieldAddress, out var whatever)
            .Returns(call =>
            {
                call[1] = target.Address;
                return(true);
            });

            // Act
            var fieldByName = entity.GetFieldFrom(structReferenceField.Name);

            // Assert
            fieldByName.Address.Should().Be(target.Address);
        }
        public void GetFieldFrom_WhenClrObjectHasReferenceField_ReturnsField([Frozen] ClrHeap heap, [Frozen] ClrType objectType, ClrObject rawClrObject, ClrInstanceField clrField, ulong fieldAddress, ClrObject target)
        {
            // Arrange
            IAddressableTypedEntity entity = rawClrObject;

            clrField.IsObjectReference.Returns(true);
            clrField.GetAddress(entity.Address).Returns(fieldAddress);

            heap.ReadPointer(fieldAddress, out var whatever)
            .Returns(call =>
            {
                call[1] = target.Address;
                return(true);
            });

            // Act
            var fieldFoundByName = entity.GetFieldFrom(clrField.Name);

            // Assert
            fieldFoundByName.Address.Should().Be(target.Address);
        }
Beispiel #13
0
 /// <summary>
 ///     Attempts to efficiently read a pointer from memory.  This acts exactly like ClrRuntime.ReadPointer, but
 ///     there is a greater chance you will hit a chache for a more efficient memory read.
 /// </summary>
 /// <param name="addr">The address to read.</param>
 /// <param name="value">The pointer value.</param>
 /// <returns>True if we successfully read the value, false if addr is not mapped into the process space.</returns>
 /// <inheritdoc />
 public bool ReadPointer(ulong addr, out ulong value) => Heap.ReadPointer(addr, out value);
        public StringSummary GetTypeReferenceStringSummary(ClrType referrerType, int fieldOffset, CancellationToken token = default)
        {
            var tallyByString = new Dictionary <string, ObjectTally>();

            ulong stringCount                 = 0;
            ulong stringByteCount             = 0;
            ulong totalManagedObjectByteCount = 0;
            long  charCount = 0;

            foreach (var seg in _heap.Segments)
            {
                var segType = seg.IsEphemeral
                    ? GCSegmentType.Ephemeral
                    : seg.IsLarge
                        ? GCSegmentType.LargeObject
                        : GCSegmentType.Regular;

                for (ulong refObj = seg.GetFirstObject(out ClrType referringType); refObj != 0; refObj = seg.NextObject(refObj, out referringType))
                {
                    if (referringType == null)
                    {
                        continue;
                    }

                    totalManagedObjectByteCount += referringType.GetSize(refObj);

                    if (!ReferenceEquals(referringType, referrerType))
                    {
                        continue;
                    }

                    token.ThrowIfCancellationRequested();

                    if (!_heap.ReadPointer(refObj + (ulong)fieldOffset, out var strObjRef) || strObjRef == 0)
                    {
                        continue;
                    }

                    var type = _heap.GetObjectType(strObjRef);
                    if (type == null)
                    {
                        continue;
                    }
                    var value = (string)type.GetValue(strObjRef);

                    charCount += value.Length;
                    stringCount++;

                    if (!tallyByString.TryGetValue(value, out var tally))
                    {
                        var size = type.GetSize(strObjRef);
                        tally = new ObjectTally(size);
                        tallyByString[value] = tally;
                    }

                    var strSeg     = _heap.GetSegmentByAddress(strObjRef);
                    int generation = strSeg.GetGeneration(strObjRef);
                    if (tally.Add(strObjRef, segType, generation))
                    {
                        stringByteCount += tally.InstanceSize;
                    }
                }
            }

            var uniqueStringCount     = tallyByString.Count;
            var stringCharCount       = tallyByString.Sum(s => s.Key.Length * (long)s.Value.Count);
            var uniqueStringCharCount = tallyByString.Keys.Sum(s => s.Length);
            var wastedBytes           = tallyByString.Values.Sum(t => (long)t.WastedBytes);
            var stringOverhead        = ((double)stringByteCount - (charCount * 2)) / stringCount;

            return(new StringSummary(
                       tallyByString.OrderByDescending(p => p.Value.WastedBytes)
                       .Select(
                           p => new StringItem(
                               p.Key,
                               (uint)p.Key.Length,
                               p.Value.InstanceSize,
                               p.Value.Addresses,
                               p.Value.CountBySegmentType,
                               p.Value.CountByGeneration)).ToList(),
                       totalManagedObjectByteCount,
                       stringByteCount,
                       (ulong)stringCharCount,
                       (ulong)uniqueStringCharCount,
                       stringCount,
                       (ulong)uniqueStringCount,
                       ulong.MaxValue, // TODO review
                       (ulong)wastedBytes,
                       (uint)Math.Round(stringOverhead)));
        }
Beispiel #15
0
        public async Task <IEnumerable <object> > Execute(OperationModel model, CancellationToken token, object customeParameter)
        {
            //TODO: add support of local variables
            return(await DebuggerSession.Instance.ExecuteOperation(() =>
            {
                var result = new List <ClrStackDump>();
                foreach (var thread in DebuggerSession.Instance.Runtime.Threads)
                {
                    if (token.IsCancellationRequested)
                    {
                        break;
                    }

                    var stackDetails = new ClrStackDump();
                    stackDetails.StackFrames = new List <object>();
                    stackDetails.StackObjects = new List <object>();
                    foreach (var stackFrame in thread.StackTrace)
                    {
                        stackDetails.StackBase = thread.StackBase;
                        stackDetails.StackLimit = thread.StackLimit;
                        stackDetails.Exception = thread.CurrentException;
                        stackDetails.OSThreadID = thread.IsAlive ? thread.OSThreadId.ToString() : "XXX";
                        stackDetails.ManagedThreadId = thread.ManagedThreadId;
                        stackDetails.StackFrames.Add(
                            new
                        {
                            StackPointer = stackFrame.StackPointer,
                            InstructionPointer = stackFrame.InstructionPointer,
                            DisplayString = stackFrame.DisplayString,
                            //FileAndLine = source != null ? source.FilePath + ": " + source.LineNumber : "",
                            Method = stackFrame.Method
                        });
                    }

                    ClrHeap heap = DebuggerSession.Instance.Runtime.GetHeap();
                    var pointerSize = DebuggerSession.Instance.Runtime.PointerSize;

                    // address of TEB (thread execution block) + pointer size
                    ulong start = thread.StackBase;
                    // address of TEB (thread execution block) + pointer size * 2
                    ulong stop = thread.StackLimit;

                    // We'll walk these in pointer order.
                    if (start > stop)
                    {
                        ulong tmp = start;
                        start = stop;
                        stop = tmp;
                    }

                    // ptr is a stack address.
                    for (ulong ptr = start; ptr <= stop; ptr += (ulong)pointerSize)
                    {
                        HashSet <ulong> stackObjects = new HashSet <ulong>();

                        // fail to read the memory
                        if (!heap.ReadPointer(ptr, out ulong obj))
                        {
                            break;
                        }

                        // the object added already
                        if (!stackObjects.Add(obj))
                        {
                            continue;
                        }

                        // not an object
                        ClrType type = heap.GetObjectType(obj);
                        if (type == null)
                        {
                            continue;
                        }

                        // free space
                        if (type.IsFree)
                        {
                            continue;
                        }

                        // All good, add it
                        stackDetails.StackObjects.Add(
                            new
                        {
                            Address = ptr,
                            Object = obj,
                            Name = type.Name,
                            Value = new ClrObject(obj, type).Fields.Value
                        });
                    }
                    result.Add(stackDetails);
                }
                return result;
            }));
        }