[cDAC] Implement MarkDebuggerAttach* DacDbi APIs - #126794

Merged
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods
Apr 23, 2026
Merged

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs#126794
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods

Conversation

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
  • Implements MarkDebuggerAttachPending and MarkDebuggerAttached in cDAC DacDbiImpl by adding corresponding Debugger_1 contract APIs and wiring them to target-memory writes of debugger control flags.
  • Removes fibermode dead code

CopilotAI requested review from Copilot and removed request for CopilotApril 11, 2026 19:28
@rcj1rcj1 changed the title Implement cDAC debugger attach state writes via g_CORDebuggerControlFlags[cDAC] Implement MarkDebuggerAttach* DacDbi APIsApr 11, 2026
@rcj1
rcj1 marked this pull request as ready for review April 11, 2026 21:00

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 extends the cDAC Debugger contract and the legacy DacDbiImpl surface to support MarkDebuggerAttachPending / MarkDebuggerAttached by writing the appropriate bits into g_CORDebuggerControlFlags, and adds unit test coverage plus documentation updates.

Changes:

  • Added IDebugger.MarkDebuggerAttachPending() and IDebugger.MarkDebuggerAttached(bool) APIs and implemented them in Debugger_1 via target-memory writes.
  • Updated DacDbiImpl to call the cDAC contract implementations (with DEBUG-only legacy cross-validation).
  • Exposed g_CORDebuggerControlFlags via the CoreCLR data descriptor and added tests/docs for the new flag semantics.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/native/managed/cdac/tests/DebuggerTests.csAdds test target plumbing + new unit tests validating control-flag writes.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.csImplements the two DBI methods by calling the cDAC Debugger contract and translating errors to HRESULTs.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.csAdds the flag enum and implements the two new attach APIs by updating CORDebuggerControlFlags.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.csIntroduces the new Globals.CORDebuggerControlFlags name constant.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugger.csExtends the contract interface with the two new methods.
src/coreclr/vm/datadescriptor/datadescriptor.incExposes g_CORDebuggerControlFlags and adjusts Debugger global gating.
src/coreclr/inc/cordbpriv.hAdds cDAC dependency annotations to DBCF_PENDING_ATTACH / DBCF_ATTACHED.
docs/design/datacontracts/Debugger.mdDocuments the new APIs, global dependency, and flag behavior.

Comment threadsrc/coreclr/vm/datadescriptor/datadescriptor.inc Outdated
CopilotAI review requested due to automatic review settings April 12, 2026 00:37

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

@github-actions

This comment has been minimized.

@rcj1

rcj1 commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Test helpers tbd in #126595

Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Comment threaddocs/design/datacontracts/Debugger.md
Comment threaddocs/design/datacontracts/Debugger.md
@github-actions

This comment has been minimized.

CopilotAI review requested due to automatic review settings April 17, 2026 17:28
Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Comment threadsrc/coreclr/debug/shared/dbgtransportsession.cpp
Comment threadsrc/coreclr/debug/inc/dbgipcevents.h
Comment threadsrc/coreclr/debug/di/process.cpp
Comment threadsrc/coreclr/debug/ee/rcthread.cpp
Comment threadsrc/native/managed/cdac/tests/DebuggerTests.cs
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Copilot Code Review — PR #126794

Note

This review was generated by Copilot (Claude Opus 4.6) with additional analysis from Claude Sonnet 4.5.

Holistic Assessment

Motivation: This PR implements debugger attach flag methods (MarkDebuggerAttachPending, MarkDebuggerAttached) in the cDAC debugger contract and DacDbi layer, migrates the debugging infrastructure from VMPTR_Assembly to VMPTR_DomainAssembly to better model AppDomain affinity, and removes dead fiber-mode debugging code. The architectural direction is sound — DomainAssembly is the correct abstraction for ICorDebug's module concept.

Approach: The change systematically threads VMPTR_DomainAssembly and VMPTR_AppDomain through the entire DacDbi interface (IDL, interface headers, DI, DAC, and cDAC implementations). The shift from a single m_pAppDomain pointer to a CordbSafeHashTable<CordbAppDomain> m_appDomains in CordbProcess is the right structural change. The dead code removal (fiber mode, unused enum flags) is clean.

Summary: ⚠️Needs Human Review. The code is architecturally well-structured and the core implementations look correct. However, there are several items that require maintainer attention: incomplete dead code cleanup, a parameter naming inconsistency in the IDL, and the DB_IPCE_EXIT_APP_DOMAIN re-enablement warrants explicit acknowledgment. The protocol breaking change counter question also needs a maintainer decision.


Detailed Findings

⚠️ DacDbi Protocol Breaking Change Counter — Not bumped

src/coreclr/debug/inc/dacdbistructures.h:692kCurrentDacDbiProtocolBreakingChangeCounter remains at 1 despite extensive breaking changes to IDacDbiInterface: ~30+ method signatures changed (Assembly → DomainAssembly), new methods added (GetAppDomainFromId, EnumerateAppDomains, GetAssemblyFromDomainAssembly, etc.), callback typedefs changed, and struct fields modified.

Per the comment at line 699-710, the counter should be explicitly bumped and documented when breaking changes are introduced. The auto-generated MD5 hash mechanism (described at line 616-618 in process.cpp) will detect the change automatically for remote transport scenarios, so this is unlikely to cause a runtime crash. However, the convention says to bump and document the counter. A maintainer should decide if a bump is needed here or if the hash is sufficient.

⚠️ Incomplete Dead Code Cleanup — CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS

src/coreclr/debug/di/process.cpp:237,8575 — The fiber-mode code was removed (DBCF_FIBERMODE, m_bHostingInFiber, the fiber check in VerifyControlBlock), but two references to CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS remain:

  1. Line 237: In IsLegalFatalError() — lists this error as a legal fatal error. Since no code path can produce this error anymore, this entry is dead.
  2. Line 8575: if (!IsLegalFatalError(errorHR) || (errorHR != CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS)) — This special-cases the fiber error to skip setting m_unrecoverableError. Since the error is never produced, the special case is also dead.

These should be cleaned up for consistency with the fiber-mode removal. Not blocking, but creates confusing dead code.

⚠️ IDL Parameter Naming Inconsistency — vmAssembly for DomainAssembly type

src/coreclr/inc/dacdbi.idl — The EnumerateModulesInAssembly method has:

HRESULT EnumerateModulesInAssembly([in] VMPTR_DomainAssembly vmAssembly, ...);

The parameter is named vmAssembly but the type is VMPTR_DomainAssembly. This should be vmDomainAssembly for consistency with all other methods in this PR.

⚠️DB_IPCE_EXIT_APP_DOMAIN Re-enabled — Needs documentation

src/coreclr/debug/inc/dbgipceventtypes.h:49 — This event type was previously commented out and is now re-enabled. The handler in process.cpp is well-written (with proper null checks and assertions). This is clearly needed for the new multi-AppDomain hash table support. However, it would be helpful to have a brief comment in the code or commit message explaining why this was re-enabled, since the previous comment suggested it was intentionally disabled.

✅ cDAC Debugger Contract Implementation — Correct

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.cs — The new MarkDebuggerAttachPending() and MarkDebuggerAttached() implementations:

  • Flag values (0x0100, 0x0200) match cordbpriv.h constants ✅
  • Bitwise operations match the native DAC implementation in dacdbiimpl.cpp:4798-4869
  • MarkDebuggerAttached(false) correctly clears both Attached and PendingAttach flags ✅
  • The read-modify-write pattern is not atomic, but this matches the native code which relies on the DD lock for synchronization ✅

TryGetDebuggerData Behavior Change — Intentional and correct

Debugger_1.cs:21-35 — Previously returned false when LeftSideInitialized == 0; now returns true with IsLeftSideInitialized in the data. This better matches the native DAC behavior: GetDefinesBitField and GetMDStructuresVersion (dacdbiimpl.cpp:7985-8009) check g_pDebugger == NULL but NOT LeftSideInitialized. The DacDbiImpl.cs wrapper at line 64 correctly uses data.IsLeftSideInitialized for the IsLeftSideInitialized DBI method. The dump test at line 93-94 was updated to cross-validate correctly.

✅ Struct Layout Binary Compatibility — Correct

src/coreclr/debug/inc/dbgipcevents.h — Replacing bool m_bHostingInFiber with BYTE padding1 maintains the same 1-byte layout within the DWORD-aligned group (m_checkedBuild + padding1 + padding2 + padding3 = 4 bytes). The transport marshaling in dbgtransportsession.cpp correctly omits the padding field. Both DebuggerIPCControlBlock and DebuggerIPCControlBlockTransport are updated consistently.

✅ Test Changes — Correct and comprehensive

src/native/managed/cdac/tests/DebuggerTests.cs — The removal of memBuilder.AddHeapFragment(debuggerControlFlagsFrag) is correct: BumpAllocator.Allocate auto-registers heap fragments with the builder. The three new tests (MarkDebuggerAttachPending_SetsPendingAttachFlag, MarkDebuggerAttached_SetsAttachedFlag_WhenTrue, MarkDebuggerAttached_ClearsAttachedAndPending_WhenFalse) provide good coverage with distinct initial states. The DacDbi dump tests add coverage for GetAppDomainFromId, EnumerateAppDomains, IsAssemblyFullyTrusted, and GetAppDomainIdFromVmObjectHandle.

✅ AppDomain Management Rearchitecture — Well-structured

src/coreclr/debug/di/process.cpp, rspriv.h — The migration from CordbAppDomain* m_pAppDomain to CordbSafeHashTable<CordbAppDomain> m_appDomains is clean:

  • NeuterChildren correctly uses NeuterAndClear instead of manual pointer cleanup
  • NeuterChildrenLeftSideResources correctly copies to an auxiliary list before releasing the lock
  • CacheAppDomain properly uses AddBaseOrThrow with RSInitHolder RAII
  • PrepopulateAppDomainsOrThrow gates on IsDacInitialized()
  • ContinueInternal handles the hash table properly with CopyToArray

💡 GetInstantiationFieldInfo Uses AppDomain::GetCurrentDomain()

src/coreclr/debug/daccess/dacdbiimpl.cpp:1817 — This method takes a VMPTR_DomainAssembly parameter but uses AppDomain::GetCurrentDomain() for CollectFields instead of deriving the AppDomain from the parameter. In modern .NET (single AppDomain), this is functionally correct and mirrors how the runtime operates. Noted as a potential follow-up if multi-domain support were ever reconsidered.

💡 Mixed Concerns in PR

The PR bundles debugger attach flag implementation, Assembly→DomainAssembly migration, fiber-mode dead code removal, RequiresAlign8 removal from RuntimeTypeSystem, and ContractRegistry simplification. While these are related to the broader cDAC migration, splitting the dead code removal and RequiresAlign8 changes into separate PRs would make the changes easier to review and bisect.

Generated by Code Review for issue #126794 ·

CopilotAI review requested due to automatic review settings April 20, 2026 18:13

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

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/debug/di/process.cpp:8386

  • CordbProcess::UnrecoverableError no longer sets m_unrecoverableError for legal fatal errors (e.g., CORDBG_E_INCOMPATIBLE_PROTOCOL), because the condition changed from effectively "all except CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS" to only !IsLegalFatalError(errorHR). This is a behavior change beyond removing fiber-mode handling and may leave the process in a non-zombie state after an unrecoverable condition. Consider restoring the previous intent (e.g., set m_unrecoverableError for legal fatal errors too, or otherwise document/handle why legal fatal errors should avoid zombie state).
 CONSISTENCY_CHECK_MSGF(IsLegalFatalError(errorHR), ("Unrecoverable internal error: hr=0x%08x!", errorHR));
if (!IsLegalFatalError(errorHR))
{
// This will throw everything into a Zombie state. The ATT_ macros will check this and fail immediately.
m_unrecoverableError = true;
//
// Mark the process as no longer synchronized.
//
Lock();
SetSynchronized(false);
IncStopCount();
Unlock();
}

@rcj1

rcj1 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

/ba-g wasm

@rcj1
rcj1 merged commit c78a047 into mainApr 23, 2026
126 of 129 checks passed
@rcj1
rcj1 deleted the copilot/implement-markdebugger-methods branch April 23, 2026 22:11
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@rcj1@noahfalk@jkotas@davidwrighton@max-charlamb@teo-tsirpanis
, '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

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs - #126794

Merged
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods
Apr 23, 2026
Merged

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs#126794
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods

Conversation

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
  • Implements MarkDebuggerAttachPending and MarkDebuggerAttached in cDAC DacDbiImpl by adding corresponding Debugger_1 contract APIs and wiring them to target-memory writes of debugger control flags.
  • Removes fibermode dead code

CopilotAI requested review from Copilot and removed request for CopilotApril 11, 2026 19:28
@rcj1rcj1 changed the title Implement cDAC debugger attach state writes via g_CORDebuggerControlFlags[cDAC] Implement MarkDebuggerAttach* DacDbi APIsApr 11, 2026
@rcj1
rcj1 marked this pull request as ready for review April 11, 2026 21:00

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 extends the cDAC Debugger contract and the legacy DacDbiImpl surface to support MarkDebuggerAttachPending / MarkDebuggerAttached by writing the appropriate bits into g_CORDebuggerControlFlags, and adds unit test coverage plus documentation updates.

Changes:

  • Added IDebugger.MarkDebuggerAttachPending() and IDebugger.MarkDebuggerAttached(bool) APIs and implemented them in Debugger_1 via target-memory writes.
  • Updated DacDbiImpl to call the cDAC contract implementations (with DEBUG-only legacy cross-validation).
  • Exposed g_CORDebuggerControlFlags via the CoreCLR data descriptor and added tests/docs for the new flag semantics.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/native/managed/cdac/tests/DebuggerTests.csAdds test target plumbing + new unit tests validating control-flag writes.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.csImplements the two DBI methods by calling the cDAC Debugger contract and translating errors to HRESULTs.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.csAdds the flag enum and implements the two new attach APIs by updating CORDebuggerControlFlags.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.csIntroduces the new Globals.CORDebuggerControlFlags name constant.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugger.csExtends the contract interface with the two new methods.
src/coreclr/vm/datadescriptor/datadescriptor.incExposes g_CORDebuggerControlFlags and adjusts Debugger global gating.
src/coreclr/inc/cordbpriv.hAdds cDAC dependency annotations to DBCF_PENDING_ATTACH / DBCF_ATTACHED.
docs/design/datacontracts/Debugger.mdDocuments the new APIs, global dependency, and flag behavior.

Comment threadsrc/coreclr/vm/datadescriptor/datadescriptor.inc Outdated
CopilotAI review requested due to automatic review settings April 12, 2026 00:37

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

@github-actions

This comment has been minimized.

@rcj1

rcj1 commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Test helpers tbd in #126595

Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Comment threaddocs/design/datacontracts/Debugger.md
Comment threaddocs/design/datacontracts/Debugger.md
@github-actions

This comment has been minimized.

CopilotAI review requested due to automatic review settings April 17, 2026 17:28
Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Comment threadsrc/coreclr/debug/shared/dbgtransportsession.cpp
Comment threadsrc/coreclr/debug/inc/dbgipcevents.h
Comment threadsrc/coreclr/debug/di/process.cpp
Comment threadsrc/coreclr/debug/ee/rcthread.cpp
Comment threadsrc/native/managed/cdac/tests/DebuggerTests.cs
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Copilot Code Review — PR #126794

Note

This review was generated by Copilot (Claude Opus 4.6) with additional analysis from Claude Sonnet 4.5.

Holistic Assessment

Motivation: This PR implements debugger attach flag methods (MarkDebuggerAttachPending, MarkDebuggerAttached) in the cDAC debugger contract and DacDbi layer, migrates the debugging infrastructure from VMPTR_Assembly to VMPTR_DomainAssembly to better model AppDomain affinity, and removes dead fiber-mode debugging code. The architectural direction is sound — DomainAssembly is the correct abstraction for ICorDebug's module concept.

Approach: The change systematically threads VMPTR_DomainAssembly and VMPTR_AppDomain through the entire DacDbi interface (IDL, interface headers, DI, DAC, and cDAC implementations). The shift from a single m_pAppDomain pointer to a CordbSafeHashTable<CordbAppDomain> m_appDomains in CordbProcess is the right structural change. The dead code removal (fiber mode, unused enum flags) is clean.

Summary: ⚠️Needs Human Review. The code is architecturally well-structured and the core implementations look correct. However, there are several items that require maintainer attention: incomplete dead code cleanup, a parameter naming inconsistency in the IDL, and the DB_IPCE_EXIT_APP_DOMAIN re-enablement warrants explicit acknowledgment. The protocol breaking change counter question also needs a maintainer decision.


Detailed Findings

⚠️ DacDbi Protocol Breaking Change Counter — Not bumped

src/coreclr/debug/inc/dacdbistructures.h:692kCurrentDacDbiProtocolBreakingChangeCounter remains at 1 despite extensive breaking changes to IDacDbiInterface: ~30+ method signatures changed (Assembly → DomainAssembly), new methods added (GetAppDomainFromId, EnumerateAppDomains, GetAssemblyFromDomainAssembly, etc.), callback typedefs changed, and struct fields modified.

Per the comment at line 699-710, the counter should be explicitly bumped and documented when breaking changes are introduced. The auto-generated MD5 hash mechanism (described at line 616-618 in process.cpp) will detect the change automatically for remote transport scenarios, so this is unlikely to cause a runtime crash. However, the convention says to bump and document the counter. A maintainer should decide if a bump is needed here or if the hash is sufficient.

⚠️ Incomplete Dead Code Cleanup — CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS

src/coreclr/debug/di/process.cpp:237,8575 — The fiber-mode code was removed (DBCF_FIBERMODE, m_bHostingInFiber, the fiber check in VerifyControlBlock), but two references to CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS remain:

  1. Line 237: In IsLegalFatalError() — lists this error as a legal fatal error. Since no code path can produce this error anymore, this entry is dead.
  2. Line 8575: if (!IsLegalFatalError(errorHR) || (errorHR != CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS)) — This special-cases the fiber error to skip setting m_unrecoverableError. Since the error is never produced, the special case is also dead.

These should be cleaned up for consistency with the fiber-mode removal. Not blocking, but creates confusing dead code.

⚠️ IDL Parameter Naming Inconsistency — vmAssembly for DomainAssembly type

src/coreclr/inc/dacdbi.idl — The EnumerateModulesInAssembly method has:

HRESULT EnumerateModulesInAssembly([in] VMPTR_DomainAssembly vmAssembly, ...);

The parameter is named vmAssembly but the type is VMPTR_DomainAssembly. This should be vmDomainAssembly for consistency with all other methods in this PR.

⚠️DB_IPCE_EXIT_APP_DOMAIN Re-enabled — Needs documentation

src/coreclr/debug/inc/dbgipceventtypes.h:49 — This event type was previously commented out and is now re-enabled. The handler in process.cpp is well-written (with proper null checks and assertions). This is clearly needed for the new multi-AppDomain hash table support. However, it would be helpful to have a brief comment in the code or commit message explaining why this was re-enabled, since the previous comment suggested it was intentionally disabled.

✅ cDAC Debugger Contract Implementation — Correct

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.cs — The new MarkDebuggerAttachPending() and MarkDebuggerAttached() implementations:

  • Flag values (0x0100, 0x0200) match cordbpriv.h constants ✅
  • Bitwise operations match the native DAC implementation in dacdbiimpl.cpp:4798-4869
  • MarkDebuggerAttached(false) correctly clears both Attached and PendingAttach flags ✅
  • The read-modify-write pattern is not atomic, but this matches the native code which relies on the DD lock for synchronization ✅

TryGetDebuggerData Behavior Change — Intentional and correct

Debugger_1.cs:21-35 — Previously returned false when LeftSideInitialized == 0; now returns true with IsLeftSideInitialized in the data. This better matches the native DAC behavior: GetDefinesBitField and GetMDStructuresVersion (dacdbiimpl.cpp:7985-8009) check g_pDebugger == NULL but NOT LeftSideInitialized. The DacDbiImpl.cs wrapper at line 64 correctly uses data.IsLeftSideInitialized for the IsLeftSideInitialized DBI method. The dump test at line 93-94 was updated to cross-validate correctly.

✅ Struct Layout Binary Compatibility — Correct

src/coreclr/debug/inc/dbgipcevents.h — Replacing bool m_bHostingInFiber with BYTE padding1 maintains the same 1-byte layout within the DWORD-aligned group (m_checkedBuild + padding1 + padding2 + padding3 = 4 bytes). The transport marshaling in dbgtransportsession.cpp correctly omits the padding field. Both DebuggerIPCControlBlock and DebuggerIPCControlBlockTransport are updated consistently.

✅ Test Changes — Correct and comprehensive

src/native/managed/cdac/tests/DebuggerTests.cs — The removal of memBuilder.AddHeapFragment(debuggerControlFlagsFrag) is correct: BumpAllocator.Allocate auto-registers heap fragments with the builder. The three new tests (MarkDebuggerAttachPending_SetsPendingAttachFlag, MarkDebuggerAttached_SetsAttachedFlag_WhenTrue, MarkDebuggerAttached_ClearsAttachedAndPending_WhenFalse) provide good coverage with distinct initial states. The DacDbi dump tests add coverage for GetAppDomainFromId, EnumerateAppDomains, IsAssemblyFullyTrusted, and GetAppDomainIdFromVmObjectHandle.

✅ AppDomain Management Rearchitecture — Well-structured

src/coreclr/debug/di/process.cpp, rspriv.h — The migration from CordbAppDomain* m_pAppDomain to CordbSafeHashTable<CordbAppDomain> m_appDomains is clean:

  • NeuterChildren correctly uses NeuterAndClear instead of manual pointer cleanup
  • NeuterChildrenLeftSideResources correctly copies to an auxiliary list before releasing the lock
  • CacheAppDomain properly uses AddBaseOrThrow with RSInitHolder RAII
  • PrepopulateAppDomainsOrThrow gates on IsDacInitialized()
  • ContinueInternal handles the hash table properly with CopyToArray

💡 GetInstantiationFieldInfo Uses AppDomain::GetCurrentDomain()

src/coreclr/debug/daccess/dacdbiimpl.cpp:1817 — This method takes a VMPTR_DomainAssembly parameter but uses AppDomain::GetCurrentDomain() for CollectFields instead of deriving the AppDomain from the parameter. In modern .NET (single AppDomain), this is functionally correct and mirrors how the runtime operates. Noted as a potential follow-up if multi-domain support were ever reconsidered.

💡 Mixed Concerns in PR

The PR bundles debugger attach flag implementation, Assembly→DomainAssembly migration, fiber-mode dead code removal, RequiresAlign8 removal from RuntimeTypeSystem, and ContractRegistry simplification. While these are related to the broader cDAC migration, splitting the dead code removal and RequiresAlign8 changes into separate PRs would make the changes easier to review and bisect.

Generated by Code Review for issue #126794 ·

CopilotAI review requested due to automatic review settings April 20, 2026 18:13

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

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/debug/di/process.cpp:8386

  • CordbProcess::UnrecoverableError no longer sets m_unrecoverableError for legal fatal errors (e.g., CORDBG_E_INCOMPATIBLE_PROTOCOL), because the condition changed from effectively "all except CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS" to only !IsLegalFatalError(errorHR). This is a behavior change beyond removing fiber-mode handling and may leave the process in a non-zombie state after an unrecoverable condition. Consider restoring the previous intent (e.g., set m_unrecoverableError for legal fatal errors too, or otherwise document/handle why legal fatal errors should avoid zombie state).
 CONSISTENCY_CHECK_MSGF(IsLegalFatalError(errorHR), ("Unrecoverable internal error: hr=0x%08x!", errorHR));
if (!IsLegalFatalError(errorHR))
{
// This will throw everything into a Zombie state. The ATT_ macros will check this and fail immediately.
m_unrecoverableError = true;
//
// Mark the process as no longer synchronized.
//
Lock();
SetSynchronized(false);
IncStopCount();
Unlock();
}

@rcj1

rcj1 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

/ba-g wasm

@rcj1
rcj1 merged commit c78a047 into mainApr 23, 2026
126 of 129 checks passed
@rcj1
rcj1 deleted the copilot/implement-markdebugger-methods branch April 23, 2026 22:11
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@rcj1@noahfalk@jkotas@davidwrighton@max-charlamb@teo-tsirpanis
, '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

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs - #126794

Merged
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods
Apr 23, 2026
Merged

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs#126794
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods

Conversation

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
  • Implements MarkDebuggerAttachPending and MarkDebuggerAttached in cDAC DacDbiImpl by adding corresponding Debugger_1 contract APIs and wiring them to target-memory writes of debugger control flags.
  • Removes fibermode dead code

CopilotAI requested review from Copilot and removed request for CopilotApril 11, 2026 19:28
@rcj1rcj1 changed the title Implement cDAC debugger attach state writes via g_CORDebuggerControlFlags[cDAC] Implement MarkDebuggerAttach* DacDbi APIsApr 11, 2026
@rcj1
rcj1 marked this pull request as ready for review April 11, 2026 21:00

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 extends the cDAC Debugger contract and the legacy DacDbiImpl surface to support MarkDebuggerAttachPending / MarkDebuggerAttached by writing the appropriate bits into g_CORDebuggerControlFlags, and adds unit test coverage plus documentation updates.

Changes:

  • Added IDebugger.MarkDebuggerAttachPending() and IDebugger.MarkDebuggerAttached(bool) APIs and implemented them in Debugger_1 via target-memory writes.
  • Updated DacDbiImpl to call the cDAC contract implementations (with DEBUG-only legacy cross-validation).
  • Exposed g_CORDebuggerControlFlags via the CoreCLR data descriptor and added tests/docs for the new flag semantics.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/native/managed/cdac/tests/DebuggerTests.csAdds test target plumbing + new unit tests validating control-flag writes.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.csImplements the two DBI methods by calling the cDAC Debugger contract and translating errors to HRESULTs.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.csAdds the flag enum and implements the two new attach APIs by updating CORDebuggerControlFlags.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.csIntroduces the new Globals.CORDebuggerControlFlags name constant.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugger.csExtends the contract interface with the two new methods.
src/coreclr/vm/datadescriptor/datadescriptor.incExposes g_CORDebuggerControlFlags and adjusts Debugger global gating.
src/coreclr/inc/cordbpriv.hAdds cDAC dependency annotations to DBCF_PENDING_ATTACH / DBCF_ATTACHED.
docs/design/datacontracts/Debugger.mdDocuments the new APIs, global dependency, and flag behavior.

Comment threadsrc/coreclr/vm/datadescriptor/datadescriptor.inc Outdated
CopilotAI review requested due to automatic review settings April 12, 2026 00:37

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

@github-actions

This comment has been minimized.

@rcj1

rcj1 commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Test helpers tbd in #126595

Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Comment threaddocs/design/datacontracts/Debugger.md
Comment threaddocs/design/datacontracts/Debugger.md
@github-actions

This comment has been minimized.

CopilotAI review requested due to automatic review settings April 17, 2026 17:28
Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Comment threadsrc/coreclr/debug/shared/dbgtransportsession.cpp
Comment threadsrc/coreclr/debug/inc/dbgipcevents.h
Comment threadsrc/coreclr/debug/di/process.cpp
Comment threadsrc/coreclr/debug/ee/rcthread.cpp
Comment threadsrc/native/managed/cdac/tests/DebuggerTests.cs
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Copilot Code Review — PR #126794

Note

This review was generated by Copilot (Claude Opus 4.6) with additional analysis from Claude Sonnet 4.5.

Holistic Assessment

Motivation: This PR implements debugger attach flag methods (MarkDebuggerAttachPending, MarkDebuggerAttached) in the cDAC debugger contract and DacDbi layer, migrates the debugging infrastructure from VMPTR_Assembly to VMPTR_DomainAssembly to better model AppDomain affinity, and removes dead fiber-mode debugging code. The architectural direction is sound — DomainAssembly is the correct abstraction for ICorDebug's module concept.

Approach: The change systematically threads VMPTR_DomainAssembly and VMPTR_AppDomain through the entire DacDbi interface (IDL, interface headers, DI, DAC, and cDAC implementations). The shift from a single m_pAppDomain pointer to a CordbSafeHashTable<CordbAppDomain> m_appDomains in CordbProcess is the right structural change. The dead code removal (fiber mode, unused enum flags) is clean.

Summary: ⚠️Needs Human Review. The code is architecturally well-structured and the core implementations look correct. However, there are several items that require maintainer attention: incomplete dead code cleanup, a parameter naming inconsistency in the IDL, and the DB_IPCE_EXIT_APP_DOMAIN re-enablement warrants explicit acknowledgment. The protocol breaking change counter question also needs a maintainer decision.


Detailed Findings

⚠️ DacDbi Protocol Breaking Change Counter — Not bumped

src/coreclr/debug/inc/dacdbistructures.h:692kCurrentDacDbiProtocolBreakingChangeCounter remains at 1 despite extensive breaking changes to IDacDbiInterface: ~30+ method signatures changed (Assembly → DomainAssembly), new methods added (GetAppDomainFromId, EnumerateAppDomains, GetAssemblyFromDomainAssembly, etc.), callback typedefs changed, and struct fields modified.

Per the comment at line 699-710, the counter should be explicitly bumped and documented when breaking changes are introduced. The auto-generated MD5 hash mechanism (described at line 616-618 in process.cpp) will detect the change automatically for remote transport scenarios, so this is unlikely to cause a runtime crash. However, the convention says to bump and document the counter. A maintainer should decide if a bump is needed here or if the hash is sufficient.

⚠️ Incomplete Dead Code Cleanup — CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS

src/coreclr/debug/di/process.cpp:237,8575 — The fiber-mode code was removed (DBCF_FIBERMODE, m_bHostingInFiber, the fiber check in VerifyControlBlock), but two references to CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS remain:

  1. Line 237: In IsLegalFatalError() — lists this error as a legal fatal error. Since no code path can produce this error anymore, this entry is dead.
  2. Line 8575: if (!IsLegalFatalError(errorHR) || (errorHR != CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS)) — This special-cases the fiber error to skip setting m_unrecoverableError. Since the error is never produced, the special case is also dead.

These should be cleaned up for consistency with the fiber-mode removal. Not blocking, but creates confusing dead code.

⚠️ IDL Parameter Naming Inconsistency — vmAssembly for DomainAssembly type

src/coreclr/inc/dacdbi.idl — The EnumerateModulesInAssembly method has:

HRESULT EnumerateModulesInAssembly([in] VMPTR_DomainAssembly vmAssembly, ...);

The parameter is named vmAssembly but the type is VMPTR_DomainAssembly. This should be vmDomainAssembly for consistency with all other methods in this PR.

⚠️DB_IPCE_EXIT_APP_DOMAIN Re-enabled — Needs documentation

src/coreclr/debug/inc/dbgipceventtypes.h:49 — This event type was previously commented out and is now re-enabled. The handler in process.cpp is well-written (with proper null checks and assertions). This is clearly needed for the new multi-AppDomain hash table support. However, it would be helpful to have a brief comment in the code or commit message explaining why this was re-enabled, since the previous comment suggested it was intentionally disabled.

✅ cDAC Debugger Contract Implementation — Correct

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.cs — The new MarkDebuggerAttachPending() and MarkDebuggerAttached() implementations:

  • Flag values (0x0100, 0x0200) match cordbpriv.h constants ✅
  • Bitwise operations match the native DAC implementation in dacdbiimpl.cpp:4798-4869
  • MarkDebuggerAttached(false) correctly clears both Attached and PendingAttach flags ✅
  • The read-modify-write pattern is not atomic, but this matches the native code which relies on the DD lock for synchronization ✅

TryGetDebuggerData Behavior Change — Intentional and correct

Debugger_1.cs:21-35 — Previously returned false when LeftSideInitialized == 0; now returns true with IsLeftSideInitialized in the data. This better matches the native DAC behavior: GetDefinesBitField and GetMDStructuresVersion (dacdbiimpl.cpp:7985-8009) check g_pDebugger == NULL but NOT LeftSideInitialized. The DacDbiImpl.cs wrapper at line 64 correctly uses data.IsLeftSideInitialized for the IsLeftSideInitialized DBI method. The dump test at line 93-94 was updated to cross-validate correctly.

✅ Struct Layout Binary Compatibility — Correct

src/coreclr/debug/inc/dbgipcevents.h — Replacing bool m_bHostingInFiber with BYTE padding1 maintains the same 1-byte layout within the DWORD-aligned group (m_checkedBuild + padding1 + padding2 + padding3 = 4 bytes). The transport marshaling in dbgtransportsession.cpp correctly omits the padding field. Both DebuggerIPCControlBlock and DebuggerIPCControlBlockTransport are updated consistently.

✅ Test Changes — Correct and comprehensive

src/native/managed/cdac/tests/DebuggerTests.cs — The removal of memBuilder.AddHeapFragment(debuggerControlFlagsFrag) is correct: BumpAllocator.Allocate auto-registers heap fragments with the builder. The three new tests (MarkDebuggerAttachPending_SetsPendingAttachFlag, MarkDebuggerAttached_SetsAttachedFlag_WhenTrue, MarkDebuggerAttached_ClearsAttachedAndPending_WhenFalse) provide good coverage with distinct initial states. The DacDbi dump tests add coverage for GetAppDomainFromId, EnumerateAppDomains, IsAssemblyFullyTrusted, and GetAppDomainIdFromVmObjectHandle.

✅ AppDomain Management Rearchitecture — Well-structured

src/coreclr/debug/di/process.cpp, rspriv.h — The migration from CordbAppDomain* m_pAppDomain to CordbSafeHashTable<CordbAppDomain> m_appDomains is clean:

  • NeuterChildren correctly uses NeuterAndClear instead of manual pointer cleanup
  • NeuterChildrenLeftSideResources correctly copies to an auxiliary list before releasing the lock
  • CacheAppDomain properly uses AddBaseOrThrow with RSInitHolder RAII
  • PrepopulateAppDomainsOrThrow gates on IsDacInitialized()
  • ContinueInternal handles the hash table properly with CopyToArray

💡 GetInstantiationFieldInfo Uses AppDomain::GetCurrentDomain()

src/coreclr/debug/daccess/dacdbiimpl.cpp:1817 — This method takes a VMPTR_DomainAssembly parameter but uses AppDomain::GetCurrentDomain() for CollectFields instead of deriving the AppDomain from the parameter. In modern .NET (single AppDomain), this is functionally correct and mirrors how the runtime operates. Noted as a potential follow-up if multi-domain support were ever reconsidered.

💡 Mixed Concerns in PR

The PR bundles debugger attach flag implementation, Assembly→DomainAssembly migration, fiber-mode dead code removal, RequiresAlign8 removal from RuntimeTypeSystem, and ContractRegistry simplification. While these are related to the broader cDAC migration, splitting the dead code removal and RequiresAlign8 changes into separate PRs would make the changes easier to review and bisect.

Generated by Code Review for issue #126794 ·

CopilotAI review requested due to automatic review settings April 20, 2026 18:13

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

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/debug/di/process.cpp:8386

  • CordbProcess::UnrecoverableError no longer sets m_unrecoverableError for legal fatal errors (e.g., CORDBG_E_INCOMPATIBLE_PROTOCOL), because the condition changed from effectively "all except CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS" to only !IsLegalFatalError(errorHR). This is a behavior change beyond removing fiber-mode handling and may leave the process in a non-zombie state after an unrecoverable condition. Consider restoring the previous intent (e.g., set m_unrecoverableError for legal fatal errors too, or otherwise document/handle why legal fatal errors should avoid zombie state).
 CONSISTENCY_CHECK_MSGF(IsLegalFatalError(errorHR), ("Unrecoverable internal error: hr=0x%08x!", errorHR));
if (!IsLegalFatalError(errorHR))
{
// This will throw everything into a Zombie state. The ATT_ macros will check this and fail immediately.
m_unrecoverableError = true;
//
// Mark the process as no longer synchronized.
//
Lock();
SetSynchronized(false);
IncStopCount();
Unlock();
}

@rcj1

rcj1 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

/ba-g wasm

@rcj1
rcj1 merged commit c78a047 into mainApr 23, 2026
126 of 129 checks passed
@rcj1
rcj1 deleted the copilot/implement-markdebugger-methods branch April 23, 2026 22:11
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@rcj1@noahfalk@jkotas@davidwrighton@max-charlamb@teo-tsirpanis
, '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

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs - #126794

Merged
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods
Apr 23, 2026
Merged

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs#126794
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods

Conversation

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
  • Implements MarkDebuggerAttachPending and MarkDebuggerAttached in cDAC DacDbiImpl by adding corresponding Debugger_1 contract APIs and wiring them to target-memory writes of debugger control flags.
  • Removes fibermode dead code

CopilotAI requested review from Copilot and removed request for CopilotApril 11, 2026 19:28
@rcj1rcj1 changed the title Implement cDAC debugger attach state writes via g_CORDebuggerControlFlags[cDAC] Implement MarkDebuggerAttach* DacDbi APIsApr 11, 2026
@rcj1
rcj1 marked this pull request as ready for review April 11, 2026 21:00

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 extends the cDAC Debugger contract and the legacy DacDbiImpl surface to support MarkDebuggerAttachPending / MarkDebuggerAttached by writing the appropriate bits into g_CORDebuggerControlFlags, and adds unit test coverage plus documentation updates.

Changes:

  • Added IDebugger.MarkDebuggerAttachPending() and IDebugger.MarkDebuggerAttached(bool) APIs and implemented them in Debugger_1 via target-memory writes.
  • Updated DacDbiImpl to call the cDAC contract implementations (with DEBUG-only legacy cross-validation).
  • Exposed g_CORDebuggerControlFlags via the CoreCLR data descriptor and added tests/docs for the new flag semantics.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/native/managed/cdac/tests/DebuggerTests.csAdds test target plumbing + new unit tests validating control-flag writes.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.csImplements the two DBI methods by calling the cDAC Debugger contract and translating errors to HRESULTs.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.csAdds the flag enum and implements the two new attach APIs by updating CORDebuggerControlFlags.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.csIntroduces the new Globals.CORDebuggerControlFlags name constant.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugger.csExtends the contract interface with the two new methods.
src/coreclr/vm/datadescriptor/datadescriptor.incExposes g_CORDebuggerControlFlags and adjusts Debugger global gating.
src/coreclr/inc/cordbpriv.hAdds cDAC dependency annotations to DBCF_PENDING_ATTACH / DBCF_ATTACHED.
docs/design/datacontracts/Debugger.mdDocuments the new APIs, global dependency, and flag behavior.

Comment threadsrc/coreclr/vm/datadescriptor/datadescriptor.inc Outdated
CopilotAI review requested due to automatic review settings April 12, 2026 00:37

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

@github-actions

This comment has been minimized.

@rcj1

rcj1 commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Test helpers tbd in #126595

Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Comment threaddocs/design/datacontracts/Debugger.md
Comment threaddocs/design/datacontracts/Debugger.md
@github-actions

This comment has been minimized.

CopilotAI review requested due to automatic review settings April 17, 2026 17:28
Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Comment threadsrc/coreclr/debug/shared/dbgtransportsession.cpp
Comment threadsrc/coreclr/debug/inc/dbgipcevents.h
Comment threadsrc/coreclr/debug/di/process.cpp
Comment threadsrc/coreclr/debug/ee/rcthread.cpp
Comment threadsrc/native/managed/cdac/tests/DebuggerTests.cs
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Copilot Code Review — PR #126794

Note

This review was generated by Copilot (Claude Opus 4.6) with additional analysis from Claude Sonnet 4.5.

Holistic Assessment

Motivation: This PR implements debugger attach flag methods (MarkDebuggerAttachPending, MarkDebuggerAttached) in the cDAC debugger contract and DacDbi layer, migrates the debugging infrastructure from VMPTR_Assembly to VMPTR_DomainAssembly to better model AppDomain affinity, and removes dead fiber-mode debugging code. The architectural direction is sound — DomainAssembly is the correct abstraction for ICorDebug's module concept.

Approach: The change systematically threads VMPTR_DomainAssembly and VMPTR_AppDomain through the entire DacDbi interface (IDL, interface headers, DI, DAC, and cDAC implementations). The shift from a single m_pAppDomain pointer to a CordbSafeHashTable<CordbAppDomain> m_appDomains in CordbProcess is the right structural change. The dead code removal (fiber mode, unused enum flags) is clean.

Summary: ⚠️Needs Human Review. The code is architecturally well-structured and the core implementations look correct. However, there are several items that require maintainer attention: incomplete dead code cleanup, a parameter naming inconsistency in the IDL, and the DB_IPCE_EXIT_APP_DOMAIN re-enablement warrants explicit acknowledgment. The protocol breaking change counter question also needs a maintainer decision.


Detailed Findings

⚠️ DacDbi Protocol Breaking Change Counter — Not bumped

src/coreclr/debug/inc/dacdbistructures.h:692kCurrentDacDbiProtocolBreakingChangeCounter remains at 1 despite extensive breaking changes to IDacDbiInterface: ~30+ method signatures changed (Assembly → DomainAssembly), new methods added (GetAppDomainFromId, EnumerateAppDomains, GetAssemblyFromDomainAssembly, etc.), callback typedefs changed, and struct fields modified.

Per the comment at line 699-710, the counter should be explicitly bumped and documented when breaking changes are introduced. The auto-generated MD5 hash mechanism (described at line 616-618 in process.cpp) will detect the change automatically for remote transport scenarios, so this is unlikely to cause a runtime crash. However, the convention says to bump and document the counter. A maintainer should decide if a bump is needed here or if the hash is sufficient.

⚠️ Incomplete Dead Code Cleanup — CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS

src/coreclr/debug/di/process.cpp:237,8575 — The fiber-mode code was removed (DBCF_FIBERMODE, m_bHostingInFiber, the fiber check in VerifyControlBlock), but two references to CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS remain:

  1. Line 237: In IsLegalFatalError() — lists this error as a legal fatal error. Since no code path can produce this error anymore, this entry is dead.
  2. Line 8575: if (!IsLegalFatalError(errorHR) || (errorHR != CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS)) — This special-cases the fiber error to skip setting m_unrecoverableError. Since the error is never produced, the special case is also dead.

These should be cleaned up for consistency with the fiber-mode removal. Not blocking, but creates confusing dead code.

⚠️ IDL Parameter Naming Inconsistency — vmAssembly for DomainAssembly type

src/coreclr/inc/dacdbi.idl — The EnumerateModulesInAssembly method has:

HRESULT EnumerateModulesInAssembly([in] VMPTR_DomainAssembly vmAssembly, ...);

The parameter is named vmAssembly but the type is VMPTR_DomainAssembly. This should be vmDomainAssembly for consistency with all other methods in this PR.

⚠️DB_IPCE_EXIT_APP_DOMAIN Re-enabled — Needs documentation

src/coreclr/debug/inc/dbgipceventtypes.h:49 — This event type was previously commented out and is now re-enabled. The handler in process.cpp is well-written (with proper null checks and assertions). This is clearly needed for the new multi-AppDomain hash table support. However, it would be helpful to have a brief comment in the code or commit message explaining why this was re-enabled, since the previous comment suggested it was intentionally disabled.

✅ cDAC Debugger Contract Implementation — Correct

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.cs — The new MarkDebuggerAttachPending() and MarkDebuggerAttached() implementations:

  • Flag values (0x0100, 0x0200) match cordbpriv.h constants ✅
  • Bitwise operations match the native DAC implementation in dacdbiimpl.cpp:4798-4869
  • MarkDebuggerAttached(false) correctly clears both Attached and PendingAttach flags ✅
  • The read-modify-write pattern is not atomic, but this matches the native code which relies on the DD lock for synchronization ✅

TryGetDebuggerData Behavior Change — Intentional and correct

Debugger_1.cs:21-35 — Previously returned false when LeftSideInitialized == 0; now returns true with IsLeftSideInitialized in the data. This better matches the native DAC behavior: GetDefinesBitField and GetMDStructuresVersion (dacdbiimpl.cpp:7985-8009) check g_pDebugger == NULL but NOT LeftSideInitialized. The DacDbiImpl.cs wrapper at line 64 correctly uses data.IsLeftSideInitialized for the IsLeftSideInitialized DBI method. The dump test at line 93-94 was updated to cross-validate correctly.

✅ Struct Layout Binary Compatibility — Correct

src/coreclr/debug/inc/dbgipcevents.h — Replacing bool m_bHostingInFiber with BYTE padding1 maintains the same 1-byte layout within the DWORD-aligned group (m_checkedBuild + padding1 + padding2 + padding3 = 4 bytes). The transport marshaling in dbgtransportsession.cpp correctly omits the padding field. Both DebuggerIPCControlBlock and DebuggerIPCControlBlockTransport are updated consistently.

✅ Test Changes — Correct and comprehensive

src/native/managed/cdac/tests/DebuggerTests.cs — The removal of memBuilder.AddHeapFragment(debuggerControlFlagsFrag) is correct: BumpAllocator.Allocate auto-registers heap fragments with the builder. The three new tests (MarkDebuggerAttachPending_SetsPendingAttachFlag, MarkDebuggerAttached_SetsAttachedFlag_WhenTrue, MarkDebuggerAttached_ClearsAttachedAndPending_WhenFalse) provide good coverage with distinct initial states. The DacDbi dump tests add coverage for GetAppDomainFromId, EnumerateAppDomains, IsAssemblyFullyTrusted, and GetAppDomainIdFromVmObjectHandle.

✅ AppDomain Management Rearchitecture — Well-structured

src/coreclr/debug/di/process.cpp, rspriv.h — The migration from CordbAppDomain* m_pAppDomain to CordbSafeHashTable<CordbAppDomain> m_appDomains is clean:

  • NeuterChildren correctly uses NeuterAndClear instead of manual pointer cleanup
  • NeuterChildrenLeftSideResources correctly copies to an auxiliary list before releasing the lock
  • CacheAppDomain properly uses AddBaseOrThrow with RSInitHolder RAII
  • PrepopulateAppDomainsOrThrow gates on IsDacInitialized()
  • ContinueInternal handles the hash table properly with CopyToArray

💡 GetInstantiationFieldInfo Uses AppDomain::GetCurrentDomain()

src/coreclr/debug/daccess/dacdbiimpl.cpp:1817 — This method takes a VMPTR_DomainAssembly parameter but uses AppDomain::GetCurrentDomain() for CollectFields instead of deriving the AppDomain from the parameter. In modern .NET (single AppDomain), this is functionally correct and mirrors how the runtime operates. Noted as a potential follow-up if multi-domain support were ever reconsidered.

💡 Mixed Concerns in PR

The PR bundles debugger attach flag implementation, Assembly→DomainAssembly migration, fiber-mode dead code removal, RequiresAlign8 removal from RuntimeTypeSystem, and ContractRegistry simplification. While these are related to the broader cDAC migration, splitting the dead code removal and RequiresAlign8 changes into separate PRs would make the changes easier to review and bisect.

Generated by Code Review for issue #126794 ·

CopilotAI review requested due to automatic review settings April 20, 2026 18:13

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

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/debug/di/process.cpp:8386

  • CordbProcess::UnrecoverableError no longer sets m_unrecoverableError for legal fatal errors (e.g., CORDBG_E_INCOMPATIBLE_PROTOCOL), because the condition changed from effectively "all except CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS" to only !IsLegalFatalError(errorHR). This is a behavior change beyond removing fiber-mode handling and may leave the process in a non-zombie state after an unrecoverable condition. Consider restoring the previous intent (e.g., set m_unrecoverableError for legal fatal errors too, or otherwise document/handle why legal fatal errors should avoid zombie state).
 CONSISTENCY_CHECK_MSGF(IsLegalFatalError(errorHR), ("Unrecoverable internal error: hr=0x%08x!", errorHR));
if (!IsLegalFatalError(errorHR))
{
// This will throw everything into a Zombie state. The ATT_ macros will check this and fail immediately.
m_unrecoverableError = true;
//
// Mark the process as no longer synchronized.
//
Lock();
SetSynchronized(false);
IncStopCount();
Unlock();
}

@rcj1

rcj1 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

/ba-g wasm

@rcj1
rcj1 merged commit c78a047 into mainApr 23, 2026
126 of 129 checks passed
@rcj1
rcj1 deleted the copilot/implement-markdebugger-methods branch April 23, 2026 22:11
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@rcj1@noahfalk@jkotas@davidwrighton@max-charlamb@teo-tsirpanis
, '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

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs - #126794

Merged
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods
Apr 23, 2026
Merged

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs#126794
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods

Conversation

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
  • Implements MarkDebuggerAttachPending and MarkDebuggerAttached in cDAC DacDbiImpl by adding corresponding Debugger_1 contract APIs and wiring them to target-memory writes of debugger control flags.
  • Removes fibermode dead code

CopilotAI requested review from Copilot and removed request for CopilotApril 11, 2026 19:28
@rcj1rcj1 changed the title Implement cDAC debugger attach state writes via g_CORDebuggerControlFlags[cDAC] Implement MarkDebuggerAttach* DacDbi APIsApr 11, 2026
@rcj1
rcj1 marked this pull request as ready for review April 11, 2026 21:00

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 extends the cDAC Debugger contract and the legacy DacDbiImpl surface to support MarkDebuggerAttachPending / MarkDebuggerAttached by writing the appropriate bits into g_CORDebuggerControlFlags, and adds unit test coverage plus documentation updates.

Changes:

  • Added IDebugger.MarkDebuggerAttachPending() and IDebugger.MarkDebuggerAttached(bool) APIs and implemented them in Debugger_1 via target-memory writes.
  • Updated DacDbiImpl to call the cDAC contract implementations (with DEBUG-only legacy cross-validation).
  • Exposed g_CORDebuggerControlFlags via the CoreCLR data descriptor and added tests/docs for the new flag semantics.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/native/managed/cdac/tests/DebuggerTests.csAdds test target plumbing + new unit tests validating control-flag writes.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.csImplements the two DBI methods by calling the cDAC Debugger contract and translating errors to HRESULTs.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.csAdds the flag enum and implements the two new attach APIs by updating CORDebuggerControlFlags.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.csIntroduces the new Globals.CORDebuggerControlFlags name constant.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugger.csExtends the contract interface with the two new methods.
src/coreclr/vm/datadescriptor/datadescriptor.incExposes g_CORDebuggerControlFlags and adjusts Debugger global gating.
src/coreclr/inc/cordbpriv.hAdds cDAC dependency annotations to DBCF_PENDING_ATTACH / DBCF_ATTACHED.
docs/design/datacontracts/Debugger.mdDocuments the new APIs, global dependency, and flag behavior.

Comment threadsrc/coreclr/vm/datadescriptor/datadescriptor.inc Outdated
CopilotAI review requested due to automatic review settings April 12, 2026 00:37

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

@github-actions

This comment has been minimized.

@rcj1

rcj1 commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Test helpers tbd in #126595

Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Comment threaddocs/design/datacontracts/Debugger.md
Comment threaddocs/design/datacontracts/Debugger.md
@github-actions

This comment has been minimized.

CopilotAI review requested due to automatic review settings April 17, 2026 17:28
Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Comment threadsrc/coreclr/debug/shared/dbgtransportsession.cpp
Comment threadsrc/coreclr/debug/inc/dbgipcevents.h
Comment threadsrc/coreclr/debug/di/process.cpp
Comment threadsrc/coreclr/debug/ee/rcthread.cpp
Comment threadsrc/native/managed/cdac/tests/DebuggerTests.cs
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Copilot Code Review — PR #126794

Note

This review was generated by Copilot (Claude Opus 4.6) with additional analysis from Claude Sonnet 4.5.

Holistic Assessment

Motivation: This PR implements debugger attach flag methods (MarkDebuggerAttachPending, MarkDebuggerAttached) in the cDAC debugger contract and DacDbi layer, migrates the debugging infrastructure from VMPTR_Assembly to VMPTR_DomainAssembly to better model AppDomain affinity, and removes dead fiber-mode debugging code. The architectural direction is sound — DomainAssembly is the correct abstraction for ICorDebug's module concept.

Approach: The change systematically threads VMPTR_DomainAssembly and VMPTR_AppDomain through the entire DacDbi interface (IDL, interface headers, DI, DAC, and cDAC implementations). The shift from a single m_pAppDomain pointer to a CordbSafeHashTable<CordbAppDomain> m_appDomains in CordbProcess is the right structural change. The dead code removal (fiber mode, unused enum flags) is clean.

Summary: ⚠️Needs Human Review. The code is architecturally well-structured and the core implementations look correct. However, there are several items that require maintainer attention: incomplete dead code cleanup, a parameter naming inconsistency in the IDL, and the DB_IPCE_EXIT_APP_DOMAIN re-enablement warrants explicit acknowledgment. The protocol breaking change counter question also needs a maintainer decision.


Detailed Findings

⚠️ DacDbi Protocol Breaking Change Counter — Not bumped

src/coreclr/debug/inc/dacdbistructures.h:692kCurrentDacDbiProtocolBreakingChangeCounter remains at 1 despite extensive breaking changes to IDacDbiInterface: ~30+ method signatures changed (Assembly → DomainAssembly), new methods added (GetAppDomainFromId, EnumerateAppDomains, GetAssemblyFromDomainAssembly, etc.), callback typedefs changed, and struct fields modified.

Per the comment at line 699-710, the counter should be explicitly bumped and documented when breaking changes are introduced. The auto-generated MD5 hash mechanism (described at line 616-618 in process.cpp) will detect the change automatically for remote transport scenarios, so this is unlikely to cause a runtime crash. However, the convention says to bump and document the counter. A maintainer should decide if a bump is needed here or if the hash is sufficient.

⚠️ Incomplete Dead Code Cleanup — CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS

src/coreclr/debug/di/process.cpp:237,8575 — The fiber-mode code was removed (DBCF_FIBERMODE, m_bHostingInFiber, the fiber check in VerifyControlBlock), but two references to CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS remain:

  1. Line 237: In IsLegalFatalError() — lists this error as a legal fatal error. Since no code path can produce this error anymore, this entry is dead.
  2. Line 8575: if (!IsLegalFatalError(errorHR) || (errorHR != CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS)) — This special-cases the fiber error to skip setting m_unrecoverableError. Since the error is never produced, the special case is also dead.

These should be cleaned up for consistency with the fiber-mode removal. Not blocking, but creates confusing dead code.

⚠️ IDL Parameter Naming Inconsistency — vmAssembly for DomainAssembly type

src/coreclr/inc/dacdbi.idl — The EnumerateModulesInAssembly method has:

HRESULT EnumerateModulesInAssembly([in] VMPTR_DomainAssembly vmAssembly, ...);

The parameter is named vmAssembly but the type is VMPTR_DomainAssembly. This should be vmDomainAssembly for consistency with all other methods in this PR.

⚠️DB_IPCE_EXIT_APP_DOMAIN Re-enabled — Needs documentation

src/coreclr/debug/inc/dbgipceventtypes.h:49 — This event type was previously commented out and is now re-enabled. The handler in process.cpp is well-written (with proper null checks and assertions). This is clearly needed for the new multi-AppDomain hash table support. However, it would be helpful to have a brief comment in the code or commit message explaining why this was re-enabled, since the previous comment suggested it was intentionally disabled.

✅ cDAC Debugger Contract Implementation — Correct

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.cs — The new MarkDebuggerAttachPending() and MarkDebuggerAttached() implementations:

  • Flag values (0x0100, 0x0200) match cordbpriv.h constants ✅
  • Bitwise operations match the native DAC implementation in dacdbiimpl.cpp:4798-4869
  • MarkDebuggerAttached(false) correctly clears both Attached and PendingAttach flags ✅
  • The read-modify-write pattern is not atomic, but this matches the native code which relies on the DD lock for synchronization ✅

TryGetDebuggerData Behavior Change — Intentional and correct

Debugger_1.cs:21-35 — Previously returned false when LeftSideInitialized == 0; now returns true with IsLeftSideInitialized in the data. This better matches the native DAC behavior: GetDefinesBitField and GetMDStructuresVersion (dacdbiimpl.cpp:7985-8009) check g_pDebugger == NULL but NOT LeftSideInitialized. The DacDbiImpl.cs wrapper at line 64 correctly uses data.IsLeftSideInitialized for the IsLeftSideInitialized DBI method. The dump test at line 93-94 was updated to cross-validate correctly.

✅ Struct Layout Binary Compatibility — Correct

src/coreclr/debug/inc/dbgipcevents.h — Replacing bool m_bHostingInFiber with BYTE padding1 maintains the same 1-byte layout within the DWORD-aligned group (m_checkedBuild + padding1 + padding2 + padding3 = 4 bytes). The transport marshaling in dbgtransportsession.cpp correctly omits the padding field. Both DebuggerIPCControlBlock and DebuggerIPCControlBlockTransport are updated consistently.

✅ Test Changes — Correct and comprehensive

src/native/managed/cdac/tests/DebuggerTests.cs — The removal of memBuilder.AddHeapFragment(debuggerControlFlagsFrag) is correct: BumpAllocator.Allocate auto-registers heap fragments with the builder. The three new tests (MarkDebuggerAttachPending_SetsPendingAttachFlag, MarkDebuggerAttached_SetsAttachedFlag_WhenTrue, MarkDebuggerAttached_ClearsAttachedAndPending_WhenFalse) provide good coverage with distinct initial states. The DacDbi dump tests add coverage for GetAppDomainFromId, EnumerateAppDomains, IsAssemblyFullyTrusted, and GetAppDomainIdFromVmObjectHandle.

✅ AppDomain Management Rearchitecture — Well-structured

src/coreclr/debug/di/process.cpp, rspriv.h — The migration from CordbAppDomain* m_pAppDomain to CordbSafeHashTable<CordbAppDomain> m_appDomains is clean:

  • NeuterChildren correctly uses NeuterAndClear instead of manual pointer cleanup
  • NeuterChildrenLeftSideResources correctly copies to an auxiliary list before releasing the lock
  • CacheAppDomain properly uses AddBaseOrThrow with RSInitHolder RAII
  • PrepopulateAppDomainsOrThrow gates on IsDacInitialized()
  • ContinueInternal handles the hash table properly with CopyToArray

💡 GetInstantiationFieldInfo Uses AppDomain::GetCurrentDomain()

src/coreclr/debug/daccess/dacdbiimpl.cpp:1817 — This method takes a VMPTR_DomainAssembly parameter but uses AppDomain::GetCurrentDomain() for CollectFields instead of deriving the AppDomain from the parameter. In modern .NET (single AppDomain), this is functionally correct and mirrors how the runtime operates. Noted as a potential follow-up if multi-domain support were ever reconsidered.

💡 Mixed Concerns in PR

The PR bundles debugger attach flag implementation, Assembly→DomainAssembly migration, fiber-mode dead code removal, RequiresAlign8 removal from RuntimeTypeSystem, and ContractRegistry simplification. While these are related to the broader cDAC migration, splitting the dead code removal and RequiresAlign8 changes into separate PRs would make the changes easier to review and bisect.

Generated by Code Review for issue #126794 ·

CopilotAI review requested due to automatic review settings April 20, 2026 18:13

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

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/debug/di/process.cpp:8386

  • CordbProcess::UnrecoverableError no longer sets m_unrecoverableError for legal fatal errors (e.g., CORDBG_E_INCOMPATIBLE_PROTOCOL), because the condition changed from effectively "all except CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS" to only !IsLegalFatalError(errorHR). This is a behavior change beyond removing fiber-mode handling and may leave the process in a non-zombie state after an unrecoverable condition. Consider restoring the previous intent (e.g., set m_unrecoverableError for legal fatal errors too, or otherwise document/handle why legal fatal errors should avoid zombie state).
 CONSISTENCY_CHECK_MSGF(IsLegalFatalError(errorHR), ("Unrecoverable internal error: hr=0x%08x!", errorHR));
if (!IsLegalFatalError(errorHR))
{
// This will throw everything into a Zombie state. The ATT_ macros will check this and fail immediately.
m_unrecoverableError = true;
//
// Mark the process as no longer synchronized.
//
Lock();
SetSynchronized(false);
IncStopCount();
Unlock();
}

@rcj1

rcj1 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

/ba-g wasm

@rcj1
rcj1 merged commit c78a047 into mainApr 23, 2026
126 of 129 checks passed
@rcj1
rcj1 deleted the copilot/implement-markdebugger-methods branch April 23, 2026 22:11
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@rcj1@noahfalk@jkotas@davidwrighton@max-charlamb@teo-tsirpanis
, '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

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs - #126794

Merged
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods
Apr 23, 2026
Merged

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs#126794
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods

Conversation

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
  • Implements MarkDebuggerAttachPending and MarkDebuggerAttached in cDAC DacDbiImpl by adding corresponding Debugger_1 contract APIs and wiring them to target-memory writes of debugger control flags.
  • Removes fibermode dead code

CopilotAI requested review from Copilot and removed request for CopilotApril 11, 2026 19:28
@rcj1rcj1 changed the title Implement cDAC debugger attach state writes via g_CORDebuggerControlFlags[cDAC] Implement MarkDebuggerAttach* DacDbi APIsApr 11, 2026
@rcj1
rcj1 marked this pull request as ready for review April 11, 2026 21:00

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 extends the cDAC Debugger contract and the legacy DacDbiImpl surface to support MarkDebuggerAttachPending / MarkDebuggerAttached by writing the appropriate bits into g_CORDebuggerControlFlags, and adds unit test coverage plus documentation updates.

Changes:

  • Added IDebugger.MarkDebuggerAttachPending() and IDebugger.MarkDebuggerAttached(bool) APIs and implemented them in Debugger_1 via target-memory writes.
  • Updated DacDbiImpl to call the cDAC contract implementations (with DEBUG-only legacy cross-validation).
  • Exposed g_CORDebuggerControlFlags via the CoreCLR data descriptor and added tests/docs for the new flag semantics.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/native/managed/cdac/tests/DebuggerTests.csAdds test target plumbing + new unit tests validating control-flag writes.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.csImplements the two DBI methods by calling the cDAC Debugger contract and translating errors to HRESULTs.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.csAdds the flag enum and implements the two new attach APIs by updating CORDebuggerControlFlags.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.csIntroduces the new Globals.CORDebuggerControlFlags name constant.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugger.csExtends the contract interface with the two new methods.
src/coreclr/vm/datadescriptor/datadescriptor.incExposes g_CORDebuggerControlFlags and adjusts Debugger global gating.
src/coreclr/inc/cordbpriv.hAdds cDAC dependency annotations to DBCF_PENDING_ATTACH / DBCF_ATTACHED.
docs/design/datacontracts/Debugger.mdDocuments the new APIs, global dependency, and flag behavior.

Comment threadsrc/coreclr/vm/datadescriptor/datadescriptor.inc Outdated
CopilotAI review requested due to automatic review settings April 12, 2026 00:37

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

@github-actions

This comment has been minimized.

@rcj1

rcj1 commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Test helpers tbd in #126595

Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Comment threaddocs/design/datacontracts/Debugger.md
Comment threaddocs/design/datacontracts/Debugger.md
@github-actions

This comment has been minimized.

CopilotAI review requested due to automatic review settings April 17, 2026 17:28
Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Comment threadsrc/coreclr/debug/shared/dbgtransportsession.cpp
Comment threadsrc/coreclr/debug/inc/dbgipcevents.h
Comment threadsrc/coreclr/debug/di/process.cpp
Comment threadsrc/coreclr/debug/ee/rcthread.cpp
Comment threadsrc/native/managed/cdac/tests/DebuggerTests.cs
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Copilot Code Review — PR #126794

Note

This review was generated by Copilot (Claude Opus 4.6) with additional analysis from Claude Sonnet 4.5.

Holistic Assessment

Motivation: This PR implements debugger attach flag methods (MarkDebuggerAttachPending, MarkDebuggerAttached) in the cDAC debugger contract and DacDbi layer, migrates the debugging infrastructure from VMPTR_Assembly to VMPTR_DomainAssembly to better model AppDomain affinity, and removes dead fiber-mode debugging code. The architectural direction is sound — DomainAssembly is the correct abstraction for ICorDebug's module concept.

Approach: The change systematically threads VMPTR_DomainAssembly and VMPTR_AppDomain through the entire DacDbi interface (IDL, interface headers, DI, DAC, and cDAC implementations). The shift from a single m_pAppDomain pointer to a CordbSafeHashTable<CordbAppDomain> m_appDomains in CordbProcess is the right structural change. The dead code removal (fiber mode, unused enum flags) is clean.

Summary: ⚠️Needs Human Review. The code is architecturally well-structured and the core implementations look correct. However, there are several items that require maintainer attention: incomplete dead code cleanup, a parameter naming inconsistency in the IDL, and the DB_IPCE_EXIT_APP_DOMAIN re-enablement warrants explicit acknowledgment. The protocol breaking change counter question also needs a maintainer decision.


Detailed Findings

⚠️ DacDbi Protocol Breaking Change Counter — Not bumped

src/coreclr/debug/inc/dacdbistructures.h:692kCurrentDacDbiProtocolBreakingChangeCounter remains at 1 despite extensive breaking changes to IDacDbiInterface: ~30+ method signatures changed (Assembly → DomainAssembly), new methods added (GetAppDomainFromId, EnumerateAppDomains, GetAssemblyFromDomainAssembly, etc.), callback typedefs changed, and struct fields modified.

Per the comment at line 699-710, the counter should be explicitly bumped and documented when breaking changes are introduced. The auto-generated MD5 hash mechanism (described at line 616-618 in process.cpp) will detect the change automatically for remote transport scenarios, so this is unlikely to cause a runtime crash. However, the convention says to bump and document the counter. A maintainer should decide if a bump is needed here or if the hash is sufficient.

⚠️ Incomplete Dead Code Cleanup — CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS

src/coreclr/debug/di/process.cpp:237,8575 — The fiber-mode code was removed (DBCF_FIBERMODE, m_bHostingInFiber, the fiber check in VerifyControlBlock), but two references to CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS remain:

  1. Line 237: In IsLegalFatalError() — lists this error as a legal fatal error. Since no code path can produce this error anymore, this entry is dead.
  2. Line 8575: if (!IsLegalFatalError(errorHR) || (errorHR != CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS)) — This special-cases the fiber error to skip setting m_unrecoverableError. Since the error is never produced, the special case is also dead.

These should be cleaned up for consistency with the fiber-mode removal. Not blocking, but creates confusing dead code.

⚠️ IDL Parameter Naming Inconsistency — vmAssembly for DomainAssembly type

src/coreclr/inc/dacdbi.idl — The EnumerateModulesInAssembly method has:

HRESULT EnumerateModulesInAssembly([in] VMPTR_DomainAssembly vmAssembly, ...);

The parameter is named vmAssembly but the type is VMPTR_DomainAssembly. This should be vmDomainAssembly for consistency with all other methods in this PR.

⚠️DB_IPCE_EXIT_APP_DOMAIN Re-enabled — Needs documentation

src/coreclr/debug/inc/dbgipceventtypes.h:49 — This event type was previously commented out and is now re-enabled. The handler in process.cpp is well-written (with proper null checks and assertions). This is clearly needed for the new multi-AppDomain hash table support. However, it would be helpful to have a brief comment in the code or commit message explaining why this was re-enabled, since the previous comment suggested it was intentionally disabled.

✅ cDAC Debugger Contract Implementation — Correct

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.cs — The new MarkDebuggerAttachPending() and MarkDebuggerAttached() implementations:

  • Flag values (0x0100, 0x0200) match cordbpriv.h constants ✅
  • Bitwise operations match the native DAC implementation in dacdbiimpl.cpp:4798-4869
  • MarkDebuggerAttached(false) correctly clears both Attached and PendingAttach flags ✅
  • The read-modify-write pattern is not atomic, but this matches the native code which relies on the DD lock for synchronization ✅

TryGetDebuggerData Behavior Change — Intentional and correct

Debugger_1.cs:21-35 — Previously returned false when LeftSideInitialized == 0; now returns true with IsLeftSideInitialized in the data. This better matches the native DAC behavior: GetDefinesBitField and GetMDStructuresVersion (dacdbiimpl.cpp:7985-8009) check g_pDebugger == NULL but NOT LeftSideInitialized. The DacDbiImpl.cs wrapper at line 64 correctly uses data.IsLeftSideInitialized for the IsLeftSideInitialized DBI method. The dump test at line 93-94 was updated to cross-validate correctly.

✅ Struct Layout Binary Compatibility — Correct

src/coreclr/debug/inc/dbgipcevents.h — Replacing bool m_bHostingInFiber with BYTE padding1 maintains the same 1-byte layout within the DWORD-aligned group (m_checkedBuild + padding1 + padding2 + padding3 = 4 bytes). The transport marshaling in dbgtransportsession.cpp correctly omits the padding field. Both DebuggerIPCControlBlock and DebuggerIPCControlBlockTransport are updated consistently.

✅ Test Changes — Correct and comprehensive

src/native/managed/cdac/tests/DebuggerTests.cs — The removal of memBuilder.AddHeapFragment(debuggerControlFlagsFrag) is correct: BumpAllocator.Allocate auto-registers heap fragments with the builder. The three new tests (MarkDebuggerAttachPending_SetsPendingAttachFlag, MarkDebuggerAttached_SetsAttachedFlag_WhenTrue, MarkDebuggerAttached_ClearsAttachedAndPending_WhenFalse) provide good coverage with distinct initial states. The DacDbi dump tests add coverage for GetAppDomainFromId, EnumerateAppDomains, IsAssemblyFullyTrusted, and GetAppDomainIdFromVmObjectHandle.

✅ AppDomain Management Rearchitecture — Well-structured

src/coreclr/debug/di/process.cpp, rspriv.h — The migration from CordbAppDomain* m_pAppDomain to CordbSafeHashTable<CordbAppDomain> m_appDomains is clean:

  • NeuterChildren correctly uses NeuterAndClear instead of manual pointer cleanup
  • NeuterChildrenLeftSideResources correctly copies to an auxiliary list before releasing the lock
  • CacheAppDomain properly uses AddBaseOrThrow with RSInitHolder RAII
  • PrepopulateAppDomainsOrThrow gates on IsDacInitialized()
  • ContinueInternal handles the hash table properly with CopyToArray

💡 GetInstantiationFieldInfo Uses AppDomain::GetCurrentDomain()

src/coreclr/debug/daccess/dacdbiimpl.cpp:1817 — This method takes a VMPTR_DomainAssembly parameter but uses AppDomain::GetCurrentDomain() for CollectFields instead of deriving the AppDomain from the parameter. In modern .NET (single AppDomain), this is functionally correct and mirrors how the runtime operates. Noted as a potential follow-up if multi-domain support were ever reconsidered.

💡 Mixed Concerns in PR

The PR bundles debugger attach flag implementation, Assembly→DomainAssembly migration, fiber-mode dead code removal, RequiresAlign8 removal from RuntimeTypeSystem, and ContractRegistry simplification. While these are related to the broader cDAC migration, splitting the dead code removal and RequiresAlign8 changes into separate PRs would make the changes easier to review and bisect.

Generated by Code Review for issue #126794 ·

CopilotAI review requested due to automatic review settings April 20, 2026 18:13

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

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/debug/di/process.cpp:8386

  • CordbProcess::UnrecoverableError no longer sets m_unrecoverableError for legal fatal errors (e.g., CORDBG_E_INCOMPATIBLE_PROTOCOL), because the condition changed from effectively "all except CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS" to only !IsLegalFatalError(errorHR). This is a behavior change beyond removing fiber-mode handling and may leave the process in a non-zombie state after an unrecoverable condition. Consider restoring the previous intent (e.g., set m_unrecoverableError for legal fatal errors too, or otherwise document/handle why legal fatal errors should avoid zombie state).
 CONSISTENCY_CHECK_MSGF(IsLegalFatalError(errorHR), ("Unrecoverable internal error: hr=0x%08x!", errorHR));
if (!IsLegalFatalError(errorHR))
{
// This will throw everything into a Zombie state. The ATT_ macros will check this and fail immediately.
m_unrecoverableError = true;
//
// Mark the process as no longer synchronized.
//
Lock();
SetSynchronized(false);
IncStopCount();
Unlock();
}

@rcj1

rcj1 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

/ba-g wasm

@rcj1
rcj1 merged commit c78a047 into mainApr 23, 2026
126 of 129 checks passed
@rcj1
rcj1 deleted the copilot/implement-markdebugger-methods branch April 23, 2026 22:11
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@rcj1@noahfalk@jkotas@davidwrighton@max-charlamb@teo-tsirpanis
, '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

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs - #126794

Merged
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods
Apr 23, 2026
Merged

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs#126794
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods

Conversation

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
  • Implements MarkDebuggerAttachPending and MarkDebuggerAttached in cDAC DacDbiImpl by adding corresponding Debugger_1 contract APIs and wiring them to target-memory writes of debugger control flags.
  • Removes fibermode dead code

CopilotAI requested review from Copilot and removed request for CopilotApril 11, 2026 19:28
@rcj1rcj1 changed the title Implement cDAC debugger attach state writes via g_CORDebuggerControlFlags[cDAC] Implement MarkDebuggerAttach* DacDbi APIsApr 11, 2026
@rcj1
rcj1 marked this pull request as ready for review April 11, 2026 21:00

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 extends the cDAC Debugger contract and the legacy DacDbiImpl surface to support MarkDebuggerAttachPending / MarkDebuggerAttached by writing the appropriate bits into g_CORDebuggerControlFlags, and adds unit test coverage plus documentation updates.

Changes:

  • Added IDebugger.MarkDebuggerAttachPending() and IDebugger.MarkDebuggerAttached(bool) APIs and implemented them in Debugger_1 via target-memory writes.
  • Updated DacDbiImpl to call the cDAC contract implementations (with DEBUG-only legacy cross-validation).
  • Exposed g_CORDebuggerControlFlags via the CoreCLR data descriptor and added tests/docs for the new flag semantics.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/native/managed/cdac/tests/DebuggerTests.csAdds test target plumbing + new unit tests validating control-flag writes.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.csImplements the two DBI methods by calling the cDAC Debugger contract and translating errors to HRESULTs.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.csAdds the flag enum and implements the two new attach APIs by updating CORDebuggerControlFlags.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.csIntroduces the new Globals.CORDebuggerControlFlags name constant.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugger.csExtends the contract interface with the two new methods.
src/coreclr/vm/datadescriptor/datadescriptor.incExposes g_CORDebuggerControlFlags and adjusts Debugger global gating.
src/coreclr/inc/cordbpriv.hAdds cDAC dependency annotations to DBCF_PENDING_ATTACH / DBCF_ATTACHED.
docs/design/datacontracts/Debugger.mdDocuments the new APIs, global dependency, and flag behavior.

Comment threadsrc/coreclr/vm/datadescriptor/datadescriptor.inc Outdated
CopilotAI review requested due to automatic review settings April 12, 2026 00:37

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

@github-actions

This comment has been minimized.

@rcj1

rcj1 commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Test helpers tbd in #126595

Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Comment threaddocs/design/datacontracts/Debugger.md
Comment threaddocs/design/datacontracts/Debugger.md
@github-actions

This comment has been minimized.

CopilotAI review requested due to automatic review settings April 17, 2026 17:28
Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Comment threadsrc/coreclr/debug/shared/dbgtransportsession.cpp
Comment threadsrc/coreclr/debug/inc/dbgipcevents.h
Comment threadsrc/coreclr/debug/di/process.cpp
Comment threadsrc/coreclr/debug/ee/rcthread.cpp
Comment threadsrc/native/managed/cdac/tests/DebuggerTests.cs
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Copilot Code Review — PR #126794

Note

This review was generated by Copilot (Claude Opus 4.6) with additional analysis from Claude Sonnet 4.5.

Holistic Assessment

Motivation: This PR implements debugger attach flag methods (MarkDebuggerAttachPending, MarkDebuggerAttached) in the cDAC debugger contract and DacDbi layer, migrates the debugging infrastructure from VMPTR_Assembly to VMPTR_DomainAssembly to better model AppDomain affinity, and removes dead fiber-mode debugging code. The architectural direction is sound — DomainAssembly is the correct abstraction for ICorDebug's module concept.

Approach: The change systematically threads VMPTR_DomainAssembly and VMPTR_AppDomain through the entire DacDbi interface (IDL, interface headers, DI, DAC, and cDAC implementations). The shift from a single m_pAppDomain pointer to a CordbSafeHashTable<CordbAppDomain> m_appDomains in CordbProcess is the right structural change. The dead code removal (fiber mode, unused enum flags) is clean.

Summary: ⚠️Needs Human Review. The code is architecturally well-structured and the core implementations look correct. However, there are several items that require maintainer attention: incomplete dead code cleanup, a parameter naming inconsistency in the IDL, and the DB_IPCE_EXIT_APP_DOMAIN re-enablement warrants explicit acknowledgment. The protocol breaking change counter question also needs a maintainer decision.


Detailed Findings

⚠️ DacDbi Protocol Breaking Change Counter — Not bumped

src/coreclr/debug/inc/dacdbistructures.h:692kCurrentDacDbiProtocolBreakingChangeCounter remains at 1 despite extensive breaking changes to IDacDbiInterface: ~30+ method signatures changed (Assembly → DomainAssembly), new methods added (GetAppDomainFromId, EnumerateAppDomains, GetAssemblyFromDomainAssembly, etc.), callback typedefs changed, and struct fields modified.

Per the comment at line 699-710, the counter should be explicitly bumped and documented when breaking changes are introduced. The auto-generated MD5 hash mechanism (described at line 616-618 in process.cpp) will detect the change automatically for remote transport scenarios, so this is unlikely to cause a runtime crash. However, the convention says to bump and document the counter. A maintainer should decide if a bump is needed here or if the hash is sufficient.

⚠️ Incomplete Dead Code Cleanup — CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS

src/coreclr/debug/di/process.cpp:237,8575 — The fiber-mode code was removed (DBCF_FIBERMODE, m_bHostingInFiber, the fiber check in VerifyControlBlock), but two references to CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS remain:

  1. Line 237: In IsLegalFatalError() — lists this error as a legal fatal error. Since no code path can produce this error anymore, this entry is dead.
  2. Line 8575: if (!IsLegalFatalError(errorHR) || (errorHR != CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS)) — This special-cases the fiber error to skip setting m_unrecoverableError. Since the error is never produced, the special case is also dead.

These should be cleaned up for consistency with the fiber-mode removal. Not blocking, but creates confusing dead code.

⚠️ IDL Parameter Naming Inconsistency — vmAssembly for DomainAssembly type

src/coreclr/inc/dacdbi.idl — The EnumerateModulesInAssembly method has:

HRESULT EnumerateModulesInAssembly([in] VMPTR_DomainAssembly vmAssembly, ...);

The parameter is named vmAssembly but the type is VMPTR_DomainAssembly. This should be vmDomainAssembly for consistency with all other methods in this PR.

⚠️DB_IPCE_EXIT_APP_DOMAIN Re-enabled — Needs documentation

src/coreclr/debug/inc/dbgipceventtypes.h:49 — This event type was previously commented out and is now re-enabled. The handler in process.cpp is well-written (with proper null checks and assertions). This is clearly needed for the new multi-AppDomain hash table support. However, it would be helpful to have a brief comment in the code or commit message explaining why this was re-enabled, since the previous comment suggested it was intentionally disabled.

✅ cDAC Debugger Contract Implementation — Correct

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.cs — The new MarkDebuggerAttachPending() and MarkDebuggerAttached() implementations:

  • Flag values (0x0100, 0x0200) match cordbpriv.h constants ✅
  • Bitwise operations match the native DAC implementation in dacdbiimpl.cpp:4798-4869
  • MarkDebuggerAttached(false) correctly clears both Attached and PendingAttach flags ✅
  • The read-modify-write pattern is not atomic, but this matches the native code which relies on the DD lock for synchronization ✅

TryGetDebuggerData Behavior Change — Intentional and correct

Debugger_1.cs:21-35 — Previously returned false when LeftSideInitialized == 0; now returns true with IsLeftSideInitialized in the data. This better matches the native DAC behavior: GetDefinesBitField and GetMDStructuresVersion (dacdbiimpl.cpp:7985-8009) check g_pDebugger == NULL but NOT LeftSideInitialized. The DacDbiImpl.cs wrapper at line 64 correctly uses data.IsLeftSideInitialized for the IsLeftSideInitialized DBI method. The dump test at line 93-94 was updated to cross-validate correctly.

✅ Struct Layout Binary Compatibility — Correct

src/coreclr/debug/inc/dbgipcevents.h — Replacing bool m_bHostingInFiber with BYTE padding1 maintains the same 1-byte layout within the DWORD-aligned group (m_checkedBuild + padding1 + padding2 + padding3 = 4 bytes). The transport marshaling in dbgtransportsession.cpp correctly omits the padding field. Both DebuggerIPCControlBlock and DebuggerIPCControlBlockTransport are updated consistently.

✅ Test Changes — Correct and comprehensive

src/native/managed/cdac/tests/DebuggerTests.cs — The removal of memBuilder.AddHeapFragment(debuggerControlFlagsFrag) is correct: BumpAllocator.Allocate auto-registers heap fragments with the builder. The three new tests (MarkDebuggerAttachPending_SetsPendingAttachFlag, MarkDebuggerAttached_SetsAttachedFlag_WhenTrue, MarkDebuggerAttached_ClearsAttachedAndPending_WhenFalse) provide good coverage with distinct initial states. The DacDbi dump tests add coverage for GetAppDomainFromId, EnumerateAppDomains, IsAssemblyFullyTrusted, and GetAppDomainIdFromVmObjectHandle.

✅ AppDomain Management Rearchitecture — Well-structured

src/coreclr/debug/di/process.cpp, rspriv.h — The migration from CordbAppDomain* m_pAppDomain to CordbSafeHashTable<CordbAppDomain> m_appDomains is clean:

  • NeuterChildren correctly uses NeuterAndClear instead of manual pointer cleanup
  • NeuterChildrenLeftSideResources correctly copies to an auxiliary list before releasing the lock
  • CacheAppDomain properly uses AddBaseOrThrow with RSInitHolder RAII
  • PrepopulateAppDomainsOrThrow gates on IsDacInitialized()
  • ContinueInternal handles the hash table properly with CopyToArray

💡 GetInstantiationFieldInfo Uses AppDomain::GetCurrentDomain()

src/coreclr/debug/daccess/dacdbiimpl.cpp:1817 — This method takes a VMPTR_DomainAssembly parameter but uses AppDomain::GetCurrentDomain() for CollectFields instead of deriving the AppDomain from the parameter. In modern .NET (single AppDomain), this is functionally correct and mirrors how the runtime operates. Noted as a potential follow-up if multi-domain support were ever reconsidered.

💡 Mixed Concerns in PR

The PR bundles debugger attach flag implementation, Assembly→DomainAssembly migration, fiber-mode dead code removal, RequiresAlign8 removal from RuntimeTypeSystem, and ContractRegistry simplification. While these are related to the broader cDAC migration, splitting the dead code removal and RequiresAlign8 changes into separate PRs would make the changes easier to review and bisect.

Generated by Code Review for issue #126794 ·

CopilotAI review requested due to automatic review settings April 20, 2026 18:13

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

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/debug/di/process.cpp:8386

  • CordbProcess::UnrecoverableError no longer sets m_unrecoverableError for legal fatal errors (e.g., CORDBG_E_INCOMPATIBLE_PROTOCOL), because the condition changed from effectively "all except CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS" to only !IsLegalFatalError(errorHR). This is a behavior change beyond removing fiber-mode handling and may leave the process in a non-zombie state after an unrecoverable condition. Consider restoring the previous intent (e.g., set m_unrecoverableError for legal fatal errors too, or otherwise document/handle why legal fatal errors should avoid zombie state).
 CONSISTENCY_CHECK_MSGF(IsLegalFatalError(errorHR), ("Unrecoverable internal error: hr=0x%08x!", errorHR));
if (!IsLegalFatalError(errorHR))
{
// This will throw everything into a Zombie state. The ATT_ macros will check this and fail immediately.
m_unrecoverableError = true;
//
// Mark the process as no longer synchronized.
//
Lock();
SetSynchronized(false);
IncStopCount();
Unlock();
}

@rcj1

rcj1 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

/ba-g wasm

@rcj1
rcj1 merged commit c78a047 into mainApr 23, 2026
126 of 129 checks passed
@rcj1
rcj1 deleted the copilot/implement-markdebugger-methods branch April 23, 2026 22:11
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@rcj1@noahfalk@jkotas@davidwrighton@max-charlamb@teo-tsirpanis
, '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

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs - #126794

Merged
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods
Apr 23, 2026
Merged

[cDAC] Implement MarkDebuggerAttach* DacDbi APIs#126794
rcj1 merged 9 commits into
mainfrom
copilot/implement-markdebugger-methods

Conversation

CopilotAI commented Apr 11, 2026

Copy link
Copy Markdown
Contributor
  • Implements MarkDebuggerAttachPending and MarkDebuggerAttached in cDAC DacDbiImpl by adding corresponding Debugger_1 contract APIs and wiring them to target-memory writes of debugger control flags.
  • Removes fibermode dead code

CopilotAI requested review from Copilot and removed request for CopilotApril 11, 2026 19:28
@rcj1rcj1 changed the title Implement cDAC debugger attach state writes via g_CORDebuggerControlFlags[cDAC] Implement MarkDebuggerAttach* DacDbi APIsApr 11, 2026
@rcj1
rcj1 marked this pull request as ready for review April 11, 2026 21:00

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 extends the cDAC Debugger contract and the legacy DacDbiImpl surface to support MarkDebuggerAttachPending / MarkDebuggerAttached by writing the appropriate bits into g_CORDebuggerControlFlags, and adds unit test coverage plus documentation updates.

Changes:

  • Added IDebugger.MarkDebuggerAttachPending() and IDebugger.MarkDebuggerAttached(bool) APIs and implemented them in Debugger_1 via target-memory writes.
  • Updated DacDbiImpl to call the cDAC contract implementations (with DEBUG-only legacy cross-validation).
  • Exposed g_CORDebuggerControlFlags via the CoreCLR data descriptor and added tests/docs for the new flag semantics.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
FileDescription
src/native/managed/cdac/tests/DebuggerTests.csAdds test target plumbing + new unit tests validating control-flag writes.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.csImplements the two DBI methods by calling the cDAC Debugger contract and translating errors to HRESULTs.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.csAdds the flag enum and implements the two new attach APIs by updating CORDebuggerControlFlags.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.csIntroduces the new Globals.CORDebuggerControlFlags name constant.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugger.csExtends the contract interface with the two new methods.
src/coreclr/vm/datadescriptor/datadescriptor.incExposes g_CORDebuggerControlFlags and adjusts Debugger global gating.
src/coreclr/inc/cordbpriv.hAdds cDAC dependency annotations to DBCF_PENDING_ATTACH / DBCF_ATTACHED.
docs/design/datacontracts/Debugger.mdDocuments the new APIs, global dependency, and flag behavior.

Comment threadsrc/coreclr/vm/datadescriptor/datadescriptor.inc Outdated
CopilotAI review requested due to automatic review settings April 12, 2026 00:37

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

@github-actions

This comment has been minimized.

@rcj1

rcj1 commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Test helpers tbd in #126595

Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Comment threaddocs/design/datacontracts/Debugger.md
Comment threaddocs/design/datacontracts/Debugger.md
@github-actions

This comment has been minimized.

CopilotAI review requested due to automatic review settings April 17, 2026 17:28
Comment threadsrc/coreclr/inc/cordbpriv.h Outdated
Co-authored-by: Jan Kotas <jkotas@microsoft.com>

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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Comment threadsrc/coreclr/debug/shared/dbgtransportsession.cpp
Comment threadsrc/coreclr/debug/inc/dbgipcevents.h
Comment threadsrc/coreclr/debug/di/process.cpp
Comment threadsrc/coreclr/debug/ee/rcthread.cpp
Comment threadsrc/native/managed/cdac/tests/DebuggerTests.cs
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Copilot Code Review — PR #126794

Note

This review was generated by Copilot (Claude Opus 4.6) with additional analysis from Claude Sonnet 4.5.

Holistic Assessment

Motivation: This PR implements debugger attach flag methods (MarkDebuggerAttachPending, MarkDebuggerAttached) in the cDAC debugger contract and DacDbi layer, migrates the debugging infrastructure from VMPTR_Assembly to VMPTR_DomainAssembly to better model AppDomain affinity, and removes dead fiber-mode debugging code. The architectural direction is sound — DomainAssembly is the correct abstraction for ICorDebug's module concept.

Approach: The change systematically threads VMPTR_DomainAssembly and VMPTR_AppDomain through the entire DacDbi interface (IDL, interface headers, DI, DAC, and cDAC implementations). The shift from a single m_pAppDomain pointer to a CordbSafeHashTable<CordbAppDomain> m_appDomains in CordbProcess is the right structural change. The dead code removal (fiber mode, unused enum flags) is clean.

Summary: ⚠️Needs Human Review. The code is architecturally well-structured and the core implementations look correct. However, there are several items that require maintainer attention: incomplete dead code cleanup, a parameter naming inconsistency in the IDL, and the DB_IPCE_EXIT_APP_DOMAIN re-enablement warrants explicit acknowledgment. The protocol breaking change counter question also needs a maintainer decision.


Detailed Findings

⚠️ DacDbi Protocol Breaking Change Counter — Not bumped

src/coreclr/debug/inc/dacdbistructures.h:692kCurrentDacDbiProtocolBreakingChangeCounter remains at 1 despite extensive breaking changes to IDacDbiInterface: ~30+ method signatures changed (Assembly → DomainAssembly), new methods added (GetAppDomainFromId, EnumerateAppDomains, GetAssemblyFromDomainAssembly, etc.), callback typedefs changed, and struct fields modified.

Per the comment at line 699-710, the counter should be explicitly bumped and documented when breaking changes are introduced. The auto-generated MD5 hash mechanism (described at line 616-618 in process.cpp) will detect the change automatically for remote transport scenarios, so this is unlikely to cause a runtime crash. However, the convention says to bump and document the counter. A maintainer should decide if a bump is needed here or if the hash is sufficient.

⚠️ Incomplete Dead Code Cleanup — CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS

src/coreclr/debug/di/process.cpp:237,8575 — The fiber-mode code was removed (DBCF_FIBERMODE, m_bHostingInFiber, the fiber check in VerifyControlBlock), but two references to CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS remain:

  1. Line 237: In IsLegalFatalError() — lists this error as a legal fatal error. Since no code path can produce this error anymore, this entry is dead.
  2. Line 8575: if (!IsLegalFatalError(errorHR) || (errorHR != CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS)) — This special-cases the fiber error to skip setting m_unrecoverableError. Since the error is never produced, the special case is also dead.

These should be cleaned up for consistency with the fiber-mode removal. Not blocking, but creates confusing dead code.

⚠️ IDL Parameter Naming Inconsistency — vmAssembly for DomainAssembly type

src/coreclr/inc/dacdbi.idl — The EnumerateModulesInAssembly method has:

HRESULT EnumerateModulesInAssembly([in] VMPTR_DomainAssembly vmAssembly, ...);

The parameter is named vmAssembly but the type is VMPTR_DomainAssembly. This should be vmDomainAssembly for consistency with all other methods in this PR.

⚠️DB_IPCE_EXIT_APP_DOMAIN Re-enabled — Needs documentation

src/coreclr/debug/inc/dbgipceventtypes.h:49 — This event type was previously commented out and is now re-enabled. The handler in process.cpp is well-written (with proper null checks and assertions). This is clearly needed for the new multi-AppDomain hash table support. However, it would be helpful to have a brief comment in the code or commit message explaining why this was re-enabled, since the previous comment suggested it was intentionally disabled.

✅ cDAC Debugger Contract Implementation — Correct

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.cs — The new MarkDebuggerAttachPending() and MarkDebuggerAttached() implementations:

  • Flag values (0x0100, 0x0200) match cordbpriv.h constants ✅
  • Bitwise operations match the native DAC implementation in dacdbiimpl.cpp:4798-4869
  • MarkDebuggerAttached(false) correctly clears both Attached and PendingAttach flags ✅
  • The read-modify-write pattern is not atomic, but this matches the native code which relies on the DD lock for synchronization ✅

TryGetDebuggerData Behavior Change — Intentional and correct

Debugger_1.cs:21-35 — Previously returned false when LeftSideInitialized == 0; now returns true with IsLeftSideInitialized in the data. This better matches the native DAC behavior: GetDefinesBitField and GetMDStructuresVersion (dacdbiimpl.cpp:7985-8009) check g_pDebugger == NULL but NOT LeftSideInitialized. The DacDbiImpl.cs wrapper at line 64 correctly uses data.IsLeftSideInitialized for the IsLeftSideInitialized DBI method. The dump test at line 93-94 was updated to cross-validate correctly.

✅ Struct Layout Binary Compatibility — Correct

src/coreclr/debug/inc/dbgipcevents.h — Replacing bool m_bHostingInFiber with BYTE padding1 maintains the same 1-byte layout within the DWORD-aligned group (m_checkedBuild + padding1 + padding2 + padding3 = 4 bytes). The transport marshaling in dbgtransportsession.cpp correctly omits the padding field. Both DebuggerIPCControlBlock and DebuggerIPCControlBlockTransport are updated consistently.

✅ Test Changes — Correct and comprehensive

src/native/managed/cdac/tests/DebuggerTests.cs — The removal of memBuilder.AddHeapFragment(debuggerControlFlagsFrag) is correct: BumpAllocator.Allocate auto-registers heap fragments with the builder. The three new tests (MarkDebuggerAttachPending_SetsPendingAttachFlag, MarkDebuggerAttached_SetsAttachedFlag_WhenTrue, MarkDebuggerAttached_ClearsAttachedAndPending_WhenFalse) provide good coverage with distinct initial states. The DacDbi dump tests add coverage for GetAppDomainFromId, EnumerateAppDomains, IsAssemblyFullyTrusted, and GetAppDomainIdFromVmObjectHandle.

✅ AppDomain Management Rearchitecture — Well-structured

src/coreclr/debug/di/process.cpp, rspriv.h — The migration from CordbAppDomain* m_pAppDomain to CordbSafeHashTable<CordbAppDomain> m_appDomains is clean:

  • NeuterChildren correctly uses NeuterAndClear instead of manual pointer cleanup
  • NeuterChildrenLeftSideResources correctly copies to an auxiliary list before releasing the lock
  • CacheAppDomain properly uses AddBaseOrThrow with RSInitHolder RAII
  • PrepopulateAppDomainsOrThrow gates on IsDacInitialized()
  • ContinueInternal handles the hash table properly with CopyToArray

💡 GetInstantiationFieldInfo Uses AppDomain::GetCurrentDomain()

src/coreclr/debug/daccess/dacdbiimpl.cpp:1817 — This method takes a VMPTR_DomainAssembly parameter but uses AppDomain::GetCurrentDomain() for CollectFields instead of deriving the AppDomain from the parameter. In modern .NET (single AppDomain), this is functionally correct and mirrors how the runtime operates. Noted as a potential follow-up if multi-domain support were ever reconsidered.

💡 Mixed Concerns in PR

The PR bundles debugger attach flag implementation, Assembly→DomainAssembly migration, fiber-mode dead code removal, RequiresAlign8 removal from RuntimeTypeSystem, and ContractRegistry simplification. While these are related to the broader cDAC migration, splitting the dead code removal and RequiresAlign8 changes into separate PRs would make the changes easier to review and bisect.

Generated by Code Review for issue #126794 ·

CopilotAI review requested due to automatic review settings April 20, 2026 18:13

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

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/debug/di/process.cpp:8386

  • CordbProcess::UnrecoverableError no longer sets m_unrecoverableError for legal fatal errors (e.g., CORDBG_E_INCOMPATIBLE_PROTOCOL), because the condition changed from effectively "all except CORDBG_E_CANNOT_DEBUG_FIBER_PROCESS" to only !IsLegalFatalError(errorHR). This is a behavior change beyond removing fiber-mode handling and may leave the process in a non-zombie state after an unrecoverable condition. Consider restoring the previous intent (e.g., set m_unrecoverableError for legal fatal errors too, or otherwise document/handle why legal fatal errors should avoid zombie state).
 CONSISTENCY_CHECK_MSGF(IsLegalFatalError(errorHR), ("Unrecoverable internal error: hr=0x%08x!", errorHR));
if (!IsLegalFatalError(errorHR))
{
// This will throw everything into a Zombie state. The ATT_ macros will check this and fail immediately.
m_unrecoverableError = true;
//
// Mark the process as no longer synchronized.
//
Lock();
SetSynchronized(false);
IncStopCount();
Unlock();
}

@rcj1

rcj1 commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

/ba-g wasm

@rcj1
rcj1 merged commit c78a047 into mainApr 23, 2026
126 of 129 checks passed
@rcj1
rcj1 deleted the copilot/implement-markdebugger-methods branch April 23, 2026 22:11
@github-actionsgithub-actionsBot locked and limited conversation to collaborators May 24, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@rcj1@noahfalk@jkotas@davidwrighton@max-charlamb@teo-tsirpanis