Skip to content

Conversation

@matouskozak
Copy link
Member

@matouskozak matouskozak commented Nov 24, 2025

This PR implements support for setting and handling user breakpoints (System.Diagnostics.Debugger.Break()) in interpreted code. Regular breakpoints, stepping, etc. are not covered by these changes.

Key Changes

Execution Control Abstraction (executioncontrol.h/cpp)

  • Introduced IExecutionControl interface to abstract breakpoint operations across different execution strategies. Currently just for interpreter but will be extended to other codegens.
  • Implemented InterpreterExecutionControl class for interpreter-specific bytecode patching
  • ApplyPatch(): Replaces bytecode instruction with INTOP_BREAKPOINT opcode
  • UnapplyPatch(): Restores original bytecode instruction

Patch Mechanism:

  • Interpreter breakpoints work by patching bytecode directly with INTOP_BREAKPOINT instruction
  • Original opcode is saved in the patch structure for restoration

Breakpoint Flow:

  1. Interpreter hits INTOP_BREAKPOINT opcode
  2. Interpreter context is prepared and is called FirstChanceNativeException()
  3. Debugger controller dispatches to appropriate breakpoint handler
  4. Original opcode is restored during patch skip activation

Notes

  • JITComplete notification handling needs revisiting for interpreter code. I've disabled it for now as it wasn't needed for user breakpoints and when left enabled it would break the execution, likely due to patches being applied to interpreter execution loop code.

Testing

  • Verified locally (macOS m2) using debugger tests that no new regressions are introduced for debugging with JIT
  • For interpreter, debugger tests do not bring any meaningful results as of now due to missing regular breakpoint support.
  • Validated using a sample console app running with interpreter
image

Future work

@matouskozak matouskozak added NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) area-System.Diagnostics-coreclr labels Nov 24, 2025
@matouskozak matouskozak force-pushed the prototype-interp-user-breakpoints branch from 0d9c6bc to 5b087e1 Compare November 25, 2025 18:45
@matouskozak matouskozak changed the title [WIP][clr-interp] Add User Breakpoint Support for Interpreter Debugging [clr-interp] Add User Breakpoint Support for Interpreter Debugging Nov 27, 2025
@kotlarmilos kotlarmilos self-requested a review November 27, 2025 10:04
@matouskozak matouskozak removed the NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) label Dec 3, 2025
@matouskozak matouskozak marked this pull request as ready for review December 3, 2025 11:20
Copy link
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

This PR implements support for user breakpoints (System.Diagnostics.Debugger.Break()) in interpreted code by introducing an execution control abstraction layer. The implementation uses bytecode patching to replace interpreter instructions with INTOP_BREAKPOINT opcodes.

Key Changes

  • Introduced IExecutionControl interface and InterpreterExecutionControl implementation for bytecode patching
  • Modified debugger controller to delegate patch operations to execution control for interpreter code
  • Implemented GetFunctionSize for InterpreterCodeManager to support debugger operations
  • Disabled JITComplete notification for interpreter code as a temporary workaround
  • Added frame filtering to prevent interpreter frames from being treated as managed frames during stack walks

Reviewed changes

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

Show a summary per file
File Description
src/coreclr/debug/ee/executioncontrol.h Defines IExecutionControl interface and InterpreterExecutionControl class for bytecode patching abstraction
src/coreclr/debug/ee/executioncontrol.cpp Implements bytecode patch application/removal by replacing opcodes with INTOP_BREAKPOINT
src/coreclr/debug/ee/controller.h Adds include for execution control header
src/coreclr/debug/ee/controller.cpp Modifies ApplyPatch/UnapplyPatch to delegate to execution control for interpreter code
src/coreclr/debug/ee/frameinfo.cpp Filters out interpreter frames from debugger stack walks
src/coreclr/debug/ee/CMakeLists.txt Adds new execution control source files to build
src/coreclr/vm/codeman.h Adds virtual GetExecutionControl() method to IJitManager and overrides for InterpreterJitManager
src/coreclr/vm/codeman.cpp Implements GetExecutionControl() and includes execution control header
src/coreclr/vm/jitinterface.cpp Temporarily disables JITComplete notification for interpreter code
src/coreclr/vm/interpexec.cpp Implements InterpBreakpoint handler that notifies debugger of breakpoint via exception mechanism
src/coreclr/vm/eetwain.cpp Implements GetFunctionSize for interpreter code manager using GC info decoder

@janvorli janvorli requested a review from jkotas December 3, 2025 15:46
@matouskozak matouskozak force-pushed the prototype-interp-user-breakpoints branch from 23ad599 to 4751352 Compare December 4, 2025 10:33
Copy link
Member

@janvorli janvorli left a comment

Choose a reason for hiding this comment

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

LGTM, thank you!

@matouskozak
Copy link
Member Author

Merging, future work is tracked in #120842

@matouskozak matouskozak merged commit f0b1041 into dotnet:main Dec 11, 2025
97 of 99 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators Jan 11, 2026
Sign up for free to 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.

7 participants