Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ public CdacTypeAttribute(params string[] names)
public string[] Names { get; }

/// <summary>
/// When <c>true</c>, the generator emits a <c>TypeHandle(Target)</c>
/// accessor that resolves the runtime <c>TypeHandle</c> by trying each
/// When <c>true</c>, the generator emits a <c>ITypeHandle(Target)</c>
/// accessor that resolves the runtime <c>ITypeHandle</c> by trying each
/// candidate name against <c>IManagedTypeSource</c>.
/// </summary>
public bool HasTypeHandle { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public interface IManagedTypeSource : IContract
bool TryGetTypeInfo(string fullyQualifiedName, out Target.TypeInfo info) => throw new NotImplementedException();
Target.TypeInfo GetTypeInfo(string fullyQualifiedName) => throw new NotImplementedException();

bool TryGetTypeHandle(string fullyQualifiedName, out TypeHandle typeHandle) => throw new NotImplementedException();
TypeHandle GetTypeHandle(string fullyQualifiedName) => throw new NotImplementedException();
bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle typeHandle) => throw new NotImplementedException();
ITypeHandle GetTypeHandle(string fullyQualifiedName) => throw new NotImplementedException();

bool TryGetStaticFieldAddress(string fullyQualifiedName, string fieldName, out TargetPointer address) => throw new NotImplementedException();
TargetPointer GetStaticFieldAddress(string fullyQualifiedName, string fieldName) => throw new NotImplementedException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts;
public interface IRuntimeMutableTypeSystem : IContract
{
static string IContract.Name { get; } = nameof(RuntimeMutableTypeSystem);
IEnumerable<TargetPointer> EnumerateAddedFieldDescs(TypeHandle typeHandle, bool staticFields) => throw new NotImplementedException();
IEnumerable<TargetPointer> EnumerateAddedFieldDescs(ITypeHandle typeHandle, bool staticFields) => throw new NotImplementedException();
bool IsFieldDescEnCNew(TargetPointer fieldDescPointer) => throw new NotImplementedException();
bool DoesEnCFieldDescNeedFixup(TargetPointer encFieldDescPointer) => throw new NotImplementedException();
TargetPointer GetEnCStaticFieldDataAddress(TargetPointer encFieldDescPointer) => throw new NotImplementedException();
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace Microsoft.Diagnostics.DataContractReader.Contracts;
public interface ISignature : IContract
{
static string IContract.Name { get; } = nameof(Signature);
TypeHandle DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, TypeHandle ctx) => throw new NotImplementedException();
ITypeHandle DecodeFieldSignature(BlobHandle blobHandle, ModuleHandle moduleHandle, ITypeHandle ctx) => throw new NotImplementedException();
TargetPointer GetVarArgArgsBase(TargetPointer vaSigCookieAddr) => throw new NotImplementedException();
void GetVarArgSignature(TargetPointer vaSigCookieAddr, out TargetPointer signatureAddress, out uint signatureLength) => throw new NotImplementedException();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ bool ICodeVersions.CodeVersionManagerSupportsMethod(TargetPointer methodDescAddr
if (rts.IsCollectibleMethod(md))
return false;
TargetPointer mtAddr = rts.GetMethodTable(md);
TypeHandle mt = rts.GetTypeHandle(mtAddr);
ITypeHandle mt = rts.GetTypeHandle(mtAddr);
TargetPointer modAddr = rts.GetModule(mt);
ILoader loader = _target.Contracts.Loader;
ModuleHandle mod = loader.GetModuleHandleFromModulePtr(modAddr);
Expand Down Expand Up @@ -342,7 +342,7 @@ private void GetModuleAndMethodDesc(TargetPointer methodDesc, out TargetPointer
IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem;
MethodDescHandle md = rts.GetMethodDescHandle(methodDesc);
TargetPointer mtAddr = rts.GetMethodTable(md);
TypeHandle typeHandle = rts.GetTypeHandle(mtAddr);
ITypeHandle typeHandle = rts.GetTypeHandle(mtAddr);
module = rts.GetModule(typeHandle);
methodDefToken = rts.GetMethodToken(md);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public List<TargetPointer> GetMOWs(TargetPointer obj, out bool hasMOWTable)
public bool IsComWrappersRCW(TargetPointer rcw)
{
TargetPointer mt = _target.Contracts.Object.GetMethodTableAddress(rcw);
return mt == Data.NativeObjectWrapper.TypeHandle(_target).Address;
return mt == Data.NativeObjectWrapper.ITypeHandle(_target).Address;
}

public TargetPointer GetComWrappersRCWForObject(TargetPointer obj)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ bool IConditionalWeakTable.TryGetValue(TargetPointer conditionalWeakTable, Targe

Data.Array entriesArray = _target.ProcessedData.GetOrAdd<Data.Array>(container.Entries);
TargetPointer entriesMT = _target.Contracts.Object.GetMethodTableAddress(container.Entries);
TypeHandle entriesTypeHandle = _target.Contracts.RuntimeTypeSystem.GetTypeHandle(entriesMT);
ITypeHandle entriesTypeHandle = _target.Contracts.RuntimeTypeSystem.GetTypeHandle(entriesMT);
uint entrySize = _target.Contracts.RuntimeTypeSystem.GetComponentSize(entriesTypeHandle);

while (entriesIndex != -1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ IEnumerable<ExceptionStackFrameInfo> IException.GetExceptionStackFrames(TargetPo
TargetPointer mt = objectContract.GetMethodTableAddress(stackTraceObj);
if (mt == TargetPointer.Null)
throw new InvalidOperationException($"Stack trace object 0x{stackTraceObj.Value:x} has no MethodTable.");
TypeHandle stackTraceHandle = rtsContract.GetTypeHandle(mt);
ITypeHandle stackTraceHandle = rtsContract.GetTypeHandle(mt);

TargetPointer i1ArrayAddr;
if (rtsContract.ContainsGCPointers(stackTraceHandle))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,7 @@ List<ExceptionClauseInfo> IExecutionManager.GetExceptionClauses(CodeBlockHandle
IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem;
MethodDescHandle mdHandle = rts.GetMethodDescHandle(methodDescPtr);
TargetPointer mtPtr = rts.GetMethodTable(mdHandle);
TypeHandle th = rts.GetTypeHandle(mtPtr);
ITypeHandle th = rts.GetTypeHandle(mtPtr);
TargetPointer handleModuleAddr = rts.GetModule(th);

List<ExceptionClauseInfo> exceptionClauses = new List<ExceptionClauseInfo>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal sealed class ManagedTypeSource_1 : IManagedTypeSource
{
private readonly Target _target;
private readonly Dictionary<string, Target.TypeInfo?> _typeInfoCache = new();
private readonly Dictionary<string, TypeHandle> _typeHandleCache = new();
private readonly Dictionary<string, ITypeHandle> _typeHandleCache = new();
private readonly Dictionary<(string Fqn, string FieldName), TargetPointer> _fieldDescCache = new();
private bool _inSearch;

Expand Down Expand Up @@ -81,22 +81,26 @@ public bool TryGetTypeInfo(string fullyQualifiedName, out Target.TypeInfo info)
}
}

public TypeHandle GetTypeHandle(string fullyQualifiedName)
public ITypeHandle GetTypeHandle(string fullyQualifiedName)
{
if (!TryGetTypeHandle(fullyQualifiedName, out TypeHandle typeHandle))
if (!TryGetTypeHandle(fullyQualifiedName, out ITypeHandle typeHandle))
throw new InvalidOperationException($"Managed type '{fullyQualifiedName}' is not resolvable through {nameof(ManagedTypeSource_1)}.");

return typeHandle;
}

public bool TryGetTypeHandle(string fullyQualifiedName, out TypeHandle typeHandle)
public bool TryGetTypeHandle(string fullyQualifiedName, out ITypeHandle typeHandle)
{
if (_typeHandleCache.TryGetValue(fullyQualifiedName, out typeHandle))
if (_typeHandleCache.TryGetValue(fullyQualifiedName, out var cached))
{
typeHandle = cached;
return !typeHandle.IsNull;
}

if (!TryResolveType(fullyQualifiedName, out typeHandle, out _, out _))
{
_typeHandleCache[fullyQualifiedName] = new TypeHandle(TargetPointer.Null);
typeHandle = ITypeHandle.Null;
_typeHandleCache[fullyQualifiedName] = ITypeHandle.Null;
return false;
}

Expand Down Expand Up @@ -128,7 +132,7 @@ public bool TryGetStaticFieldAddress(string fullyQualifiedName, string fieldName
// Gate on the statics base being allocated for the enclosing class so callers cannot
// dereference a small offset-from-zero when the class has not been initialized.
TargetPointer enclosingMT = rts.GetMTOfEnclosingClass(fieldDescAddr);
TypeHandle ctx = rts.GetTypeHandle(enclosingMT);
ITypeHandle ctx = rts.GetTypeHandle(enclosingMT);
CorElementType type = rts.GetFieldDescType(fieldDescAddr);
bool isGC = type is CorElementType.Class or CorElementType.ValueType;
TargetPointer @base = isGC ? rts.GetGCStaticsBasePointer(ctx) : rts.GetNonGCStaticsBasePointer(ctx);
Expand Down Expand Up @@ -163,7 +167,7 @@ public bool TryGetThreadStaticFieldAddress(string fullyQualifiedName, string fie
// cannot dereference a small offset-from-zero when this thread has not initialized
// thread-static storage for the type.
TargetPointer enclosingMT = rts.GetMTOfEnclosingClass(fieldDescAddr);
TypeHandle ctx = rts.GetTypeHandle(enclosingMT);
ITypeHandle ctx = rts.GetTypeHandle(enclosingMT);
CorElementType type = rts.GetFieldDescType(fieldDescAddr);
bool isGC = type is CorElementType.Class or CorElementType.ValueType;
TargetPointer @base = isGC
Expand All @@ -182,7 +186,7 @@ private bool TryGetFieldDesc(string fullyQualifiedName, string fieldName, out Ta
if (_fieldDescCache.TryGetValue(key, out fieldDescAddr))
return fieldDescAddr != TargetPointer.Null;

if (!TryResolveType(fullyQualifiedName, out TypeHandle th, out _, out _))
if (!TryResolveType(fullyQualifiedName, out ITypeHandle th, out _, out _))
{
fieldDescAddr = TargetPointer.Null;
_fieldDescCache[key] = TargetPointer.Null;
Expand All @@ -198,7 +202,7 @@ private bool TryBuildTypeInfo(string managedFqName, out Target.TypeInfo info)
{
info = default;

if (!TryResolveType(managedFqName, out TypeHandle th, out MetadataReader? mdReader, out TypeDefinition typeDef))
if (!TryResolveType(managedFqName, out ITypeHandle th, out MetadataReader? mdReader, out TypeDefinition typeDef))
return false;

IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem;
Expand Down Expand Up @@ -246,9 +250,9 @@ private bool TryBuildTypeInfo(string managedFqName, out Target.TypeInfo info)
return true;
}

private bool TryResolveType(string managedFqName, out TypeHandle th, [NotNullWhen(true)] out MetadataReader? mdReader, out TypeDefinition typeDef)
private bool TryResolveType(string managedFqName, out ITypeHandle th, [NotNullWhen(true)] out MetadataReader? mdReader, out TypeDefinition typeDef)
{
th = new TypeHandle(TargetPointer.Null);
th = ITypeHandle.Null;
typeDef = default;

ILoader loader = _target.Contracts.Loader;
Expand All @@ -264,7 +268,7 @@ private bool TryResolveType(string managedFqName, out TypeHandle th, [NotNullWhe
if (!TryFindTypeDefinition(moduleHandle, managedFqName, out mdReader, out TypeDefinitionHandle typeDefHandle))
return false;

// Look up the runtime TypeHandle via the module's TypeDef → MethodTable map.
// Look up the runtime ITypeHandle via the module's TypeDef → MethodTable map.
int token = MetadataTokens.GetToken((EntityHandle)typeDefHandle);
TargetPointer typeDefToMethodTable = loader.GetLookupTables(moduleHandle).TypeDefToMethodTable;
TargetPointer typeHandlePtr = loader.GetModuleLookupMapElement(typeDefToMethodTable, (uint)token, out _);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public TargetPointer GetArrayData(TargetPointer address, out uint count, out Tar
if (mt == TargetPointer.Null)
throw new ArgumentException("Address represents a set-free object");
Contracts.IRuntimeTypeSystem typeSystemContract = _target.Contracts.RuntimeTypeSystem;
TypeHandle typeHandle = typeSystemContract.GetTypeHandle(mt);
ITypeHandle typeHandle = typeSystemContract.GetTypeHandle(mt);
uint rank;
if (!typeSystemContract.IsArray(typeHandle, out rank))
throw new ArgumentException("Address does not represent an array object", nameof(address));
Expand Down Expand Up @@ -207,7 +207,7 @@ public ulong GetSize(TargetPointer address)
if (mt == TargetPointer.Null)
throw new ArgumentException("Address represents a free object");
Contracts.IRuntimeTypeSystem typeSystemContract = _target.Contracts.RuntimeTypeSystem;
TypeHandle typeHandle = typeSystemContract.GetTypeHandle(mt);
ITypeHandle typeHandle = typeSystemContract.GetTypeHandle(mt);

ulong size = typeSystemContract.GetBaseSize(typeHandle);
uint componentSize = typeSystemContract.GetComponentSize(typeHandle);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ bool IRuntimeMutableTypeSystem.IsFieldDescEnCNew(TargetPointer fieldDescPointer)
return offset == _target.ReadGlobal<uint>(Constants.Globals.FieldOffsetNewEnc);
}

IEnumerable<TargetPointer> IRuntimeMutableTypeSystem.EnumerateAddedFieldDescs(TypeHandle typeHandle, bool staticFields)
IEnumerable<TargetPointer> IRuntimeMutableTypeSystem.EnumerateAddedFieldDescs(ITypeHandle typeHandle, bool staticFields)
{
// Only MethodTable type handles can have EnC-added fields. TypeDescs (TypeVar, FnPtr, etc.) cannot.
if (!typeHandle.IsMethodTable())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;

namespace Microsoft.Diagnostics.DataContractReader.Contracts;

/// <summary>
/// An ITypeHandle backed by a real target-process address (MethodTable* or TypeDesc*).
/// </summary>
public readonly struct TargetTypeHandle : ITypeHandle, IEquatable<TargetTypeHandle>
{
public TargetTypeHandle(TargetPointer address)
{
Address = address;
}

public TargetPointer Address { get; }
public bool IsNull => Address == 0;
public bool IsSynthetic => false;

public bool Equals(ITypeHandle? other)
{
if (other is null) return false;
if (other is TargetTypeHandle t) return Address == t.Address;
// A zero-address TargetTypeHandle is equivalent to a NullTypeHandle
if (IsNull && other.IsNull && !other.IsSynthetic) return true;
return false;
}
public bool Equals(TargetTypeHandle other) => Address == other.Address;
public override bool Equals(object? obj)
=> obj is ITypeHandle th && Equals(th);
public override int GetHashCode() => Address.GetHashCode();
}

/// <summary>
/// A reader-fabricated ITypeHandle for an unloaded constructed type
/// (Ptr, Byref, SzArray, or Array). Has no backing target memory.
/// </summary>
internal sealed class SyntheticTypeHandle : ITypeHandle, IEquatable<SyntheticTypeHandle>
{
public SyntheticTypeHandle(CorElementType kind, ITypeHandle element, int rank = 0)
{
Kind = kind;
Element = element;
Rank = rank;
}

/// <summary>The outermost CorElementType (Ptr, Byref, SzArray, or Array).</summary>
public CorElementType Kind { get; }

/// <summary>The element (referent) ITypeHandle. May itself be synthetic.</summary>
public ITypeHandle Element { get; }

/// <summary>Array rank (meaningful only for Array; SzArray is always 1).</summary>
public int Rank { get; }

public TargetPointer Address => TargetPointer.Null;
public bool IsNull => false;
public bool IsSynthetic => true;

public bool Equals(ITypeHandle? other) => other is SyntheticTypeHandle s && Equals(s);
public bool Equals(SyntheticTypeHandle? other)
=> other is not null
&& Kind == other.Kind
&& Rank == other.Rank
&& EqualityComparer<ITypeHandle>.Default.Equals(Element, other.Element);
public override bool Equals(object? obj) => obj is ITypeHandle th && Equals(th);
public override int GetHashCode() => HashCode.Combine((int)Kind, Rank, Element?.GetHashCode() ?? 0);
}
Loading
Loading