Skip to content

SOS: activate data access through dbgshim using cDAC support policy - #5966

Draft
hoyosjs wants to merge 4 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/consume-changes
Draft

SOS: activate data access through dbgshim using cDAC support policy#5966
hoyosjs wants to merge 4 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/consume-changes

Conversation

@hoyosjs

@hoyosjs hoyosjs commented Aug 17, 2026

Copy link
Copy Markdown
Member

Summary

Route SOS data-access activation through the co-located dbgshim and let the cDAC
decide whether it supports each target by validating its contracts, instead of
pre-filtering targets by runtime version.

  • Add an optional IClrDataProcessActivator service implemented by SOS.Hosting.
    It creates a runtime-bound data target, loads the co-located dbgshim, applies the
    requested cDAC policy, and requests IXCLRDataProcess through
    ICLRDebugging::OpenVirtualProcess.
  • Register the created interface with ClrMD through
    DataTarget.AddLoadedRuntime, so ClrMD builds its normal runtime services without
    loading another DAC.
  • Use the same data-access service from native SOS.
  • Remove the direct ClrMD cDAC load and the separate cDAC path resolver; cDAC activation only occurs through the service.
  • Remove the managed and native .NET 11+ version gates. Under the default policy,
    every eligible CoreCLR target tries the cDAC; unsupported targets fall back to the
    matching DAC.
  • Add an additive cDAC-only flag to the existing IRuntime::GetClrDataProcess flags
    ABI. Forced cDAC rejection is preserved through native SOS and CLRMA instead of
    being replaced by DbgEng's DAC.
  • Move the managed ICLRDebugging / ICLRDebuggingPolicy interop definitions from
    the test project into SOS.Hosting as the product implementation.
  • Log every data-access decision with greppable data-access: messages.

Behavior

Policy / target Result
Default, .NET 10 cDAC declines with CDAC_E_DESCRIPTOR_MALFORMED; matching DAC is loaded
Default, current .NET 11 cDAC services the target through dbgshim
Forced cDAC, .NET 10 cDAC decline is returned; no DAC fallback
Forced cDAC, current .NET 11 cDAC services the target through dbgshim
Legacy DAC cDAC is not selected

dbgshim policy is set for each activation while holding the activator lock, so
concurrent requests cannot race different policy values on the shared
ICLRDebugging instance.

Verification

Built from:

  • diagnostics base 6bbbb2ce
  • runtime cDAC from runtime main 68069b76e67
  • .NET 10 runtime 10.0.11
  • .NET 11 runtime 11.0.0-rc.1.26413.103
  • CDB 10.0.26100.1

Product builds

  • SOS.Hosting.csproj: 0 warnings, 0 errors
  • dotnet-dump.csproj: 0 warnings, 0 errors
  • native SOS + dbgshim: succeeded
  • runtime tools.cdac: 0 warnings, 0 errors

End-to-end

Ran runtimes, clrstack, and dumpheap -stat against fresh full dumps:

Host .NET 10 .NET 11
dotnet-dump cDAC decline -> DAC; Program.Main; 246 objects cDAC through dbgshim; Program.Main; 346 objects
CDB + this SOS cDAC decline -> DAC; Program.Main; 246 objects cDAC through dbgshim; Program.Main; 346 objects

Forced-cDAC cases were also verified under both hosts:

  • .NET 10 fails without DAC fallback (0x80131C46 at the SOS boundary).
  • .NET 11 succeeds through dbgshim with CDacOnly.

Tests

  • DbgShim.UnitTests with PrivateBuildTesting=true: 36 passed, 0 failed.

Known test-environment issues

  • The repository-wide build reaches the test phase but its nested
    Debuggees.proj process exits with -2147450725. The affected product projects
    and native build succeed independently.
  • The full public DbgShim matrix reports 148 passed / 28 failed. All 28 failures
    are single-file configurations returning
    CORDBG_E_LIBRARY_PROVIDER_ERROR (0x80131C43) after the debuggee-asset build
    failure above. The supported private matrix passes.
  • The minimal cdb-sos package does not contain the default ntsdexts, uext, or
    exts extension DLLs. CDB warns while loading them, but the explicitly loaded
    SOS and every command used for this verification succeed.

SOS enumerates the runtime and hands the module base to dbgshim, which prefers the co-located cDAC and falls back to the legacy DAC. The resulting IXCLRDataProcess is registered with ClrMD (managed host, via DataTarget.AddLoadedRuntime) or returned to native SOS, replacing the direct cDAC LoadLibrary path.

Remove the runtime-version gate from the cDAC load policy: every runtime attempts the cDAC and the cDAC's own contract-support validation decides. Rework Runtime.CreateRuntime so a cDAC that loads but declines falls back to the in-box DAC; a forced cDAC (UseCDac) stays a hard failure rather than silently using the DAC. Extract TryCreateRuntimeFromLibrary.

Move the dbgshim managed interop (ICLRDebugging, ICLRDebuggingPolicy) from the test project into SOS.Hosting as the single product copy.

Add IClrDataProcessActivator (DebugServices) implemented by ClrDataProcessActivator (SOS.Hosting), which loads the co-located dbgshim, sets the prefer-cDAC policy, builds a runtime-bound DataTargetWrapper, and returns the IXCLRDataProcess from OpenVirtualProcess.
Add greppable 'data-access:' trace lines at every branch of the cDAC/DAC decision in both the managed ClrMD path (Runtime.CreateRuntime) and the native SOS path (RuntimeWrapper.GetClrDataProcess): seam tried, seam activated the cDAC, seam declined, no seam in host, direct cDAC tried/declined, forced-cDAC hard failure, and in-box DAC fallback. A log now shows exactly which engine served each runtime.
Remove the remaining native runtime-version check and let the cDAC validate whether it can service each target. Carry the effective cDAC policy through the hosted dbgshim activator, including a cDAC-only mode that cannot silently fall back to the DAC.

Preserve forced-cDAC rejection across the RuntimeWrapper boundary so native SOS and CLRMA do not replace it with DbgEng's DAC. Serialize per-activation dbgshim policy changes and keep the default prefer-cDAC fallback behavior for unsupported targets.
Make the IXCLRDataProcess service contract implementation-neutral and remove comments that describe callers, fallback policy, or historical behavior.

Remove the direct ClrMD cDAC load and the separate cDAC path resolver from Runtime. cDAC activation now only occurs through the registered service; ClrMD loads only the DAC fallback.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant