Support loading cDAC from SOS installations - #5874

Merged
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac
Jun 18, 2026
Merged

Support loading cDAC from SOS installations#5874
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac

Conversation

@hoyosjs

Copy link
Copy Markdown
Member

Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC:

  • .NET 11+ defaults to cDAC unless DOTNET_ENABLE_CDAC is set to allow for runtime-diagnostics pipeline to still do dac/cdac diffing.
  • Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC as specified above/
  • Runtimes command now has a tri-state UseCDac (null= default policy described above, true=force, false=never) with --usecdac true|false|policy**
  • DataTarget implements ICLRContractLocator and stores resolved contract descriptor address for cDAC initialization
  • sos-packaging.props cleanup to allow any arch packaging; PackageWithCDac=true by default on main branch so all platforms (win-x64/x86/arm64, linux-*, osx-*) bundle cDAC alongside sos.

max-charlamb added a commit to dotnet/runtime that referenced this pull request Jun 17, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@hoyosjs
hoyosjs marked this pull request as ready for review June 17, 2026 18:20
@hoyosjs
hoyosjs requested a review from a team as a code ownerJune 17, 2026 18:20
CopilotAI review requested due to automatic review settings June 17, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates SOS/tool packaging and runtime-loading behavior to bundle and preferentially load the cDAC (mscordaccore_universal) from diagnostics tool installations, with a default policy for .NET 11+ and a new tri-state user control surface.

Changes:

  • Add cDAC discovery/loading paths across native SOS, SOS.Hosting, and ClrMD runtime creation (including contract descriptor plumbing via ICLRContractLocator).
  • Introduce an asset/layout resolver (IHostAssetResolver + SOSPackageLayout) so tools consistently locate native binaries (including bundled cDAC) regardless of host.
  • Update packaging/build logic to optionally bundle cDAC into tool packages and adjust tests/scripts for current SOS output differences.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/SOS.UnitTests/SOS.csUpdates test skip conditions (notably Win-x86) for tracked regression coverage.
src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.scriptMakes stack verification tolerant to shifted source line numbers.
src/SOS/Strike/util.cppRequests cDAC-capable CLR data process in the main SOS load path; whitespace cleanup.
src/SOS/Strike/platform/runtimeimpl.hAdds cDAC path/process members and policy/helpers to native Runtime.
src/SOS/Strike/platform/runtimeimpl.cppImplements cDAC path resolution (next to SOS), policy, IXCLRDataProcess creation, and contract descriptor lookup.
src/SOS/Strike/platform/datatarget.hExtends DataTarget to implement ICLRContractLocator.
src/SOS/Strike/platform/datatarget.cppImplements ICLRContractLocator::GetContractDescriptor and QueryInterface wiring.
src/SOS/Strike/clrma/managedanalysis.cppImproves tracing when runtime-based DAC retrieval fails and falls back.
src/SOS/SOS.Package/SOS.Symbol.Package.csprojAdds single-RID packing support via conditional symbol inclusion.
src/SOS/SOS.Package/SOS.Package.csprojEnsures dotnet run for manifest generation uses the active configuration.
src/SOS/SOS.Package/GenerateManifest/Directory.Build.targetsShields file-based app build by preventing repo targets import (intentionally empty).
src/SOS/SOS.Package/GenerateManifest/Directory.Build.propsShields file-based app build by preventing repo props import (intentionally empty).
src/SOS/SOS.InstallHelper/SOS.InstallHelper.csprojLinks shared SOSPackageLayout implementation into InstallHelper.
src/SOS/SOS.InstallHelper/InstallHelper.csSwitches native/managed source path resolution to SOSPackageLayout.
src/SOS/SOS.Hosting/SOSPackageLayout.csDefines package-relative layout rules for native vs managed SOS assets.
src/SOS/SOS.Hosting/SOSLibrary.csUses IHostAssetResolver for native binary location; updates ISOSModule semantics/comments.
src/SOS/SOS.Hosting/SOS.Hosting.csprojRemoves InstallHelper project reference (no longer needed).
src/SOS/SOS.Hosting/RuntimeWrapper.csPrefers cDAC for IXCLRDataProcess path; refactors DAC/cDAC load handling.
src/SOS/SOS.Hosting/HostAssetResolver.csNew global service that resolves native binaries directory and cDAC path.
src/SOS/SOS.Extensions/HostServices.csRemoves unnecessary unsafe modifier; continues to expose ISOSModule data.
src/sos-packaging.propsReworks packaging inputs/conditions, adds SingleTargetRidPackage/PackageWithCDac semantics.
src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.csReplaces previous flags with tri-state `--usecdac true
src/Microsoft.Diagnostics.ExtensionCommands/Host/CommandFormatHelpers.csUpdates settings output to reflect tri-state cDAC policy.
src/Microsoft.Diagnostics.DebugServices/ISettingsService.csReplaces prior cDAC flags with bool? UseCDac and documents policy semantics.
src/Microsoft.Diagnostics.DebugServices/IRuntime.csClarifies DAC vs cDAC path responsibilities and nullability for cDAC.
src/Microsoft.Diagnostics.DebugServices/IHostAssetResolver.csNew contract for resolving host-native asset locations (including cDAC).
src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.csRemoves SOS.InstallHelper from default assemblies list for extension loading.
src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.csAdds signature-verification override for the trusted bundled cDAC path.
src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.csImplements cDAC policy, uses host resolver for cDAC path, and prefers cDAC for ClrMD runtime creation.
src/Microsoft.Diagnostics.DebugServices.Implementation/Host.csUpdates settings storage to bool? UseCDac.
src/dbgshim/pkg/Microsoft.Diagnostics.DbgShim.propsOptionally packages cDAC next to dbgshim when enabled.
eng/Versions.propsDefaults PackageWithCDac=true on preview branches unless overridden.
eng/InstallNativePackages.targetsDownloads/stages cDAC transport pack content when PackageWithCDac=true.
eng/CdacPackageItems.propsRemoves prior per-RID cDAC transport pack itemization (now in targets).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ExtDbgOut("GetCDacFilePath: dladdr failed to locate the sos module\n");
return nullptr;
}
strcpy_s(szSOSModulePath.GetPtr(), MAX_LONGPATH, info.dli_fname);
Comment threadeng/InstallNativePackages.targets
Comment on lines +241 to +245
// Prefer the cDAC for the data-access (IXCLRDataProcess) path when the runtime policy
// selects it (GetCDacFilePath returns non-null); fall back to the in-box DAC otherwise.
// The ICorDebug/DBI path (CreateCorDebugProcess) always uses the in-box DAC. The flags
// parameter is retained for the native IRuntime contract but no longer consulted here.
if (_cdacDataProcess == IntPtr.Zero)
steveisok
steveisok previously approved these changes Jun 17, 2026
max-charlamb
max-charlamb previously approved these changes Jun 17, 2026
Comment threadsrc/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs Outdated
@hoyosjs
hoyosjs dismissed stale reviews from max-charlamb and steveisok via e8921a9June 18, 2026 04:47

@noahfalknoahfalk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yey! 💯

@hoyosjs
hoyosjs merged commit dc90e42 into dotnet:mainJun 18, 2026
14 of 18 checks passed
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 9, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit to dotnet/runtime that referenced this pull request Jul 15, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 19, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@hoyosjs@steveisok@noahfalk@max-charlamb
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Support loading cDAC from SOS installations - #5874

Merged
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac
Jun 18, 2026
Merged

Support loading cDAC from SOS installations#5874
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac

Conversation

@hoyosjs

Copy link
Copy Markdown
Member

Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC:

  • .NET 11+ defaults to cDAC unless DOTNET_ENABLE_CDAC is set to allow for runtime-diagnostics pipeline to still do dac/cdac diffing.
  • Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC as specified above/
  • Runtimes command now has a tri-state UseCDac (null= default policy described above, true=force, false=never) with --usecdac true|false|policy**
  • DataTarget implements ICLRContractLocator and stores resolved contract descriptor address for cDAC initialization
  • sos-packaging.props cleanup to allow any arch packaging; PackageWithCDac=true by default on main branch so all platforms (win-x64/x86/arm64, linux-*, osx-*) bundle cDAC alongside sos.

max-charlamb added a commit to dotnet/runtime that referenced this pull request Jun 17, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@hoyosjs
hoyosjs marked this pull request as ready for review June 17, 2026 18:20
@hoyosjs
hoyosjs requested a review from a team as a code ownerJune 17, 2026 18:20
CopilotAI review requested due to automatic review settings June 17, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates SOS/tool packaging and runtime-loading behavior to bundle and preferentially load the cDAC (mscordaccore_universal) from diagnostics tool installations, with a default policy for .NET 11+ and a new tri-state user control surface.

Changes:

  • Add cDAC discovery/loading paths across native SOS, SOS.Hosting, and ClrMD runtime creation (including contract descriptor plumbing via ICLRContractLocator).
  • Introduce an asset/layout resolver (IHostAssetResolver + SOSPackageLayout) so tools consistently locate native binaries (including bundled cDAC) regardless of host.
  • Update packaging/build logic to optionally bundle cDAC into tool packages and adjust tests/scripts for current SOS output differences.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/SOS.UnitTests/SOS.csUpdates test skip conditions (notably Win-x86) for tracked regression coverage.
src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.scriptMakes stack verification tolerant to shifted source line numbers.
src/SOS/Strike/util.cppRequests cDAC-capable CLR data process in the main SOS load path; whitespace cleanup.
src/SOS/Strike/platform/runtimeimpl.hAdds cDAC path/process members and policy/helpers to native Runtime.
src/SOS/Strike/platform/runtimeimpl.cppImplements cDAC path resolution (next to SOS), policy, IXCLRDataProcess creation, and contract descriptor lookup.
src/SOS/Strike/platform/datatarget.hExtends DataTarget to implement ICLRContractLocator.
src/SOS/Strike/platform/datatarget.cppImplements ICLRContractLocator::GetContractDescriptor and QueryInterface wiring.
src/SOS/Strike/clrma/managedanalysis.cppImproves tracing when runtime-based DAC retrieval fails and falls back.
src/SOS/SOS.Package/SOS.Symbol.Package.csprojAdds single-RID packing support via conditional symbol inclusion.
src/SOS/SOS.Package/SOS.Package.csprojEnsures dotnet run for manifest generation uses the active configuration.
src/SOS/SOS.Package/GenerateManifest/Directory.Build.targetsShields file-based app build by preventing repo targets import (intentionally empty).
src/SOS/SOS.Package/GenerateManifest/Directory.Build.propsShields file-based app build by preventing repo props import (intentionally empty).
src/SOS/SOS.InstallHelper/SOS.InstallHelper.csprojLinks shared SOSPackageLayout implementation into InstallHelper.
src/SOS/SOS.InstallHelper/InstallHelper.csSwitches native/managed source path resolution to SOSPackageLayout.
src/SOS/SOS.Hosting/SOSPackageLayout.csDefines package-relative layout rules for native vs managed SOS assets.
src/SOS/SOS.Hosting/SOSLibrary.csUses IHostAssetResolver for native binary location; updates ISOSModule semantics/comments.
src/SOS/SOS.Hosting/SOS.Hosting.csprojRemoves InstallHelper project reference (no longer needed).
src/SOS/SOS.Hosting/RuntimeWrapper.csPrefers cDAC for IXCLRDataProcess path; refactors DAC/cDAC load handling.
src/SOS/SOS.Hosting/HostAssetResolver.csNew global service that resolves native binaries directory and cDAC path.
src/SOS/SOS.Extensions/HostServices.csRemoves unnecessary unsafe modifier; continues to expose ISOSModule data.
src/sos-packaging.propsReworks packaging inputs/conditions, adds SingleTargetRidPackage/PackageWithCDac semantics.
src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.csReplaces previous flags with tri-state `--usecdac true
src/Microsoft.Diagnostics.ExtensionCommands/Host/CommandFormatHelpers.csUpdates settings output to reflect tri-state cDAC policy.
src/Microsoft.Diagnostics.DebugServices/ISettingsService.csReplaces prior cDAC flags with bool? UseCDac and documents policy semantics.
src/Microsoft.Diagnostics.DebugServices/IRuntime.csClarifies DAC vs cDAC path responsibilities and nullability for cDAC.
src/Microsoft.Diagnostics.DebugServices/IHostAssetResolver.csNew contract for resolving host-native asset locations (including cDAC).
src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.csRemoves SOS.InstallHelper from default assemblies list for extension loading.
src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.csAdds signature-verification override for the trusted bundled cDAC path.
src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.csImplements cDAC policy, uses host resolver for cDAC path, and prefers cDAC for ClrMD runtime creation.
src/Microsoft.Diagnostics.DebugServices.Implementation/Host.csUpdates settings storage to bool? UseCDac.
src/dbgshim/pkg/Microsoft.Diagnostics.DbgShim.propsOptionally packages cDAC next to dbgshim when enabled.
eng/Versions.propsDefaults PackageWithCDac=true on preview branches unless overridden.
eng/InstallNativePackages.targetsDownloads/stages cDAC transport pack content when PackageWithCDac=true.
eng/CdacPackageItems.propsRemoves prior per-RID cDAC transport pack itemization (now in targets).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ExtDbgOut("GetCDacFilePath: dladdr failed to locate the sos module\n");
return nullptr;
}
strcpy_s(szSOSModulePath.GetPtr(), MAX_LONGPATH, info.dli_fname);
Comment threadeng/InstallNativePackages.targets
Comment on lines +241 to +245
// Prefer the cDAC for the data-access (IXCLRDataProcess) path when the runtime policy
// selects it (GetCDacFilePath returns non-null); fall back to the in-box DAC otherwise.
// The ICorDebug/DBI path (CreateCorDebugProcess) always uses the in-box DAC. The flags
// parameter is retained for the native IRuntime contract but no longer consulted here.
if (_cdacDataProcess == IntPtr.Zero)
steveisok
steveisok previously approved these changes Jun 17, 2026
max-charlamb
max-charlamb previously approved these changes Jun 17, 2026
Comment threadsrc/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs Outdated
@hoyosjs
hoyosjs dismissed stale reviews from max-charlamb and steveisok via e8921a9June 18, 2026 04:47

@noahfalknoahfalk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yey! 💯

@hoyosjs
hoyosjs merged commit dc90e42 into dotnet:mainJun 18, 2026
14 of 18 checks passed
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 9, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit to dotnet/runtime that referenced this pull request Jul 15, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 19, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@hoyosjs@steveisok@noahfalk@max-charlamb
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Support loading cDAC from SOS installations - #5874

Merged
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac
Jun 18, 2026
Merged

Support loading cDAC from SOS installations#5874
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac

Conversation

@hoyosjs

Copy link
Copy Markdown
Member

Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC:

  • .NET 11+ defaults to cDAC unless DOTNET_ENABLE_CDAC is set to allow for runtime-diagnostics pipeline to still do dac/cdac diffing.
  • Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC as specified above/
  • Runtimes command now has a tri-state UseCDac (null= default policy described above, true=force, false=never) with --usecdac true|false|policy**
  • DataTarget implements ICLRContractLocator and stores resolved contract descriptor address for cDAC initialization
  • sos-packaging.props cleanup to allow any arch packaging; PackageWithCDac=true by default on main branch so all platforms (win-x64/x86/arm64, linux-*, osx-*) bundle cDAC alongside sos.

max-charlamb added a commit to dotnet/runtime that referenced this pull request Jun 17, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@hoyosjs
hoyosjs marked this pull request as ready for review June 17, 2026 18:20
@hoyosjs
hoyosjs requested a review from a team as a code ownerJune 17, 2026 18:20
CopilotAI review requested due to automatic review settings June 17, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates SOS/tool packaging and runtime-loading behavior to bundle and preferentially load the cDAC (mscordaccore_universal) from diagnostics tool installations, with a default policy for .NET 11+ and a new tri-state user control surface.

Changes:

  • Add cDAC discovery/loading paths across native SOS, SOS.Hosting, and ClrMD runtime creation (including contract descriptor plumbing via ICLRContractLocator).
  • Introduce an asset/layout resolver (IHostAssetResolver + SOSPackageLayout) so tools consistently locate native binaries (including bundled cDAC) regardless of host.
  • Update packaging/build logic to optionally bundle cDAC into tool packages and adjust tests/scripts for current SOS output differences.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/SOS.UnitTests/SOS.csUpdates test skip conditions (notably Win-x86) for tracked regression coverage.
src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.scriptMakes stack verification tolerant to shifted source line numbers.
src/SOS/Strike/util.cppRequests cDAC-capable CLR data process in the main SOS load path; whitespace cleanup.
src/SOS/Strike/platform/runtimeimpl.hAdds cDAC path/process members and policy/helpers to native Runtime.
src/SOS/Strike/platform/runtimeimpl.cppImplements cDAC path resolution (next to SOS), policy, IXCLRDataProcess creation, and contract descriptor lookup.
src/SOS/Strike/platform/datatarget.hExtends DataTarget to implement ICLRContractLocator.
src/SOS/Strike/platform/datatarget.cppImplements ICLRContractLocator::GetContractDescriptor and QueryInterface wiring.
src/SOS/Strike/clrma/managedanalysis.cppImproves tracing when runtime-based DAC retrieval fails and falls back.
src/SOS/SOS.Package/SOS.Symbol.Package.csprojAdds single-RID packing support via conditional symbol inclusion.
src/SOS/SOS.Package/SOS.Package.csprojEnsures dotnet run for manifest generation uses the active configuration.
src/SOS/SOS.Package/GenerateManifest/Directory.Build.targetsShields file-based app build by preventing repo targets import (intentionally empty).
src/SOS/SOS.Package/GenerateManifest/Directory.Build.propsShields file-based app build by preventing repo props import (intentionally empty).
src/SOS/SOS.InstallHelper/SOS.InstallHelper.csprojLinks shared SOSPackageLayout implementation into InstallHelper.
src/SOS/SOS.InstallHelper/InstallHelper.csSwitches native/managed source path resolution to SOSPackageLayout.
src/SOS/SOS.Hosting/SOSPackageLayout.csDefines package-relative layout rules for native vs managed SOS assets.
src/SOS/SOS.Hosting/SOSLibrary.csUses IHostAssetResolver for native binary location; updates ISOSModule semantics/comments.
src/SOS/SOS.Hosting/SOS.Hosting.csprojRemoves InstallHelper project reference (no longer needed).
src/SOS/SOS.Hosting/RuntimeWrapper.csPrefers cDAC for IXCLRDataProcess path; refactors DAC/cDAC load handling.
src/SOS/SOS.Hosting/HostAssetResolver.csNew global service that resolves native binaries directory and cDAC path.
src/SOS/SOS.Extensions/HostServices.csRemoves unnecessary unsafe modifier; continues to expose ISOSModule data.
src/sos-packaging.propsReworks packaging inputs/conditions, adds SingleTargetRidPackage/PackageWithCDac semantics.
src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.csReplaces previous flags with tri-state `--usecdac true
src/Microsoft.Diagnostics.ExtensionCommands/Host/CommandFormatHelpers.csUpdates settings output to reflect tri-state cDAC policy.
src/Microsoft.Diagnostics.DebugServices/ISettingsService.csReplaces prior cDAC flags with bool? UseCDac and documents policy semantics.
src/Microsoft.Diagnostics.DebugServices/IRuntime.csClarifies DAC vs cDAC path responsibilities and nullability for cDAC.
src/Microsoft.Diagnostics.DebugServices/IHostAssetResolver.csNew contract for resolving host-native asset locations (including cDAC).
src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.csRemoves SOS.InstallHelper from default assemblies list for extension loading.
src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.csAdds signature-verification override for the trusted bundled cDAC path.
src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.csImplements cDAC policy, uses host resolver for cDAC path, and prefers cDAC for ClrMD runtime creation.
src/Microsoft.Diagnostics.DebugServices.Implementation/Host.csUpdates settings storage to bool? UseCDac.
src/dbgshim/pkg/Microsoft.Diagnostics.DbgShim.propsOptionally packages cDAC next to dbgshim when enabled.
eng/Versions.propsDefaults PackageWithCDac=true on preview branches unless overridden.
eng/InstallNativePackages.targetsDownloads/stages cDAC transport pack content when PackageWithCDac=true.
eng/CdacPackageItems.propsRemoves prior per-RID cDAC transport pack itemization (now in targets).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ExtDbgOut("GetCDacFilePath: dladdr failed to locate the sos module\n");
return nullptr;
}
strcpy_s(szSOSModulePath.GetPtr(), MAX_LONGPATH, info.dli_fname);
Comment threadeng/InstallNativePackages.targets
Comment on lines +241 to +245
// Prefer the cDAC for the data-access (IXCLRDataProcess) path when the runtime policy
// selects it (GetCDacFilePath returns non-null); fall back to the in-box DAC otherwise.
// The ICorDebug/DBI path (CreateCorDebugProcess) always uses the in-box DAC. The flags
// parameter is retained for the native IRuntime contract but no longer consulted here.
if (_cdacDataProcess == IntPtr.Zero)
steveisok
steveisok previously approved these changes Jun 17, 2026
max-charlamb
max-charlamb previously approved these changes Jun 17, 2026
Comment threadsrc/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs Outdated
@hoyosjs
hoyosjs dismissed stale reviews from max-charlamb and steveisok via e8921a9June 18, 2026 04:47

@noahfalknoahfalk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yey! 💯

@hoyosjs
hoyosjs merged commit dc90e42 into dotnet:mainJun 18, 2026
14 of 18 checks passed
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 9, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit to dotnet/runtime that referenced this pull request Jul 15, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 19, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@hoyosjs@steveisok@noahfalk@max-charlamb
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Support loading cDAC from SOS installations - #5874

Merged
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac
Jun 18, 2026
Merged

Support loading cDAC from SOS installations#5874
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac

Conversation

@hoyosjs

Copy link
Copy Markdown
Member

Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC:

  • .NET 11+ defaults to cDAC unless DOTNET_ENABLE_CDAC is set to allow for runtime-diagnostics pipeline to still do dac/cdac diffing.
  • Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC as specified above/
  • Runtimes command now has a tri-state UseCDac (null= default policy described above, true=force, false=never) with --usecdac true|false|policy**
  • DataTarget implements ICLRContractLocator and stores resolved contract descriptor address for cDAC initialization
  • sos-packaging.props cleanup to allow any arch packaging; PackageWithCDac=true by default on main branch so all platforms (win-x64/x86/arm64, linux-*, osx-*) bundle cDAC alongside sos.

max-charlamb added a commit to dotnet/runtime that referenced this pull request Jun 17, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@hoyosjs
hoyosjs marked this pull request as ready for review June 17, 2026 18:20
@hoyosjs
hoyosjs requested a review from a team as a code ownerJune 17, 2026 18:20
CopilotAI review requested due to automatic review settings June 17, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates SOS/tool packaging and runtime-loading behavior to bundle and preferentially load the cDAC (mscordaccore_universal) from diagnostics tool installations, with a default policy for .NET 11+ and a new tri-state user control surface.

Changes:

  • Add cDAC discovery/loading paths across native SOS, SOS.Hosting, and ClrMD runtime creation (including contract descriptor plumbing via ICLRContractLocator).
  • Introduce an asset/layout resolver (IHostAssetResolver + SOSPackageLayout) so tools consistently locate native binaries (including bundled cDAC) regardless of host.
  • Update packaging/build logic to optionally bundle cDAC into tool packages and adjust tests/scripts for current SOS output differences.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/SOS.UnitTests/SOS.csUpdates test skip conditions (notably Win-x86) for tracked regression coverage.
src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.scriptMakes stack verification tolerant to shifted source line numbers.
src/SOS/Strike/util.cppRequests cDAC-capable CLR data process in the main SOS load path; whitespace cleanup.
src/SOS/Strike/platform/runtimeimpl.hAdds cDAC path/process members and policy/helpers to native Runtime.
src/SOS/Strike/platform/runtimeimpl.cppImplements cDAC path resolution (next to SOS), policy, IXCLRDataProcess creation, and contract descriptor lookup.
src/SOS/Strike/platform/datatarget.hExtends DataTarget to implement ICLRContractLocator.
src/SOS/Strike/platform/datatarget.cppImplements ICLRContractLocator::GetContractDescriptor and QueryInterface wiring.
src/SOS/Strike/clrma/managedanalysis.cppImproves tracing when runtime-based DAC retrieval fails and falls back.
src/SOS/SOS.Package/SOS.Symbol.Package.csprojAdds single-RID packing support via conditional symbol inclusion.
src/SOS/SOS.Package/SOS.Package.csprojEnsures dotnet run for manifest generation uses the active configuration.
src/SOS/SOS.Package/GenerateManifest/Directory.Build.targetsShields file-based app build by preventing repo targets import (intentionally empty).
src/SOS/SOS.Package/GenerateManifest/Directory.Build.propsShields file-based app build by preventing repo props import (intentionally empty).
src/SOS/SOS.InstallHelper/SOS.InstallHelper.csprojLinks shared SOSPackageLayout implementation into InstallHelper.
src/SOS/SOS.InstallHelper/InstallHelper.csSwitches native/managed source path resolution to SOSPackageLayout.
src/SOS/SOS.Hosting/SOSPackageLayout.csDefines package-relative layout rules for native vs managed SOS assets.
src/SOS/SOS.Hosting/SOSLibrary.csUses IHostAssetResolver for native binary location; updates ISOSModule semantics/comments.
src/SOS/SOS.Hosting/SOS.Hosting.csprojRemoves InstallHelper project reference (no longer needed).
src/SOS/SOS.Hosting/RuntimeWrapper.csPrefers cDAC for IXCLRDataProcess path; refactors DAC/cDAC load handling.
src/SOS/SOS.Hosting/HostAssetResolver.csNew global service that resolves native binaries directory and cDAC path.
src/SOS/SOS.Extensions/HostServices.csRemoves unnecessary unsafe modifier; continues to expose ISOSModule data.
src/sos-packaging.propsReworks packaging inputs/conditions, adds SingleTargetRidPackage/PackageWithCDac semantics.
src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.csReplaces previous flags with tri-state `--usecdac true
src/Microsoft.Diagnostics.ExtensionCommands/Host/CommandFormatHelpers.csUpdates settings output to reflect tri-state cDAC policy.
src/Microsoft.Diagnostics.DebugServices/ISettingsService.csReplaces prior cDAC flags with bool? UseCDac and documents policy semantics.
src/Microsoft.Diagnostics.DebugServices/IRuntime.csClarifies DAC vs cDAC path responsibilities and nullability for cDAC.
src/Microsoft.Diagnostics.DebugServices/IHostAssetResolver.csNew contract for resolving host-native asset locations (including cDAC).
src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.csRemoves SOS.InstallHelper from default assemblies list for extension loading.
src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.csAdds signature-verification override for the trusted bundled cDAC path.
src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.csImplements cDAC policy, uses host resolver for cDAC path, and prefers cDAC for ClrMD runtime creation.
src/Microsoft.Diagnostics.DebugServices.Implementation/Host.csUpdates settings storage to bool? UseCDac.
src/dbgshim/pkg/Microsoft.Diagnostics.DbgShim.propsOptionally packages cDAC next to dbgshim when enabled.
eng/Versions.propsDefaults PackageWithCDac=true on preview branches unless overridden.
eng/InstallNativePackages.targetsDownloads/stages cDAC transport pack content when PackageWithCDac=true.
eng/CdacPackageItems.propsRemoves prior per-RID cDAC transport pack itemization (now in targets).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ExtDbgOut("GetCDacFilePath: dladdr failed to locate the sos module\n");
return nullptr;
}
strcpy_s(szSOSModulePath.GetPtr(), MAX_LONGPATH, info.dli_fname);
Comment threadeng/InstallNativePackages.targets
Comment on lines +241 to +245
// Prefer the cDAC for the data-access (IXCLRDataProcess) path when the runtime policy
// selects it (GetCDacFilePath returns non-null); fall back to the in-box DAC otherwise.
// The ICorDebug/DBI path (CreateCorDebugProcess) always uses the in-box DAC. The flags
// parameter is retained for the native IRuntime contract but no longer consulted here.
if (_cdacDataProcess == IntPtr.Zero)
steveisok
steveisok previously approved these changes Jun 17, 2026
max-charlamb
max-charlamb previously approved these changes Jun 17, 2026
Comment threadsrc/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs Outdated
@hoyosjs
hoyosjs dismissed stale reviews from max-charlamb and steveisok via e8921a9June 18, 2026 04:47

@noahfalknoahfalk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yey! 💯

@hoyosjs
hoyosjs merged commit dc90e42 into dotnet:mainJun 18, 2026
14 of 18 checks passed
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 9, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit to dotnet/runtime that referenced this pull request Jul 15, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 19, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@hoyosjs@steveisok@noahfalk@max-charlamb
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Support loading cDAC from SOS installations - #5874

Merged
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac
Jun 18, 2026
Merged

Support loading cDAC from SOS installations#5874
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac

Conversation

@hoyosjs

Copy link
Copy Markdown
Member

Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC:

  • .NET 11+ defaults to cDAC unless DOTNET_ENABLE_CDAC is set to allow for runtime-diagnostics pipeline to still do dac/cdac diffing.
  • Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC as specified above/
  • Runtimes command now has a tri-state UseCDac (null= default policy described above, true=force, false=never) with --usecdac true|false|policy**
  • DataTarget implements ICLRContractLocator and stores resolved contract descriptor address for cDAC initialization
  • sos-packaging.props cleanup to allow any arch packaging; PackageWithCDac=true by default on main branch so all platforms (win-x64/x86/arm64, linux-*, osx-*) bundle cDAC alongside sos.

max-charlamb added a commit to dotnet/runtime that referenced this pull request Jun 17, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@hoyosjs
hoyosjs marked this pull request as ready for review June 17, 2026 18:20
@hoyosjs
hoyosjs requested a review from a team as a code ownerJune 17, 2026 18:20
CopilotAI review requested due to automatic review settings June 17, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates SOS/tool packaging and runtime-loading behavior to bundle and preferentially load the cDAC (mscordaccore_universal) from diagnostics tool installations, with a default policy for .NET 11+ and a new tri-state user control surface.

Changes:

  • Add cDAC discovery/loading paths across native SOS, SOS.Hosting, and ClrMD runtime creation (including contract descriptor plumbing via ICLRContractLocator).
  • Introduce an asset/layout resolver (IHostAssetResolver + SOSPackageLayout) so tools consistently locate native binaries (including bundled cDAC) regardless of host.
  • Update packaging/build logic to optionally bundle cDAC into tool packages and adjust tests/scripts for current SOS output differences.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/SOS.UnitTests/SOS.csUpdates test skip conditions (notably Win-x86) for tracked regression coverage.
src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.scriptMakes stack verification tolerant to shifted source line numbers.
src/SOS/Strike/util.cppRequests cDAC-capable CLR data process in the main SOS load path; whitespace cleanup.
src/SOS/Strike/platform/runtimeimpl.hAdds cDAC path/process members and policy/helpers to native Runtime.
src/SOS/Strike/platform/runtimeimpl.cppImplements cDAC path resolution (next to SOS), policy, IXCLRDataProcess creation, and contract descriptor lookup.
src/SOS/Strike/platform/datatarget.hExtends DataTarget to implement ICLRContractLocator.
src/SOS/Strike/platform/datatarget.cppImplements ICLRContractLocator::GetContractDescriptor and QueryInterface wiring.
src/SOS/Strike/clrma/managedanalysis.cppImproves tracing when runtime-based DAC retrieval fails and falls back.
src/SOS/SOS.Package/SOS.Symbol.Package.csprojAdds single-RID packing support via conditional symbol inclusion.
src/SOS/SOS.Package/SOS.Package.csprojEnsures dotnet run for manifest generation uses the active configuration.
src/SOS/SOS.Package/GenerateManifest/Directory.Build.targetsShields file-based app build by preventing repo targets import (intentionally empty).
src/SOS/SOS.Package/GenerateManifest/Directory.Build.propsShields file-based app build by preventing repo props import (intentionally empty).
src/SOS/SOS.InstallHelper/SOS.InstallHelper.csprojLinks shared SOSPackageLayout implementation into InstallHelper.
src/SOS/SOS.InstallHelper/InstallHelper.csSwitches native/managed source path resolution to SOSPackageLayout.
src/SOS/SOS.Hosting/SOSPackageLayout.csDefines package-relative layout rules for native vs managed SOS assets.
src/SOS/SOS.Hosting/SOSLibrary.csUses IHostAssetResolver for native binary location; updates ISOSModule semantics/comments.
src/SOS/SOS.Hosting/SOS.Hosting.csprojRemoves InstallHelper project reference (no longer needed).
src/SOS/SOS.Hosting/RuntimeWrapper.csPrefers cDAC for IXCLRDataProcess path; refactors DAC/cDAC load handling.
src/SOS/SOS.Hosting/HostAssetResolver.csNew global service that resolves native binaries directory and cDAC path.
src/SOS/SOS.Extensions/HostServices.csRemoves unnecessary unsafe modifier; continues to expose ISOSModule data.
src/sos-packaging.propsReworks packaging inputs/conditions, adds SingleTargetRidPackage/PackageWithCDac semantics.
src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.csReplaces previous flags with tri-state `--usecdac true
src/Microsoft.Diagnostics.ExtensionCommands/Host/CommandFormatHelpers.csUpdates settings output to reflect tri-state cDAC policy.
src/Microsoft.Diagnostics.DebugServices/ISettingsService.csReplaces prior cDAC flags with bool? UseCDac and documents policy semantics.
src/Microsoft.Diagnostics.DebugServices/IRuntime.csClarifies DAC vs cDAC path responsibilities and nullability for cDAC.
src/Microsoft.Diagnostics.DebugServices/IHostAssetResolver.csNew contract for resolving host-native asset locations (including cDAC).
src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.csRemoves SOS.InstallHelper from default assemblies list for extension loading.
src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.csAdds signature-verification override for the trusted bundled cDAC path.
src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.csImplements cDAC policy, uses host resolver for cDAC path, and prefers cDAC for ClrMD runtime creation.
src/Microsoft.Diagnostics.DebugServices.Implementation/Host.csUpdates settings storage to bool? UseCDac.
src/dbgshim/pkg/Microsoft.Diagnostics.DbgShim.propsOptionally packages cDAC next to dbgshim when enabled.
eng/Versions.propsDefaults PackageWithCDac=true on preview branches unless overridden.
eng/InstallNativePackages.targetsDownloads/stages cDAC transport pack content when PackageWithCDac=true.
eng/CdacPackageItems.propsRemoves prior per-RID cDAC transport pack itemization (now in targets).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ExtDbgOut("GetCDacFilePath: dladdr failed to locate the sos module\n");
return nullptr;
}
strcpy_s(szSOSModulePath.GetPtr(), MAX_LONGPATH, info.dli_fname);
Comment threadeng/InstallNativePackages.targets
Comment on lines +241 to +245
// Prefer the cDAC for the data-access (IXCLRDataProcess) path when the runtime policy
// selects it (GetCDacFilePath returns non-null); fall back to the in-box DAC otherwise.
// The ICorDebug/DBI path (CreateCorDebugProcess) always uses the in-box DAC. The flags
// parameter is retained for the native IRuntime contract but no longer consulted here.
if (_cdacDataProcess == IntPtr.Zero)
steveisok
steveisok previously approved these changes Jun 17, 2026
max-charlamb
max-charlamb previously approved these changes Jun 17, 2026
Comment threadsrc/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs Outdated
@hoyosjs
hoyosjs dismissed stale reviews from max-charlamb and steveisok via e8921a9June 18, 2026 04:47

@noahfalknoahfalk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yey! 💯

@hoyosjs
hoyosjs merged commit dc90e42 into dotnet:mainJun 18, 2026
14 of 18 checks passed
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 9, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit to dotnet/runtime that referenced this pull request Jul 15, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 19, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@hoyosjs@steveisok@noahfalk@max-charlamb
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Support loading cDAC from SOS installations - #5874

Merged
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac
Jun 18, 2026
Merged

Support loading cDAC from SOS installations#5874
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac

Conversation

@hoyosjs

Copy link
Copy Markdown
Member

Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC:

  • .NET 11+ defaults to cDAC unless DOTNET_ENABLE_CDAC is set to allow for runtime-diagnostics pipeline to still do dac/cdac diffing.
  • Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC as specified above/
  • Runtimes command now has a tri-state UseCDac (null= default policy described above, true=force, false=never) with --usecdac true|false|policy**
  • DataTarget implements ICLRContractLocator and stores resolved contract descriptor address for cDAC initialization
  • sos-packaging.props cleanup to allow any arch packaging; PackageWithCDac=true by default on main branch so all platforms (win-x64/x86/arm64, linux-*, osx-*) bundle cDAC alongside sos.

max-charlamb added a commit to dotnet/runtime that referenced this pull request Jun 17, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@hoyosjs
hoyosjs marked this pull request as ready for review June 17, 2026 18:20
@hoyosjs
hoyosjs requested a review from a team as a code ownerJune 17, 2026 18:20
CopilotAI review requested due to automatic review settings June 17, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates SOS/tool packaging and runtime-loading behavior to bundle and preferentially load the cDAC (mscordaccore_universal) from diagnostics tool installations, with a default policy for .NET 11+ and a new tri-state user control surface.

Changes:

  • Add cDAC discovery/loading paths across native SOS, SOS.Hosting, and ClrMD runtime creation (including contract descriptor plumbing via ICLRContractLocator).
  • Introduce an asset/layout resolver (IHostAssetResolver + SOSPackageLayout) so tools consistently locate native binaries (including bundled cDAC) regardless of host.
  • Update packaging/build logic to optionally bundle cDAC into tool packages and adjust tests/scripts for current SOS output differences.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/SOS.UnitTests/SOS.csUpdates test skip conditions (notably Win-x86) for tracked regression coverage.
src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.scriptMakes stack verification tolerant to shifted source line numbers.
src/SOS/Strike/util.cppRequests cDAC-capable CLR data process in the main SOS load path; whitespace cleanup.
src/SOS/Strike/platform/runtimeimpl.hAdds cDAC path/process members and policy/helpers to native Runtime.
src/SOS/Strike/platform/runtimeimpl.cppImplements cDAC path resolution (next to SOS), policy, IXCLRDataProcess creation, and contract descriptor lookup.
src/SOS/Strike/platform/datatarget.hExtends DataTarget to implement ICLRContractLocator.
src/SOS/Strike/platform/datatarget.cppImplements ICLRContractLocator::GetContractDescriptor and QueryInterface wiring.
src/SOS/Strike/clrma/managedanalysis.cppImproves tracing when runtime-based DAC retrieval fails and falls back.
src/SOS/SOS.Package/SOS.Symbol.Package.csprojAdds single-RID packing support via conditional symbol inclusion.
src/SOS/SOS.Package/SOS.Package.csprojEnsures dotnet run for manifest generation uses the active configuration.
src/SOS/SOS.Package/GenerateManifest/Directory.Build.targetsShields file-based app build by preventing repo targets import (intentionally empty).
src/SOS/SOS.Package/GenerateManifest/Directory.Build.propsShields file-based app build by preventing repo props import (intentionally empty).
src/SOS/SOS.InstallHelper/SOS.InstallHelper.csprojLinks shared SOSPackageLayout implementation into InstallHelper.
src/SOS/SOS.InstallHelper/InstallHelper.csSwitches native/managed source path resolution to SOSPackageLayout.
src/SOS/SOS.Hosting/SOSPackageLayout.csDefines package-relative layout rules for native vs managed SOS assets.
src/SOS/SOS.Hosting/SOSLibrary.csUses IHostAssetResolver for native binary location; updates ISOSModule semantics/comments.
src/SOS/SOS.Hosting/SOS.Hosting.csprojRemoves InstallHelper project reference (no longer needed).
src/SOS/SOS.Hosting/RuntimeWrapper.csPrefers cDAC for IXCLRDataProcess path; refactors DAC/cDAC load handling.
src/SOS/SOS.Hosting/HostAssetResolver.csNew global service that resolves native binaries directory and cDAC path.
src/SOS/SOS.Extensions/HostServices.csRemoves unnecessary unsafe modifier; continues to expose ISOSModule data.
src/sos-packaging.propsReworks packaging inputs/conditions, adds SingleTargetRidPackage/PackageWithCDac semantics.
src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.csReplaces previous flags with tri-state `--usecdac true
src/Microsoft.Diagnostics.ExtensionCommands/Host/CommandFormatHelpers.csUpdates settings output to reflect tri-state cDAC policy.
src/Microsoft.Diagnostics.DebugServices/ISettingsService.csReplaces prior cDAC flags with bool? UseCDac and documents policy semantics.
src/Microsoft.Diagnostics.DebugServices/IRuntime.csClarifies DAC vs cDAC path responsibilities and nullability for cDAC.
src/Microsoft.Diagnostics.DebugServices/IHostAssetResolver.csNew contract for resolving host-native asset locations (including cDAC).
src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.csRemoves SOS.InstallHelper from default assemblies list for extension loading.
src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.csAdds signature-verification override for the trusted bundled cDAC path.
src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.csImplements cDAC policy, uses host resolver for cDAC path, and prefers cDAC for ClrMD runtime creation.
src/Microsoft.Diagnostics.DebugServices.Implementation/Host.csUpdates settings storage to bool? UseCDac.
src/dbgshim/pkg/Microsoft.Diagnostics.DbgShim.propsOptionally packages cDAC next to dbgshim when enabled.
eng/Versions.propsDefaults PackageWithCDac=true on preview branches unless overridden.
eng/InstallNativePackages.targetsDownloads/stages cDAC transport pack content when PackageWithCDac=true.
eng/CdacPackageItems.propsRemoves prior per-RID cDAC transport pack itemization (now in targets).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ExtDbgOut("GetCDacFilePath: dladdr failed to locate the sos module\n");
return nullptr;
}
strcpy_s(szSOSModulePath.GetPtr(), MAX_LONGPATH, info.dli_fname);
Comment threadeng/InstallNativePackages.targets
Comment on lines +241 to +245
// Prefer the cDAC for the data-access (IXCLRDataProcess) path when the runtime policy
// selects it (GetCDacFilePath returns non-null); fall back to the in-box DAC otherwise.
// The ICorDebug/DBI path (CreateCorDebugProcess) always uses the in-box DAC. The flags
// parameter is retained for the native IRuntime contract but no longer consulted here.
if (_cdacDataProcess == IntPtr.Zero)
steveisok
steveisok previously approved these changes Jun 17, 2026
max-charlamb
max-charlamb previously approved these changes Jun 17, 2026
Comment threadsrc/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs Outdated
@hoyosjs
hoyosjs dismissed stale reviews from max-charlamb and steveisok via e8921a9June 18, 2026 04:47

@noahfalknoahfalk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yey! 💯

@hoyosjs
hoyosjs merged commit dc90e42 into dotnet:mainJun 18, 2026
14 of 18 checks passed
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 9, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit to dotnet/runtime that referenced this pull request Jul 15, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 19, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@hoyosjs@steveisok@noahfalk@max-charlamb
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Support loading cDAC from SOS installations - #5874

Merged
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac
Jun 18, 2026
Merged

Support loading cDAC from SOS installations#5874
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac

Conversation

@hoyosjs

Copy link
Copy Markdown
Member

Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC:

  • .NET 11+ defaults to cDAC unless DOTNET_ENABLE_CDAC is set to allow for runtime-diagnostics pipeline to still do dac/cdac diffing.
  • Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC as specified above/
  • Runtimes command now has a tri-state UseCDac (null= default policy described above, true=force, false=never) with --usecdac true|false|policy**
  • DataTarget implements ICLRContractLocator and stores resolved contract descriptor address for cDAC initialization
  • sos-packaging.props cleanup to allow any arch packaging; PackageWithCDac=true by default on main branch so all platforms (win-x64/x86/arm64, linux-*, osx-*) bundle cDAC alongside sos.

max-charlamb added a commit to dotnet/runtime that referenced this pull request Jun 17, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@hoyosjs
hoyosjs marked this pull request as ready for review June 17, 2026 18:20
@hoyosjs
hoyosjs requested a review from a team as a code ownerJune 17, 2026 18:20
CopilotAI review requested due to automatic review settings June 17, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates SOS/tool packaging and runtime-loading behavior to bundle and preferentially load the cDAC (mscordaccore_universal) from diagnostics tool installations, with a default policy for .NET 11+ and a new tri-state user control surface.

Changes:

  • Add cDAC discovery/loading paths across native SOS, SOS.Hosting, and ClrMD runtime creation (including contract descriptor plumbing via ICLRContractLocator).
  • Introduce an asset/layout resolver (IHostAssetResolver + SOSPackageLayout) so tools consistently locate native binaries (including bundled cDAC) regardless of host.
  • Update packaging/build logic to optionally bundle cDAC into tool packages and adjust tests/scripts for current SOS output differences.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/SOS.UnitTests/SOS.csUpdates test skip conditions (notably Win-x86) for tracked regression coverage.
src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.scriptMakes stack verification tolerant to shifted source line numbers.
src/SOS/Strike/util.cppRequests cDAC-capable CLR data process in the main SOS load path; whitespace cleanup.
src/SOS/Strike/platform/runtimeimpl.hAdds cDAC path/process members and policy/helpers to native Runtime.
src/SOS/Strike/platform/runtimeimpl.cppImplements cDAC path resolution (next to SOS), policy, IXCLRDataProcess creation, and contract descriptor lookup.
src/SOS/Strike/platform/datatarget.hExtends DataTarget to implement ICLRContractLocator.
src/SOS/Strike/platform/datatarget.cppImplements ICLRContractLocator::GetContractDescriptor and QueryInterface wiring.
src/SOS/Strike/clrma/managedanalysis.cppImproves tracing when runtime-based DAC retrieval fails and falls back.
src/SOS/SOS.Package/SOS.Symbol.Package.csprojAdds single-RID packing support via conditional symbol inclusion.
src/SOS/SOS.Package/SOS.Package.csprojEnsures dotnet run for manifest generation uses the active configuration.
src/SOS/SOS.Package/GenerateManifest/Directory.Build.targetsShields file-based app build by preventing repo targets import (intentionally empty).
src/SOS/SOS.Package/GenerateManifest/Directory.Build.propsShields file-based app build by preventing repo props import (intentionally empty).
src/SOS/SOS.InstallHelper/SOS.InstallHelper.csprojLinks shared SOSPackageLayout implementation into InstallHelper.
src/SOS/SOS.InstallHelper/InstallHelper.csSwitches native/managed source path resolution to SOSPackageLayout.
src/SOS/SOS.Hosting/SOSPackageLayout.csDefines package-relative layout rules for native vs managed SOS assets.
src/SOS/SOS.Hosting/SOSLibrary.csUses IHostAssetResolver for native binary location; updates ISOSModule semantics/comments.
src/SOS/SOS.Hosting/SOS.Hosting.csprojRemoves InstallHelper project reference (no longer needed).
src/SOS/SOS.Hosting/RuntimeWrapper.csPrefers cDAC for IXCLRDataProcess path; refactors DAC/cDAC load handling.
src/SOS/SOS.Hosting/HostAssetResolver.csNew global service that resolves native binaries directory and cDAC path.
src/SOS/SOS.Extensions/HostServices.csRemoves unnecessary unsafe modifier; continues to expose ISOSModule data.
src/sos-packaging.propsReworks packaging inputs/conditions, adds SingleTargetRidPackage/PackageWithCDac semantics.
src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.csReplaces previous flags with tri-state `--usecdac true
src/Microsoft.Diagnostics.ExtensionCommands/Host/CommandFormatHelpers.csUpdates settings output to reflect tri-state cDAC policy.
src/Microsoft.Diagnostics.DebugServices/ISettingsService.csReplaces prior cDAC flags with bool? UseCDac and documents policy semantics.
src/Microsoft.Diagnostics.DebugServices/IRuntime.csClarifies DAC vs cDAC path responsibilities and nullability for cDAC.
src/Microsoft.Diagnostics.DebugServices/IHostAssetResolver.csNew contract for resolving host-native asset locations (including cDAC).
src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.csRemoves SOS.InstallHelper from default assemblies list for extension loading.
src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.csAdds signature-verification override for the trusted bundled cDAC path.
src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.csImplements cDAC policy, uses host resolver for cDAC path, and prefers cDAC for ClrMD runtime creation.
src/Microsoft.Diagnostics.DebugServices.Implementation/Host.csUpdates settings storage to bool? UseCDac.
src/dbgshim/pkg/Microsoft.Diagnostics.DbgShim.propsOptionally packages cDAC next to dbgshim when enabled.
eng/Versions.propsDefaults PackageWithCDac=true on preview branches unless overridden.
eng/InstallNativePackages.targetsDownloads/stages cDAC transport pack content when PackageWithCDac=true.
eng/CdacPackageItems.propsRemoves prior per-RID cDAC transport pack itemization (now in targets).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ExtDbgOut("GetCDacFilePath: dladdr failed to locate the sos module\n");
return nullptr;
}
strcpy_s(szSOSModulePath.GetPtr(), MAX_LONGPATH, info.dli_fname);
Comment threadeng/InstallNativePackages.targets
Comment on lines +241 to +245
// Prefer the cDAC for the data-access (IXCLRDataProcess) path when the runtime policy
// selects it (GetCDacFilePath returns non-null); fall back to the in-box DAC otherwise.
// The ICorDebug/DBI path (CreateCorDebugProcess) always uses the in-box DAC. The flags
// parameter is retained for the native IRuntime contract but no longer consulted here.
if (_cdacDataProcess == IntPtr.Zero)
steveisok
steveisok previously approved these changes Jun 17, 2026
max-charlamb
max-charlamb previously approved these changes Jun 17, 2026
Comment threadsrc/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs Outdated
@hoyosjs
hoyosjs dismissed stale reviews from max-charlamb and steveisok via e8921a9June 18, 2026 04:47

@noahfalknoahfalk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yey! 💯

@hoyosjs
hoyosjs merged commit dc90e42 into dotnet:mainJun 18, 2026
14 of 18 checks passed
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 9, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit to dotnet/runtime that referenced this pull request Jul 15, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 19, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@hoyosjs@steveisok@noahfalk@max-charlamb
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Support loading cDAC from SOS installations - #5874

Merged
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac
Jun 18, 2026
Merged

Support loading cDAC from SOS installations#5874
hoyosjs merged 8 commits into
dotnet:mainfrom
hoyosjs:juhoyosa/bundle-cdac

Conversation

@hoyosjs

Copy link
Copy Markdown
Member

Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC:

  • .NET 11+ defaults to cDAC unless DOTNET_ENABLE_CDAC is set to allow for runtime-diagnostics pipeline to still do dac/cdac diffing.
  • Bundle the cDAC into diagnostics tool packages and implement interim loading policy for DAC/cDAC as specified above/
  • Runtimes command now has a tri-state UseCDac (null= default policy described above, true=force, false=never) with --usecdac true|false|policy**
  • DataTarget implements ICLRContractLocator and stores resolved contract descriptor address for cDAC initialization
  • sos-packaging.props cleanup to allow any arch packaging; PackageWithCDac=true by default on main branch so all platforms (win-x64/x86/arm64, linux-*, osx-*) bundle cDAC alongside sos.

max-charlamb added a commit to dotnet/runtime that referenced this pull request Jun 17, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@hoyosjs
hoyosjs marked this pull request as ready for review June 17, 2026 18:20
@hoyosjs
hoyosjs requested a review from a team as a code ownerJune 17, 2026 18:20
CopilotAI review requested due to automatic review settings June 17, 2026 18:20

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates SOS/tool packaging and runtime-loading behavior to bundle and preferentially load the cDAC (mscordaccore_universal) from diagnostics tool installations, with a default policy for .NET 11+ and a new tri-state user control surface.

Changes:

  • Add cDAC discovery/loading paths across native SOS, SOS.Hosting, and ClrMD runtime creation (including contract descriptor plumbing via ICLRContractLocator).
  • Introduce an asset/layout resolver (IHostAssetResolver + SOSPackageLayout) so tools consistently locate native binaries (including bundled cDAC) regardless of host.
  • Update packaging/build logic to optionally bundle cDAC into tool packages and adjust tests/scripts for current SOS output differences.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 3 comments.

Show a summary per file
FileDescription
src/tests/SOS.UnitTests/SOS.csUpdates test skip conditions (notably Win-x86) for tracked regression coverage.
src/tests/SOS.UnitTests/Scripts/StackAndOtherTests.scriptMakes stack verification tolerant to shifted source line numbers.
src/SOS/Strike/util.cppRequests cDAC-capable CLR data process in the main SOS load path; whitespace cleanup.
src/SOS/Strike/platform/runtimeimpl.hAdds cDAC path/process members and policy/helpers to native Runtime.
src/SOS/Strike/platform/runtimeimpl.cppImplements cDAC path resolution (next to SOS), policy, IXCLRDataProcess creation, and contract descriptor lookup.
src/SOS/Strike/platform/datatarget.hExtends DataTarget to implement ICLRContractLocator.
src/SOS/Strike/platform/datatarget.cppImplements ICLRContractLocator::GetContractDescriptor and QueryInterface wiring.
src/SOS/Strike/clrma/managedanalysis.cppImproves tracing when runtime-based DAC retrieval fails and falls back.
src/SOS/SOS.Package/SOS.Symbol.Package.csprojAdds single-RID packing support via conditional symbol inclusion.
src/SOS/SOS.Package/SOS.Package.csprojEnsures dotnet run for manifest generation uses the active configuration.
src/SOS/SOS.Package/GenerateManifest/Directory.Build.targetsShields file-based app build by preventing repo targets import (intentionally empty).
src/SOS/SOS.Package/GenerateManifest/Directory.Build.propsShields file-based app build by preventing repo props import (intentionally empty).
src/SOS/SOS.InstallHelper/SOS.InstallHelper.csprojLinks shared SOSPackageLayout implementation into InstallHelper.
src/SOS/SOS.InstallHelper/InstallHelper.csSwitches native/managed source path resolution to SOSPackageLayout.
src/SOS/SOS.Hosting/SOSPackageLayout.csDefines package-relative layout rules for native vs managed SOS assets.
src/SOS/SOS.Hosting/SOSLibrary.csUses IHostAssetResolver for native binary location; updates ISOSModule semantics/comments.
src/SOS/SOS.Hosting/SOS.Hosting.csprojRemoves InstallHelper project reference (no longer needed).
src/SOS/SOS.Hosting/RuntimeWrapper.csPrefers cDAC for IXCLRDataProcess path; refactors DAC/cDAC load handling.
src/SOS/SOS.Hosting/HostAssetResolver.csNew global service that resolves native binaries directory and cDAC path.
src/SOS/SOS.Extensions/HostServices.csRemoves unnecessary unsafe modifier; continues to expose ISOSModule data.
src/sos-packaging.propsReworks packaging inputs/conditions, adds SingleTargetRidPackage/PackageWithCDac semantics.
src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.csReplaces previous flags with tri-state `--usecdac true
src/Microsoft.Diagnostics.ExtensionCommands/Host/CommandFormatHelpers.csUpdates settings output to reflect tri-state cDAC policy.
src/Microsoft.Diagnostics.DebugServices/ISettingsService.csReplaces prior cDAC flags with bool? UseCDac and documents policy semantics.
src/Microsoft.Diagnostics.DebugServices/IRuntime.csClarifies DAC vs cDAC path responsibilities and nullability for cDAC.
src/Microsoft.Diagnostics.DebugServices/IHostAssetResolver.csNew contract for resolving host-native asset locations (including cDAC).
src/Microsoft.Diagnostics.DebugServices.Implementation/ServiceManager.csRemoves SOS.InstallHelper from default assemblies list for extension loading.
src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.csAdds signature-verification override for the trusted bundled cDAC path.
src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.csImplements cDAC policy, uses host resolver for cDAC path, and prefers cDAC for ClrMD runtime creation.
src/Microsoft.Diagnostics.DebugServices.Implementation/Host.csUpdates settings storage to bool? UseCDac.
src/dbgshim/pkg/Microsoft.Diagnostics.DbgShim.propsOptionally packages cDAC next to dbgshim when enabled.
eng/Versions.propsDefaults PackageWithCDac=true on preview branches unless overridden.
eng/InstallNativePackages.targetsDownloads/stages cDAC transport pack content when PackageWithCDac=true.
eng/CdacPackageItems.propsRemoves prior per-RID cDAC transport pack itemization (now in targets).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

ExtDbgOut("GetCDacFilePath: dladdr failed to locate the sos module\n");
return nullptr;
}
strcpy_s(szSOSModulePath.GetPtr(), MAX_LONGPATH, info.dli_fname);
Comment threadeng/InstallNativePackages.targets
Comment on lines +241 to +245
// Prefer the cDAC for the data-access (IXCLRDataProcess) path when the runtime policy
// selects it (GetCDacFilePath returns non-null); fall back to the in-box DAC otherwise.
// The ICorDebug/DBI path (CreateCorDebugProcess) always uses the in-box DAC. The flags
// parameter is retained for the native IRuntime contract but no longer consulted here.
if (_cdacDataProcess == IntPtr.Zero)
steveisok
steveisok previously approved these changes Jun 17, 2026
max-charlamb
max-charlamb previously approved these changes Jun 17, 2026
Comment threadsrc/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs Outdated
@hoyosjs
hoyosjs dismissed stale reviews from max-charlamb and steveisok via e8921a9June 18, 2026 04:47

@noahfalknoahfalk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yey! 💯

@hoyosjs
hoyosjs merged commit dc90e42 into dotnet:mainJun 18, 2026
14 of 18 checks passed
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 23, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 24, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jun 25, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 4, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 9, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actionsBot added a commit to jeffhandley/dotnet-core-release-notes that referenced this pull request Jul 13, 2026
Cover diagnostics@dc90e42 (score 5): Support loading cDAC from SOS
installations (dotnet/diagnostics#5874).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
eiriktsarpalis pushed a commit to dotnet/runtime that referenced this pull request Jul 15, 2026
…ntract (#129456)
> [!NOTE]
> This PR was authored with assistance from GitHub Copilot.
## Summary
Fixes a cDAC `GetCodeHeaderData` failure that surfaced as `Unable to get
codeHeader information` when SOS ran `!clru` against an IL stub
MethodDesc on **Windows x86** with cDAC enabled (the new default
behavior on .NET 11 introduced by
[dotnet/diagnostics#5874](dotnet/diagnostics#5874)).
The CI failure that motivated this is
`SOSMethodTests.VarargPInvokeInteropMD` on x86 in dotnet/diagnostics:
`!IP2MD` returned the IL stub MethodDesc correctly, but the immediate
follow-up `!clru <MD>` printed only `Unable to get codeHeader
information`. x64 / arm64 / .NET 8/9/10 were unaffected.
## Root cause
x86 uses a fundamentally different GC info encoding from every other
architecture: the legacy bit-packed `InfoHdr` byte-stream format from
[`src/coreclr/vm/gc_unwind_x86.inl`](https://github.com/dotnet/runtime/blob/main/src/coreclr/vm/gc_unwind_x86.inl)
and
[`src/coreclr/inc/gcdecoder.cpp`](https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcdecoder.cpp)
(`USE_GC_INFO_DECODER` is defined for every target except x86, see
`eetwain.h:34`).
The cDAC `GCInfo` contract registered IGCInfo implementations for
X64/Arm64/Arm/LoongArch64/RiscV64 but **not** X86 -- so on x86 it fell
through to `default(GCInfo)` and threw `NotImplementedException` from
the interface's default `DecodePlatformSpecificGCInfo`. Any SOS path
that needed method size on x86 (`!clru`, `GetCodeHeaderData`,
`GetMethodRegionInfo`) failed.
## Approach
The cDAC already had a substantial x86 `InfoHdr` decoder under
`Contracts/StackWalk/Context/X86/GCInfoDecoding/`, used by the x86 stack
walker. Rather than write a parallel decoder, this PR **relocates** that
existing decoder under the `GCInfo` contract so there is **one canonical
x86 GC info implementation** shared between SOS callers and the stack
walker -- mirroring how the other architectures' decoders are
structured.
## Changes
* **Move** `Contracts/StackWalk/Context/X86/GCInfoDecoding/*` →
`Contracts/GCInfo/X86/*` (6 files, tracked as renames). Rename namespace
`StackWalkHelpers.X86` → `GCInfoHelpers.X86`.
* **Rename** the moved class `GCInfo` → `X86GCInfo` to avoid collision
with the empty `Contracts.GCInfo` IGCInfo fallback struct.
* Make `relativeOffset` ctor arg optional. Implement `IGCInfoDecoder`
directly on `X86GCInfo`: `GetCodeLength` / `GetStackBaseRegister` /
`GetSizeOfStackParameterArea` are wired up. `GetInterruptibleRanges` and
`EnumerateLiveSlots` throw `NotSupportedException` (future work, needed
for `!gcroot` / `!clrstack -l` etc.).
* Add `GCInfoX86_1` IGCInfo for x86; register it in
`CoreCLRContracts.cs` for `RuntimeInfoArchitecture.X86`.
* Update `ExecutionManagerCore.GetStackParameterSize` to delegate to
`IGCInfo.GetSizeOfStackParameterArea` (one source of truth).
* `X86Unwinder` continues to construct `X86GCInfo` directly because it
needs offset-bound state (`IsInProlog` / `IsInEpilog` / `PushedArgSize`)
not exposed through `IGCInfoDecoder`.
## Tests
* New `VarargPInvoke_GetCodeHeaderDataForILStub_ReturnsMethodSize`
regression test in `cdac/tests/DumpTests/StackWalkDumpTests.cs` --
asserts the IL stub path returns S_OK with non-zero `MethodSize`. Runs
against the existing cdac-dump-helix `windows_x86` matrix on every PR
(no pipeline changes needed).
* Existing 2509 cDAC unit tests still pass.
* Validated end-to-end against `SOSMethodTests.VarargPInvokeInteropMD`
x86 .NET 11prev6 cDAC: 4/4 pass after this fix; failed before.
## Docs
* `docs/design/datacontracts/GCInfo.md` -- intro now reflects partial
x86 support; `GetSizeOfStackParameterArea` API documented; per-method
status notes for x86.
* `docs/design/datacontracts/StackWalk.md` -- x86 section points at the
consolidated decoder location and explains how it's shared.
## Out of scope (future work)
* `GetInterruptibleRanges` and `EnumerateLiveSlots` for x86. The
underlying transition data is decoded but the adapter to the cDAC
`IGCInfoDecoder` shape is not wired up yet. This is what's needed to
unblock `!gcroot`, `!clrstack -l`, `!pe` on x86 cDAC. The two
pre-existing `[SkipOnArch("x86", "GCInfo decoder does not support
x86")]` markers in `StackReferenceDumpTests.cs` should become removable
once that lands.
---------
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jul 19, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@hoyosjs@steveisok@noahfalk@max-charlamb