diff --git a/src/Microsoft.Diagnostics.Runtime/ClrArray.cs b/src/Microsoft.Diagnostics.Runtime/ClrArray.cs index 506346b35..cc44e5235 100644 --- a/src/Microsoft.Diagnostics.Runtime/ClrArray.cs +++ b/src/Microsoft.Diagnostics.Runtime/ClrArray.cs @@ -33,7 +33,7 @@ public int Length { if (_length == -1) { - _length = Type.Module.DataReader.Read(Address + (ulong)IntPtr.Size); + _length = Type.Module.DataReader.Read(Address + (ulong)Type.Module.DataReader.PointerSize); } return _length; @@ -49,9 +49,9 @@ public readonly int Rank } } - private readonly bool IsMultiDimensional => Type.StaticSize > (uint)(3 * IntPtr.Size); + private readonly bool IsMultiDimensional => Type.StaticSize > (uint)(3 * Type.Module.DataReader.PointerSize); - private readonly int MultiDimensionalRank => (int)((Type.StaticSize - (uint)(3 * IntPtr.Size)) / (2 * sizeof(int))); + private readonly int MultiDimensionalRank => (int)((Type.StaticSize - (uint)(3 * Type.Module.DataReader.PointerSize)) / (2 * sizeof(int))); IClrType IClrArray.Type => Type; @@ -183,7 +183,10 @@ public ClrObject GetObjectValue(int index) if (Type.ComponentType != null && !Type.ComponentType.IsObjectReference) throw new InvalidOperationException($"{Type} does not contain object references."); - return Type.Heap.GetObject(ReadValue(index)); + int pointerSize = Type.Module.DataReader.PointerSize; + ulong address = GetElementAddress(pointerSize, index); + Type.Module.DataReader.ReadPointer(address, out ulong value); + return Type.Heap.GetObject(value); } public ClrObject GetObjectValue(params int[] indices) @@ -191,7 +194,10 @@ public ClrObject GetObjectValue(params int[] indices) if (Type.ComponentType != null && !Type.ComponentType.IsObjectReference) throw new InvalidOperationException($"{Type} does not contain object references."); - return Type.Heap.GetObject(ReadValue(indices)); + int pointerSize = Type.Module.DataReader.PointerSize; + ulong address = GetElementAddress(pointerSize, indices); + Type.Module.DataReader.ReadPointer(address, out ulong value); + return Type.Heap.GetObject(value); } private unsafe T ReadValue(int index) where T : unmanaged @@ -210,7 +216,7 @@ private unsafe ulong GetElementAddress(int elementSize, int index) throw new ArgumentException($"Array {Address:x} was not a one-dimensional array. Type: {Type?.Name ?? "null"}"); int valueOffset = index; - int dataByteOffset = 2 * sizeof(nint); + int dataByteOffset = 2 * Type.Module.DataReader.PointerSize; if (IsMultiDimensional) { @@ -240,7 +246,7 @@ private unsafe ulong GetElementAddress(int elementSize, int[] indices) throw new ArgumentException($"Indices length does not match the array rank. Array {Address:x} Rank = {rank}, {nameof(indices)} Rank = {indices.Length}"); int valueOffset = 0; - int dataByteOffset = 2 * sizeof(nint); + int dataByteOffset = 2 * Type.Module.DataReader.PointerSize; if (rank == 1) { @@ -285,7 +291,7 @@ private unsafe ulong GetElementAddress(int elementSize, int[] indices) // ^ // | Address private readonly int GetMultiDimensionalBound(int offset) => - Type.Module.DataReader.Read(Address + (ulong)(2 * IntPtr.Size) + (ulong)(offset * sizeof(int))); + Type.Module.DataReader.Read(Address + (ulong)(2 * Type.Module.DataReader.PointerSize) + (ulong)(offset * sizeof(int))); IClrValue IClrArray.GetObjectValue(int index) => GetObjectValue(index); diff --git a/src/Microsoft.Diagnostics.Runtime/ClrDelegate.cs b/src/Microsoft.Diagnostics.Runtime/ClrDelegate.cs index b1cac36ed..6a7a1e9b3 100644 --- a/src/Microsoft.Diagnostics.Runtime/ClrDelegate.cs +++ b/src/Microsoft.Diagnostics.Runtime/ClrDelegate.cs @@ -71,7 +71,7 @@ public bool HasMultipleTargets { if (field.ElementType == ClrElementType.NativeInt) { - ulong targetMethod = field.Read(Object, interior: false).ToUInt64(); + ulong targetMethod = field.ReadPointer(Object.Address, interior: false); if (targetMethod != 0) { @@ -184,23 +184,17 @@ public IEnumerable EnumerateDelegateTargets() ClrArray invocationArray = invocationList.AsArray(); count = Math.Min(count, invocationArray.Length); - ClrHeap heap = Object.Type!.Heap; - - UIntPtr[]? pointers = invocationArray.ReadValues(0, count); - if (pointers is not null) + for (int i = 0; i < count; i++) { - foreach (UIntPtr ptr in pointers) - { - if (ptr == UIntPtr.Zero) - continue; + ClrObject delegateObj = invocationArray.GetObjectValue(i); + if (!delegateObj.IsValid || delegateObj.Address == 0) + continue; - ClrObject delegateObj = heap.GetObject(ptr.ToUInt64()); - if (delegateObj.IsDelegate) - { - ClrDelegateTarget? delegateTarget = new ClrDelegate(delegateObj).GetDelegateTarget(); - if (delegateTarget is not null) - yield return delegateTarget; - } + if (delegateObj.IsDelegate) + { + ClrDelegateTarget? delegateTarget = new ClrDelegate(delegateObj).GetDelegateTarget(); + if (delegateTarget is not null) + yield return delegateTarget; } } } diff --git a/src/Microsoft.Diagnostics.Runtime/ClrEnum.cs b/src/Microsoft.Diagnostics.Runtime/ClrEnum.cs index 1d6adbf7d..d9ce6c10b 100644 --- a/src/Microsoft.Diagnostics.Runtime/ClrEnum.cs +++ b/src/Microsoft.Diagnostics.Runtime/ClrEnum.cs @@ -81,23 +81,27 @@ public T GetEnumValue(string name) where T : unmanaged return values.ToArray(); } - private unsafe object? GetValueForPointer(ClrElementType pdwCPlusTypeFlag, IntPtr ppValue) => pdwCPlusTypeFlag switch + private unsafe object? GetValueForPointer(ClrElementType pdwCPlusTypeFlag, IntPtr ppValue) { - ClrElementType.Boolean => *(byte*)ppValue, - ClrElementType.Char => *(char*)ppValue, - ClrElementType.Double => *(double*)ppValue, - ClrElementType.Float => *(float*)ppValue, - ClrElementType.Int8 => *(sbyte*)ppValue, - ClrElementType.Int16 => *(short*)ppValue, - ClrElementType.Int32 => *(int*)ppValue, - ClrElementType.Int64 => *(long*)ppValue, - ClrElementType.UInt8 => *(byte*)ppValue, - ClrElementType.UInt16 => *(ushort*)ppValue, - ClrElementType.UInt32 => *(uint*)ppValue, - ClrElementType.UInt64 => *(ulong*)ppValue, - ClrElementType.NativeInt => *(nint*)ppValue, - ClrElementType.NativeUInt => *(nuint*)ppValue, - _ => null, - }; + int pointerSize = Type.Module.DataReader.PointerSize; + return pdwCPlusTypeFlag switch + { + ClrElementType.Boolean => *(byte*)ppValue, + ClrElementType.Char => *(char*)ppValue, + ClrElementType.Double => *(double*)ppValue, + ClrElementType.Float => *(float*)ppValue, + ClrElementType.Int8 => *(sbyte*)ppValue, + ClrElementType.Int16 => *(short*)ppValue, + ClrElementType.Int32 => *(int*)ppValue, + ClrElementType.Int64 => *(long*)ppValue, + ClrElementType.UInt8 => *(byte*)ppValue, + ClrElementType.UInt16 => *(ushort*)ppValue, + ClrElementType.UInt32 => *(uint*)ppValue, + ClrElementType.UInt64 => *(ulong*)ppValue, + ClrElementType.NativeInt => pointerSize == 8 ? *(long*)ppValue : *(int*)ppValue, + ClrElementType.NativeUInt => pointerSize == 8 ? *(ulong*)ppValue : *(uint*)ppValue, + _ => null, + }; + } } } \ No newline at end of file diff --git a/src/Microsoft.Diagnostics.Runtime/ClrException.cs b/src/Microsoft.Diagnostics.Runtime/ClrException.cs index 98bb0fb24..be9a03482 100644 --- a/src/Microsoft.Diagnostics.Runtime/ClrException.cs +++ b/src/Microsoft.Diagnostics.Runtime/ClrException.cs @@ -142,10 +142,11 @@ public override string ToString() private uint GetStackTraceOffset(ClrType type) { + int pointerSize = Type.Module.DataReader.PointerSize; ClrField? field = type.Fields.FirstOrDefault(f => f.Name == "_stackTrace"); if (field != null && field.Offset >= 0) - return (uint)(field.Offset + IntPtr.Size); + return (uint)(field.Offset + pointerSize); uint result = Type.Module.Heap.Runtime.ClrInfo.Flavor switch { @@ -166,15 +167,16 @@ private uint GetStackTraceOffset(ClrType type) _ => uint.MaxValue }; - return result == uint.MaxValue ? 0 : result + (uint)IntPtr.Size; + return result == uint.MaxValue ? 0 : result + (uint)pointerSize; } private uint GetInnerExceptionOffset(ClrType type) { + int pointerSize = Type.Module.DataReader.PointerSize; ClrField? field = type.Fields.FirstOrDefault(f => f.Name == "_innerException"); if (field != null && field.Offset >= 0) - return (uint)(field.Offset + IntPtr.Size); + return (uint)(field.Offset + pointerSize); uint result = Type.Module.Heap.Runtime.ClrInfo.Flavor switch { @@ -195,15 +197,16 @@ private uint GetInnerExceptionOffset(ClrType type) _ => uint.MaxValue }; - return result == uint.MaxValue ? 0 : result + (uint)IntPtr.Size; + return result == uint.MaxValue ? 0 : result + (uint)pointerSize; } private uint GetHResultOffset(ClrType type) { + int pointerSize = Type.Module.DataReader.PointerSize; ClrField? field = type.Fields.FirstOrDefault(f => f.Name == "_HResult"); if (field != null && field.Offset >= 0) - return (uint)(field.Offset + IntPtr.Size); + return (uint)(field.Offset + pointerSize); uint result = Type.Module.Heap.Runtime.ClrInfo.Flavor switch { @@ -224,15 +227,16 @@ private uint GetHResultOffset(ClrType type) _ => uint.MaxValue }; - return result == uint.MaxValue ? 0 : result + (uint)IntPtr.Size; + return result == uint.MaxValue ? 0 : result + (uint)pointerSize; } private uint GetMessageOffset(ClrType type) { + int pointerSize = Type.Module.DataReader.PointerSize; ClrField? field = type.Fields.FirstOrDefault(f => f.Name == "_message"); if (field != null && field.Offset >= 0) - return (uint)(field.Offset + IntPtr.Size); + return (uint)(field.Offset + pointerSize); uint result = Type.Module.Heap.Runtime.ClrInfo.Flavor switch { @@ -253,7 +257,7 @@ private uint GetMessageOffset(ClrType type) _ => uint.MaxValue }; - return result == uint.MaxValue ? 0 : result + (uint)IntPtr.Size; + return result == uint.MaxValue ? 0 : result + (uint)pointerSize; } private ImmutableArray GetExceptionStackTrace() @@ -264,6 +268,7 @@ private ImmutableArray GetExceptionStackTrace() return ImmutableArray.Empty; IDataReader dataReader = Type.Module.DataReader; + int pointerSize = dataReader.PointerSize; ulong address = dataReader.ReadPointer(_object.Address + offset); ClrObject _stackTrace = Type.Module.Heap.GetObject(address); @@ -274,8 +279,8 @@ private ImmutableArray GetExceptionStackTrace() if (len == 0) return ImmutableArray.Empty; - int elementSize = IntPtr.Size * 4; - ulong dataPtr = _stackTrace + (ulong)(IntPtr.Size * 2); + int elementSize = pointerSize * 4; + ulong dataPtr = _stackTrace + (ulong)(pointerSize * 2); if (!dataReader.ReadPointer(dataPtr, out ulong count)) return ImmutableArray.Empty; @@ -283,13 +288,13 @@ private ImmutableArray GetExceptionStackTrace() result.Count = result.Capacity; // Skip size and header - dataPtr += (ulong)(IntPtr.Size * 2); + dataPtr += (ulong)(pointerSize * 2); for (int i = 0; i < (int)count; ++i) { ulong ip = dataReader.ReadPointer(dataPtr); - ulong sp = dataReader.ReadPointer(dataPtr + (ulong)IntPtr.Size); - ulong md = dataReader.ReadPointer(dataPtr + (ulong)IntPtr.Size + (ulong)IntPtr.Size); + ulong sp = dataReader.ReadPointer(dataPtr + (ulong)pointerSize); + ulong md = dataReader.ReadPointer(dataPtr + (ulong)pointerSize + (ulong)pointerSize); ClrMethod? method = Type.Module.Heap.Runtime.GetMethodByHandle(md); result[i] = new ClrStackFrame(Thread, null, ip, sp, ClrStackFrameKind.ManagedMethod, method, frameName: null); diff --git a/src/Microsoft.Diagnostics.Runtime/ClrField.cs b/src/Microsoft.Diagnostics.Runtime/ClrField.cs index 6edba70fc..af9b15263 100644 --- a/src/Microsoft.Diagnostics.Runtime/ClrField.cs +++ b/src/Microsoft.Diagnostics.Runtime/ClrField.cs @@ -172,7 +172,7 @@ private void InitData(bool forName) /// /// Gets the size of this field. /// - public int Size => GetSize(Type, ElementType); + public int Size => GetSize(Type, ElementType, ContainingType.Module.DataReader.PointerSize); /// /// Attributes of this field; @@ -205,7 +205,7 @@ public FieldAttributes Attributes return $"{type.Name} {Name}"; } - internal static int GetSize(ClrType? type, ClrElementType cet) + internal static int GetSize(ClrType? type, ClrElementType cet, int pointerSize) { // todo: What if we have a struct which is not fully constructed (null MT, // null type) and need to get the size of the field? @@ -255,7 +255,7 @@ internal static int GetSize(ClrType? type, ClrElementType cet) case ClrElementType.NativeUInt: // native unsigned int case ClrElementType.Pointer: case ClrElementType.FunctionPointer: - return IntPtr.Size; + return pointerSize; case ClrElementType.UInt16: case ClrElementType.Int16: diff --git a/src/Microsoft.Diagnostics.Runtime/ClrHeap.cs b/src/Microsoft.Diagnostics.Runtime/ClrHeap.cs index 83541dfd6..d55a388d7 100644 --- a/src/Microsoft.Diagnostics.Runtime/ClrHeap.cs +++ b/src/Microsoft.Diagnostics.Runtime/ClrHeap.cs @@ -29,8 +29,8 @@ public sealed class ClrHeap : IClrHeap private const int SyncBlockIndexBits = 26; private const uint SyncBlockIndexMask = ((1u << SyncBlockIndexBits) - 1u); - private readonly uint _firstChar = (uint)IntPtr.Size + 4; - private readonly uint _stringLength = (uint)IntPtr.Size; + private readonly uint _firstChar; + private readonly uint _stringLength; private readonly ClrTypeFactory _typeFactory; private readonly IMemoryReader _memoryReader; @@ -45,6 +45,8 @@ internal ClrHeap(ClrRuntime runtime, IMemoryReader memoryReader, IAbstractHeap h { Runtime = runtime; _memoryReader = memoryReader; + _firstChar = (uint)memoryReader.PointerSize + 4; + _stringLength = (uint)memoryReader.PointerSize; Helpers = helpers; GCState gcInfo = helpers.State; @@ -511,7 +513,7 @@ public bool ReadPointer(ulong address, out ulong value) return _memoryReader.ReadPointer(address, out value); int offset = (int)(address - Base); - value = _cache.AsSpan().AsPointer(offset); + value = _cache.AsSpan().AsPointer(_pointerSize, offset); return true; } @@ -630,7 +632,7 @@ private ulong SkipAllocationContext(ClrSegment seg, ulong address) Dictionary allocationContexts = GetAllocationContexts(); - uint minObjSize = (uint)IntPtr.Size * 3; + uint minObjSize = (uint)_memoryReader.PointerSize * 3; while (allocationContexts.TryGetValue(address, out ulong nextObj)) { nextObj += Align(minObjSize, seg); @@ -645,12 +647,12 @@ private ulong SkipAllocationContext(ClrSegment seg, ulong address) return address; } - private static ulong Align(ulong size, ClrSegment seg) + private ulong Align(ulong size, ClrSegment seg) { ulong AlignConst; ulong AlignLargeConst = 7; - if (IntPtr.Size == 4) + if (_memoryReader.PointerSize == 4) AlignConst = 3; else AlignConst = 7; @@ -691,7 +693,8 @@ public IEnumerable EnumerateRoots() ClrArray array = m_userObject.AsArray(); for (int i = 0; i < array.Length; i++) { - ulong innerAddress = m_userObject + (ulong)(2 * IntPtr.Size + i * IntPtr.Size); + int pointerSize = _memoryReader.PointerSize; + ulong innerAddress = m_userObject + (ulong)(2 * pointerSize + i * pointerSize); ClrObject innerObj = array.GetObjectValue(i); if (innerObj.IsValid) @@ -855,7 +858,7 @@ internal ulong GetObjectSize(ulong objRef, ClrType type) } else { - uint countOffset = (uint)IntPtr.Size; + uint countOffset = (uint)_memoryReader.PointerSize; ulong loc = objRef + countOffset; uint count = _memoryReader.Read(loc); @@ -867,7 +870,7 @@ internal ulong GetObjectSize(ulong objRef, ClrType type) size = count * (ulong)type.ComponentSize + (ulong)type.StaticSize; } - uint minSize = (uint)IntPtr.Size * 3; + uint minSize = (uint)_memoryReader.PointerSize * 3; if (size < minSize) size = minSize; return size; @@ -938,7 +941,7 @@ internal IEnumerable EnumerateObjectReferences(ulong obj, ClrType typ int intSize = (int)size; byte[] buffer = ArrayPool.Shared.Rent(intSize); int read = _memoryReader.Read(obj, new Span(buffer, 0, intSize)); - if (read > IntPtr.Size) + if (read > _memoryReader.PointerSize) { foreach ((ulong reference, int offset) in gcdesc.WalkObject(buffer, read)) yield return new(reference, GetObjectType(reference) ?? ErrorType); @@ -1008,14 +1011,14 @@ internal IEnumerable EnumerateReferencesWithFields(ulong obj, ClrT int intSize = (int)size; byte[] buffer = ArrayPool.Shared.Rent(intSize); int read = _memoryReader.Read(obj, new Span(buffer, 0, intSize)); - if (read > IntPtr.Size) + if (read > _memoryReader.PointerSize) { foreach ((ulong reference, int offset) in gcdesc.WalkObject(buffer, read)) { ClrObject target = new(reference, GetObjectType(reference) ?? ErrorType); - DebugOnly.Assert(offset >= IntPtr.Size); - yield return ClrReference.CreateFromFieldOrArray(target, type, offset - IntPtr.Size); + DebugOnly.Assert(offset >= _memoryReader.PointerSize); + yield return ClrReference.CreateFromFieldOrArray(target, type, offset - _memoryReader.PointerSize); } } ArrayPool.Shared.Return(buffer); @@ -1078,12 +1081,12 @@ internal IEnumerable EnumerateReferenceAddresses(ulong obj, ClrType type, int intSize = (int)size; byte[] buffer = ArrayPool.Shared.Rent(intSize); int read = _memoryReader.Read(obj, new Span(buffer, 0, intSize)); - if (read > IntPtr.Size) + if (read > _memoryReader.PointerSize) { foreach ((ulong reference, int offset) in gcdesc.WalkObject(buffer, read)) { yield return reference; - DebugOnly.Assert(offset >= IntPtr.Size); + DebugOnly.Assert(offset >= _memoryReader.PointerSize); } } ArrayPool.Shared.Return(buffer); @@ -1125,7 +1128,7 @@ private IEnumerable EnumerateFinalizers(IEnumerable memory { foreach (MemoryRange seg in memoryRanges) { - for (ulong ptr = seg.Start; ptr < seg.End; ptr += (uint)IntPtr.Size) + for (ulong ptr = seg.Start; ptr < seg.End; ptr += (uint)_memoryReader.PointerSize) { ulong obj = _memoryReader.ReadPointer(ptr); if (obj == 0) diff --git a/src/Microsoft.Diagnostics.Runtime/ClrInstanceField.cs b/src/Microsoft.Diagnostics.Runtime/ClrInstanceField.cs index 02c25b11a..d20a8001d 100644 --- a/src/Microsoft.Diagnostics.Runtime/ClrInstanceField.cs +++ b/src/Microsoft.Diagnostics.Runtime/ClrInstanceField.cs @@ -37,6 +37,21 @@ public T Read(ulong objRef, bool interior) where T : unmanaged return value; } + /// + /// Reads the value of a pointer-sized field using the target's pointer size. + /// + internal ulong ReadPointer(ulong objRef, bool interior) + { + ulong address = GetAddress(objRef, interior); + if (address == 0) + return 0; + + if (!ContainingType.Module.DataReader.ReadPointer(address, out ulong value)) + return 0; + + return value; + } + /// /// Reads the value of an object field. /// @@ -110,7 +125,7 @@ public ulong GetAddress(ulong objRef, bool interior) if (interior) return objRef + (ulong)Offset; - return objRef + (ulong)(Offset + IntPtr.Size); + return objRef + (ulong)(Offset + ContainingType.Module.DataReader.PointerSize); } } } \ No newline at end of file diff --git a/src/Microsoft.Diagnostics.Runtime/ClrObject.cs b/src/Microsoft.Diagnostics.Runtime/ClrObject.cs index 3d80041ed..a95077bd6 100644 --- a/src/Microsoft.Diagnostics.Runtime/ClrObject.cs +++ b/src/Microsoft.Diagnostics.Runtime/ClrObject.cs @@ -109,7 +109,7 @@ public T ReadBoxedValue() where T : unmanaged if (helpers is null) return default; - return DataReader.Read(Address + (ulong)IntPtr.Size); + return DataReader.Read(Address + (ulong)DataReader.PointerSize); } public bool IsException => Type != null && Type.IsException; @@ -492,9 +492,17 @@ public bool TryReadField(string fieldName, out T result) ulong mt; if (field.ElementType == ClrElementType.NativeInt) - mt = (ulong)ReadField("m_handle"); + { + mt = field.ReadPointer(Address, interior: false); + } else - mt = (ulong)ReadValueTypeField("m_handle").ReadField("m_ptr"); + { + ClrValueType handle = ReadValueTypeField("m_handle"); + ClrInstanceField? ptrField = handle.Type?.GetFieldByName("m_ptr"); + if (ptrField is null) + return null; + mt = ptrField.ReadPointer(handle.Address, interior: true); + } return type.Heap.Runtime.GetTypeByMethodTable(mt); } diff --git a/src/Microsoft.Diagnostics.Runtime/DacImplementation/DacHeap.cs b/src/Microsoft.Diagnostics.Runtime/DacImplementation/DacHeap.cs index 088ec4862..6aa391b73 100644 --- a/src/Microsoft.Diagnostics.Runtime/DacImplementation/DacHeap.cs +++ b/src/Microsoft.Diagnostics.Runtime/DacImplementation/DacHeap.cs @@ -290,7 +290,7 @@ private bool TryCreateSegment(SubHeapInfo subHeap, ulong address, int generation ulong committedStart; if (kind == GCSegmentKind.Frozen) - committedStart = allocated.Start - (uint)IntPtr.Size; + committedStart = allocated.Start - (uint)_memoryReader.PointerSize; else if ((allocated.Start & 0x1ffful) == 0x1000) committedStart = allocated.Start - 0x1000; else diff --git a/src/Microsoft.Diagnostics.Runtime/DacImplementation/DacThreadHelpers.cs b/src/Microsoft.Diagnostics.Runtime/DacImplementation/DacThreadHelpers.cs index ed1b1a058..104effb12 100644 --- a/src/Microsoft.Diagnostics.Runtime/DacImplementation/DacThreadHelpers.cs +++ b/src/Microsoft.Diagnostics.Runtime/DacImplementation/DacThreadHelpers.cs @@ -144,8 +144,8 @@ public IEnumerable EnumerateStackTrace(uint osThreadId, bool inc break; } - ulong ip = context.AsSpan().AsPointer(ipOffset); - ulong sp = context.AsSpan().AsPointer(spOffset); + ulong ip = context.AsSpan().AsPointer(_dataReader.PointerSize, ipOffset); + ulong sp = context.AsSpan().AsPointer(_dataReader.PointerSize, spOffset); ulong frameVtbl = stackwalk.GetFrameVtable(); string? frameName = null; diff --git a/src/Microsoft.Diagnostics.Runtime/DacInterface/MetadataImport.cs b/src/Microsoft.Diagnostics.Runtime/DacInterface/MetadataImport.cs index 023841a26..9c7b2c845 100644 --- a/src/Microsoft.Diagnostics.Runtime/DacInterface/MetadataImport.cs +++ b/src/Microsoft.Diagnostics.Runtime/DacInterface/MetadataImport.cs @@ -233,14 +233,6 @@ public bool GetGenericParamProps(int token, out int index, out GenericParameterA return true; } - public SigParser GetSigFromToken(int token) - { - HResult hr = VTable.GetSigFromToken(Self, token, out IntPtr sig, out int len); - if (hr) - return new SigParser(sig, len); - - return default; - } } [StructLayout(LayoutKind.Sequential)] @@ -284,7 +276,7 @@ internal readonly unsafe struct IMetaDataImportVTable private readonly IntPtr GetFieldMarshal; public readonly delegate* unmanaged[Stdcall] GetRVA; private readonly IntPtr GetPermissionSetProps; - public readonly delegate* unmanaged[Stdcall] GetSigFromToken; + private readonly IntPtr GetSigFromToken; private readonly IntPtr GetModuleRefProps; private readonly IntPtr EnumModuleRefs; private readonly IntPtr GetTypeSpecFromToken; diff --git a/src/Microsoft.Diagnostics.Runtime/DataReaders/CommonMemoryReader.cs b/src/Microsoft.Diagnostics.Runtime/DataReaders/CommonMemoryReader.cs index f2d46f6ec..a4f2f671a 100644 --- a/src/Microsoft.Diagnostics.Runtime/DataReaders/CommonMemoryReader.cs +++ b/src/Microsoft.Diagnostics.Runtime/DataReaders/CommonMemoryReader.cs @@ -36,10 +36,11 @@ public T Read(ulong address) public bool ReadPointer(ulong address, out ulong value) { - Span buffer = stackalloc byte[IntPtr.Size]; - if (Read(address, buffer) == IntPtr.Size) + int pointerSize = PointerSize; + Span buffer = stackalloc byte[pointerSize]; + if (Read(address, buffer) == pointerSize) { - value = buffer.AsPointer(); + value = buffer.AsPointer(pointerSize, 0); return true; } diff --git a/src/Microsoft.Diagnostics.Runtime/Extensions/SpanExtensions.cs b/src/Microsoft.Diagnostics.Runtime/Extensions/SpanExtensions.cs index d2db7c153..21c473dfe 100644 --- a/src/Microsoft.Diagnostics.Runtime/Extensions/SpanExtensions.cs +++ b/src/Microsoft.Diagnostics.Runtime/Extensions/SpanExtensions.cs @@ -45,19 +45,24 @@ public static unsafe string GetString(this Encoding encoding, ReadOnlySpan } } #endif - public static unsafe ulong AsPointer(this Span span) => AsPointer(span, 0); - - public static unsafe ulong AsPointer(this Span span, int offset = 0) + public static unsafe ulong AsPointer(this Span span, int pointerSize, int offset) { if (offset > 0) span = span.Slice(offset); - DebugOnly.Assert(span.Length >= sizeof(nuint)); - DebugOnly.Assert(unchecked((int)Unsafe.AsPointer(ref MemoryMarshal.GetReference(span))) % sizeof(nuint) == 0); - return Unsafe.As(ref MemoryMarshal.GetReference(span)); + if (pointerSize == 8) + { + DebugOnly.Assert(span.Length >= sizeof(ulong)); + return Unsafe.As(ref MemoryMarshal.GetReference(span)); + } + else + { + DebugOnly.Assert(span.Length >= sizeof(uint)); + return Unsafe.As(ref MemoryMarshal.GetReference(span)); + } } - public static unsafe ulong AsPointer(this Span span, ulong offset = 0) => AsPointer(span, (int)offset); + public static unsafe ulong AsPointer(this Span span, int pointerSize, ulong offset) => AsPointer(span, pointerSize, (int)offset); public static unsafe int AsInt32(this Span span, int offset = 0) { diff --git a/src/Microsoft.Diagnostics.Runtime/GCDesc.cs b/src/Microsoft.Diagnostics.Runtime/GCDesc.cs index 658a95f29..a1222ec57 100644 --- a/src/Microsoft.Diagnostics.Runtime/GCDesc.cs +++ b/src/Microsoft.Diagnostics.Runtime/GCDesc.cs @@ -8,20 +8,23 @@ namespace Microsoft.Diagnostics.Runtime { public readonly struct GCDesc { - private static readonly int s_GCDescSize = IntPtr.Size * 2; + private readonly int _pointerSize; + private readonly int _gcDescSize; private readonly byte[] _data; public bool IsEmpty => _data is null; - public GCDesc(byte[] data) + public GCDesc(byte[] data, int pointerSize) { _data = data; + _pointerSize = pointerSize; + _gcDescSize = pointerSize * 2; } public IEnumerable<(ulong ReferencedObject, int Offset)> WalkObject(byte[] buffer, int size) { - DebugOnly.Assert(size >= IntPtr.Size); + DebugOnly.Assert(size >= _pointerSize); int series = GetNumSeries(); int highest = GetHighestSeries(); @@ -37,35 +40,35 @@ public GCDesc(byte[] data) while (offset < stop) { - ulong ret = new Span(buffer).AsPointer((int)offset); + ulong ret = new Span(buffer).AsPointer(_pointerSize, (int)offset); if (ret != 0) yield return (ret, (int)offset); - offset += IntPtr.Size; + offset += _pointerSize; } - curr -= s_GCDescSize; + curr -= _gcDescSize; } while (curr >= lowest); } else { long offset = GetSeriesOffset(curr); - while (offset < size - IntPtr.Size) + while (offset < size - _pointerSize) { for (int i = 0; i > series; i--) { int nptrs = GetPointers(curr, i); int skip = GetSkip(curr, i); - long stop = offset + (nptrs * IntPtr.Size); + long stop = offset + (nptrs * _pointerSize); do { - ulong ret = new Span(buffer).AsPointer((int)offset); + ulong ret = new Span(buffer).AsPointer(_pointerSize, (int)offset); if (ret != 0) yield return (ret, (int)offset); - offset += IntPtr.Size; + offset += _pointerSize; } while (offset < stop); offset += skip; @@ -76,8 +79,8 @@ public GCDesc(byte[] data) private int GetPointers(int curr, int i) { - int offset = i * IntPtr.Size; - if (IntPtr.Size == 4) + int offset = i * _pointerSize; + if (_pointerSize == 4) return BitConverter.ToUInt16(_data, curr + offset); return BitConverter.ToInt32(_data, curr + offset); @@ -85,8 +88,8 @@ private int GetPointers(int curr, int i) private int GetSkip(int curr, int i) { - int offset = i * IntPtr.Size + IntPtr.Size / 2; - if (IntPtr.Size == 4) + int offset = i * _pointerSize + _pointerSize / 2; + if (_pointerSize == 4) return BitConverter.ToInt16(_data, curr + offset); return BitConverter.ToInt32(_data, curr + offset); @@ -94,7 +97,7 @@ private int GetSkip(int curr, int i) private int GetSeriesSize(int curr) { - if (IntPtr.Size == 4) + if (_pointerSize == 4) return BitConverter.ToInt32(_data, curr); return (int)BitConverter.ToInt64(_data, curr); @@ -103,17 +106,17 @@ private int GetSeriesSize(int curr) private long GetSeriesOffset(int curr) { long offset; - if (IntPtr.Size == 4) - offset = BitConverter.ToUInt32(_data, curr + IntPtr.Size); + if (_pointerSize == 4) + offset = BitConverter.ToUInt32(_data, curr + _pointerSize); else - offset = BitConverter.ToInt64(_data, curr + IntPtr.Size); + offset = BitConverter.ToInt64(_data, curr + _pointerSize); return offset; } private int GetHighestSeries() { - return _data.Length - IntPtr.Size * 3; + return _data.Length - _pointerSize * 3; } private int GetLowestSeries() @@ -121,17 +124,17 @@ private int GetLowestSeries() return _data.Length - ComputeSize(GetNumSeries()); } - private static int ComputeSize(int series) + private int ComputeSize(int series) { - return IntPtr.Size + series * IntPtr.Size * 2; + return _pointerSize + series * _pointerSize * 2; } private int GetNumSeries() { - if (IntPtr.Size == 4) - return BitConverter.ToInt32(_data, _data.Length - IntPtr.Size); + if (_pointerSize == 4) + return BitConverter.ToInt32(_data, _data.Length - _pointerSize); - return (int)BitConverter.ToInt64(_data, _data.Length - IntPtr.Size); + return (int)BitConverter.ToInt64(_data, _data.Length - _pointerSize); } } } \ No newline at end of file diff --git a/src/Microsoft.Diagnostics.Runtime/Implementation/ClrDacType.cs b/src/Microsoft.Diagnostics.Runtime/Implementation/ClrDacType.cs index 68408f350..848784bf3 100644 --- a/src/Microsoft.Diagnostics.Runtime/Implementation/ClrDacType.cs +++ b/src/Microsoft.Diagnostics.Runtime/Implementation/ClrDacType.cs @@ -113,8 +113,9 @@ private GCDesc GetOrCreateGCDesc() if (reader is null) return default; + int pointerSize = reader.PointerSize; DebugOnly.Assert(MethodTable != 0, "Attempted to fill GC desc with a constructed (not real) type."); - if (!reader.Read(MethodTable - (ulong)IntPtr.Size, out int entries)) + if (!reader.Read(MethodTable - (ulong)pointerSize, out int entries)) { _gcDesc = default; return default; @@ -125,15 +126,15 @@ private GCDesc GetOrCreateGCDesc() entries = -entries; int slots = 1 + entries * 2; - byte[] buffer = new byte[slots * IntPtr.Size]; - if (reader.Read(MethodTable - (ulong)(slots * IntPtr.Size), buffer) != buffer.Length) + byte[] buffer = new byte[slots * pointerSize]; + if (reader.Read(MethodTable - (ulong)(slots * pointerSize), buffer) != buffer.Length) { _gcDesc = default; return default; } // Construct the gc desc - return _gcDesc = new GCDesc(buffer); + return _gcDesc = new GCDesc(buffer, pointerSize); } private ClrElementType GetElementType() @@ -148,7 +149,7 @@ private ClrElementType GetElementType() return _elementType = ClrElementType.String; if (ComponentSize > 0) - return _elementType = StaticSize > (uint)(3 * IntPtr.Size) ? ClrElementType.Array : ClrElementType.SZArray; + return _elementType = StaticSize > (uint)(3 * Module.DataReader.PointerSize) ? ClrElementType.Array : ClrElementType.SZArray; ClrType? baseType = BaseType; if (baseType is null) @@ -286,7 +287,7 @@ public override ulong GetArrayElementAddress(ulong objRef, int index) else if (componentType != null) { if (!componentType.IsObjectReference) - _baseArrayOffset = IntPtr.Size * 2; + _baseArrayOffset = Module.DataReader.PointerSize * 2; } else { diff --git a/src/Microsoft.Diagnostics.Runtime/Implementation/ClrPrimitiveType.cs b/src/Microsoft.Diagnostics.Runtime/Implementation/ClrPrimitiveType.cs index af4c5d300..601983a75 100644 --- a/src/Microsoft.Diagnostics.Runtime/Implementation/ClrPrimitiveType.cs +++ b/src/Microsoft.Diagnostics.Runtime/Implementation/ClrPrimitiveType.cs @@ -13,7 +13,7 @@ namespace Microsoft.Diagnostics.Runtime.Implementation internal sealed class ClrPrimitiveType : ClrType { public ClrPrimitiveType(IAbstractTypeHelpers helpers, ClrModule module, ClrHeap heap, ClrElementType type) - : base(module, new() { StaticSize = ClrField.GetSize(null, type) }, helpers) + : base(module, new() { StaticSize = ClrField.GetSize(null, type, module.DataReader.PointerSize) }, helpers) { if (helpers is null) throw new ArgumentNullException(nameof(helpers)); diff --git a/src/Microsoft.Diagnostics.Runtime/Implementation/ClrTypeFactory.cs b/src/Microsoft.Diagnostics.Runtime/Implementation/ClrTypeFactory.cs index 973665b35..937bc7f4d 100644 --- a/src/Microsoft.Diagnostics.Runtime/Implementation/ClrTypeFactory.cs +++ b/src/Microsoft.Diagnostics.Runtime/Implementation/ClrTypeFactory.cs @@ -55,7 +55,7 @@ public ClrType CreateStringType() ParentMethodTable = _gcInfo.ObjectMethodTable, MethodTable = _gcInfo.StringMethodTable, IsShared = true, - StaticSize = IntPtr.Size + sizeof(int), + StaticSize = _heap.Runtime.DataTarget.DataReader.PointerSize + sizeof(int), ComponentSize = sizeof(char), }; } diff --git a/src/Microsoft.Diagnostics.Runtime/Utilities/SigParser/SigParser.cs b/src/Microsoft.Diagnostics.Runtime/Utilities/SigParser/SigParser.cs index 44e6420cb..c152e3d9c 100644 --- a/src/Microsoft.Diagnostics.Runtime/Utilities/SigParser/SigParser.cs +++ b/src/Microsoft.Diagnostics.Runtime/Utilities/SigParser/SigParser.cs @@ -206,74 +206,6 @@ public bool PeekElemType(out int etype) return PeekElemTypeSlow(out etype); } - private bool PeekElemTypeSize(out int pSize) - { - pSize = 0; - SigParser sigTemp = new(this); - - if (!sigTemp.SkipAnyVASentinel()) - return false; - - if (!sigTemp.GetByte(out byte bElementType)) - return false; - - switch (bElementType) - { - case ELEMENT_TYPE_I8: - case ELEMENT_TYPE_U8: - case ELEMENT_TYPE_R8: - pSize = 8; - break; - - case ELEMENT_TYPE_I4: - case ELEMENT_TYPE_U4: - case ELEMENT_TYPE_R4: - pSize = 4; - break; - - case ELEMENT_TYPE_I2: - case ELEMENT_TYPE_U2: - case ELEMENT_TYPE_CHAR: - pSize = 2; - break; - - case ELEMENT_TYPE_I1: - case ELEMENT_TYPE_U1: - case ELEMENT_TYPE_BOOLEAN: - pSize = 1; - break; - - case ELEMENT_TYPE_I: - case ELEMENT_TYPE_U: - case ELEMENT_TYPE_STRING: - case ELEMENT_TYPE_PTR: - case ELEMENT_TYPE_BYREF: - case ELEMENT_TYPE_CLASS: - case ELEMENT_TYPE_OBJECT: - case ELEMENT_TYPE_FNPTR: - case ELEMENT_TYPE_TYPEDBYREF: - case ELEMENT_TYPE_ARRAY: - case ELEMENT_TYPE_SZARRAY: - pSize = IntPtr.Size; - break; - - case ELEMENT_TYPE_VOID: - break; - - case ELEMENT_TYPE_END: - case ELEMENT_TYPE_CMOD_REQD: - case ELEMENT_TYPE_CMOD_OPT: - case ELEMENT_TYPE_VALUETYPE: - Debug.Fail("Asked for the size of an element that doesn't have a size!"); - return false; - - default: - Debug.Fail("CorSigGetElementTypeSize given invalid signature to size!"); - return false; - } - - return true; - } private bool AtSentinel() {