[cDAC] Add GetApproxTypeHandle DacDbi API#128921
Conversation
Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
…y+metadataToken Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds dump-based coverage for DacDbiImpl.GetApproxTypeHandle by mirroring the existing exact-type-handle dump tests: it enumerates heap objects reachable from GC handles in the ExactTypeHandle debuggee, constructs the flattened DebuggerIPCE_TypeArgData[] tree (a managed port of CordbType::GatherTypeData), round-trips that through GetApproxTypeHandle, and asserts the returned vmTypeHandle matches an independently canonicalized expected MethodTable. To support this, it also adds a managed TypeDataWalk implementation and refactors some type lookup logic into a helper.
Changes:
- Add a new dump test suite
DacDbiApproxTypeHandleDumpTestsimplementing the right-side “gather type data” flattening and expected-handle canonicalization. - Implement managed
GetApproxTypeHandlesupport via a newTypeDataWalkport and supporting helper types. - Replace
IsObjRef(TypeHandle)usage with a newIsCorElementTypeObjRef(CorElementType)helper across tests, the contract, and documentation.
Show a summary per file
| File | Description |
|---|---|
| src/native/managed/cdac/tests/MethodTableTests.cs | Updates objref classification assertions to use IsCorElementTypeObjRef(GetInternalCorElementType(...)). |
| src/native/managed/cdac/tests/DumpTests/RuntimeTypeSystemDumpTests.cs | Updates dump-based RTS “objref consistency” test to use the new helper. |
| src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiObjectDumpTests.cs | Updates reference-type offset logic to use the new helper. |
| src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiApproxTypeHandleDumpTests.cs | New dump test covering round-trip behavior for GetApproxTypeHandle across reachable handle objects. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/TypeDataWalk.cs | New managed port of the native flattened-type-data walker used by GetApproxTypeHandle. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs | Adds DebuggerIPCE_TypeArgData / TypeInfoList and tightens GetApproxTypeHandle signature to a typed pointer. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DbiHelpers.cs | New helper for resolving typeDef/typeRef MethodTables from an assembly+token via loader lookup tables. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs | Implements managed GetApproxTypeHandle and switches some ref-type checks to IsCorElementTypeObjRef. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs | Replaces IsObjRef with IsCorElementTypeObjRef implementation used by the contract. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs | Changes the contract surface by removing IsObjRef(TypeHandle) and adding IsCorElementTypeObjRef(CorElementType). |
| docs/design/datacontracts/RuntimeTypeSystem.md | Updates contract documentation to match the new helper. |
Copilot's findings
- Files reviewed: 11/11 changed files
- Comments generated: 5
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Fixed the CdacDumpTests build break. The failure was a set of CS0246/CS0103 errors in |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
| // True if the CorElementType represents a GC-collectable object reference. | ||
| bool IsCorElementTypeObjRef(CorElementType elementType) => throw new NotImplementedException(); | ||
| // Returns the address of one of the runtime's well-known singleton MethodTables, | ||
| // or TargetPointer.Null if the runtime has not yet initialized that global. | ||
| TargetPointer GetWellKnownMethodTable(WellKnownMethodTable kind) => throw new NotImplementedException(); | ||
| bool IsObjRef(TypeHandle typeHandle) => throw new NotImplementedException(); | ||
| // True if the MethodTable represents a type that contains managed references |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
| Assert.True(contract.IsCorElementTypeObjRef(contract.GetInternalCorElementType(contract.GetTypeHandle(objectTypePtr)))); | ||
| Assert.True(contract.IsCorElementTypeObjRef(contract.GetInternalCorElementType(contract.GetTypeHandle(stringTypePtr)))); | ||
| Assert.True(contract.IsCorElementTypeObjRef(contract.GetInternalCorElementType(contract.GetTypeHandle(szArrayTypePtr)))); | ||
| Assert.False(contract.IsCorElementTypeObjRef(contract.GetInternalCorElementType(contract.GetTypeHandle(truePrimitiveTypePtr)))); |
| /// - Top-level Class / ValueType keeps the typeDef; only its type-args are canonicalized. | ||
| /// - Reference-typed generic args collapse to <c>System.__Canon</c>. | ||
| /// - Value-type args are recursively approximated (with the same rules applied to their args). | ||
| /// - Array / Ptr / Byref: outer shape preserved; the inner type goes through the | ||
| /// type-arg canonicalization rules. | ||
| /// </para> |
| IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; | ||
|
|
||
| TargetPointer canonMtPtr = _target.ReadPointer(_target.ReadGlobalPointer(Constants.Globals.CanonMethodTable)); | ||
| TypeHandle canonTh = rts.GetTypeHandle(canonMtPtr); | ||
|
|
| using System; | ||
| using System.Collections.Immutable; | ||
| using System.Runtime.InteropServices; | ||
| using Microsoft.Diagnostics.DataContractReader.Contracts; |
| // True if the MethodTable is the System.Object MethodTable (g_pObjectClass) | ||
| bool IsObject(TypeHandle typeHandle) => throw new NotImplementedException(); | ||
| bool IsString(TypeHandle typeHandle) => throw new NotImplementedException(); | ||
| // True if the CorElementType represents a GC-collectable object reference. | ||
| bool IsCorElementTypeObjRef(CorElementType elementType) => throw new NotImplementedException(); | ||
| // Returns the address of one of the runtime's well-known singleton MethodTables, | ||
| // or TargetPointer.Null if the runtime has not yet initialized that global. | ||
| TargetPointer GetWellKnownMethodTable(WellKnownMethodTable kind) => throw new NotImplementedException(); | ||
| bool IsObjRef(TypeHandle typeHandle) => throw new NotImplementedException(); | ||
| // True if the MethodTable represents a type that contains managed references |
Add this API using a port of the native type-walk logic and a slight tweak to the RuntimeTypeSystem API that determines if something is a reference type.