diff --git a/src/coreclr/inc/vptr_list.h b/src/coreclr/inc/vptr_list.h index 8150147bfa2cb..f0d686f139cea 100644 --- a/src/coreclr/inc/vptr_list.h +++ b/src/coreclr/inc/vptr_list.h @@ -55,6 +55,9 @@ VPTR_CLASS(DebuggerSecurityCodeMarkFrame) VPTR_CLASS(DebuggerExitFrame) VPTR_CLASS(DebuggerU2MCatchHandlerFrame) VPTR_CLASS(FaultingExceptionFrame) +#ifdef FEATURE_EH_FUNCLETS +VPTR_CLASS(SoftwareExceptionFrame) +#endif // FEATURE_EH_FUNCLETS VPTR_CLASS(FuncEvalFrame) VPTR_CLASS(HelperMethodFrame) VPTR_CLASS(HelperMethodFrame_1OBJ) diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index 8418202b93389..ece90cbda507b 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -11553,3 +11553,79 @@ MethodDesc * GetUserMethodForILStub(Thread * pThread, UINT_PTR uStubSP, MethodDe #endif // FEATURE_COMINTEROP return pUserMD; } + + +#ifdef FEATURE_EH_FUNCLETS + +void SoftwareExceptionFrame::UpdateRegDisplay(const PREGDISPLAY pRD, bool updateFloats) +{ + LIMITED_METHOD_DAC_CONTRACT; + +#define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContext->regname = *dac_cast((TADDR)m_ContextPointers.regname); + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + +#define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContextPointers->regname = m_ContextPointers.regname; + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + +#define CALLEE_SAVED_REGISTER(regname) pRD->pCurrentContext->regname = m_Context.regname; + ENUM_FP_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + + SetIP(pRD->pCurrentContext, ::GetIP(&m_Context)); + SetSP(pRD->pCurrentContext, ::GetSP(&m_Context)); + + pRD->ControlPC = ::GetIP(&m_Context); + pRD->SP = ::GetSP(&m_Context); + + pRD->IsCallerContextValid = FALSE; + pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary. +} + +#ifndef DACCESS_COMPILE +// +// Init a new frame +// +void SoftwareExceptionFrame::Init() +{ + WRAPPER_NO_CONTRACT; + +#define CALLEE_SAVED_REGISTER(regname) m_ContextPointers.regname = NULL; + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + +#ifndef TARGET_UNIX + Thread::VirtualUnwindCallFrame(&m_Context, &m_ContextPointers); +#else // !TARGET_UNIX + BOOL success = PAL_VirtualUnwind(&m_Context, &m_ContextPointers); + if (!success) + { + _ASSERTE(!"SoftwareExceptionFrame::Init failed"); + EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE); + } +#endif // !TARGET_UNIX + +#define CALLEE_SAVED_REGISTER(regname) if (m_ContextPointers.regname == NULL) m_ContextPointers.regname = &m_Context.regname; + ENUM_CALLEE_SAVED_REGISTERS(); +#undef CALLEE_SAVED_REGISTER + + _ASSERTE(ExecutionManager::IsManagedCode(::GetIP(&m_Context))); + + m_ReturnAddress = ::GetIP(&m_Context); +} + +// +// Init and Link in a new frame +// +void SoftwareExceptionFrame::InitAndLink(Thread *pThread) +{ + WRAPPER_NO_CONTRACT; + + Init(); + + Push(pThread); +} + +#endif // DACCESS_COMPILE +#endif // FEATURE_EH_FUNCLETS diff --git a/src/coreclr/vm/frames.h b/src/coreclr/vm/frames.h index 8031a94dce557..071a96c8301b6 100644 --- a/src/coreclr/vm/frames.h +++ b/src/coreclr/vm/frames.h @@ -190,6 +190,9 @@ FRAME_TYPE_NAME(ResumableFrame) FRAME_TYPE_NAME(RedirectedThreadFrame) #endif // FEATURE_HIJACK FRAME_TYPE_NAME(FaultingExceptionFrame) +#ifdef FEATURE_EH_FUNCLETS +FRAME_TYPE_NAME(SoftwareExceptionFrame) +#endif // FEATURE_EH_FUNCLETS #ifdef DEBUGGING_SUPPORTED FRAME_TYPE_NAME(FuncEvalFrame) #endif // DEBUGGING_SUPPORTED @@ -1146,6 +1149,69 @@ class FaultingExceptionFrame : public Frame DEFINE_VTABLE_GETTER_AND_DTOR(FaultingExceptionFrame) }; +#ifdef FEATURE_EH_FUNCLETS + +class SoftwareExceptionFrame : public Frame +{ + TADDR m_ReturnAddress; + T_CONTEXT m_Context; + T_KNONVOLATILE_CONTEXT_POINTERS m_ContextPointers; + + VPTR_VTABLE_CLASS(SoftwareExceptionFrame, Frame) + +public: +#ifndef DACCESS_COMPILE + SoftwareExceptionFrame() { + LIMITED_METHOD_CONTRACT; + } +#endif + + virtual TADDR GetReturnAddressPtr() + { + LIMITED_METHOD_DAC_CONTRACT; + return PTR_HOST_MEMBER_TADDR(SoftwareExceptionFrame, this, m_ReturnAddress); + } + + void Init(); + void InitAndLink(Thread *pThread); + + Interception GetInterception() + { + LIMITED_METHOD_DAC_CONTRACT; + return INTERCEPTION_EXCEPTION; + } + + virtual ETransitionType GetTransitionType() + { + LIMITED_METHOD_DAC_CONTRACT; + return TT_InternalCall; + } + + unsigned GetFrameAttribs() + { + LIMITED_METHOD_DAC_CONTRACT; + return FRAME_ATTR_EXCEPTION; + } + + T_CONTEXT* GetContext() + { + LIMITED_METHOD_DAC_CONTRACT; + return &m_Context; + } + + virtual BOOL NeedsUpdateRegDisplay() + { + return TRUE; + } + + virtual void UpdateRegDisplay(const PREGDISPLAY, bool updateFloats = false); + + // Keep as last entry in class + DEFINE_VTABLE_GETTER_AND_DTOR(SoftwareExceptionFrame) +}; + +#endif // FEATURE_EH_FUNCLETS + //----------------------------------------------------------------------- // Frame for debugger function evaluation // @@ -3190,6 +3256,7 @@ class FrameWithCookie void Poll() { WRAPPER_NO_CONTRACT; m_frame.Poll(); } void SetStackPointerPtr(TADDR sp) { WRAPPER_NO_CONTRACT; m_frame.SetStackPointerPtr(sp); } void InitAndLink(T_CONTEXT *pContext) { WRAPPER_NO_CONTRACT; m_frame.InitAndLink(pContext); } + void InitAndLink(Thread *pThread) { WRAPPER_NO_CONTRACT; m_frame.InitAndLink(pThread); } void Init(Thread *pThread, OBJECTREF *pObjRefs, UINT numObjRefs, BOOL maybeInterior) { WRAPPER_NO_CONTRACT; m_frame.Init(pThread, pObjRefs, numObjRefs, maybeInterior); } ValueClassInfo ** GetValueClassInfoList() { WRAPPER_NO_CONTRACT; return m_frame.GetValueClassInfoList(); } diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 5438a2a92e959..5b617b8e1d013 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -2675,65 +2675,68 @@ HCIMPLEND /*************************************************************/ -#ifdef FEATURE_EH_FUNCLETS -void ThrowNew(OBJECTREF oref) +HCIMPL1(void, IL_Throw, Object* obj) { - if (oref == 0) - DispatchManagedException(kNullReferenceException); - else - if (!IsException(oref->GetMethodTable())) + FCALL_CONTRACT; + + /* Make no assumptions about the current machine state */ + ResetCurrentContext(); + + FC_GC_POLL_NOT_NEEDED(); // throws always open up for GC + + OBJECTREF oref = ObjectToOBJECTREF(obj); + +#ifdef FEATURE_EH_FUNCLETS + if (g_isNewExceptionHandlingEnabled) { - GCPROTECT_BEGIN(oref); + Thread *pThread = GetThread(); - WrapNonCompliantException(&oref); + FrameWithCookie exceptionFrame; + *(&exceptionFrame)->GetGSCookiePtr() = GetProcessGSCookie(); + RtlCaptureContext(exceptionFrame.GetContext()); + exceptionFrame.InitAndLink(pThread); - GCPROTECT_END(); - } - else - { // We know that the object derives from System.Exception + FC_CAN_TRIGGER_GC(); - // If the flag indicating ForeignExceptionRaise has been set, - // then do not clear the "_stackTrace" field of the exception object. - if (GetThread()->GetExceptionState()->IsRaisingForeignException()) - { - ((EXCEPTIONREF)oref)->SetStackTraceString(NULL); - } + if (oref == 0) + DispatchManagedException(kNullReferenceException); else + if (!IsException(oref->GetMethodTable())) { - ((EXCEPTIONREF)oref)->ClearStackTracePreservingRemoteStackTrace(); - } - } + GCPROTECT_BEGIN(oref); - DispatchManagedException(oref); -} -#endif // FEATURE_EH_FUNCLETS + WrapNonCompliantException(&oref); -HCIMPL1(void, IL_Throw, Object* obj) -{ - FCALL_CONTRACT; + GCPROTECT_END(); + } + else + { // We know that the object derives from System.Exception - /* Make no assumptions about the current machine state */ - ResetCurrentContext(); + // If the flag indicating ForeignExceptionRaise has been set, + // then do not clear the "_stackTrace" field of the exception object. + if (pThread->GetExceptionState()->IsRaisingForeignException()) + { + ((EXCEPTIONREF)oref)->SetStackTraceString(NULL); + } + else + { + ((EXCEPTIONREF)oref)->ClearStackTracePreservingRemoteStackTrace(); + } + } - FC_GC_POLL_NOT_NEEDED(); // throws always open up for GC + DispatchManagedException(oref, exceptionFrame.GetContext()); + FC_CAN_TRIGGER_GC_END(); + UNREACHABLE(); + } +#endif // FEATURE_EH_FUNCLETS HELPER_METHOD_FRAME_BEGIN_ATTRIB_NOPOLL(Frame::FRAME_ATTR_EXCEPTION); // Set up a frame - OBJECTREF oref = ObjectToOBJECTREF(obj); - #if defined(_DEBUG) && defined(TARGET_X86) __helperframe.InsureInit(NULL); g_ExceptionEIP = (LPVOID)__helperframe.GetReturnAddress(); #endif // defined(_DEBUG) && defined(TARGET_X86) -#ifdef FEATURE_EH_FUNCLETS - if (g_isNewExceptionHandlingEnabled) - { - ThrowNew(oref); - UNREACHABLE(); - } -#endif - if (oref == 0) COMPlusThrow(kNullReferenceException); else @@ -2768,49 +2771,48 @@ HCIMPLEND /*************************************************************/ -#ifdef FEATURE_EH_FUNCLETS -void RethrowNew() +HCIMPL0(void, IL_Rethrow) { - Thread *pThread = GetThread(); + FCALL_CONTRACT; - ExInfo *pActiveExInfo = (ExInfo*)pThread->GetExceptionState()->GetCurrentExceptionTracker(); + FC_GC_POLL_NOT_NEEDED(); // throws always open up for GC - CONTEXT exceptionContext; - RtlCaptureContext(&exceptionContext); +#ifdef FEATURE_EH_FUNCLETS + if (g_isNewExceptionHandlingEnabled) + { + Thread *pThread = GetThread(); - ExInfo exInfo(pThread, pActiveExInfo->m_ptrs.ExceptionRecord, &exceptionContext, ExKind::None); + FrameWithCookie exceptionFrame; + *(&exceptionFrame)->GetGSCookiePtr() = GetProcessGSCookie(); + RtlCaptureContext(exceptionFrame.GetContext()); + exceptionFrame.InitAndLink(pThread); - GCPROTECT_BEGIN(exInfo.m_exception); - PREPARE_NONVIRTUAL_CALLSITE(METHOD__EH__RH_RETHROW); - DECLARE_ARGHOLDER_ARRAY(args, 2); + ExInfo *pActiveExInfo = (ExInfo*)pThread->GetExceptionState()->GetCurrentExceptionTracker(); - args[ARGNUM_0] = PTR_TO_ARGHOLDER(pActiveExInfo); - args[ARGNUM_1] = PTR_TO_ARGHOLDER(&exInfo); + ExInfo exInfo(pThread, pActiveExInfo->m_ptrs.ExceptionRecord, exceptionFrame.GetContext(), ExKind::None); - pThread->IncPreventAbort(); + FC_CAN_TRIGGER_GC(); - //Ex.RhRethrow(ref ExInfo activeExInfo, ref ExInfo exInfo) - CALL_MANAGED_METHOD_NORET(args) - GCPROTECT_END(); -} -#endif // FEATURE_EH_FUNCLETS + GCPROTECT_BEGIN(exInfo.m_exception); + PREPARE_NONVIRTUAL_CALLSITE(METHOD__EH__RH_RETHROW); + DECLARE_ARGHOLDER_ARRAY(args, 2); -HCIMPL0(void, IL_Rethrow) -{ - FCALL_CONTRACT; + args[ARGNUM_0] = PTR_TO_ARGHOLDER(pActiveExInfo); + args[ARGNUM_1] = PTR_TO_ARGHOLDER(&exInfo); - FC_GC_POLL_NOT_NEEDED(); // throws always open up for GC + pThread->IncPreventAbort(); - HELPER_METHOD_FRAME_BEGIN_ATTRIB_NOPOLL(Frame::FRAME_ATTR_EXCEPTION); // Set up a frame + //Ex.RhRethrow(ref ExInfo activeExInfo, ref ExInfo exInfo) + CALL_MANAGED_METHOD_NORET(args) + GCPROTECT_END(); -#ifdef FEATURE_EH_FUNCLETS - if (g_isNewExceptionHandlingEnabled) - { - RethrowNew(); + FC_CAN_TRIGGER_GC_END(); UNREACHABLE(); } #endif + HELPER_METHOD_FRAME_BEGIN_ATTRIB_NOPOLL(Frame::FRAME_ATTR_EXCEPTION); // Set up a frame + OBJECTREF throwable = GetThread()->GetThrowable(); if (throwable != NULL) {