You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
1. Embedded GC refs in large value types passed by value
Native:MetaSig::GcScanRoots ELEMENT_TYPE_VALUETYPE case
(src/coreclr/vm/siginfo.cpp:5437-5457) -> ReportPointersFromValueTypeArg -> walks the
type's CGCDesc series and reports each embedded GC ref.
cDAC today:GcTypeKind.Other parameters are silently skipped
(src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcScanner.cs).
Where to implement: new helper in GcScanner.cs (or sibling ValueTypeGcWalker.cs)
consuming a new IRuntimeTypeSystem.GetGCDescSeries(typeHandle) accessor. Requires GcSignatureTypeProvider / decoder consumers to surface the TypeHandle alongside GcTypeKind.Other so the walker has the type to enumerate. The ArgIterator port already
provides IsArgPassedByRef, which is the first branch native takes here.
2. String..ctorthis-slot handling
Native:src/coreclr/vm/frames.cpp:1523-1525:
if (msig.HasThis() && pFunction->GetMethodTable() == g_pStringClass && pFunction->IsCtor())
msig.ClearHasThis();
The caller does not pass this for String..ctor; the runtime allocates and overwrites it.
cDAC today: no special case; the slot is treated as a tracked ref.
Where to implement:GcScanner.PromoteCallerStack (around the existing hasThis
capture). Needs IRuntimeTypeSystem accessors for the well-known StringMethodTable
and an IsCtor predicate on MethodDesc.
3. SuppressParamTypeArg
Native:src/coreclr/vm/frames.cpp:1527-1528:
if (pFunction->RequiresInstArg() && !SuppressParamTypeArg())
msig.SetHasParamTypeArg();
Per-Frame-subclass virtual; some frame kinds suppress the inst-arg slot.
cDAC today:RequiresInstArg is honored unconditionally in GcScanner.PromoteCallerStack.
Where to implement: extend the frame-kind table in the StackWalk contract with a SuppressParamTypeArg bool per FrameKind, then in GcScanner.PromoteCallerStack: requiresInstArg = rts.RequiresInstArg(mdh) && !frameSuppressesParamTypeArg;.
4. SysV AMD64 struct classification
Native:SystemVStructClassifier::Classify splits structs <= 16 bytes into two 8-byte "eightbytes", classifies each as SSE/INTEGER/MEMORY per the SysV ABI, and places them in mixed (rdi, xmm0)-style register combos. ArgIterator::GetNextOffset on UNIX_AMD64_ABI uses this classification.
cDAC today:ArgIterator.GetNextOffsetX64 has a placeholder that routes all SysV-x64 structs through GP regs / stack. Results in wrong offsets for every struct arg on Linux/macOS x64 -> missed or misreported refs in struct { object, object }, struct { float, float }, mixed classes, etc.
Where to implement: port SystemVStructClassifier into the cDAC CallingConvention/ namespace and wire it into GetNextOffsetX64 when IsX64UnixABI is set. Needs to walk MT fields recursively to classify each eightbyte.
5. GCRefMap parser for ExternalMethodFrame / StubDispatchFrame
Native:TransitionFrame::PromoteCallerStackUsingGCRefMap (src/coreclr/vm/frames.cpp:1622) walks a precomputed bitmap emitted by crossgen at fixup call sites. Used unconditionally by ExternalMethodFrame::GcScanRoots_Impl (frames.cpp:1018) and as the fast path by StubDispatchFrame::GcScanRoots_Impl (frames.cpp:939-947) when available.
cDAC today: no GCRefMap parser. ExternalMethodFrame stack args are not scanned at all; StubDispatchFrame falls through to signature-walk (which is wrong for stub-dispatch slots where the MethodDesc may not describe the real callee).
Where to implement: new GcRefMapDecoder next to GcScanner; needs data-descriptor exposure for ExternalMethodFrame.m_pGCRefMap and the R2R FindGCRefMap lookup path for indirection cells.
Native:MetaSig::GetByValType resolves TypeSpec blobs through the loader (LoadTypeHandleFromSignature) so HFA classification works for ValueTuple<float,float,float,float>, Nullable<long>, etc.
cDAC today:GcSignatureTypeProvider.GetTypeFromSpecification and GetGenericInstantiation return GcArgInfo.OtherUnresolved -> falls back to pointer-sized placeholder. Generic HFA structs are misclassified on ARM64 (routed through int regs instead of float regs), causing all subsequent arg offsets to be wrong.
Where to implement: add signature-to-TypeHandle resolution in the Loader contract (mirror of LoadTypeHandleFromSignature) and wire it into GcSignatureTypeProvider's TypeSpec/instantiation paths.
7. TypedReference TypeHandle lookup
Native:MetaSig::GetByValType for ELEMENT_TYPE_TYPEDBYREF returns the well-known g_TypedReferenceMT TypeHandle.
cDAC today:GcSignatureTypeProvider.GetPrimitiveType for PrimitiveTypeCode.TypedReference returns GcArgInfo.OtherUnresolved with no TypeHandle. ArgIterator gets pointer-sized placeholder; the embedded ref inside TypedReference is not reported.
Where to implement: add a GetWellKnownTypeHandle(WellKnownType) accessor to IRuntimeTypeSystem (or piggy-back on GetCoreLibFieldDescAndDef's lookup pattern) and wire it into the TypedReference branch of GcSignatureTypeProvider.
cDAC today: PR3 (Fix ThinSList size and unify EMPTY_BASES definitions #127911) ports ArgIterator code paths for ARM/ARM64 but there are no DumpTests that capture dumps on those platforms. The HFA classification path (FeatureHFA datadescriptor + IsHFA + HFA element sizing) is unverified against real dumps.
Where to implement: extend the cDAC DumpTests Helix legs to run on linux-arm64 / windows-arm64, and add HFA-focused debuggees (struct { double, double, double }, Vector128<float> args, etc.) under tests/DumpTests/Debuggees/.
Note
Sections 4-8 added by an AI/Copilot-generated edit.
Gaps vs native DAC
1. Embedded GC refs in large value types passed by value
MetaSig::GcScanRootsELEMENT_TYPE_VALUETYPE case(
src/coreclr/vm/siginfo.cpp:5437-5457) ->ReportPointersFromValueTypeArg-> walks thetype's
CGCDescseries and reports each embedded GC ref.GcTypeKind.Otherparameters are silently skipped(
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/GC/GcScanner.cs).GcScanner.cs(or siblingValueTypeGcWalker.cs)consuming a new
IRuntimeTypeSystem.GetGCDescSeries(typeHandle)accessor. RequiresGcSignatureTypeProvider/ decoder consumers to surface theTypeHandlealongsideGcTypeKind.Otherso the walker has the type to enumerate. TheArgIteratorport alreadyprovides
IsArgPassedByRef, which is the first branch native takes here.2.
String..ctorthis-slot handlingsrc/coreclr/vm/frames.cpp:1523-1525:thisforString..ctor; the runtime allocates and overwrites it.GcScanner.PromoteCallerStack(around the existinghasThiscapture). Needs
IRuntimeTypeSystemaccessors for the well-knownStringMethodTableand an
IsCtorpredicate onMethodDesc.3.
SuppressParamTypeArgsrc/coreclr/vm/frames.cpp:1527-1528:Frame-subclass virtual; some frame kinds suppress the inst-arg slot.RequiresInstArgis honored unconditionally inGcScanner.PromoteCallerStack.StackWalkcontract with aSuppressParamTypeArgbool perFrameKind, then inGcScanner.PromoteCallerStack:requiresInstArg = rts.RequiresInstArg(mdh) && !frameSuppressesParamTypeArg;.4. SysV AMD64 struct classification
SystemVStructClassifier::Classifysplits structs <= 16 bytes into two 8-byte "eightbytes", classifies each as SSE/INTEGER/MEMORY per the SysV ABI, and places them in mixed(rdi, xmm0)-style register combos.ArgIterator::GetNextOffseton UNIX_AMD64_ABI uses this classification.ArgIterator.GetNextOffsetX64has a placeholder that routes all SysV-x64 structs through GP regs / stack. Results in wrong offsets for every struct arg on Linux/macOS x64 -> missed or misreported refs instruct { object, object },struct { float, float }, mixed classes, etc.SystemVStructClassifierinto the cDAC CallingConvention/ namespace and wire it intoGetNextOffsetX64whenIsX64UnixABIis set. Needs to walk MT fields recursively to classify each eightbyte.5. GCRefMap parser for ExternalMethodFrame / StubDispatchFrame
TransitionFrame::PromoteCallerStackUsingGCRefMap(src/coreclr/vm/frames.cpp:1622) walks a precomputed bitmap emitted by crossgen at fixup call sites. Used unconditionally byExternalMethodFrame::GcScanRoots_Impl(frames.cpp:1018) and as the fast path byStubDispatchFrame::GcScanRoots_Impl(frames.cpp:939-947) when available.GcRefMapDecodernext toGcScanner; needs data-descriptor exposure forExternalMethodFrame.m_pGCRefMapand the R2RFindGCRefMaplookup path for indirection cells.6. TypeSpec / generic value-type signature resolution
MetaSig::GetByValTyperesolves TypeSpec blobs through the loader (LoadTypeHandleFromSignature) so HFA classification works forValueTuple<float,float,float,float>,Nullable<long>, etc.GcSignatureTypeProvider.GetTypeFromSpecificationandGetGenericInstantiationreturnGcArgInfo.OtherUnresolved-> falls back to pointer-sized placeholder. Generic HFA structs are misclassified on ARM64 (routed through int regs instead of float regs), causing all subsequent arg offsets to be wrong.LoadTypeHandleFromSignature) and wire it intoGcSignatureTypeProvider's TypeSpec/instantiation paths.7. TypedReference TypeHandle lookup
MetaSig::GetByValTypeforELEMENT_TYPE_TYPEDBYREFreturns the well-knowng_TypedReferenceMTTypeHandle.GcSignatureTypeProvider.GetPrimitiveTypeforPrimitiveTypeCode.TypedReferencereturnsGcArgInfo.OtherUnresolvedwith no TypeHandle. ArgIterator gets pointer-sized placeholder; the embedded ref insideTypedReferenceis not reported.GetWellKnownTypeHandle(WellKnownType)accessor toIRuntimeTypeSystem(or piggy-back onGetCoreLibFieldDescAndDef's lookup pattern) and wire it into the TypedReference branch ofGcSignatureTypeProvider.8. ARM / ARM64 dump test coverage
EMPTY_BASESdefinitions #127911) ports ArgIterator code paths for ARM/ARM64 but there are no DumpTests that capture dumps on those platforms. The HFA classification path (FeatureHFA datadescriptor +IsHFA+ HFA element sizing) is unverified against real dumps.struct { double, double, double },Vector128<float>args, etc.) undertests/DumpTests/Debuggees/.Note
Sections 4-8 added by an AI/Copilot-generated edit.