From 18f05b74e0391836647ce7645db7a03488faa5c1 Mon Sep 17 00:00:00 2001 From: Adeel <3840695+am11@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:00:07 +0300 Subject: [PATCH 1/8] Make UCO MethodDesc globals DAC-accessible --- src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp | 11 +++++++++++ src/coreclr/debug/di/rsstackwalk.cpp | 5 +++++ src/coreclr/debug/ee/controller.cpp | 6 ++++++ src/coreclr/debug/inc/dacdbiinterface.h | 1 + src/coreclr/inc/dacvars.h | 2 ++ src/coreclr/vm/assembly.cpp | 2 -- src/coreclr/vm/debugdebugger.cpp | 2 -- src/coreclr/vm/eepolicy.cpp | 4 +--- src/coreclr/vm/exceptionhandling.cpp | 1 - src/coreclr/vm/proftoeeinterfaceimpl.cpp | 8 ++++++++ src/coreclr/vm/vars.cpp | 2 ++ src/coreclr/vm/vars.hpp | 2 ++ 12 files changed, 38 insertions(+), 8 deletions(-) diff --git a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp index 4450a7df8384ef..1542c8906ab7a8 100644 --- a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp @@ -307,6 +307,12 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::UnwindStackWalkFrame(StackWalkHan continue; } + // Runtime-invoked UCO entrypoint method (Environment.CallEntryPoint) + if (pMD == g_pEnvironmentCallEntryPointMethodDesc) + { + continue; + } + fIsAtEndOfStack = FALSE; } else @@ -421,6 +427,11 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetStackWalkCurrentFrameInfo(Stac { ftResult = kManagedExceptionHandlingCodeFrame; } + // Runtime-invoked UCO entrypoint method (Environment.CallEntryPoint) + else if (pMD == g_pEnvironmentCallEntryPointMethodDesc) + { + ftResult = kRuntimeEntryPointFrame; + } else { ftResult = kManagedStackFrame; diff --git a/src/coreclr/debug/di/rsstackwalk.cpp b/src/coreclr/debug/di/rsstackwalk.cpp index 23cf231eab5cbc..5a6e7cf629935f 100644 --- a/src/coreclr/debug/di/rsstackwalk.cpp +++ b/src/coreclr/debug/di/rsstackwalk.cpp @@ -602,6 +602,11 @@ HRESULT CordbStackWalk::GetFrameWorker(ICorDebugFrame ** ppFrame) STRESS_LOG1(LF_CORDB, LL_INFO1000, "CSW::GFW - managed exception handling code frame (%p)", this); return S_FALSE; } + else if (ft == IDacDbiInterface::kRuntimeEntryPointFrame) + { + STRESS_LOG1(LF_CORDB, LL_INFO1000, "CSW::GFW - runtime entry point frame (%p)", this); + return S_FALSE; + } else if (ft == IDacDbiInterface::kExplicitFrame) { STRESS_LOG1(LF_CORDB, LL_INFO1000, "CSW::GFW - explicit frame (%p)", this); diff --git a/src/coreclr/debug/ee/controller.cpp b/src/coreclr/debug/ee/controller.cpp index 72b0360c53c3d4..5902a7dcbf0893 100644 --- a/src/coreclr/debug/ee/controller.cpp +++ b/src/coreclr/debug/ee/controller.cpp @@ -6775,6 +6775,12 @@ bool DebuggerStepper::IsInterestingFrame(FrameInfo * pFrame) { return false; } + + // Ignore runtime-invoked UCO entrypoint method (Environment.CallEntryPoint) + if (pFrame->md == g_pEnvironmentCallEntryPointMethodDesc) + { + return false; + } } return true; diff --git a/src/coreclr/debug/inc/dacdbiinterface.h b/src/coreclr/debug/inc/dacdbiinterface.h index 5660b92b11e05e..101670e207892d 100644 --- a/src/coreclr/debug/inc/dacdbiinterface.h +++ b/src/coreclr/debug/inc/dacdbiinterface.h @@ -1231,6 +1231,7 @@ IDacDbiInterface : public IUnknown kNativeStackFrame, kNativeRuntimeUnwindableStackFrame, kManagedExceptionHandlingCodeFrame, + kRuntimeEntryPointFrame, kAtEndOfStack, } FrameType; diff --git a/src/coreclr/inc/dacvars.h b/src/coreclr/inc/dacvars.h index e3265d520b9632..0b07ee0ceb0b15 100644 --- a/src/coreclr/inc/dacvars.h +++ b/src/coreclr/inc/dacvars.h @@ -125,6 +125,8 @@ DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pEHClass, ::g_pEHClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pExceptionServicesInternalCallsClass, ::g_pExceptionServicesInternalCallsClass) DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pStackFrameIteratorClass, ::g_pStackFrameIteratorClass) +DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pEnvironmentCallEntryPointMethodDesc, ::g_pEnvironmentCallEntryPointMethodDesc) + DEFINE_DACVAR(PTR_SString, SString__s_Empty, SString::s_Empty) DEFINE_DACVAR(INT32, ArrayBase__s_arrayBoundsZero, ArrayBase::s_arrayBoundsZero) diff --git a/src/coreclr/vm/assembly.cpp b/src/coreclr/vm/assembly.cpp index 5d227d37f681b0..b2a28d7b7119af 100644 --- a/src/coreclr/vm/assembly.cpp +++ b/src/coreclr/vm/assembly.cpp @@ -1165,8 +1165,6 @@ struct Param bool captureException; } param; -MethodDesc* g_pEnvironmentCallEntryPointMethodDesc = nullptr; - #if defined(TARGET_BROWSER) extern "C" void SystemJS_ResolveMainPromise(int exitCode); #endif // TARGET_BROWSER diff --git a/src/coreclr/vm/debugdebugger.cpp b/src/coreclr/vm/debugdebugger.cpp index 9b11ac63280df3..e96abc4497b250 100644 --- a/src/coreclr/vm/debugdebugger.cpp +++ b/src/coreclr/vm/debugdebugger.cpp @@ -32,8 +32,6 @@ #ifndef DACCESS_COMPILE -extern MethodDesc* g_pEnvironmentCallEntryPointMethodDesc; - // // Notes: // If a managed debugger is attached, this should send the managed UserBreak event. diff --git a/src/coreclr/vm/eepolicy.cpp b/src/coreclr/vm/eepolicy.cpp index 24d3e9168fbd08..f756091105964e 100644 --- a/src/coreclr/vm/eepolicy.cpp +++ b/src/coreclr/vm/eepolicy.cpp @@ -23,8 +23,6 @@ #include "eventtrace.h" #undef ExitProcess -extern MethodDesc* g_pEnvironmentCallEntryPointMethodDesc; - void SafeExitProcess(UINT exitCode, ShutdownCompleteAction sca = SCA_ExitProcessWhenShutdownComplete) { STRESS_LOG2(LF_SYNC, LL_INFO10, "SafeExitProcess: exitCode = %d sca = %d\n", exitCode, sca); @@ -180,7 +178,7 @@ class CallStackLogger MethodDesc* pMD = pCF->GetFunction(); - // Skip Environment.CallEntryPoint so it doesn't appear in vanilla + // Skip Environment.CallEntryPoint so it doesn't appear in // unhandled exception experiences. if (pMD != nullptr && pMD == g_pEnvironmentCallEntryPointMethodDesc) { diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index 5b1a222ec0227d..00f6db4a17d612 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -18,7 +18,6 @@ #include "exinfo.h" #include "configuration.h" -extern MethodDesc* g_pEnvironmentCallEntryPointMethodDesc; extern MethodDesc* g_pThreadStartCallbackMethodDesc; extern MethodDesc* g_pGCRunFinalizersMethodDesc; diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index 8869fd4f0397a4..80db7a238de12e 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -8065,6 +8065,14 @@ StackWalkAction ProfilerStackWalkCallback(CrawlFrame *pCf, PROFILER_STACK_WALK_D return SWA_CONTINUE; } + // + // Skip runtime-invoked UCO entrypoint method (Environment.CallEntryPoint) + // + if (pFunc != NULL && pFunc == g_pEnvironmentCallEntryPointMethodDesc) + { + return SWA_CONTINUE; + } + // // For Unmanaged-to-managed transitions we get a NativeMarker back, which we want // to return to the profiler as the context seed if it wants to walk the unmanaged diff --git a/src/coreclr/vm/vars.cpp b/src/coreclr/vm/vars.cpp index 02e97870b61671..a567a206749c62 100644 --- a/src/coreclr/vm/vars.cpp +++ b/src/coreclr/vm/vars.cpp @@ -112,6 +112,8 @@ GPTR_IMPL(MethodTable, g_pEHClass); GPTR_IMPL(MethodTable, g_pExceptionServicesInternalCallsClass); GPTR_IMPL(MethodTable, g_pStackFrameIteratorClass); +GPTR_IMPL(MethodDesc, g_pEnvironmentCallEntryPointMethodDesc); + GVAL_IMPL_INIT(PTR_WSTR, g_EntryAssemblyPath, NULL); #ifndef DACCESS_COMPILE diff --git a/src/coreclr/vm/vars.hpp b/src/coreclr/vm/vars.hpp index 7558c0882857da..c249db40571b90 100644 --- a/src/coreclr/vm/vars.hpp +++ b/src/coreclr/vm/vars.hpp @@ -381,6 +381,8 @@ GPTR_DECL(MethodTable, g_pEHClass); GPTR_DECL(MethodTable, g_pExceptionServicesInternalCallsClass); GPTR_DECL(MethodTable, g_pStackFrameIteratorClass); +GPTR_DECL(MethodDesc, g_pEnvironmentCallEntryPointMethodDesc); + // Full path to the managed entry assembly - stored for ease of identifying the entry asssembly for diagnostics GVAL_DECL(PTR_WSTR, g_EntryAssemblyPath); From cf9ec87c03dd2950013911bb9de4ce2385e3738f Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 14 Apr 2026 21:07:05 -0700 Subject: [PATCH 2/8] Apply suggestions from code review Co-authored-by: Jan Kotas --- src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp | 7 +++++-- src/coreclr/debug/ee/controller.cpp | 6 +++++- src/coreclr/vm/proftoeeinterfaceimpl.cpp | 8 -------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp index 1542c8906ab7a8..b04e59cf7f53ff 100644 --- a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp @@ -299,7 +299,9 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::UnwindStackWalkFrame(StackWalkHan { // Skip the new exception handling managed code, the debugger clients are not supposed to see them MethodDesc *pMD = pIter->m_crawl.GetFunction(); + MethodDesc *pMD = pIter->m_crawl.GetFunction(); + // Skip the exception handling managed code, the debugger clients are not supposed to see them // EH.DispatchEx, EH.RhThrowEx, EH.RhThrowHwEx, ExceptionServices.InternalCalls.SfiInit, ExceptionServices.InternalCalls.SfiNext // and System.Runtime.StackFrameIterator.* if (pMD->GetMethodTable() == g_pEHClass || pMD->GetMethodTable() == g_pExceptionServicesInternalCallsClass || pMD->GetMethodTable() == g_pStackFrameIteratorClass) @@ -307,7 +309,8 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::UnwindStackWalkFrame(StackWalkHan continue; } - // Runtime-invoked UCO entrypoint method (Environment.CallEntryPoint) + // Skip the runtime helper that invokes the main program entrypoint, the debuggers do not want to see it. + // Environment.CallEntryPoint if (pMD == g_pEnvironmentCallEntryPointMethodDesc) { continue; @@ -427,7 +430,7 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetStackWalkCurrentFrameInfo(Stac { ftResult = kManagedExceptionHandlingCodeFrame; } - // Runtime-invoked UCO entrypoint method (Environment.CallEntryPoint) + // Environment.CallEntryPoint else if (pMD == g_pEnvironmentCallEntryPointMethodDesc) { ftResult = kRuntimeEntryPointFrame; diff --git a/src/coreclr/debug/ee/controller.cpp b/src/coreclr/debug/ee/controller.cpp index 5902a7dcbf0893..d9721696228087 100644 --- a/src/coreclr/debug/ee/controller.cpp +++ b/src/coreclr/debug/ee/controller.cpp @@ -6769,14 +6769,18 @@ bool DebuggerStepper::IsInterestingFrame(FrameInfo * pFrame) // Ignore managed exception handling frames if (pFrame->md != NULL) + { + if (pFrame->md != NULL) { MethodTable *pMT = pFrame->md->GetMethodTable(); + + // Ignore managed exception handling frames if ((pMT == g_pEHClass) || (pMT == g_pExceptionServicesInternalCallsClass)) { return false; } - // Ignore runtime-invoked UCO entrypoint method (Environment.CallEntryPoint) + // Ignore the runtime helper that invokes the main program entrypoint if (pFrame->md == g_pEnvironmentCallEntryPointMethodDesc) { return false; diff --git a/src/coreclr/vm/proftoeeinterfaceimpl.cpp b/src/coreclr/vm/proftoeeinterfaceimpl.cpp index 80db7a238de12e..8869fd4f0397a4 100644 --- a/src/coreclr/vm/proftoeeinterfaceimpl.cpp +++ b/src/coreclr/vm/proftoeeinterfaceimpl.cpp @@ -8065,14 +8065,6 @@ StackWalkAction ProfilerStackWalkCallback(CrawlFrame *pCf, PROFILER_STACK_WALK_D return SWA_CONTINUE; } - // - // Skip runtime-invoked UCO entrypoint method (Environment.CallEntryPoint) - // - if (pFunc != NULL && pFunc == g_pEnvironmentCallEntryPointMethodDesc) - { - return SWA_CONTINUE; - } - // // For Unmanaged-to-managed transitions we get a NativeMarker back, which we want // to return to the profiler as the context seed if it wants to walk the unmanaged From fe6ce9413caa9ea4ea622d80ec3d8e1c2c3bc0ad Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 14 Apr 2026 21:07:25 -0700 Subject: [PATCH 3/8] Apply suggestion from @jkotas --- src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp index b04e59cf7f53ff..ebf7f4b6376b52 100644 --- a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp @@ -299,7 +299,6 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::UnwindStackWalkFrame(StackWalkHan { // Skip the new exception handling managed code, the debugger clients are not supposed to see them MethodDesc *pMD = pIter->m_crawl.GetFunction(); - MethodDesc *pMD = pIter->m_crawl.GetFunction(); // Skip the exception handling managed code, the debugger clients are not supposed to see them // EH.DispatchEx, EH.RhThrowEx, EH.RhThrowHwEx, ExceptionServices.InternalCalls.SfiInit, ExceptionServices.InternalCalls.SfiNext From def6290037908e4e489b578245239ba63e3e0800 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 14 Apr 2026 21:07:57 -0700 Subject: [PATCH 4/8] Apply suggestion from @jkotas --- src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp index ebf7f4b6376b52..943fe4aae5411c 100644 --- a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp @@ -297,7 +297,6 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::UnwindStackWalkFrame(StackWalkHan } else if (pIter->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD) { - // Skip the new exception handling managed code, the debugger clients are not supposed to see them MethodDesc *pMD = pIter->m_crawl.GetFunction(); // Skip the exception handling managed code, the debugger clients are not supposed to see them From 25f5bece1a3af1a4266def7943d93017b5f6c1f8 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 14 Apr 2026 21:08:38 -0700 Subject: [PATCH 5/8] Apply suggestion from @jkotas --- src/coreclr/debug/ee/controller.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/coreclr/debug/ee/controller.cpp b/src/coreclr/debug/ee/controller.cpp index d9721696228087..e933a38d784f02 100644 --- a/src/coreclr/debug/ee/controller.cpp +++ b/src/coreclr/debug/ee/controller.cpp @@ -6767,8 +6767,6 @@ bool DebuggerStepper::IsInterestingFrame(FrameInfo * pFrame) { LIMITED_METHOD_CONTRACT; - // Ignore managed exception handling frames - if (pFrame->md != NULL) { if (pFrame->md != NULL) { From 341ab296ee913ad07abb77fa1df96ea4bd153420 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 14 Apr 2026 21:09:02 -0700 Subject: [PATCH 6/8] Apply suggestion from @jkotas --- src/coreclr/debug/ee/controller.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/coreclr/debug/ee/controller.cpp b/src/coreclr/debug/ee/controller.cpp index e933a38d784f02..8c04187ee6fe60 100644 --- a/src/coreclr/debug/ee/controller.cpp +++ b/src/coreclr/debug/ee/controller.cpp @@ -6767,7 +6767,6 @@ bool DebuggerStepper::IsInterestingFrame(FrameInfo * pFrame) { LIMITED_METHOD_CONTRACT; - { if (pFrame->md != NULL) { MethodTable *pMT = pFrame->md->GetMethodTable(); From aaf379a0ebe77e75775db9ef17616c51af27a56e Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 14 Apr 2026 21:31:03 -0700 Subject: [PATCH 7/8] Update src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp --- src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp index 943fe4aae5411c..837ceb996d0842 100644 --- a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp @@ -298,6 +298,7 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::UnwindStackWalkFrame(StackWalkHan else if (pIter->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD) { MethodDesc *pMD = pIter->m_crawl.GetFunction(); + MethodTable *pMT = pMD->GetMethodTable(); // Skip the exception handling managed code, the debugger clients are not supposed to see them // EH.DispatchEx, EH.RhThrowEx, EH.RhThrowHwEx, ExceptionServices.InternalCalls.SfiInit, ExceptionServices.InternalCalls.SfiNext From 1210a25fe666400660986d4bb26ba6385ca848f5 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Tue, 14 Apr 2026 21:31:10 -0700 Subject: [PATCH 8/8] Update src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp --- src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp index 837ceb996d0842..1c874152bf706d 100644 --- a/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp +++ b/src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp @@ -303,7 +303,7 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::UnwindStackWalkFrame(StackWalkHan // Skip the exception handling managed code, the debugger clients are not supposed to see them // EH.DispatchEx, EH.RhThrowEx, EH.RhThrowHwEx, ExceptionServices.InternalCalls.SfiInit, ExceptionServices.InternalCalls.SfiNext // and System.Runtime.StackFrameIterator.* - if (pMD->GetMethodTable() == g_pEHClass || pMD->GetMethodTable() == g_pExceptionServicesInternalCallsClass || pMD->GetMethodTable() == g_pStackFrameIteratorClass) + if (pMT == g_pEHClass || pMT == g_pExceptionServicesInternalCallsClass || pMT == g_pStackFrameIteratorClass) { continue; }