diff --git a/docs/design/datacontracts/RuntimeTypeSystem.md b/docs/design/datacontracts/RuntimeTypeSystem.md index b1d65b7c825273..69443e0b22a63a 100644 --- a/docs/design/datacontracts/RuntimeTypeSystem.md +++ b/docs/design/datacontracts/RuntimeTypeSystem.md @@ -51,14 +51,18 @@ partial interface IRuntimeTypeSystem : IContract // True if the MethodTable represents a type that contains managed references public virtual bool ContainsGCPointers(TypeHandle typeHandle); public virtual bool IsDynamicStatics(TypeHandle typeHandle); - public virtual ushort GetNumMethods(TypeHandle typeHandle); public virtual ushort GetNumInterfaces(TypeHandle typeHandle); // Returns an ECMA-335 TypeDef table token for this type, or for its generic type definition if it is a generic instantiation public virtual uint GetTypeDefToken(TypeHandle typeHandle); + public virtual ushort GetNumMethods(TypeHandle typeHandle); // Returns the ECMA 335 TypeDef table Flags value (a bitmask of TypeAttributes) for this type, // or for its generic type definition if it is a generic instantiation public virtual uint GetTypeDefTypeAttributes(TypeHandle typeHandle); + public ushort GetNumInstanceFields(TypeHandle typeHandle); + public ushort GetNumStaticFields(TypeHandle typeHandle); + public ushort GetNumThreadStaticFields(TypeHandle typeHandle); + public TargetPointer GetFieldDescList(TypeHandle typeHandle); public virtual ReadOnlySpan GetInstantiation(TypeHandle typeHandle); public virtual bool IsGenericTypeDefinition(TypeHandle typeHandle); @@ -348,6 +352,10 @@ The contract additionally depends on these data descriptors | `EEClass` | `NumMethods` | Count of methods attached to the EEClass | | `EEClass` | `NumNonVirtualSlots` | Count of non-virtual slots for the EEClass | | `EEClass` | `CorTypeAttr` | Various flags | +| `EEClass` | `NumInstanceFields` | Count of instance fields of the EEClass | +| `EEClass` | `NumStaticFields` | Count of static fields of the EEClass | +| `EEClass` | `NumThreadStaticFields` | Count of threadstatic fields of the EEClass | +| `EEClass` | `FieldDescList` | A list of fields in the type | | `ArrayClass` | `Rank` | Rank of the associated array MethodTable | | `TypeDesc` | `TypeAndFlags` | The lower 8 bits are the CorElementType of the `TypeDesc`, the upper 24 bits are reserved for flags | | `ParamTypeDesc` | `TypeArg` | Associated type argument | @@ -374,11 +382,35 @@ The contract additionally depends on these data descriptors return TypeHandle { Address = typeHandlePointer } } + public TargetPointer GetModule(TypeHandle TypeHandle) + { + if (typeHandle.IsMethodTable()) + { + return _methodTables[TypeHandle.Address].Module; + } + else if (typeHandle.IsTypeDesc()) + { + if (HasTypeParam(typeHandle)) + { + return GetModule(GetTypeParam(typeHandle)); + } + else if (IsGenericVariable(typeHandle, out TargetPointer genericParamModule, out _)) + { + return genericParamModule; + } + } + return TargetPointer.Null; + } + internal static EEClassOrCanonMTBits GetEEClassOrCanonMTBits(TargetPointer eeClassOrCanonMTPtr) { return (EEClassOrCanonMTBits)(eeClassOrCanonMTPtr & (ulong)EEClassOrCanonMTBits.Mask); } + public TargetPointer GetCanonicalMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(TypeHandle).MethodTable; + + public TargetPointer GetParentMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[TypeHandle.Address].ParentMethodTable; + public uint GetBaseSize(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[TypeHandle.Address].Flags.BaseSize; public uint GetComponentSize(TypeHandle TypeHandle) =>!typeHandle.IsMethodTable() ? (uint)0 : GetComponentSize(_methodTables[TypeHandle.Address]); @@ -397,36 +429,16 @@ The contract additionally depends on these data descriptors ... // read Data.EEClass data from eeClassPtr } - - public TargetPointer GetCanonicalMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(TypeHandle).MethodTable; - - public TargetPointer GetModule(TypeHandle TypeHandle) - { - if (typeHandle.IsMethodTable()) - { - return _methodTables[TypeHandle.Address].Module; - } - else if (typeHandle.IsTypeDesc()) - { - if (HasTypeParam(typeHandle)) - { - return GetModule(GetTypeParam(typeHandle)); - } - else if (IsGenericVariable(typeHandle, out TargetPointer genericParamModule, out _)) - { - return genericParamModule; - } - } - return TargetPointer.Null; - } - - public TargetPointer GetParentMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[TypeHandle.Address].ParentMethodTable; - public bool IsFreeObjectMethodTable(TypeHandle TypeHandle) => FreeObjectMethodTablePointer == TypeHandle.Address; public bool IsString(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsString; + public bool ContainsGCPointers(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.ContainsGCPointers; + public bool IsDynamicStatics(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsDynamicStatics; + + public ushort GetNumInterfaces(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : _methodTables[TypeHandle.Address].NumInterfaces; + public uint GetTypeDefToken(TypeHandle TypeHandle) { if (!typeHandle.IsMethodTable()) @@ -438,11 +450,15 @@ The contract additionally depends on these data descriptors public ushort GetNumMethods(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : GetClassData(TypeHandle).NumMethods; - public ushort GetNumInterfaces(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : _methodTables[TypeHandle.Address].NumInterfaces; - public uint GetTypeDefTypeAttributes(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : GetClassData(TypeHandle).CorTypeAttr; - public bool IsDynamicStatics(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsDynamicStatics; + public ushort GetNumInstanceFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumInstanceFields; + + public ushort GetNumStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumStaticFields; + + public ushort GetNumThreadStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumThreadStaticFields; + + public TargetPointer GetFieldDescList(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).FieldDescList; public ReadOnlySpan GetInstantiation(TypeHandle TypeHandle) { diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.h b/src/coreclr/debug/runtimeinfo/datadescriptor.h index ee4192dcbb830c..d931b30ad86589 100644 --- a/src/coreclr/debug/runtimeinfo/datadescriptor.h +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.h @@ -333,8 +333,12 @@ CDAC_TYPE_BEGIN(EEClass) CDAC_TYPE_INDETERMINATE(EEClass) CDAC_TYPE_FIELD(EEClass, /*pointer*/, MethodTable, cdac_data::MethodTable) CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumMethods, cdac_data::NumMethods) +CDAC_TYPE_FIELD(EEClass, /*pointer*/, FieldDescList, cdac_data::FieldDescList) CDAC_TYPE_FIELD(EEClass, /*uint32*/, CorTypeAttr, cdac_data::CorTypeAttr) CDAC_TYPE_FIELD(EEClass, /*uint8*/, InternalCorElementType, cdac_data::InternalCorElementType) +CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumInstanceFields, cdac_data::NumInstanceFields) +CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumStaticFields, cdac_data::NumStaticFields) +CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumThreadStaticFields, cdac_data::NumThreadStaticFields) CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumNonVirtualSlots, cdac_data::NumNonVirtualSlots) CDAC_TYPE_END(EEClass) diff --git a/src/coreclr/vm/class.h b/src/coreclr/vm/class.h index edfe860af53be4..0ee57a801ad5bd 100644 --- a/src/coreclr/vm/class.h +++ b/src/coreclr/vm/class.h @@ -1799,8 +1799,12 @@ template<> struct cdac_data { static constexpr size_t InternalCorElementType = offsetof(EEClass, m_NormType); static constexpr size_t MethodTable = offsetof(EEClass, m_pMethodTable); + static constexpr size_t FieldDescList = offsetof(EEClass, m_pFieldDescList); static constexpr size_t NumMethods = offsetof(EEClass, m_NumMethods); static constexpr size_t CorTypeAttr = offsetof(EEClass, m_dwAttrClass); + static constexpr size_t NumInstanceFields = offsetof(EEClass, m_NumInstanceFields); + static constexpr size_t NumStaticFields = offsetof(EEClass, m_NumStaticFields); + static constexpr size_t NumThreadStaticFields = offsetof(EEClass, m_NumThreadStaticFields); static constexpr size_t NumNonVirtualSlots = offsetof(EEClass, m_NumNonVirtualSlots); }; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs index 61c4274fc763e5..0fb29e318c1d42 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs @@ -98,14 +98,19 @@ public interface IRuntimeTypeSystem : IContract // True if the MethodTable represents a type that contains managed references bool ContainsGCPointers(TypeHandle typeHandle) => throw new NotImplementedException(); bool IsDynamicStatics(TypeHandle typeHandle) => throw new NotImplementedException(); - ushort GetNumMethods(TypeHandle typeHandle) => throw new NotImplementedException(); ushort GetNumInterfaces(TypeHandle typeHandle) => throw new NotImplementedException(); // Returns an ECMA-335 TypeDef table token for this type, or for its generic type definition if it is a generic instantiation uint GetTypeDefToken(TypeHandle typeHandle) => throw new NotImplementedException(); + ushort GetNumMethods(TypeHandle typeHandle) => throw new NotImplementedException(); // Returns the ECMA 335 TypeDef table Flags value (a bitmask of TypeAttributes) for this type, // or for its generic type definition if it is a generic instantiation uint GetTypeDefTypeAttributes(TypeHandle typeHandle) => throw new NotImplementedException(); + ushort GetNumInstanceFields(TypeHandle typeHandle) => throw new NotImplementedException(); + ushort GetNumStaticFields(TypeHandle typeHandle) => throw new NotImplementedException(); + ushort GetNumThreadStaticFields(TypeHandle typeHandle) => throw new NotImplementedException(); + TargetPointer GetFieldDescList(TypeHandle typeHandle) => throw new NotImplementedException(); + ReadOnlySpan GetInstantiation(TypeHandle typeHandle) => throw new NotImplementedException(); bool IsGenericTypeDefinition(TypeHandle typeHandle) => throw new NotImplementedException(); diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs index 1225c281df73ee..ab96052d094780 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs @@ -314,6 +314,35 @@ public TypeHandle GetTypeHandle(TargetPointer typeHandlePointer) _ = _methodTables.TryAdd(methodTablePointer, trustedMethodTableF); return new TypeHandle(methodTablePointer); } + public TargetPointer GetModule(TypeHandle typeHandle) + { + if (typeHandle.IsMethodTable()) + { + return _methodTables[typeHandle.Address].Module; + } + else if (typeHandle.IsTypeDesc()) + { + if (HasTypeParam(typeHandle)) + { + return GetModule(GetTypeParam(typeHandle)); + } + else if (IsGenericVariable(typeHandle, out TargetPointer genericParamModule, out _)) + { + return genericParamModule; + } + else + { + System.Diagnostics.Debug.Assert(IsFunctionPointer(typeHandle, out _, out _)); + return TargetPointer.Null; + } + } + else + { + return TargetPointer.Null; + } + } + public TargetPointer GetCanonicalMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).MethodTable; + public TargetPointer GetParentMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[typeHandle.Address].ParentMethodTable; public uint GetBaseSize(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[typeHandle.Address].Flags.BaseSize; @@ -343,42 +372,13 @@ private Data.EEClass GetClassData(TypeHandle typeHandle) return _target.ProcessedData.GetOrAdd(clsPtr); } - public TargetPointer GetCanonicalMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).MethodTable; - - public TargetPointer GetModule(TypeHandle typeHandle) - { - if (typeHandle.IsMethodTable()) - { - return _methodTables[typeHandle.Address].Module; - } - else if (typeHandle.IsTypeDesc()) - { - if (HasTypeParam(typeHandle)) - { - return GetModule(GetTypeParam(typeHandle)); - } - else if (IsGenericVariable(typeHandle, out TargetPointer genericParamModule, out _)) - { - return genericParamModule; - } - else - { - System.Diagnostics.Debug.Assert(IsFunctionPointer(typeHandle, out _, out _)); - return TargetPointer.Null; - } - } - else - { - return TargetPointer.Null; - } - } - - public TargetPointer GetParentMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[typeHandle.Address].ParentMethodTable; public bool IsFreeObjectMethodTable(TypeHandle typeHandle) => FreeObjectMethodTablePointer == typeHandle.Address; public bool IsString(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsString; public bool ContainsGCPointers(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.ContainsGCPointers; + public bool IsDynamicStatics(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsDynamicStatics; + public ushort GetNumInterfaces(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : _methodTables[typeHandle.Address].NumInterfaces; public uint GetTypeDefToken(TypeHandle typeHandle) { @@ -387,14 +387,13 @@ public uint GetTypeDefToken(TypeHandle typeHandle) MethodTable methodTable = _methodTables[typeHandle.Address]; return (uint)(methodTable.Flags.GetTypeDefRid() | ((int)TableIndex.TypeDef << 24)); } - public ushort GetNumMethods(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumMethods; - - public ushort GetNumInterfaces(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : _methodTables[typeHandle.Address].NumInterfaces; - public uint GetTypeDefTypeAttributes(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : GetClassData(typeHandle).CorTypeAttr; + public ushort GetNumInstanceFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumInstanceFields; + public ushort GetNumStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumStaticFields; + public ushort GetNumThreadStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumThreadStaticFields; + public TargetPointer GetFieldDescList(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).FieldDescList; - public bool IsDynamicStatics(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsDynamicStatics; public ReadOnlySpan GetInstantiation(TypeHandle typeHandle) { diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/EEClass.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/EEClass.cs index c9e62eb39e85ef..6936bf50f8ba2e 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/EEClass.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/EEClass.cs @@ -14,6 +14,10 @@ public EEClass(Target target, TargetPointer address) NumMethods = target.Read(address + (ulong)type.Fields[nameof(NumMethods)].Offset); CorTypeAttr = target.Read(address + (ulong)type.Fields[nameof(CorTypeAttr)].Offset); InternalCorElementType = target.Read(address + (ulong)type.Fields[nameof(InternalCorElementType)].Offset); + NumInstanceFields = target.Read(address + (ulong)type.Fields[nameof(NumInstanceFields)].Offset); + NumStaticFields = target.Read(address + (ulong)type.Fields[nameof(NumStaticFields)].Offset); + NumThreadStaticFields = target.Read(address + (ulong)type.Fields[nameof(NumThreadStaticFields)].Offset); + FieldDescList = target.Read(address + (ulong)type.Fields[nameof(FieldDescList)].Offset); NumNonVirtualSlots = target.Read(address + (ulong)type.Fields[nameof(NumNonVirtualSlots)].Offset); } @@ -29,7 +33,10 @@ public EEClass(Target target, TargetPointer address) // Enums are the element type of their underlying type // ValueTypes which can exactly be represented as an element type are represented as such public byte InternalCorElementType { get; init; } - + public ushort NumInstanceFields { get; init; } + public ushort NumStaticFields { get; init; } + public ushort NumThreadStaticFields { get; init; } + public TargetPointer FieldDescList { get; init; } public ushort NumNonVirtualSlots { get; init; } } diff --git a/src/native/managed/cdac/mscordaccore_universal/Legacy/ISOSDacInterface.cs b/src/native/managed/cdac/mscordaccore_universal/Legacy/ISOSDacInterface.cs index 73eb5aa3c24c5d..572e98c55493bc 100644 --- a/src/native/managed/cdac/mscordaccore_universal/Legacy/ISOSDacInterface.cs +++ b/src/native/managed/cdac/mscordaccore_universal/Legacy/ISOSDacInterface.cs @@ -128,6 +128,16 @@ internal struct DacpUsefulGlobalsData } #pragma warning restore CS0649 // Field is never assigned to, and will always have its default value +internal struct DacpMethodTableFieldData +{ + public ushort wNumInstanceFields; + public ushort wNumStaticFields; + public ushort wNumThreadStaticFields; + public ClrDataAddress FirstField; + public ushort wContextStaticOffset; + public ushort wContextStaticsSize; +}; + internal struct DacpReJitData { // FIXME[cdac]: the C++ definition enum doesn't have an explicit underlying type or constant values for the flags @@ -276,7 +286,7 @@ internal unsafe partial interface ISOSDacInterface [PreserveSig] int GetMethodTableSlot(ClrDataAddress mt, uint slot, ClrDataAddress* value); [PreserveSig] - int GetMethodTableFieldData(ClrDataAddress mt, /*struct DacpMethodTableFieldData*/ void* data); + int GetMethodTableFieldData(ClrDataAddress mt, DacpMethodTableFieldData* data); [PreserveSig] int GetMethodTableTransparencyData(ClrDataAddress mt, /*struct DacpMethodTableTransparencyData*/ void* data); diff --git a/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs b/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs index 4a07701f68daa1..4f60eb143478ef 100644 --- a/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs @@ -949,8 +949,52 @@ int ISOSDacInterface.GetMethodTableData(ClrDataAddress mt, DacpMethodTableData* #endif return hr; } - int ISOSDacInterface.GetMethodTableFieldData(ClrDataAddress mt, void* data) - => _legacyImpl is not null ? _legacyImpl.GetMethodTableFieldData(mt, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetMethodTableFieldData(ClrDataAddress mt, DacpMethodTableFieldData* data) + { + int hr = HResults.S_OK; + try + { + if (mt == 0 || data == null) + { + hr = HResults.E_INVALIDARG; + } + else + { + TargetPointer mtAddress = mt.ToTargetPointer(_target); + Contracts.IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; + TypeHandle typeHandle = rtsContract.GetTypeHandle(mtAddress); + data->FirstField = rtsContract.GetFieldDescList(typeHandle).ToClrDataAddress(_target); + data->wNumInstanceFields = rtsContract.GetNumInstanceFields(typeHandle); + data->wNumStaticFields = rtsContract.GetNumStaticFields(typeHandle); + data->wNumThreadStaticFields = rtsContract.GetNumThreadStaticFields(typeHandle); + data->wContextStaticsSize = 0; + data->wContextStaticOffset = 0; + } + } + catch (System.Exception ex) + { + hr = ex.HResult; + } +#if DEBUG + { + if (_legacyImpl is not null) + { + DacpMethodTableFieldData mtFieldDataLocal = default; + int hrLocal = _legacyImpl.GetMethodTableFieldData(mt, &mtFieldDataLocal); + Debug.Assert(hrLocal == hr, $"cDAC: {hr:x}, DAC: {hrLocal:x}"); + if (hr == HResults.S_OK) + { + Debug.Assert(data->wNumInstanceFields == mtFieldDataLocal.wNumInstanceFields); + Debug.Assert(data->wNumStaticFields == mtFieldDataLocal.wNumStaticFields); + Debug.Assert(data->wNumThreadStaticFields == mtFieldDataLocal.wNumThreadStaticFields); + Debug.Assert(data->wContextStaticOffset == mtFieldDataLocal.wContextStaticOffset); + Debug.Assert(data->wContextStaticsSize == mtFieldDataLocal.wContextStaticsSize); + } + } + } +#endif + return hr; + } int ISOSDacInterface.GetMethodTableForEEClass(ClrDataAddress eeClassReallyCanonMT, ClrDataAddress* value) { if (eeClassReallyCanonMT == 0 || value == null) diff --git a/src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.cs b/src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.cs index 10d7d1418daffa..45a6b7d5cde038 100644 --- a/src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.cs +++ b/src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.cs @@ -41,6 +41,10 @@ internal record TypeFields new(nameof(Data.EEClass.CorTypeAttr), DataType.uint32), new(nameof(Data.EEClass.NumMethods), DataType.uint16), new(nameof(Data.EEClass.InternalCorElementType), DataType.uint8), + new(nameof(Data.EEClass.NumInstanceFields), DataType.uint16), + new(nameof(Data.EEClass.NumStaticFields), DataType.uint16), + new(nameof(Data.EEClass.NumThreadStaticFields), DataType.uint16), + new(nameof(Data.EEClass.FieldDescList), DataType.pointer), new(nameof(Data.EEClass.NumNonVirtualSlots), DataType.uint16), ] };