From 4540874d18afb10d286b919aff9d6f58b72a95cc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 16:13:33 +0000 Subject: [PATCH 1/2] Initial plan From 3e5b8e09200422b50119b57efe58c572824f3b65 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 16:19:53 +0000 Subject: [PATCH 2/2] Add tracking issue doc for tail-call stepping in R2R assemblies Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com> --- .../tailcall-stepping-r2r-tracking-issue.md | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 docs/design/coreclr/tailcall-stepping-r2r-tracking-issue.md diff --git a/docs/design/coreclr/tailcall-stepping-r2r-tracking-issue.md b/docs/design/coreclr/tailcall-stepping-r2r-tracking-issue.md new file mode 100644 index 00000000000000..ffa435f902088f --- /dev/null +++ b/docs/design/coreclr/tailcall-stepping-r2r-tracking-issue.md @@ -0,0 +1,58 @@ +# Tracking Issue: Tail-call stepping correctness in ReadyToRun assemblies + +## Description + +The `IsTailCall` function in `src/coreclr/debug/ee/controller.cpp` assumes that given a call IP, we can immediately determine the destination `MethodDesc` that will be invoked. However, this assumption breaks for cross ReadyToRun (R2R) image tail calls. + +Specifically, if ReadyToRun image A has method `Foo1()` which tail-calls to `Foo2()` in image B, then `Foo1()` may have a call to one of the tail-call helpers at the end that is indirected through an `ExternalMethodFixup`. The `StubManager` for `ExternalMethodFixup` does not immediately figure out the destination `MethodDesc` - it uses callbacks that pass content to `TraceManager()` to determine where execution will go next. + +This means the debugger may not correctly handle stepping through tail calls that cross ReadyToRun image boundaries. + +## Background + +This issue was discovered as part of PR #123640, which fixed an access violation (AV) in `IsTailCall` when `trace.GetAddress()` returns NULL. The AV was fixed by adding a NULL check before calling `GetNativeCodeMethodDesc()`, but the underlying stepping correctness issue remains. + +Related changes: +- PR #108942 introduced `TRACE_MULTICAST_DELEGATE_HELPER` trace type +- PR #108414 introduced `TRACE_EXTERNAL_METHOD_FIXUP` trace type + +These trace types set `address = NULL` by design because: +1. `TRACE_UNJITTED_METHOD` - The `MethodDesc` field describes a method that will be jitted and executed in the future, code address not yet known. +2. `TRACE_MULTICAST_DELEGATE_HELPER` and `TRACE_EXTERNAL_METHOD_FIXUP` - A callback can be turned on and the content of that callback can be passed to `TraceManager()` to determine where execution will go next. +3. Other trace types - The address is some IP that will be executed in the future where a breakpoint can be placed and then further actions taken from there. + +## Current Behavior + +When stepping through a tail call that crosses R2R image boundaries (via `ExternalMethodFixup`), the debugger may not correctly step into the target method because `IsTailCall` cannot determine the destination `MethodDesc` at the time of the call. + +## Expected Behavior + +The debugger should correctly step through tail calls regardless of whether they cross ReadyToRun image boundaries. + +## Affected Code + +- `src/coreclr/debug/ee/controller.cpp` - `IsTailCall` function (lines ~5820-5860) +- `src/coreclr/vm/stubmgr.cpp` - `ExternalMethodFixupStubManager` + +## Potential Solutions + +This will require redesigning how `IsTailCall` determines the target method for calls that go through `ExternalMethodFixup` stubs. Possible approaches include: +1. Enhancing the `StubManager` to provide target method information for `ExternalMethodFixup` +2. Using the callback mechanism (`TraceManager()`) within `IsTailCall` to resolve the target +3. Special-casing R2R cross-image tail calls in the stepping logic + +## References + +- PR #123640 - Fix AV in IsTailCall by checking for NULL trace address +- PR #108942 - Introduced `TRACE_MULTICAST_DELEGATE_HELPER` trace type +- PR #108414 - Introduced `TRACE_EXTERNAL_METHOD_FIXUP` trace type +- [Comment discussion](https://github.com/dotnet/runtime/pull/123640#issuecomment-3803767807) + +## Labels + +- `area-Diagnostics-coreclr` +- `bug` + +## Assignees + +cc @noahfalk @lateralusX @rcj1