Remove functional cDAC fallbacks - #132720
Conversation
|
Azure Pipelines: Successfully started running 5 pipeline(s). 11 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
There was a problem hiding this comment.
Pull request overview
This PR removes functional legacy-DAC fallback behavior in the managed cDAC layer, keeping legacy interfaces only for Debug cross-validation and lifetime rooting, and returning E_NOTIMPL for unsupported operations. It also adjusts CoreCLR’s ENABLE_CDAC path to avoid routing ICLRDataEnumMemoryRegions creation through cDAC (dump creation still relies on legacy memory enumeration).
Changes:
- Remove legacy fallback helper and update many legacy-interop call sites so legacy failures no longer influence cDAC return values (Debug validation only).
- Tighten cDAC/CoreCLR bootstrap behavior: validate required contracts before publishing interfaces and skip cDAC for
ICLRDataEnumMemoryRegions. - Update tests/docs to reflect the new “no fallback” policy and
E_NOTIMPLexpectations.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/native/managed/cdac/tests/UnitTests/MetaDataImportImplTests.cs | Adds coverage for IMetaDataImport2.GetModuleFromScope returning E_NOTIMPL. |
| src/native/managed/cdac/README.md | Updates documentation to reflect “Debug validation only” legacy usage and release lifetime-root behavior. |
| src/native/managed/cdac/mscordaccore_universal/Entrypoints.cs | Makes data-access contract validation unconditional before publishing interfaces; adjusts legacy-impl plumbing. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.IXCLRDataProcess.cs | Stops functional legacy fallback for unsupported ops and tightens validation-only legacy sync patterns. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.ICLRDataEnumMemoryRegions.cs | Returns E_NOTIMPL for memory region enumeration (no legacy fallback). |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs | Keeps legacy object rooted for lifetime; avoids using legacy for functional behavior in release builds. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/README.md | Replaces prior “delegation placement” guidance with the new “no fallback, Debug validation state only” policy. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/MetaDataImportImpl.cs | Removes legacy delegation for not-implemented IMetaDataImport/IMetaDataAssemblyImport members. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/LegacyFallbackHelper.cs | Deletes the allowlist-based fallback mechanism. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs | Nulls legacy DBI in release builds; preserves lifetime management and Debug validation patterns. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataTypeInstance.cs | Removes functional fallback paths and limits legacy use to Debug comparisons. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataTypeDefinition.cs | Removes functional fallback paths; keeps legacy sync for validation only. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataTask.cs | Stops propagating legacy HRESULTs into cDAC behavior; retains Debug validation. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataStackWalk.cs | Same: cDAC behavior no longer depends on legacy return values; Debug validates mismatches. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataModule.cs | Removes fallback returns for multiple enumeration APIs; keeps sync for validation. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodInstance.cs | Removes LegacyFallbackHelper gating and avoids returning legacy failures as cDAC failures. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodDefinition.cs | Removes “fallback to legacy result” exception handling and keeps legacy in sync for validation only. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataFrame.cs | Returns E_NOTIMPL for unsupported operations instead of falling back. |
| src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataExceptionState.cs | Removes LegacyFallbackHelper gating and uses legacy only for validation. |
| src/native/managed/cdac/inc/cdac_reader.h | Updates API comments describing legacy impl usage (lifetime + Debug comparisons only). |
| src/coreclr/debug/daccess/daccess.cpp | Skips cDAC creation for ICLRDataEnumMemoryRegions under ENABLE_CDAC; handles CreateSosInterface failure without asserting. |
| src/coreclr/debug/daccess/cdac.h | Changes CreateSosInterface to return an int status. |
| src/coreclr/debug/daccess/cdac.cpp | Propagates cdac_reader_create_sos_interface failure code instead of asserting success. |
Suppressed comments (1)
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/MetaDataImportImpl.cs:160
ResetEnumis implemented for cDAC-owned enumeration handles; for an unknown handle, returningE_NOTIMPLis misleading. ReturnE_INVALIDARGto indicate the handle is invalid for this implementation.
if (_cdacEnumHandles.ContainsKey(hEnum))
{
MetadataEnum e = GetEnum(hEnum);
e.Position = (int)Math.Min(ulPos, (uint)e.Tokens.Count);
return HResults.S_OK;
}
return HResults.E_NOTIMPL;
There was a problem hiding this comment.
🟡 Changes recommended
CDAC::CreateSosInterface can fail without reliably initializing the out-parameter, which is a correctness risk in the ENABLE_CDAC path.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/native/managed/cdac/tests/UnitTests/MetaDataImportImplTests.cs:1080
- Test method name is inconsistent with nearby tests (e.g., "..._ReturnsZero"); rename to "..._ReturnsInvalidArg" for consistency and readability.
- Files reviewed: 23/23 changed files
- Comments generated: 1
- Review effort level: Lite
There was a problem hiding this comment.
🔵 Needs a closer look
There are correctness/reliability issues in the updated code/tests (notably output initialization for E_NOTIMPL paths and a potentially fragile test sentinel) that should be addressed before merging.
Review details
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataTypeInstance.cs:36
- When returning
E_NOTIMPLfrom a COM method with output pointer parameters, initialize outputs to a safe default (e.g.,*handle = 0) to avoid callers accidentally using an uninitialized value in cleanup paths.
src/native/managed/cdac/tests/UnitTests/MetaDataImportImplTests.cs:1085 unknownHandleis set to1, which can coincide with a validGCHandle.ToIntPtr(...)value if any cDAC enum handle has been allocated in this test process, making this test potentially flaky. Use a non-trivial sentinel value that cannot realistically be a valid cDAC enum handle.
- Files reviewed: 23/23 changed files
- Comments generated: 0 new
- Review effort level: Lite
There was a problem hiding this comment.
🟡 Changes recommended
CDAC::CreateDacDbiInterface remains assertion-based and can still AV in Release if the export is missing or fails, which is inconsistent with the newly-hardened CreateSosInterface path.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 24/24 changed files
- Comments generated: 1
- Review effort level: Lite
There was a problem hiding this comment.
🔵 Needs a closer look
It changes core debugger/DAC behavior across managed + native layers (fallback removal, lifetime/validation semantics), which has a large compatibility surface and warrants maintainer review.
Review details
- Files reviewed: 25/25 changed files
- Comments generated: 0 new
- Review effort level: Lite
|
/azp run runtime-diagnostics |
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Keep legacy DAC interfaces only for Debug comparison and required lifetime management. Return E_NOTIMPL for unsupported cDAC operations. Fixed code paths where the behavior of the DAC comparison API call influenced the return value from cDAC. The FallbackHepler is now removed and most legacy interface pointers store NULL in release builds. DOTNET_ENABLE_CDAC no longer forwards the creation of ICLRDataEnumMemoryRegions to cDAC. If needed for testing this can be restored once the interface is implemented, but ideally we are moving towards eliminating DOTNET_ENABLE_CDAC env var and DAC->cDAC bootstrapping. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f8812ce5-101b-43e9-915a-835174a9d2ad
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Fix the cross-platform IID check that broke CI, harden SOS interface creation, and complete the remaining debug-validation and metadata enumeration review updates. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e3ee7201-c7f9-4f0d-b979-fbff0c77208b
Validate and clear the SOS interface out parameter before resolving the managed cDAC export, and align the metadata enumeration test name with local conventions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e3ee7201-c7f9-4f0d-b979-fbff0c77208b
Clear enumeration handles before returning E_NOTIMPL across the affected legacy wrappers, add regression coverage for cleanup safety, and use a robust invalid metadata handle sentinel. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e3ee7201-c7f9-4f0d-b979-fbff0c77208b
Validate and clear the DBI output pointer, handle a missing managed export without calling through null, propagate the entrypoint HRESULT, and require successful creation at the caller. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: e3ee7201-c7f9-4f0d-b979-fbff0c77208b
f4947f1 to
24c0cd7
Compare
|
The force push above rebased against main which now includes the implementation of GetVersionId that was added in #133535. This should resolve the glass test failure that was detected in Tom's test run. |
There was a problem hiding this comment.
🟡 Changes recommended
Preserve and validate the DacSetTargetConsistencyChecks HRESULT in the Debug synchronization path.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 25/25 changed files
- Comments generated: 1
- Review effort level: Lite
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 31071aae-417c-4f0f-a519-bce0410327
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved cDAC QueryInterface exposure, token forwarding, and fallback-removal test coverage block approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (2)
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataMethodInstance.cs:114
- The Debug-only comparison still passes the caller's
tokenpointer to the legacy implementation. A legacy DAC can write that pointer after cDAC has populated it, so the value returned by this method is no longer guaranteed to be the cDAC result. Passnullhere (the module-only synchronization does not need the token); the later comparison already usestokenLocal.
if (_legacyImpl is not null)
{
DacComNullableByRef<IXCLRDataModule> legacyModOut = new(isNullRef: false);
int hrLegacy = _legacyImpl.GetTokenAndScope(token, legacyModOut);
if (hrLegacy >= 0)
legacyMod = legacyModOut.Interface;
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/MetaDataImportImpl.cs:265
- This change removes the legacy delegation for the metadata methods, but the existing tests still construct
MetaDataImportImplwithlegacyImport: null, so they would also pass if a future edit accidentally consulted the legacy interface. Add a recording/failing legacy importer and assert that representative formerly delegated calls returnE_NOTIMPLwithout invoking it (including the assembly/import2 paths) so this fallback-removal contract is covered.
return HResults.E_NOTIMPL;
- Files reviewed: 25/25 changed files
- Comments generated: 1
- Review effort level: Lite
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 31071aae-417c-4f0f-a519-bce0410327
There was a problem hiding this comment.
🔵 Needs a closer look
The direct DBI entry point needs contract validation before the interface is published.
Review details
Suppressed comments (1)
src/native/managed/cdac/mscordaccore_universal/Entrypoints.cs:466
- This eager validation covers the SOS/contract-descriptor path, but the direct
DacDbiInterfaceInstancepath above still constructsDacDbiImplwithout callingValidateForDataAccess. That path has no legacy object (legacyObj: null), so a target missing a required DBI contract such asIRuntimeMutableTypeSystemcan still publish the interface and fail later inside an operation instead of failing creation, contrary to the all-or-nothing contract described inCoreCLRContracts.ValidateForDataAccess. Add the same validation before publishing the direct DBI interface, or route both entry points through a common validation step.
Contracts.CoreCLRContracts.ValidateForDataAccess(target, apiLock);
- Files reviewed: 26/26 changed files
- Comments generated: 0 new
- Review effort level: Lite
Keep legacy DAC interfaces only for Debug comparison and required lifetime management. Return E_NOTIMPL for unsupported cDAC operations. Fixed code paths where the behavior of the DAC comparison API call influenced the return value from cDAC. The FallbackHepler is now removed and most legacy interface pointers store NULL in release builds. DOTNET_ENABLE_CDAC no longer forwards the creation of ICLRDataEnumMemoryRegions to cDAC. If needed for testing this can be restored once the interface is implemented, but ideally we are moving towards eliminating DOTNET_ENABLE_CDAC env var and DAC->cDAC bootstrapping.
Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com