Skip to content

Commit b97bebe

Browse files
authored
Adding GetMethodTableFieldData cDAC API (#117684)
* adding GetMethodTableFieldData cDAC API
1 parent c9ccccf commit b97bebe

File tree

9 files changed

+163
-70
lines changed

9 files changed

+163
-70
lines changed

docs/design/datacontracts/RuntimeTypeSystem.md

Lines changed: 45 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,18 @@ partial interface IRuntimeTypeSystem : IContract
5151
// True if the MethodTable represents a type that contains managed references
5252
public virtual bool ContainsGCPointers(TypeHandle typeHandle);
5353
public virtual bool IsDynamicStatics(TypeHandle typeHandle);
54-
public virtual ushort GetNumMethods(TypeHandle typeHandle);
5554
public virtual ushort GetNumInterfaces(TypeHandle typeHandle);
5655

5756
// Returns an ECMA-335 TypeDef table token for this type, or for its generic type definition if it is a generic instantiation
5857
public virtual uint GetTypeDefToken(TypeHandle typeHandle);
58+
public virtual ushort GetNumMethods(TypeHandle typeHandle);
5959
// Returns the ECMA 335 TypeDef table Flags value (a bitmask of TypeAttributes) for this type,
6060
// or for its generic type definition if it is a generic instantiation
6161
public virtual uint GetTypeDefTypeAttributes(TypeHandle typeHandle);
62+
public ushort GetNumInstanceFields(TypeHandle typeHandle);
63+
public ushort GetNumStaticFields(TypeHandle typeHandle);
64+
public ushort GetNumThreadStaticFields(TypeHandle typeHandle);
65+
public TargetPointer GetFieldDescList(TypeHandle typeHandle);
6266
public virtual ReadOnlySpan<TypeHandle> GetInstantiation(TypeHandle typeHandle);
6367
public virtual bool IsGenericTypeDefinition(TypeHandle typeHandle);
6468

@@ -348,6 +352,10 @@ The contract additionally depends on these data descriptors
348352
| `EEClass` | `NumMethods` | Count of methods attached to the EEClass |
349353
| `EEClass` | `NumNonVirtualSlots` | Count of non-virtual slots for the EEClass |
350354
| `EEClass` | `CorTypeAttr` | Various flags |
355+
| `EEClass` | `NumInstanceFields` | Count of instance fields of the EEClass |
356+
| `EEClass` | `NumStaticFields` | Count of static fields of the EEClass |
357+
| `EEClass` | `NumThreadStaticFields` | Count of threadstatic fields of the EEClass |
358+
| `EEClass` | `FieldDescList` | A list of fields in the type |
351359
| `ArrayClass` | `Rank` | Rank of the associated array MethodTable |
352360
| `TypeDesc` | `TypeAndFlags` | The lower 8 bits are the CorElementType of the `TypeDesc`, the upper 24 bits are reserved for flags |
353361
| `ParamTypeDesc` | `TypeArg` | Associated type argument |
@@ -374,11 +382,35 @@ The contract additionally depends on these data descriptors
374382
return TypeHandle { Address = typeHandlePointer }
375383
}
376384

385+
public TargetPointer GetModule(TypeHandle TypeHandle)
386+
{
387+
if (typeHandle.IsMethodTable())
388+
{
389+
return _methodTables[TypeHandle.Address].Module;
390+
}
391+
else if (typeHandle.IsTypeDesc())
392+
{
393+
if (HasTypeParam(typeHandle))
394+
{
395+
return GetModule(GetTypeParam(typeHandle));
396+
}
397+
else if (IsGenericVariable(typeHandle, out TargetPointer genericParamModule, out _))
398+
{
399+
return genericParamModule;
400+
}
401+
}
402+
return TargetPointer.Null;
403+
}
404+
377405
internal static EEClassOrCanonMTBits GetEEClassOrCanonMTBits(TargetPointer eeClassOrCanonMTPtr)
378406
{
379407
return (EEClassOrCanonMTBits)(eeClassOrCanonMTPtr & (ulong)EEClassOrCanonMTBits.Mask);
380408
}
381409

410+
public TargetPointer GetCanonicalMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(TypeHandle).MethodTable;
411+
412+
public TargetPointer GetParentMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[TypeHandle.Address].ParentMethodTable;
413+
382414
public uint GetBaseSize(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[TypeHandle.Address].Flags.BaseSize;
383415

384416
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
397429
... // read Data.EEClass data from eeClassPtr
398430
}
399431

400-
401-
public TargetPointer GetCanonicalMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(TypeHandle).MethodTable;
402-
403-
public TargetPointer GetModule(TypeHandle TypeHandle)
404-
{
405-
if (typeHandle.IsMethodTable())
406-
{
407-
return _methodTables[TypeHandle.Address].Module;
408-
}
409-
else if (typeHandle.IsTypeDesc())
410-
{
411-
if (HasTypeParam(typeHandle))
412-
{
413-
return GetModule(GetTypeParam(typeHandle));
414-
}
415-
else if (IsGenericVariable(typeHandle, out TargetPointer genericParamModule, out _))
416-
{
417-
return genericParamModule;
418-
}
419-
}
420-
return TargetPointer.Null;
421-
}
422-
423-
public TargetPointer GetParentMethodTable(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[TypeHandle.Address].ParentMethodTable;
424-
425432
public bool IsFreeObjectMethodTable(TypeHandle TypeHandle) => FreeObjectMethodTablePointer == TypeHandle.Address;
426433

427434
public bool IsString(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsString;
435+
428436
public bool ContainsGCPointers(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.ContainsGCPointers;
429437

438+
public bool IsDynamicStatics(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsDynamicStatics;
439+
440+
public ushort GetNumInterfaces(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : _methodTables[TypeHandle.Address].NumInterfaces;
441+
430442
public uint GetTypeDefToken(TypeHandle TypeHandle)
431443
{
432444
if (!typeHandle.IsMethodTable())
@@ -438,11 +450,15 @@ The contract additionally depends on these data descriptors
438450

439451
public ushort GetNumMethods(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : GetClassData(TypeHandle).NumMethods;
440452

441-
public ushort GetNumInterfaces(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : _methodTables[TypeHandle.Address].NumInterfaces;
442-
443453
public uint GetTypeDefTypeAttributes(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? 0 : GetClassData(TypeHandle).CorTypeAttr;
444454

445-
public bool IsDynamicStatics(TypeHandle TypeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[TypeHandle.Address].Flags.IsDynamicStatics;
455+
public ushort GetNumInstanceFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumInstanceFields;
456+
457+
public ushort GetNumStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumStaticFields;
458+
459+
public ushort GetNumThreadStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumThreadStaticFields;
460+
461+
public TargetPointer GetFieldDescList(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).FieldDescList;
446462

447463
public ReadOnlySpan<TypeHandle> GetInstantiation(TypeHandle TypeHandle)
448464
{

src/coreclr/debug/runtimeinfo/datadescriptor.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,12 @@ CDAC_TYPE_BEGIN(EEClass)
333333
CDAC_TYPE_INDETERMINATE(EEClass)
334334
CDAC_TYPE_FIELD(EEClass, /*pointer*/, MethodTable, cdac_data<EEClass>::MethodTable)
335335
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumMethods, cdac_data<EEClass>::NumMethods)
336+
CDAC_TYPE_FIELD(EEClass, /*pointer*/, FieldDescList, cdac_data<EEClass>::FieldDescList)
336337
CDAC_TYPE_FIELD(EEClass, /*uint32*/, CorTypeAttr, cdac_data<EEClass>::CorTypeAttr)
337338
CDAC_TYPE_FIELD(EEClass, /*uint8*/, InternalCorElementType, cdac_data<EEClass>::InternalCorElementType)
339+
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumInstanceFields, cdac_data<EEClass>::NumInstanceFields)
340+
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumStaticFields, cdac_data<EEClass>::NumStaticFields)
341+
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumThreadStaticFields, cdac_data<EEClass>::NumThreadStaticFields)
338342
CDAC_TYPE_FIELD(EEClass, /*uint16*/, NumNonVirtualSlots, cdac_data<EEClass>::NumNonVirtualSlots)
339343
CDAC_TYPE_END(EEClass)
340344

src/coreclr/vm/class.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,8 +1799,12 @@ template<> struct cdac_data<EEClass>
17991799
{
18001800
static constexpr size_t InternalCorElementType = offsetof(EEClass, m_NormType);
18011801
static constexpr size_t MethodTable = offsetof(EEClass, m_pMethodTable);
1802+
static constexpr size_t FieldDescList = offsetof(EEClass, m_pFieldDescList);
18021803
static constexpr size_t NumMethods = offsetof(EEClass, m_NumMethods);
18031804
static constexpr size_t CorTypeAttr = offsetof(EEClass, m_dwAttrClass);
1805+
static constexpr size_t NumInstanceFields = offsetof(EEClass, m_NumInstanceFields);
1806+
static constexpr size_t NumStaticFields = offsetof(EEClass, m_NumStaticFields);
1807+
static constexpr size_t NumThreadStaticFields = offsetof(EEClass, m_NumThreadStaticFields);
18041808
static constexpr size_t NumNonVirtualSlots = offsetof(EEClass, m_NumNonVirtualSlots);
18051809
};
18061810

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,14 +98,19 @@ public interface IRuntimeTypeSystem : IContract
9898
// True if the MethodTable represents a type that contains managed references
9999
bool ContainsGCPointers(TypeHandle typeHandle) => throw new NotImplementedException();
100100
bool IsDynamicStatics(TypeHandle typeHandle) => throw new NotImplementedException();
101-
ushort GetNumMethods(TypeHandle typeHandle) => throw new NotImplementedException();
102101
ushort GetNumInterfaces(TypeHandle typeHandle) => throw new NotImplementedException();
103102

104103
// Returns an ECMA-335 TypeDef table token for this type, or for its generic type definition if it is a generic instantiation
105104
uint GetTypeDefToken(TypeHandle typeHandle) => throw new NotImplementedException();
105+
ushort GetNumMethods(TypeHandle typeHandle) => throw new NotImplementedException();
106106
// Returns the ECMA 335 TypeDef table Flags value (a bitmask of TypeAttributes) for this type,
107107
// or for its generic type definition if it is a generic instantiation
108108
uint GetTypeDefTypeAttributes(TypeHandle typeHandle) => throw new NotImplementedException();
109+
ushort GetNumInstanceFields(TypeHandle typeHandle) => throw new NotImplementedException();
110+
ushort GetNumStaticFields(TypeHandle typeHandle) => throw new NotImplementedException();
111+
ushort GetNumThreadStaticFields(TypeHandle typeHandle) => throw new NotImplementedException();
112+
TargetPointer GetFieldDescList(TypeHandle typeHandle) => throw new NotImplementedException();
113+
109114

110115
ReadOnlySpan<TypeHandle> GetInstantiation(TypeHandle typeHandle) => throw new NotImplementedException();
111116
bool IsGenericTypeDefinition(TypeHandle typeHandle) => throw new NotImplementedException();

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,35 @@ public TypeHandle GetTypeHandle(TargetPointer typeHandlePointer)
314314
_ = _methodTables.TryAdd(methodTablePointer, trustedMethodTableF);
315315
return new TypeHandle(methodTablePointer);
316316
}
317+
public TargetPointer GetModule(TypeHandle typeHandle)
318+
{
319+
if (typeHandle.IsMethodTable())
320+
{
321+
return _methodTables[typeHandle.Address].Module;
322+
}
323+
else if (typeHandle.IsTypeDesc())
324+
{
325+
if (HasTypeParam(typeHandle))
326+
{
327+
return GetModule(GetTypeParam(typeHandle));
328+
}
329+
else if (IsGenericVariable(typeHandle, out TargetPointer genericParamModule, out _))
330+
{
331+
return genericParamModule;
332+
}
333+
else
334+
{
335+
System.Diagnostics.Debug.Assert(IsFunctionPointer(typeHandle, out _, out _));
336+
return TargetPointer.Null;
337+
}
338+
}
339+
else
340+
{
341+
return TargetPointer.Null;
342+
}
343+
}
344+
public TargetPointer GetCanonicalMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).MethodTable;
345+
public TargetPointer GetParentMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[typeHandle.Address].ParentMethodTable;
317346

318347
public uint GetBaseSize(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : _methodTables[typeHandle.Address].Flags.BaseSize;
319348

@@ -343,42 +372,13 @@ private Data.EEClass GetClassData(TypeHandle typeHandle)
343372
return _target.ProcessedData.GetOrAdd<Data.EEClass>(clsPtr);
344373
}
345374

346-
public TargetPointer GetCanonicalMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).MethodTable;
347-
348-
public TargetPointer GetModule(TypeHandle typeHandle)
349-
{
350-
if (typeHandle.IsMethodTable())
351-
{
352-
return _methodTables[typeHandle.Address].Module;
353-
}
354-
else if (typeHandle.IsTypeDesc())
355-
{
356-
if (HasTypeParam(typeHandle))
357-
{
358-
return GetModule(GetTypeParam(typeHandle));
359-
}
360-
else if (IsGenericVariable(typeHandle, out TargetPointer genericParamModule, out _))
361-
{
362-
return genericParamModule;
363-
}
364-
else
365-
{
366-
System.Diagnostics.Debug.Assert(IsFunctionPointer(typeHandle, out _, out _));
367-
return TargetPointer.Null;
368-
}
369-
}
370-
else
371-
{
372-
return TargetPointer.Null;
373-
}
374-
}
375-
376-
public TargetPointer GetParentMethodTable(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : _methodTables[typeHandle.Address].ParentMethodTable;
377375

378376
public bool IsFreeObjectMethodTable(TypeHandle typeHandle) => FreeObjectMethodTablePointer == typeHandle.Address;
379377

380378
public bool IsString(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsString;
381379
public bool ContainsGCPointers(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.ContainsGCPointers;
380+
public bool IsDynamicStatics(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsDynamicStatics;
381+
public ushort GetNumInterfaces(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : _methodTables[typeHandle.Address].NumInterfaces;
382382

383383
public uint GetTypeDefToken(TypeHandle typeHandle)
384384
{
@@ -387,14 +387,13 @@ public uint GetTypeDefToken(TypeHandle typeHandle)
387387
MethodTable methodTable = _methodTables[typeHandle.Address];
388388
return (uint)(methodTable.Flags.GetTypeDefRid() | ((int)TableIndex.TypeDef << 24));
389389
}
390-
391390
public ushort GetNumMethods(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumMethods;
392-
393-
public ushort GetNumInterfaces(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : _methodTables[typeHandle.Address].NumInterfaces;
394-
395391
public uint GetTypeDefTypeAttributes(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (uint)0 : GetClassData(typeHandle).CorTypeAttr;
392+
public ushort GetNumInstanceFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumInstanceFields;
393+
public ushort GetNumStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumStaticFields;
394+
public ushort GetNumThreadStaticFields(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? (ushort)0 : GetClassData(typeHandle).NumThreadStaticFields;
395+
public TargetPointer GetFieldDescList(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? TargetPointer.Null : GetClassData(typeHandle).FieldDescList;
396396

397-
public bool IsDynamicStatics(TypeHandle typeHandle) => !typeHandle.IsMethodTable() ? false : _methodTables[typeHandle.Address].Flags.IsDynamicStatics;
398397

399398
public ReadOnlySpan<TypeHandle> GetInstantiation(TypeHandle typeHandle)
400399
{

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/EEClass.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ public EEClass(Target target, TargetPointer address)
1414
NumMethods = target.Read<ushort>(address + (ulong)type.Fields[nameof(NumMethods)].Offset);
1515
CorTypeAttr = target.Read<uint>(address + (ulong)type.Fields[nameof(CorTypeAttr)].Offset);
1616
InternalCorElementType = target.Read<byte>(address + (ulong)type.Fields[nameof(InternalCorElementType)].Offset);
17+
NumInstanceFields = target.Read<ushort>(address + (ulong)type.Fields[nameof(NumInstanceFields)].Offset);
18+
NumStaticFields = target.Read<ushort>(address + (ulong)type.Fields[nameof(NumStaticFields)].Offset);
19+
NumThreadStaticFields = target.Read<ushort>(address + (ulong)type.Fields[nameof(NumThreadStaticFields)].Offset);
20+
FieldDescList = target.Read<ulong>(address + (ulong)type.Fields[nameof(FieldDescList)].Offset);
1721
NumNonVirtualSlots = target.Read<ushort>(address + (ulong)type.Fields[nameof(NumNonVirtualSlots)].Offset);
1822
}
1923

@@ -29,7 +33,10 @@ public EEClass(Target target, TargetPointer address)
2933
// Enums are the element type of their underlying type
3034
// ValueTypes which can exactly be represented as an element type are represented as such
3135
public byte InternalCorElementType { get; init; }
32-
36+
public ushort NumInstanceFields { get; init; }
37+
public ushort NumStaticFields { get; init; }
38+
public ushort NumThreadStaticFields { get; init; }
39+
public TargetPointer FieldDescList { get; init; }
3340
public ushort NumNonVirtualSlots { get; init; }
3441
}
3542

src/native/managed/cdac/mscordaccore_universal/Legacy/ISOSDacInterface.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,16 @@ internal struct DacpUsefulGlobalsData
134134
}
135135
#pragma warning restore CS0649 // Field is never assigned to, and will always have its default value
136136

137+
internal struct DacpMethodTableFieldData
138+
{
139+
public ushort wNumInstanceFields;
140+
public ushort wNumStaticFields;
141+
public ushort wNumThreadStaticFields;
142+
public ClrDataAddress FirstField;
143+
public ushort wContextStaticOffset;
144+
public ushort wContextStaticsSize;
145+
};
146+
137147
internal struct DacpReJitData
138148
{
139149
// FIXME[cdac]: the C++ definition enum doesn't have an explicit underlying type or constant values for the flags
@@ -282,7 +292,7 @@ internal unsafe partial interface ISOSDacInterface
282292
[PreserveSig]
283293
int GetMethodTableSlot(ClrDataAddress mt, uint slot, ClrDataAddress* value);
284294
[PreserveSig]
285-
int GetMethodTableFieldData(ClrDataAddress mt, /*struct DacpMethodTableFieldData*/ void* data);
295+
int GetMethodTableFieldData(ClrDataAddress mt, DacpMethodTableFieldData* data);
286296
[PreserveSig]
287297
int GetMethodTableTransparencyData(ClrDataAddress mt, /*struct DacpMethodTableTransparencyData*/ void* data);
288298

0 commit comments

Comments
 (0)