From d76c9af8f1dafdd700979c873a333852e6ef36e6 Mon Sep 17 00:00:00 2001 From: Tom McDonald Date: Mon, 27 Jul 2026 11:50:32 -0400 Subject: [PATCH] Hide remaining managed EH helpers from the debugger stack After #130646 replaced DAC-side frame filtering with attribute-based hiding, managed exception-handling helpers that were previously hidden by class-wide DBI filtering now appear in the logical call stack (mdbg `where`, current-location, and stepping) on arm64/interpreter configurations. #130646 annotated most of these helpers but missed a few: - System.Runtime.EH.AppendExceptionStackFrameViaClasslib - System.Runtime.EH.UpdateStackTrace - System.Runtime.StackFrameIterator.Next (all three overloads) Annotate each with both [StackTraceHidden] and [DebuggerHidden], matching the convention already used by every other annotated helper in this shared code (the 8 EH.* throw/dispatch helpers, StackFrameIterator.Init, and System.Environment.CallEntryPoint). Validated on x64 and arm64: StackWalking.ExceptionStack/BigStackTest and the Exceptions suite (DivZeroTest, FirstChanceSuppressTest, ReflectionTest, TooManyTest) pass. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9db6edb0-ab23-43c8-9a18-192885f442a0 --- .../Runtime.Base/src/System/Runtime/ExceptionHandling.cs | 4 ++++ .../Runtime.Base/src/System/Runtime/StackFrameIterator.cs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs index 1ee0790037dede..7b1d9ac811835e 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs @@ -253,6 +253,8 @@ private enum RhEHFrameType RH_EH_FIRST_RETHROW_FRAME = 2, } + [StackTraceHidden] + [DebuggerHidden] private static void AppendExceptionStackFrameViaClasslib(object exception, IntPtr ip, UIntPtr sp, ref ExInfo exInfo, ref bool isFirstRethrowFrame, ref bool isFirstFrame) @@ -994,6 +996,8 @@ private static uint CalculateCodeOffset(byte* pbControlPC, in MethodRegionInfo m return codeOffset; } + [StackTraceHidden] + [DebuggerHidden] private static void UpdateStackTrace(object exceptionObj, UIntPtr curFramePtr, IntPtr ip, UIntPtr sp, ref bool isFirstRethrowFrame, ref UIntPtr prevFramePtr, ref bool isFirstFrame, ref ExInfo exInfo) { diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/StackFrameIterator.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/StackFrameIterator.cs index 1d2684dabe4009..6a9577fd935b36 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/StackFrameIterator.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/StackFrameIterator.cs @@ -68,16 +68,22 @@ internal bool Init(EH.PAL_LIMITED_CONTEXT* pStackwalkCtx, bool instructionFault return InternalCalls.RhpSfiInit(ref this, pStackwalkCtx, instructionFault, fIsExceptionIntercepted); } + [StackTraceHidden] + [DebuggerHidden] internal bool Next() { return Next(null, null, null); } + [StackTraceHidden] + [DebuggerHidden] internal bool Next(uint* uExCollideClauseIdx, bool* fIsExceptionIntercepted) { return Next(uExCollideClauseIdx, null, fIsExceptionIntercepted); } + [StackTraceHidden] + [DebuggerHidden] internal bool Next(uint* uExCollideClauseIdx, bool* fUnwoundReversePInvoke, bool* fIsExceptionIntercepted) { return InternalCalls.RhpSfiNext(ref this, uExCollideClauseIdx, fUnwoundReversePInvoke, fIsExceptionIntercepted);