Skip to content

Fix x86 DAC stack walk regression from Environment.CallEntryPoint skip#127199

Merged
tommcdon merged 2 commits intodotnet:mainfrom
tommcdon:dev/tommcdon/fix_getframeworker_x86
Apr 22, 2026
Merged

Fix x86 DAC stack walk regression from Environment.CallEntryPoint skip#127199
tommcdon merged 2 commits intodotnet:mainfrom
tommcdon:dev/tommcdon/fix_getframeworker_x86

Conversation

@tommcdon
Copy link
Copy Markdown
Member

@tommcdon tommcdon commented Apr 21, 2026

Found using internal VS testing, any DBI stack walk on x86 where Environment.CallEntryPoint is on the stack would produce wrong frame pointers for the frames below it (like Main). This resulted in ICorDebugStackWalk enumeration on that thread would fail. It only affects x86 because that's the only architecture where GetFrameWorker unwinds one frame ahead to compute the frame pointer. On x64/arm64, the frame pointer is obtained directly without that extra unwind, so the continue skip is harmless there.

The fix is to avoid skipping Environment.CallEntryPoint in UnwindStackWalkFrame. The frame is still hidden from debugger UI via kRuntimeEntryPointFrame classification and S_FALSE return in GetFrameWorker.

Don't skip Environment.CallEntryPoint in UnwindStackWalkFrame with continue.
On x86, GetFrameWorker unwinds one frame ahead to compute the frame pointer.
Skipping this frame produces an incorrect frame pointer for the caller,
breaking post-step stack walks (NoCurrentFrameException).

The frame is still hidden from debugger UI via kRuntimeEntryPointFrame
classification and S_FALSE return in GetFrameWorker.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@tommcdon tommcdon added this to the 11.0.0 milestone Apr 21, 2026
@tommcdon tommcdon requested review from jkotas and noahfalk April 21, 2026 02:25
@tommcdon tommcdon self-assigned this Apr 21, 2026
Copilot AI review requested due to automatic review settings April 21, 2026 02:25
@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.

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

Fixes an x86-specific DAC/DBI stack-walking regression where skipping Environment.CallEntryPoint during unwind caused the x86 “one-frame-ahead” unwind to compute an incorrect caller frame pointer (breaking ICorDebugStackWalk enumeration).

Changes:

  • Stop skipping Environment.CallEntryPoint in DacDbiInterfaceImpl::UnwindStackWalkFrame so the x86 extra-unwind lands on the correct frame.
  • Document why the frame must remain in the internal enumeration and how it remains hidden (classified as kRuntimeEntryPointFrame and filtered by GetFrameWorker returning S_FALSE).

Comment thread src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp Outdated
Comment thread src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp Outdated
Address jkotas feedback: the same x86 GetFrameWorker one-frame-ahead
reasoning applies to exception handling frames. Move all runtime-internal
frame hiding to GetStackWalkCurrentFrameInfo + GetFrameWorker(S_FALSE).

Also add g_pStackFrameIteratorClass to GetStackWalkCurrentFrameInfo
classification, which was previously only handled by the continue skip.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

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

Thanks!

@tommcdon
Copy link
Copy Markdown
Member Author

/ba-g failures are unrelated

@tommcdon tommcdon merged commit e24fb47 into dotnet:main Apr 22, 2026
105 of 115 checks passed
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.

4 participants