Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions src/Microsoft.Diagnostics.Runtime/ClrArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public int Length
{
if (_length == -1)
{
_length = Type.Module.DataReader.Read<int>(Address + (ulong)IntPtr.Size);
_length = Type.Module.DataReader.Read<int>(Address + (ulong)Type.Module.DataReader.PointerSize);
}

return _length;
Expand All @@ -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;

Expand Down Expand Up @@ -183,15 +183,21 @@ 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<nuint>(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)
{
if (Type.ComponentType != null && !Type.ComponentType.IsObjectReference)
throw new InvalidOperationException($"{Type} does not contain object references.");

return Type.Heap.GetObject(ReadValue<nuint>(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<T>(int index) where T : unmanaged
Expand All @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -285,7 +291,7 @@ private unsafe ulong GetElementAddress(int elementSize, int[] indices)
// ^
// | Address
private readonly int GetMultiDimensionalBound(int offset) =>
Type.Module.DataReader.Read<int>(Address + (ulong)(2 * IntPtr.Size) + (ulong)(offset * sizeof(int)));
Type.Module.DataReader.Read<int>(Address + (ulong)(2 * Type.Module.DataReader.PointerSize) + (ulong)(offset * sizeof(int)));

IClrValue IClrArray.GetObjectValue(int index) => GetObjectValue(index);

Expand Down
26 changes: 10 additions & 16 deletions src/Microsoft.Diagnostics.Runtime/ClrDelegate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public bool HasMultipleTargets
{
if (field.ElementType == ClrElementType.NativeInt)
{
ulong targetMethod = field.Read<UIntPtr>(Object, interior: false).ToUInt64();
ulong targetMethod = field.ReadPointer(Object.Address, interior: false);

if (targetMethod != 0)
{
Expand Down Expand Up @@ -184,23 +184,17 @@ public IEnumerable<ClrDelegateTarget> EnumerateDelegateTargets()
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)
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;
}
}
}
Expand Down
38 changes: 21 additions & 17 deletions src/Microsoft.Diagnostics.Runtime/ClrEnum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,23 +81,27 @@ public T GetEnumValue<T>(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,
};
}
}
}
31 changes: 18 additions & 13 deletions src/Microsoft.Diagnostics.Runtime/ClrException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand All @@ -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
{
Expand All @@ -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
{
Expand All @@ -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
{
Expand All @@ -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<ClrStackFrame> GetExceptionStackTrace()
Expand All @@ -264,6 +268,7 @@ private ImmutableArray<ClrStackFrame> GetExceptionStackTrace()
return ImmutableArray<ClrStackFrame>.Empty;

IDataReader dataReader = Type.Module.DataReader;
int pointerSize = dataReader.PointerSize;
ulong address = dataReader.ReadPointer(_object.Address + offset);
ClrObject _stackTrace = Type.Module.Heap.GetObject(address);

Expand All @@ -274,22 +279,22 @@ private ImmutableArray<ClrStackFrame> GetExceptionStackTrace()
if (len == 0)
return ImmutableArray<ClrStackFrame>.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<ClrStackFrame>.Empty;

ImmutableArray<ClrStackFrame>.Builder result = ImmutableArray.CreateBuilder<ClrStackFrame>((int)count);
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);
Expand Down
6 changes: 3 additions & 3 deletions src/Microsoft.Diagnostics.Runtime/ClrField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ private void InitData(bool forName)
/// <summary>
/// Gets the size of this field.
/// </summary>
public int Size => GetSize(Type, ElementType);
public int Size => GetSize(Type, ElementType, ContainingType.Module.DataReader.PointerSize);

/// <summary>
/// Attributes of this field;
Expand Down Expand Up @@ -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?
Expand Down Expand Up @@ -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:
Expand Down
Loading