Skip to content

[cDAC] Implement SetCompilerFlags for cDAC#127244

Merged
barosiak merged 7 commits intomainfrom
copilot/implement-set-compiler-flags
Apr 23, 2026
Merged

[cDAC] Implement SetCompilerFlags for cDAC#127244
barosiak merged 7 commits intomainfrom
copilot/implement-set-compiler-flags

Conversation

@barosiak
Copy link
Copy Markdown
Member

@barosiak barosiak commented Apr 21, 2026

Summary

Implement SetCompilerFlags in cDAC DacDbiImpl using ILoader contract to set debugger assembly control flags.

Changes

  • DacDbiImpl.cs - SetCompilerFlags implementation
  • CorDbHResults.cs - Add CORDBG_S_NOT_ALL_BITS_SET success HRESULT
  • Loader contract - Add DACF_IGNORE_PDBS flag and EncCapable module flag
  • ProfControlBlock - Expose MainProfilerProfInterface and NotificationProfilerCount fields (data descriptors + docs)
  • DacDbiImplTests.cs - Add 8 test cases covering both flags set/unset, EnC precondition failures (not capable, no PDBs ignored, profiler present), and JIT opts toggling across architectures

Copilot AI and others added 3 commits April 20, 2026 21:36
Replace the legacy-delegation stub with a contract-based implementation
that:
- Gets the ILoader contract and resolves the assembly pointer to a
  ModuleHandle
- Reads current debugger info bits, clears DACF_ALLOW_JIT_OPTS and
  DACF_ENC_ENABLED, masks with DACF_CONTROL_FLAGS_MASK
- Conditionally ORs in the requested flags
- Delegates to SetDebuggerInfoBits which handles EncCapable check,
  JIT optimization disabled state, and EditAndContinue flag logic
- Returns CORDBG_S_NOT_ALL_BITS_SET if EnC was requested but could
  not be enabled
- Includes #if DEBUG legacy validation block

Add CORDBG_S_NOT_ALL_BITS_SET constant to CorDbgHResults.

Add unit tests covering: both flags set (EnC capable), both flags
unset, EnC requested but not capable, and JIT opts toggling.

Agent-Logs-Url: https://github.com/dotnet/runtime/sessions/0d4cb517-9044-4d94-902e-a91169e2d2f5

Co-authored-by: barosiak <76071368+barosiak@users.noreply.github.com>
@barosiak barosiak self-assigned this Apr 21, 2026
Copilot AI review requested due to automatic review settings April 21, 2026 21:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Implements SetCompilerFlags in the cDAC DacDbiImpl using the ILoader contract to update debugger assembly control flags and adds coverage/tests and a missing success HRESULT constant to match native DAC semantics.

Changes:

  • Implement DacDbiImpl.SetCompilerFlags via ILoader and return CORDBG_S_NOT_ALL_BITS_SET when EnC cannot be enabled.
  • Add CORDBG_S_NOT_ALL_BITS_SET to CorDbgHResults.
  • Add SetCompilerFlagsTests covering flag set/unset and EnC capability behavior across architectures.

Reviewed changes

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

File Description
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs Adds SetCompilerFlags implementation using ILoader and post-write EnC enablement check
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CorDbHResults.cs Adds missing CORDBG_S_NOT_ALL_BITS_SET HRESULT constant
src/native/managed/cdac/tests/LoaderTests.cs Adds new test coverage for SetCompilerFlags behavior

@github-actions

This comment has been minimized.

Comment thread src/native/managed/cdac/tests/LoaderTests.cs Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 12 out of 12 changed files in this pull request and generated 1 comment.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 23, 2026 18:03
@barosiak
Copy link
Copy Markdown
Member Author

/ba-g unrelated failures and style fix, no need to re-run

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 12 out of 12 changed files in this pull request and generated 2 comments.

@github-actions
Copy link
Copy Markdown
Contributor

🤖 Copilot Code Review — PR #127244

Note

This review was generated by Copilot and reflects an automated analysis. Multi-model review used: Claude Opus 4.6 (primary) + Claude Sonnet 4.5 (secondary). A GPT-5.3-Codex agent was also launched but did not complete within the timeout window.

Holistic Assessment

Motivation: This PR replaces several legacy DAC delegation stubs in DacDbiImpl with contract-based implementations — part of the ongoing cDAC migration effort. The implementations for SetCompilerFlags, GetCompilerFlags, GetModuleData, IsModuleMapped, and IsDiagnosticsHiddenOrLCGMethod are all well-motivated and follow the established cDAC pattern.

Approach: The approach is sound. Each method follows the cDAC pattern: try-catch for HResult conversion, use of contracts (ILoader, IRuntimeTypeSystem), and #if DEBUG legacy validation. The TryGetPEImage refactoring properly deduplicates code. The IsMapped Webcil fix, DACF_IGNORE_PDBS addition, and loader heap traversal APIs are logical supporting changes.

Summary: ✅ LGTM. The implementations correctly match their native C++ counterparts. I verified SetCompilerFlags against DacDbiInterfaceImpl::SetCompilerFlags/CanSetEnCBits, GetCompilerFlags against the native's AreJITOptimizationsDisabled/IsEditAndContinueEnabled, and IsDiagnosticsHiddenOrLCGMethod against IsDiagnosticsHidden/IsLCGMethod. All match. Test coverage is solid for the core SetCompilerFlags logic with 8 test cases covering the key scenarios. Two minor observations below.


Detailed Findings

✅ SetCompilerFlags — Correct match to native logic

Verified against dacdbiimpl.cpp:767-813. The cDAC faithfully reproduces the native behavior:

  • Clears DACF_ALLOW_JIT_OPTS and DACF_ENC_ENABLED, masks with DACF_CONTROL_FLAGS_MASK
  • The canSetEnC check matches CanSetEnCBits(): EncCapable + !CORProfilerPresent + fIgnorePdbs
  • CORProfilerPresent() gracefully handles missing ProfilerControlBlock global (profiling not supported), matching #ifdef PROFILING_SUPPORTED_DATA in native
  • BOOL parameter handling (!= Interop.BOOL.FALSE) correctly follows the recommended pattern for COM BOOL interop

One sub-agent flagged the exception handler overwriting hr = CORDBG_S_NOT_ALL_BITS_SET if SetDebuggerInfoBits throws. I evaluated this and it is not a bug — the native code has identical behavior (the EX_CATCH_HRESULT(hr) macro would similarly overwrite hr), and if the flag write fails, the error should indeed take precedence over the warning.

✅ GetCompilerFlags — Semantics match native

The native reads AreJITOptimizationsDisabled() (checks IS_JIT_OPTIMIZATION_DISABLED module flag) and IsEditAndContinueEnabled() (checks IS_EDIT_AND_CONTINUE module flag). The cDAC reads ModuleFlags.JitOptimizationDisabled and ModuleFlags.EditAndContinue respectively — these map to the same underlying bits. The inversion of JIT opts (Disabled == 0 → AllowJITOpts = TRUE) is correct.

✅ IsDiagnosticsHiddenOrLCGMethod — Logic correctly handles ordering

The native IsDiagnosticsHidden() = IsILStub() || IsAsyncThunkMethod() || IsWrapperStub(), and IsLCGMethod() = IsDynamicMethod() && !IsILStub(). The cDAC checks these in the same priority order, so the else if (IsDynamicMethod) branch naturally excludes IL stubs. Correct.

✅ IsModuleMapped — Matches native S_FALSE/S_OK semantics

The native (dacdbiimpl.cpp:4170-4192) defaults to S_FALSE, returning S_OK only when HasLoadedPEImage() is true. The cDAC mirrors this with TryGetLoadedImageContents as the equivalent check. The IsMapped Webcil fix (Format == Webcil → false) is also correct.

✅ TryGetPEImage refactoring — Clean deduplication

The extracted TryGetPEImage helper eliminates the duplicated PEAssembly→PEImage traversal from TryGetLoadedImageContents, IsModuleMapped, and IsProbeExtensionResultValid. Good use of [NotNullWhen(true)].

✅ EnumerateThreads signature improvement

Changing nint fpCallback to delegate* unmanaged<ulong, nint, void> fpCallback improves type safety and eliminates the manual cast. The null check for fpCallback is a good addition.

💡 CORProfilerPresent — String literals for field names

CORProfilerPresent() uses string literals "MainProfilerProfInterface" and "NotificationProfilerCount" instead of nameof(Data.ProfControlBlock.MainProfilerProfInterface). While functional, using nameof would catch field renames at compile time. This is a minor consistency point — other code in DacDbiImpl uses string literals in similar contexts, so this follows existing convention.

💡 Test coverage — Minor gaps for non-SetCompilerFlags methods

The new DacDbiImplTests.cs has excellent coverage for SetCompilerFlags (8 test cases including profiler blocking, EnC capability, and JIT opts toggling) and GetCompilerFlags (5 data-driven cases). IsModuleMapped has Loader-level tests in LoaderTests.cs. The GetModuleData and IsDiagnosticsHiddenOrLCGMethod implementations don't have DacDbi-level tests, though they do have #if DEBUG legacy validation blocks. These could be follow-up additions.

Generated by Code Review for issue #127244 ·

@barosiak
Copy link
Copy Markdown
Member Author

/ba-g unrelated failures and style fix, no need to re-run

@barosiak barosiak merged commit ef0d0bc into main Apr 23, 2026
34 of 105 checks passed
@barosiak barosiak deleted the copilot/implement-set-compiler-flags branch April 23, 2026 18:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants