/// <summary> /// Gets the given object reference field from this ClrObject. /// </summary> /// <param name="fieldName">The name of the field to retrieve.</param> /// <returns>A ClrObject of the given field.</returns> /// <exception cref="ArgumentException"> /// The given field does not exist in the object. /// -or- /// The given field was not an object reference. /// </exception> public ClrObject GetObjectField(string fieldName) { ClrInstanceField?field = Type.GetFieldByName(fieldName); if (field is null) { throw new ArgumentException($"Type '{Type.Name}' does not contain a field named '{fieldName}'"); } if (!field.IsObjectReference) { throw new ArgumentException($"Field '{Type.Name}.{fieldName}' is not an object reference."); } ClrHeap heap = Type.Heap; ulong addr = field.GetAddress(Address, _interior); if (!DataReader.ReadPointer(addr, out ulong obj)) { throw new MemoryReadException(addr); } return(heap.GetObject(obj)); }
/// <summary> /// Enumerates all delegate targets of this delegate. If called on a MulitcastDelegate, this will enumerate all /// targets that will be called when this delegate is invoked. If called on a non-MulticastDelegate, this will /// enumerate the value of GetDelegateTarget. /// </summary> /// <returns></returns> public IEnumerable <ClrDelegateTarget> EnumerateDelegateTargets() { ClrDelegateTarget?first = GetDelegateTarget(); if (first != null) { yield return(first); } // The call to GetDelegateMethod will validate that we are a valid object and a subclass of System.Delegate if (!Object.TryReadField("_invocationCount", out int count) || count == 0 || !Object.TryReadObjectField("_invocationList", out ClrObject invocationList) || !invocationList.IsArray) { yield break; } ClrArray invocationArray = invocationList.AsArray(); count = Math.Min(count, invocationArray.Length); ClrHeap heap = Object.Type !.Heap; UIntPtr[]? pointers = invocationArray.ReadValues <UIntPtr>(0, count); if (pointers is not null) { foreach (UIntPtr ptr in pointers) { if (ptr == UIntPtr.Zero) { continue; } ClrObject delegateObj = heap.GetObject(ptr.ToUInt64()); if (delegateObj.IsDelegate) { ClrDelegateTarget?delegateTarget = new ClrDelegate(delegateObj).GetDelegateTarget(); if (delegateTarget is not null) { yield return(delegateTarget); } } } } }