Skip to content

Add design document for stub target debug data#124035

Draft
Copilot wants to merge 3 commits intomainfrom
copilot/add-stub-target-data
Draft

Add design document for stub target debug data#124035
Copilot wants to merge 3 commits intomainfrom
copilot/add-stub-target-data

Conversation

Copy link
Contributor

Copilot AI commented Feb 5, 2026

Description

Proposes declarative debug data for stubs to simplify debugger stepping. Current approach requires each StubManager to implement bespoke prediction logic that must understand stub internals and can fail in restricted contexts (locks, GC no-trigger regions).

Changes

  • Design document at docs/design/coreclr/stub-target-debug-data-design.md

    • Surveys 11 existing StubManager types (ThePreStubManager, ILStubManager, VirtualCallStubManager, etc.)
    • Documents 3 stub generation mechanisms: ILStubs (IL-based), StubLinker (assembly), VSD (dynamic dispatch)
    • Categorizes stubs by feasibility: high (StubLinker delegates, precodes), moderate (VSD, prestub), low (multicast delegates)
  • Proposed solution: Store instruction offset of branch/call to target

    • Hybrid approach: Extend Stub class for StubLinker stubs, leverage JIT debug info for ILStubs
    • New UniversalStubManager reads debug data and sets breakpoint at recorded instruction
    • 5-phase implementation plan (weeks 1-10)
  • Open questions (13 total):

    • VSD performance impact on hot path
    • Handling multiple call sites per stub
    • Cross-platform debug data format
    • DAC marshaling and out-of-process debugger API

Example of proposed Stub class extension:

class Stub {
    enum { DEBUG_DATA_BIT = 0x08000000 };
    
    bool HasTargetDebugData() const {
        return (m_numCodeBytesAndFlags & DEBUG_DATA_BIT) != 0;
    }
    
    uint32_t GetTargetCallOffset() const {
        uint32_t* pData = (uint32_t*)(GetBlob() + GetNumCodeBytes());
        return *pData;
    }
};

Ready for team review and feedback before prototype implementation.

Original prompt

This section details on the original issue you should resolve

<issue_title>Add stub target debug data</issue_title>
<issue_description>### Background

In the runtime we have a variety of 'stubs' which tend to be little adapter methods that do some setup work and then branch/call to some other target method. Some of these code bodies are generated from IL using ILStubs or TransientIL. Others are generated directly in assembly code using the StubLinker. When a developer is doing managed debugging and stepping through code they may need to traverse some of these stubs. Unlike normal managed methods where we'd show the debugger user the code after each step and let them decide whether to step in/over/out stubs are considered runtime implementation details that we want to step through automatically as if they weren't present. For example C# source code might show that method A calls method B but in the generated assembly method A calls Stub X and Stub X calls B. When a user has a debugging session stopped on the source line where A is about to call B and steps in we want the debugger to automatically step through Stub X and arrive at B before breaking in the debugger once again.

In order to implement this automatic stub stepping behavior we have a set of components called StubManagers that recognize different kinds of stubs and predict the code path they will take when executed. This allows the debugger to step through a stub repeatedly asking for a prediction, setting a breakpoint at the predicted location, and then executing until the breakpoint is hit. Eventually one of the predictions will be the address of a non-stub method where the stepping operation can complete.

The challenge

These stub managers need particularized understanding of each type of stub in order to recognize them and anticipate their future execution behavior. There is a complexity and maintainance cost to keep them in sync with the stub code generators. The logic that runs within the StubManagers to predict forward execution can also be non-trivial which is a problem if the breakpoints occur inside locks or in GC no-trigger regions where the logic may not be legal to run. Last we'd like to make progress towards making stepping (and all execution control) more compatible with out-of-process debuggers that would benefit from being able to follow simple declarative stepping patterns.

A potential solution to explore

Rather than have each StubManager implement bespoke stub-prediction logic we'd instead like to store a piece of debug data for each stub that records the address of the stub instruction which branches/calls to the target method. Then a single general purpose StubManager could recognize all stubs which implement this pattern. Prediction becomes easy, the StubManager reads the debug data and predicts execution will go to the recorded address. Once execution reaches that address the debugger can single-step to either arrive at the final method or arrive at another stub where the process repeats.

At this point the proposal is just a general idea that needs to be explored to determine how many of our stubs could accomodate this pattern and how difficult is it to generate the debug data.</issue_description>

<agent_instructions>As a first step I want you to survey the existing stubs, consider options for how the debug data could be generated + stored, and write your findings in an initial draft of a design document. If you have questions please include them in the design document as well. We will iterate on a design before writing the code.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: noahfalk <6243776+noahfalk@users.noreply.github.com>
Copilot AI changed the title [WIP] Add stub target debug data for managed debugging Add design document for stub target debug data Feb 5, 2026
Copilot AI requested a review from noahfalk February 5, 2026 10:01
@github-actions github-actions bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Feb 6, 2026
@noahfalk
Copy link
Member

noahfalk commented Feb 7, 2026

@jkotas - I iterated a little offline with copilot. The design is still incomplete/rough but I think it points in a better direction than the original one did. Getting to a final design that we'd want to implement still seems like more work is required, especially since doing a nice job on the inlining increases the complexity. What I'd like to do is just bank the progress thus far and put this on the shelf until we have a more urgent need to move it forward. I acknowledge right at the top of the doc that the design isn't done to try and avoid anyone else trying to run with it as-is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add stub target debug data

3 participants