Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
d8b570c
cdac: Stack walk GC scanning, exception handling, and IsFilterFunclet…
Feb 27, 2026
933a96c
cdac: Implement EnumerateLiveSlots in managed GCInfoDecoder
Feb 27, 2026
57b16fb
cdac: Fix build errors in stack walk and execution manager
Feb 27, 2026
7d56297
cdac: Complete GcScanner.EnumGcRefs with live slot enumeration
Feb 27, 2026
8cc1e70
cdac: Implement GetStackReferences end-to-end
Feb 27, 2026
316d0dd
cdac: Add dump tests for GetStackReferences
Mar 2, 2026
82816bd
cdac: Restore datadescriptor entries with proper native support
Mar 2, 2026
521b94b
update
Mar 2, 2026
f30563a
add tests
Mar 2, 2026
95f6b65
update test script
Mar 2, 2026
4264428
clean up
Mar 2, 2026
c08e71a
add debug verification
Mar 2, 2026
e1f3c73
cdac: Add Frame GcScanRoots dispatch for non-frameless frames
Mar 2, 2026
76be992
cdac: Fix stack slot register in GcScanner, add set-based debug valid…
Mar 3, 2026
7eb79ae
cdac: Fix GCInfo slot table decoding bugs
Mar 3, 2026
c6fcf57
cdac: Fix ARM64 stack base register and ExecutionAborted exit path
Mar 3, 2026
b8c9d73
cdac: Match native skip behavior and add FindSafePoint TODO
Mar 3, 2026
96d2958
cdac: Implement scratch register/slot filtering in GCInfo decoder
Mar 3, 2026
a7bb140
Implement context register fetching by number
Mar 3, 2026
59b637a
cdac: Address PR review comments
Mar 3, 2026
8b5e023
GCReportCallback missing object dereference
Mar 6, 2026
2a40690
Fix cDAC stack walking bugs found via GC stress verification
Mar 9, 2026
db6d9b3
Fix Frame skip to use caller SP instead of initial SP
Mar 11, 2026
b567fbc
Guard new Data fields with ContainsKey for backward compatibility
Mar 11, 2026
5b66392
Address PR review comments: cleanup and safety fixes
Mar 11, 2026
8656473
Address remaining PR review comments
Mar 11, 2026
efb4301
Restore GetMethodDescPtr docs and fix patchpointinfo friend
Mar 11, 2026
f71402c
Remove unused m_lastReportedFunclet from ExInfo
Mar 11, 2026
6fc9f4e
remove guards that were not required
Mar 12, 2026
c921258
remove stale comment
Mar 12, 2026
84ce5aa
Fix GCReportCallback to throw on read failure and document funclet gaps
Mar 13, 2026
85de66c
Add cDAC GC stress verification tool (GCSTRESS_CDAC=0x20)
Mar 13, 2026
ccc74f8
Triple-match cDAC vs DAC vs runtime GC ref comparison
Mar 13, 2026
b53d67f
Remove DAC from stress tool, add cDAC ref filtering
Mar 13, 2026
0104d35
Add known issues doc and filter dynamic methods in GC stress
Mar 16, 2026
3c3d3c9
Move gcstress docs to cDAC tests directory and add README section
Mar 16, 2026
3beae98
Fix review issues: thread safety, buffer overflow, revert stale changes
Mar 16, 2026
52c150e
nit cleanup
Mar 16, 2026
2ebe34a
Merge remote-tracking branch 'origin/main' into cdac-stackreferences-…
Mar 16, 2026
f85d81f
updates
Mar 17, 2026
9b9a13a
include cdacdata.h
Mar 17, 2026
f0ea129
update to use the existing exception clause info
Mar 17, 2026
5d0748b
comments
Mar 17, 2026
45cadcd
comments
Mar 18, 2026
ae43c33
Merge remote-tracking branch 'origin/main' into cdac-stackreferences-…
Mar 18, 2026
2657230
Fix infinite loop in repo root discovery on Windows filesystem root
Mar 18, 2026
ebfbe16
Remove RegisterNumber from RegisterAttribute and context structs
Mar 18, 2026
5161d0d
Fix mock descriptors for new ExceptionInfo, RealCodeHeader, and Ready…
Mar 18, 2026
7f6da84
Fix cross-platform build errors: cdac_data<ExInfo> and _wfopen
Mar 19, 2026
3c1ebf6
Fix stack slot register encoding to match native GetStackReg
Mar 19, 2026
377e9f3
Improve GC stress comparison to validate Address and log Register/Offset
Mar 19, 2026
43d9a34
Fail initialization if ISOSDacInterface QI fails
Mar 19, 2026
f06f18d
Make IGCInfoDecoder.EnumerateLiveSlots abstract instead of default-th…
Mar 19, 2026
263d536
Only set ContinueOnAssert when not in FailFast mode
Mar 19, 2026
3188705
Merge remote-tracking branch 'origin/main' into pr-125505
Mar 19, 2026
cd25a01
Move skipBelowSP into CreateStackWalkCore helper
Mar 19, 2026
650ffb5
Simplify StackWalk_1.cs flags and logic
Mar 24, 2026
ce2762f
Fix GC stress register ref comparison with two-phase matching
Mar 24, 2026
67bfe49
Add extra Release for leaked enumerator ref-count in GC stress
Mar 25, 2026
d21fbbe
Implement PromoteCallerStack for cDAC stub frame scanning
Mar 18, 2026
6665a9f
Fix EH clause handling and add cDAC GC stress verification
Mar 18, 2026
96d130e
Remove dead code from StackWalk_1 and CorSigParser
Mar 25, 2026
fb98d33
Add DOTNET_CdacStress config and rename CdacGcStress to CdacStress
Mar 25, 2026
addbd38
Read FilterContext for stack walk starting context
Mar 26, 2026
db0c8c8
Add three-way cDAC/DAC/RT comparison and fix stack walk bugs
Mar 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/design/datacontracts/ExecutionManager.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ struct CodeBlockHandle
List<ExceptionClauseInfo> GetExceptionClauses(CodeBlockHandle codeInfoHandle);

// Extension Methods (implemented in terms of other APIs)
// Returns true if the code block is a funclet (exception handler, filter, or finally)
bool IsFunclet(CodeBlockHandle codeInfoHandle);
// Returns true if the code block is specifically a filter funclet
bool IsFilterFunclet(CodeBlockHandle codeInfoHandle);
```

```csharp
Expand Down Expand Up @@ -450,6 +453,8 @@ There are two distinct clause data types. JIT-compiled code uses `EEExceptionCla

After obtaining the clause array bounds, the common iteration logic classifies each clause by its flags. The native `COR_ILEXCEPTION_CLAUSE` flags are bit flags: `Filter` (0x1), `Finally` (0x2), `Fault` (0x4). If none are set, the clause is `Typed`. For typed clauses, if the `CachedClass` flag (0x10000000) is set (JIT-only, used for dynamic methods), the union field contains a resolved `TypeHandle` pointer; the clause is a catch-all if this pointer equals the `ObjectMethodTable` global. Otherwise, the union field is a metadata `ClassToken`. To determine whether a typed clause is a catch-all handler, the `ClassToken` (which may be a `TypeDef` or `TypeRef`) is resolved to a `MethodTable` via the `Loader` contract's module lookup maps (`TypeDefToMethodTable` or `TypeRefToMethodTable`) and compared against the `ObjectMethodTable` global. For typed clauses without a cached type handle, the module address is resolved by walking `CodeBlockHandle` → `MethodDesc` → `MethodTable` → `TypeHandle` → `Module` via the `RuntimeTypeSystem` contract.

`IsFilterFunclet` first checks `IsFunclet`. If the code block is a funclet, it retrieves the EH clauses for the method and checks whether any filter clause's handler offset matches the funclet's relative offset. If a match is found, the funclet is a filter funclet.

### RangeSectionMap

The range section map logically partitions the entire 32-bit or 64-bit addressable space into chunks.
Expand Down
23 changes: 21 additions & 2 deletions docs/design/datacontracts/StackWalk.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ This contract depends on the following descriptors:
| `StubDispatchFrame` | `MethodDescPtr` | Pointer to Frame's method desc |
| `StubDispatchFrame` | `RepresentativeMTPtr` | Pointer to Frame's method table pointer |
| `StubDispatchFrame` | `RepresentativeSlot` | Frame's method table slot |
| `StubDispatchFrame` | `GCRefMap` | Cached pointer to GC reference map blob for caller stack promotion |
| `ExternalMethodFrame` | `GCRefMap` | Cached pointer to GC reference map blob for caller stack promotion |
| `DynamicHelperFrame` | `DynamicHelperFrameFlags` | Flags indicating which argument registers contain GC references |
| `TransitionBlock` | `ReturnAddress` | Return address associated with the TransitionBlock |
| `TransitionBlock` | `CalleeSavedRegisters` | Platform specific CalleeSavedRegisters struct associated with the TransitionBlock |
| `TransitionBlock` (arm) | `ArgumentRegisters` | ARM specific `ArgumentRegisters` struct |
Expand All @@ -74,11 +77,27 @@ This contract depends on the following descriptors:
| `CalleeSavedRegisters` | For each callee saved register `r`, `r` | Register names associated with stored register values |
| `TailCallFrame` (x86 Windows) | `CalleeSavedRegisters` | CalleeSavedRegisters data structure |
| `TailCallFrame` (x86 Windows) | `ReturnAddress` | Frame's stored instruction pointer |
| `ExceptionInfo` | `ExceptionFlags` | Bit flags from `ExceptionFlags` class (`exstatecommon.h`). Used for GC reference reporting during stack walks with funclet handling. |
| `ExceptionInfo` | `StackLowBound` | Low bound of the stack range unwound by this exception |
| `ExceptionInfo` | `StackHighBound` | High bound of the stack range unwound by this exception |
| `ExceptionInfo` | `CSFEHClause` | Caller stack frame of the current EH clause |
| `ExceptionInfo` | `CSFEnclosingClause` | Caller stack frame of the enclosing clause |
| `ExceptionInfo` | `CallerOfActualHandlerFrame` | Stack frame of the caller of the catch handler |
| `ExceptionInfo` | `PreviousNestedInfo` | Pointer to previous nested ExInfo |
| `ExceptionInfo` | `PassNumber` | Exception handling pass (1 or 2) |

Global variables used:
| Global Name | Type | Purpose |
| --- | --- | --- |
| For each FrameType `<frameType>`, `<frameType>##Identifier` | `FrameIdentifier` enum value | Identifier used to determine concrete type of Frames |
| `TransitionBlockOffsetOfFirstGCRefMapSlot` | `uint32` | Byte offset within TransitionBlock where GCRefMap slot enumeration begins. ARM64: RetBuffArgReg offset; others: ArgumentRegisters offset. |
| `TransitionBlockOffsetOfArgumentRegisters` | `uint32` | Byte offset of the ArgumentRegisters within the TransitionBlock |
| `TransitionBlockOffsetOfArgs` | `uint32` | Byte offset of stack arguments (first arg after registers) = `sizeof(TransitionBlock)` |

Constants used:
| Source | Name | Value | Purpose |
| --- | --- | --- | --- |
| `ExceptionFlags` (`exstatecommon.h`) | `Ex_UnwindHasStarted` | `0x00000004` | Bit flag in `ExceptionInfo.ExceptionFlags` indicating exception unwinding (2nd pass) has started. Used by `IsInStackRegionUnwoundBySpecifiedException` to skip ExInfo trackers still in the 1st pass. |

Contracts used:
| Contract Name |
Expand Down Expand Up @@ -369,11 +388,11 @@ TargetPointer GetMethodDescPtr(TargetPointer framePtr)
4. The InlinedCallFrame's return address method has a MDContext arg

In this case, we report the actual interop MethodDesc. A pointer to the MethodDesc immediately follows the InlinedCallFrame in memory.
This API is implemeted as follows:
This API is implemented as follows:
1. Try to get the current frame address `framePtr` with `GetFrameAddress`.
2. If the address is not null, compute `reportInteropMD` as listed above. Otherwise skip to step 5.
3. If `reportInteropMD`, dereference the pointer immediately following the InlinedCallFrame and return that value.
4. If `!reportIteropMD`, return `GetMethodDescPtr(framePtr)`.
4. If `!reportInteropMD`, return `GetMethodDescPtr(framePtr)`.
5. Check if the current context IP is a managed context using the ExecutionManager contract. If it is a managed context, use the ExecutionManager context to find the related MethodDesc and return the pointer to it.
```csharp
TargetPointer GetMethodDescPtr(IStackDataFrameHandle stackDataFrameHandle)
Expand Down
5 changes: 5 additions & 0 deletions eng/Subsets.props
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@
<SubsetName Include="Tools.ILLinkTests" OnDemand="true" Description="Unit tests for the tools.illink subset." />
<SubsetName Include="Tools.CdacTests" OnDemand="true" Description="Unit tests for the diagnostic data contract reader." />
<SubsetName Include="Tools.CdacDumpTests" OnDemand="true" Description="Dump-based integration tests for the diagnostic data contract reader." />
<SubsetName Include="Tools.CdacGCStressTests" OnDemand="true" Description="GC stress integration tests for the diagnostic data contract reader." />
<SubsetName Include="Tools.ILAsm" OnDemand="true" Description="Build only the managed ilasm tool." />

<!-- Host -->
Expand Down Expand Up @@ -528,6 +529,10 @@
<ProjectToBuild Include="$(SharedNativeRoot)managed\cdac\tests\DumpTests\Microsoft.Diagnostics.DataContractReader.DumpTests.csproj" Test="true" Category="tools"/>
</ItemGroup>

<ItemGroup Condition="$(_subset.Contains('+tools.cdacgcstresstests+'))">
<ProjectToBuild Include="$(SharedNativeRoot)managed\cdac\tests\GCStressTests\Microsoft.Diagnostics.DataContractReader.GCStressTests.csproj" Test="true" Category="tools"/>
</ItemGroup>

<ItemGroup Condition="$(_subset.Contains('+tools.illink+'))">
<ProjectToBuild Include="$(ToolsProjectRoot)illink\src\linker\Mono.Linker.csproj" Category="tools" />
<ProjectToBuild Include="$(ToolsProjectRoot)illink\src\ILLink.Tasks\ILLink.Tasks.csproj" Category="tools" />
Expand Down
6 changes: 5 additions & 1 deletion src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitEnableNoWayAssert, W("JitEnableNoWayAssert"

RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_JitFramed, W("JitFramed"), 0, "Forces EBP frames")
CONFIG_DWORD_INFO(INTERNAL_JitThrowOnAssertionFailure, W("JitThrowOnAssertionFailure"), 0, "Throw managed exception on assertion failures during JIT instead of failfast")
CONFIG_DWORD_INFO(INTERNAL_JitGCStress, W("JitGCStress"), 0, "GC stress mode for jit")
CONFIG_DWORD_INFO(INTERNAL_JitGCStress, W("JitGCStress"), 0, "cDAC stress mode for jit")
CONFIG_DWORD_INFO(INTERNAL_JitHeartbeat, W("JitHeartbeat"), 0, "")
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_JITMinOpts, W("JITMinOpts"), 0, "Forces MinOpts")

Expand Down Expand Up @@ -747,6 +747,10 @@ CONFIG_STRING_INFO(INTERNAL_PerfTypesToLog, W("PerfTypesToLog"), "Log facility L
CONFIG_STRING_INFO(INTERNAL_PrestubGC, W("PrestubGC"), "")
CONFIG_STRING_INFO(INTERNAL_PrestubHalt, W("PrestubHalt"), "")
RETAIL_CONFIG_STRING_INFO(EXTERNAL_RestrictedGCStressExe, W("RestrictedGCStressExe"), "")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_CdacStressFailFast, W("CdacStressFailFast"), 0, "If nonzero, assert on cDAC/runtime GC ref mismatch during cDAC stress (GCSTRESS_CDAC mode).")
RETAIL_CONFIG_STRING_INFO(INTERNAL_CdacStressLogFile, W("CdacStressLogFile"), "Log file path for cDAC cDAC stress verification results.")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_CdacStressStep, W("CdacStressStep"), 1, "Verify every Nth cDAC stress point (1=every point, 100=every 100th). Reduces overhead while maintaining code path diversity.")
RETAIL_CONFIG_DWORD_INFO(INTERNAL_CdacStress, W("CdacStress"), 0, "Enable cDAC stack reference verification. Bit flags: 0x1=alloc points, 0x2=GC trigger points, 0x4=unique stacks only, 0x8=instruction points.")
CONFIG_DWORD_INFO(INTERNAL_ReturnSourceTypeForTesting, W("ReturnSourceTypeForTesting"), 0, "Allows returning the (internal only) source type of an IL to Native mapping for debugging purposes")
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RSStressLog, W("RSStressLog"), 0, "Allows turning on logging for RS startup")
CONFIG_DWORD_INFO(INTERNAL_SBDumpOnNewIndex, W("SBDumpOnNewIndex"), 0, "Used for Syncblock debugging. It's been a while since any of those have been used.")
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/inc/gcinfotypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ inline UINT32 CeilOfLog2(size_t x)
#endif
}

// [cDAC] [StackWalk]: GCInfo decoder depends on these values.
enum GcSlotFlags
{
GC_SLOT_BASE = 0x0,
Expand All @@ -65,6 +66,7 @@ enum GcSlotFlags
GC_SLOT_IS_DELETED = 0x10,
};

// [cDAC] [StackWalk]: GCInfo decoder depends on these values.
enum GcStackSlotBase
{
GC_CALLER_SP_REL = 0x0,
Expand Down Expand Up @@ -131,6 +133,7 @@ struct GcStackSlot
//
//--------------------------------------------------------------------------------

// [cDAC] [StackWalk]: GCInfo decoder depends on these values.
enum ReturnKind {

// Cases for Return in one register
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/inc/patchpointinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include <clrtypes.h>

#include "../vm/cdacdata.h"

#ifndef _PATCHPOINTINFO_H_
#define _PATCHPOINTINFO_H_

Expand Down Expand Up @@ -217,6 +219,8 @@ struct PatchpointInfo
}

private:
friend struct ::cdac_data<PatchpointInfo>;

enum
{
OFFSET_SHIFT = 0x1,
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ set(VM_SOURCES_WKS
finalizerthread.cpp
floatdouble.cpp
floatsingle.cpp
cdacstress.cpp
frozenobjectheap.cpp
gccover.cpp
gcenv.ee.cpp
Expand Down
Loading
Loading