[cDAC]: Implement GetTypedByRefInfo, GetStringData, GetArrayData, GetBasicObjectInfo#129200
[cDAC]: Implement GetTypedByRefInfo, GetStringData, GetArrayData, GetBasicObjectInfo#129200rcj1 wants to merge 3 commits into
Conversation
rcj1
commented
Jun 9, 2026
- Add two cDAC APIs on Object contract:
- Add one cDAC API on RuntimeTypeSystem:
- Implement DacDbi APIs, slightly modifying out params to be more specific to each API
- Moving, renaming, and re-typing DebuggerIPCE_ObjectData
…sicObjectInfo (managed side) Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
This PR extends the cDAC contracts and legacy DAC/DBI bridge to support additional object/typed-by-ref inspection APIs, and updates the CoreCLR DAC/DBI interface + right-side debugger plumbing to use more specific out-parameters (and a new object-data structure) for string/array/basic object queries.
Changes:
- Add
TypedByRefdata descriptor +IRuntimeTypeSystem.GetTypedByRefInfo(...)(with unit tests). - Add
IObject.GetStringData(...)andIObject.GetSize(...), and implement corresponding DAC/DBI entrypoints (GetStringData,GetArrayData,GetBasicObjectInfo,GetTypedByRefInfo) in the managed legacy bridge. - Refactor debugger-side object data plumbing: replace
DebuggerIPCE_ObjectDatawithDacDbiObjectDataand update IDL/interface declarations and DI callers accordingly.
Show a summary per file
| File | Description |
|---|---|
| src/native/managed/cdac/tests/UnitTests/MethodTableTests.cs | Adds unit tests validating GetTypedByRefInfo reads data/type fields correctly. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs | Updates managed COM projection signatures and introduces DacDbiArrayInfo. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs | Implements the updated DAC/DBI APIs using cDAC contracts, with DEBUG cross-checks. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/DataType.cs | Adds DataType.TypedByRef descriptor name. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/TypedByRef.cs | New data descriptor for TypedByRef (Data + Type fields). |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/RuntimeTypeSystem_1.cs | Implements GetTypedByRefInfo in the RuntimeTypeSystem contract. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Object_1.cs | Adds GetStringData and GetSize implementations in the Object contract. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IRuntimeTypeSystem.cs | Adds public TypedByRefInfo and GetTypedByRefInfo API surface. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IObject.cs | Adds public GetSize and GetStringData API surface. |
| src/coreclr/vm/datadescriptor/datadescriptor.inc | Adds TypedByRef to the CoreCLR cDAC data descriptor list. |
| src/coreclr/inc/dacdbi.idl | Updates IDL to the new out-parameter shapes and struct names. |
| src/coreclr/debug/inc/dbgipcevents.h | Removes DebuggerIPCE_ObjectData definition. |
| src/coreclr/debug/inc/dacdbistructures.h | Introduces DacDbiArrayInfo and DacDbiObjectData structures. |
| src/coreclr/debug/inc/dacdbiinterface.h | Updates DAC/DBI interface method signatures and associated comments. |
| src/coreclr/debug/di/rspriv.h | Switches DI-side storage/parameters from DebuggerIPCE_ObjectData to DacDbiObjectData. |
| src/coreclr/debug/di/process.cpp | Updates GetObjectInternal to use the new GetBasicObjectInfo signature. |
| src/coreclr/debug/di/divalue.cpp | Updates reference/object data initialization to call new DAC/DBI signatures for string/array/typed-byref. |
| src/coreclr/debug/daccess/dacdbiimpl.h | Updates DAC implementation declarations to new signatures. |
| src/coreclr/debug/daccess/dacdbiimpl.cpp | Updates DAC implementations for typed-byref/string/array/basic object queries. |
| docs/design/datacontracts/RuntimeTypeSystem.md | Documents the new TypedByRef descriptor + GetTypedByRefInfo API. |
| docs/design/datacontracts/Object.md | Documents GetStringData / GetSize additions and intended behavior. |
Copilot's findings
- Files reviewed: 21/21 changed files
- Comments generated: 5
| DacDbiObjectData objData; | ||
| BOOL isValidRef = FALSE; | ||
|
|
||
| NewHolder<CordbObjectValue> pNewObjectValue(new CordbObjectValue(cdbAppDomain, pType, TargetBuffer(addr, (ULONG)objData.objSize), &objData)); | ||
| IfFailThrow(m_pDacPrimitives->GetBasicObjectInfo(addr, &isValidRef, &objData.objSize, &objData.objOffsetToVars, &objData.objTypeData)); | ||
| objData.objRefBad = !isValidRef; |
| // Arguments: | ||
| // input: objectAddress - address of the object for which we want information | ||
| // type - the basic type of the object (we may find more specific type | ||
| // information for the object) | ||
| // output: pObjectData - fills in the size and type information fields | ||
| // input: objectAddress - address of the object for which we want information | ||
| // type - the basic type of the object (we may find more specific type | ||
| // information for the object) | ||
| // output: pIsValidRef - FALSE if the object reference is bad |
| TargetPointer mt = GetMethodTableAddress(address); | ||
| if (mt == TargetPointer.Null) | ||
| throw new ArgumentException("Address represents a free object"); | ||
| Contracts.IRuntimeTypeSystem typeSystemContract = _target.Contracts.RuntimeTypeSystem; |
This comment has been minimized.
This comment has been minimized.
|
Note This review was generated by Copilot. 🤖 Copilot Code Review — PR #129200Holistic AssessmentMotivation: Well-justified. The monolithic Approach: The right approach — break the left-side (DAC) interface into specific parameters while the right-side (debugger) retains a convenience struct ( Summary: Detailed Findings
|
| public readonly record struct TypedByRefInfo(TargetPointer Data, TargetPointer TypeHandle); | ||
|
|
| public int GetStringData(ulong objectAddress, uint* pLength, uint* pOffsetToStringBase) | ||
| { | ||
| int hr = HResults.S_OK; | ||
| try | ||
| { |
| DacDbiObjectData objData; | ||
| BOOL isValidRef = FALSE; | ||
|
|
||
| NewHolder<CordbObjectValue> pNewObjectValue(new CordbObjectValue(cdbAppDomain, pType, TargetBuffer(addr, (ULONG)objData.objSize), &objData)); | ||
| IfFailThrow(m_pDacPrimitives->GetBasicObjectInfo(addr, &isValidRef, &objData.objSize, &objData.objOffsetToVars, &objData.objTypeData)); | ||
| objData.objRefBad = !isValidRef; |
| // Arguments: | ||
| // input: objectAddress - address of the object for which we want information | ||
| // type - the basic type of the object (we may find more specific type | ||
| // information for the object) | ||
| // output: pObjectData - fills in the size and type information fields | ||
| // input: objectAddress - address of the object for which we want information | ||
| // type - the basic type of the object (we may find more specific type | ||
| // information for the object) |
| @@ -6023,12 +5993,26 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetBasicObjectInfo(CORDB_ADDRESS | |||
| { | |||
|
|
|||
| PTR_Object objPtr = PTR_Object(TADDR(objectAddress)); | |||
| pObjectData->objRefBad = CheckRef(objPtr); | |||
| if (pObjectData->objRefBad != true) | |||
| BOOL objRefBad = CheckRef(objPtr); | |||
| *pIsValidRef = !objRefBad; | |||
| if (!objRefBad) | |||
| public void GetStringData(TargetPointer address, out uint length, out uint offsetToFirstChar) | ||
| { | ||
| TargetPointer mt = GetMethodTableAddress(address); | ||
| if (mt == TargetPointer.Null) | ||
| throw new ArgumentException("Address represents a set-free object"); | ||
| if (mt != _stringMethodTable) | ||
| throw new ArgumentException("Address does not represent a string object", nameof(address)); | ||
|
|
||
| Data.String str = _target.ProcessedData.GetOrAdd<Data.String>(address); | ||
| length = str.StringLength; | ||
| offsetToFirstChar = (uint)(str.FirstChar.Value - address.Value); | ||
| } |