diff --git a/src/coreclr/debug/ee/debugger.cpp b/src/coreclr/debug/ee/debugger.cpp index bbae9cf6d28e1c..f8a3adc971a460 100644 --- a/src/coreclr/debug/ee/debugger.cpp +++ b/src/coreclr/debug/ee/debugger.cpp @@ -13191,19 +13191,14 @@ void STDCALL ExceptionHijackWorker( // See code:ExceptionHijackPersonalityRoutine for more information. // // Arguments: -// * pExceptionRecord - not used -// * MemoryStackFp - not used -// * BackingStoreFp - not used -// * pContextRecord - not used -// * pDispatcherContext - not used -// * GlobalPointer - not used +// Standard personality routine signature. // // Return Value: // Always return ExceptionContinueSearch. // EXCEPTION_DISPOSITION EmptyPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord, - IN ULONG64 MemoryStackFp, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext) { @@ -13216,7 +13211,7 @@ EXCEPTION_DISPOSITION EmptyPersonalityRoutine(IN PEXCEPTION_RECORD pExcept // Personality routine for unwinder the assembly hijack stub on 64-bit. // // Arguments: -// standard Personality routine signature. +// Standard personality routine signature. // // Assumptions: // This is caleld by the OS exception logic during exception handling. @@ -13243,9 +13238,8 @@ EXCEPTION_DISPOSITION EmptyPersonalityRoutine(IN PEXCEPTION_RECORD pExcept // On AMD64, we work around this by using an empty personality routine. EXTERN_C EXCEPTION_DISPOSITION -ExceptionHijackPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG32 MemoryStackFp), +ExceptionHijackPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -13268,7 +13262,7 @@ ExceptionHijackPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord // This copies pHijackContext into pDispatcherContext, which the OS can then // use to walk the stack. - FixupDispatcherContext(pDispatcherContext, pHijackContext, pContextRecord, (PEXCEPTION_ROUTINE)EmptyPersonalityRoutine); + FixupDispatcherContext(pDispatcherContext, pHijackContext, (PEXCEPTION_ROUTINE)EmptyPersonalityRoutine); #else _ASSERTE(!"NYI - ExceptionHijackPersonalityRoutine()"); #endif diff --git a/src/coreclr/debug/ee/debugger.h b/src/coreclr/debug/ee/debugger.h index 695b88aaef1ba4..f73f9c83810dc3 100644 --- a/src/coreclr/debug/ee/debugger.h +++ b/src/coreclr/debug/ee/debugger.h @@ -3872,7 +3872,7 @@ HANDLE OpenWin32EventOrThrow( bool DbgIsSpecialILOffset(DWORD offset); #if !defined(TARGET_X86) -void FixupDispatcherContext(T_DISPATCHER_CONTEXT* pDispatcherContext, T_CONTEXT* pContext, T_CONTEXT* pOriginalContext, PEXCEPTION_ROUTINE pUnwindPersonalityRoutine = NULL); +void FixupDispatcherContext(T_DISPATCHER_CONTEXT* pDispatcherContext, T_CONTEXT* pContext, PEXCEPTION_ROUTINE pUnwindPersonalityRoutine = NULL); #endif #endif /* DEBUGGER_H_ */ diff --git a/src/coreclr/debug/ee/funceval.cpp b/src/coreclr/debug/ee/funceval.cpp index 1d09d9df25355f..82fe538d9f3fb7 100644 --- a/src/coreclr/debug/ee/funceval.cpp +++ b/src/coreclr/debug/ee/funceval.cpp @@ -3579,7 +3579,7 @@ static void GCProtectArgsAndDoNormalFuncEval(DebuggerEval *pDE, GCX_FORBID(); RecordFuncEvalException( pDE, ppException); } - // Note: we need to catch all exceptioins here because they all get reported as the result of + // Note: we need to catch all exceptions here because they all get reported as the result of // the funceval. If a ThreadAbort occurred other than for a funcEval abort, we'll re-throw it manually. EX_END_CATCH(SwallowAllExceptions); @@ -3994,32 +3994,34 @@ void * STDCALL FuncEvalHijackWorker(DebuggerEval *pDE) #if defined(FEATURE_EH_FUNCLETS) && !defined(TARGET_UNIX) EXTERN_C EXCEPTION_DISPOSITION -FuncEvalHijackPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG32 MemoryStackFp), +FuncEvalHijackPersonalityRoutine(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) { - DebuggerEval* pDE = NULL; + // The offset of the DebuggerEval pointer relative to the establisher frame. + SIZE_T debuggerEvalPtrOffset = 0; #if defined(TARGET_AMD64) - pDE = *(DebuggerEval**)(pDispatcherContext->EstablisherFrame); + // On AMD64 the establisher frame is the SP of FuncEvalHijack itself. + // In FuncEvalHijack we store RCX at the current SP. + debuggerEvalPtrOffset = 0; #elif defined(TARGET_ARM) - // on ARM the establisher frame is the SP of the caller of FuncEvalHijack, on other platforms it's FuncEvalHijack's SP. - // in FuncEvalHijack we allocate 8 bytes of stack space and then store R0 at the current SP, so if we subtract 8 from + // On ARM the establisher frame is the SP of the FuncEvalHijack's caller. + // In FuncEvalHijack we allocate 8 bytes of stack space and then store R0 at the current SP, so if we subtract 8 from // the establisher frame we can get the stack location where R0 was stored. - pDE = *(DebuggerEval**)(pDispatcherContext->EstablisherFrame - 8); - + debuggerEvalPtrOffset = 8; #elif defined(TARGET_ARM64) - // on ARM64 the establisher frame is the SP of the caller of FuncEvalHijack. - // in FuncEvalHijack we allocate 32 bytes of stack space and then store R0 at the current SP + 16, so if we subtract 16 from - // the establisher frame we can get the stack location where R0 was stored. - pDE = *(DebuggerEval**)(pDispatcherContext->EstablisherFrame - 16); + // On ARM64 the establisher frame is the SP of the FuncEvalHijack's caller. + // In FuncEvalHijack we allocate 32 bytes of stack space and then store X0 at the current SP + 16, so if we subtract 16 from + // the establisher frame we can get the stack location where X0 was stored. + debuggerEvalPtrOffset = 16; #else _ASSERTE(!"NYI - FuncEvalHijackPersonalityRoutine()"); #endif - FixupDispatcherContext(pDispatcherContext, &(pDE->m_context), pContextRecord); + DebuggerEval* pDE = *(DebuggerEval**)(pDispatcherContext->EstablisherFrame - debuggerEvalPtrOffset); + FixupDispatcherContext(pDispatcherContext, &(pDE->m_context)); // Returning ExceptionCollidedUnwind will cause the OS to take our new context record and // dispatcher context and restart the exception dispatching on this call frame, which is diff --git a/src/coreclr/vm/excep.cpp b/src/coreclr/vm/excep.cpp index c23a4de544ce43..183bee15b52493 100644 --- a/src/coreclr/vm/excep.cpp +++ b/src/coreclr/vm/excep.cpp @@ -5637,7 +5637,7 @@ LONG CallOutFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pv) { CallOutFilterParam *pParam = static_cast(pv); - _ASSERTE(pParam->OneShot && (pParam->OneShot == TRUE || pParam->OneShot == FALSE)); + _ASSERTE(pParam && (pParam->OneShot == TRUE || pParam->OneShot == FALSE)); if (pParam->OneShot == TRUE) { @@ -6576,10 +6576,7 @@ static LONG HandleManagedFaultFilter(EXCEPTION_POINTERS* ep, LPVOID pv) return EXCEPTION_CONTINUE_SEARCH; } -void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, - CONTEXT* pContext, - EXCEPTION_REGISTRATION_RECORD* pEstablisherFrame, - Thread* pThread) +void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, CONTEXT* pContext) { WRAPPER_NO_CONTRACT; @@ -6726,27 +6723,16 @@ bool ShouldHandleManagedFault( #ifndef TARGET_UNIX -LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo); - -enum VEH_ACTION -{ - VEH_NO_ACTION = 0, - VEH_EXECUTE_HANDLE_MANAGED_EXCEPTION, - VEH_CONTINUE_EXECUTION, - VEH_CONTINUE_SEARCH, - VEH_EXECUTE_HANDLER -}; - - +VEH_ACTION WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo); VEH_ACTION WINAPI CLRVectoredExceptionHandlerPhase3(PEXCEPTION_POINTERS pExceptionInfo); -LONG WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) +VEH_ACTION WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { // It is not safe to execute code inside VM after we shutdown EE. One example is DisablePreemptiveGC // will block forever. if (g_fForbidEnterEE) { - return EXCEPTION_CONTINUE_SEARCH; + return VEH_CONTINUE_SEARCH; } @@ -6836,7 +6822,7 @@ LONG WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) pExceptionInfo->ContextRecord->Rip = hijackArgs.ReturnAddress; } - return EXCEPTION_CONTINUE_EXECUTION; + return VEH_CONTINUE_EXECUTION; } #endif @@ -6860,11 +6846,9 @@ LONG WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) // // Not an Out-of-memory situation, so no need for a forbid fault region here // - return EXCEPTION_CONTINUE_SEARCH; + return VEH_CONTINUE_SEARCH; } - LONG retVal = 0; - // We can't probe here, because we won't return from the CLRVectoredExceptionHandlerPhase2 // on WIN64 // @@ -6875,15 +6859,10 @@ LONG WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) CantAllocHolder caHolder; } - retVal = CLRVectoredExceptionHandlerPhase2(pExceptionInfo); - - // - //END_ENTRYPOINT_VOIDRET; - // - return retVal; + return CLRVectoredExceptionHandlerPhase2(pExceptionInfo); } -LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo) +VEH_ACTION WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo) { // // DO NOT USE CONTRACTS HERE AS THIS ROUTINE MAY NEVER RETURN. You can use @@ -6917,31 +6896,16 @@ LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo action = CLRVectoredExceptionHandlerPhase3(pExceptionInfo); } - if (action == VEH_CONTINUE_EXECUTION) - { - return EXCEPTION_CONTINUE_EXECUTION; - } - - if (action == VEH_CONTINUE_SEARCH) + if ((action == VEH_CONTINUE_EXECUTION) || (action == VEH_CONTINUE_SEARCH) || (action == VEH_EXECUTE_HANDLER)) { - return EXCEPTION_CONTINUE_SEARCH; - } - - if (action == VEH_EXECUTE_HANDLER) - { - return EXCEPTION_EXECUTE_HANDLER; + return action; } #if defined(FEATURE_EH_FUNCLETS) if (action == VEH_EXECUTE_HANDLE_MANAGED_EXCEPTION) { - HandleManagedFault(pExceptionInfo->ExceptionRecord, - pExceptionInfo->ContextRecord, - NULL, // establisher frame (x86 only) - NULL // pThread (x86 only) - ); - return EXCEPTION_CONTINUE_EXECUTION; + return action; } #endif // defined(FEATURE_EH_FUNCLETS) @@ -6961,7 +6925,7 @@ LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo // the choice to break the no-trigger region after taking all necessary precautions. if (IsDebuggerFault(pExceptionRecord, pExceptionInfo->ContextRecord, pExceptionRecord->ExceptionCode, GetThreadNULLOk())) { - return EXCEPTION_CONTINUE_EXECUTION; + return VEH_CONTINUE_EXECUTION; } } @@ -6993,11 +6957,11 @@ LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo { // The breakpoint was not ours. Someone else can handle it. (Or if not, we'll get it again as // an unhandled exception.) - return EXCEPTION_CONTINUE_SEARCH; + return VEH_CONTINUE_SEARCH; } // The breakpoint was from managed or the runtime. Handle it. - return UserBreakpointFilter(pExceptionInfo); + return (VEH_ACTION)UserBreakpointFilter(pExceptionInfo); } #if defined(FEATURE_EH_FUNCLETS) @@ -7015,19 +6979,11 @@ LONG WINAPI CLRVectoredExceptionHandlerPhase2(PEXCEPTION_POINTERS pExceptionInfo if (fShouldHandleManagedFault) { - // - // HandleManagedFault may never return, so we cannot use a forbid fault region around it. - // - HandleManagedFault(pExceptionInfo->ExceptionRecord, - pExceptionInfo->ContextRecord, - NULL, // establisher frame (x86 only) - NULL // pThread (x86 only) - ); - return EXCEPTION_CONTINUE_EXECUTION; -} + return VEH_EXECUTE_HANDLE_MANAGED_EXCEPTION; + } #endif // defined(FEATURE_EH_FUNCLETS) - return EXCEPTION_EXECUTE_HANDLER; + return VEH_EXECUTE_HANDLER; } /* @@ -7594,13 +7550,34 @@ LONG WINAPI CLRVectoredExceptionHandlerShim(PEXCEPTION_POINTERS pExceptionInfo) if (pThread || fExceptionInEE) { if (!bIsGCMarker) - result = CLRVectoredExceptionHandler(pExceptionInfo); - else - result = EXCEPTION_CONTINUE_EXECUTION; + { + VEH_ACTION action = CLRVectoredExceptionHandler(pExceptionInfo); + +#ifdef FEATURE_EH_FUNCLETS + if (VEH_EXECUTE_HANDLE_MANAGED_EXCEPTION == action) + { + // + // HandleManagedFault may never return, so we cannot use a forbid fault region around it. + // + HandleManagedFault(pExceptionInfo->ExceptionRecord, pExceptionInfo->ContextRecord); + return EXCEPTION_CONTINUE_EXECUTION; + } +#endif // FEATURE_EH_FUNCLETS + + if (VEH_EXECUTE_HANDLER == action) + { + result = EXCEPTION_CONTINUE_SEARCH; + } + else + { + _ASSERTE((action == VEH_CONTINUE_EXECUTION) || (action == VEH_CONTINUE_SEARCH)); + result = (LONG)action; + } - if (EXCEPTION_EXECUTE_HANDLER == result) + } + else { - result = EXCEPTION_CONTINUE_SEARCH; + result = EXCEPTION_CONTINUE_EXECUTION; } #ifdef _DEBUG @@ -8321,7 +8298,7 @@ void SetReversePInvokeEscapingUnhandledExceptionStatus(BOOL fIsUnwinding, #if defined(TARGET_X86) EXCEPTION_REGISTRATION_RECORD * pEstablisherFrame #elif defined(FEATURE_EH_FUNCLETS) - ULONG64 pEstablisherFrame + PVOID pEstablisherFrame #else #error Unsupported platform #endif diff --git a/src/coreclr/vm/excep.h b/src/coreclr/vm/excep.h index eefaaa1ffc48eb..d30cff50f25b9e 100644 --- a/src/coreclr/vm/excep.h +++ b/src/coreclr/vm/excep.h @@ -744,14 +744,11 @@ bool IsGcMarker(T_CONTEXT *pContext, EXCEPTION_RECORD *pExceptionRecord); bool ShouldHandleManagedFault( EXCEPTION_RECORD* pExceptionRecord, - T_CONTEXT* pContext, + T_CONTEXT* pContext, EXCEPTION_REGISTRATION_RECORD* pEstablisherFrame, Thread* pThread); -void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, - T_CONTEXT* pContext, - EXCEPTION_REGISTRATION_RECORD* pEstablisherFrame, - Thread* pThread); +void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord, T_CONTEXT* pContext); LONG WatsonLastChance( Thread *pThread, @@ -778,7 +775,7 @@ void SetReversePInvokeEscapingUnhandledExceptionStatus(BOOL fIsUnwinding, #ifdef TARGET_X86 EXCEPTION_REGISTRATION_RECORD * pEstablisherFrame #elif defined(FEATURE_EH_FUNCLETS) - ULONG64 pEstablisherFrame + PVOID pEstablisherFrame #else #error Unsupported platform #endif diff --git a/src/coreclr/vm/exceptionhandling.cpp b/src/coreclr/vm/exceptionhandling.cpp index 21fe40769384be..9623dee9dfdcfa 100644 --- a/src/coreclr/vm/exceptionhandling.cpp +++ b/src/coreclr/vm/exceptionhandling.cpp @@ -837,12 +837,9 @@ UINT_PTR ExceptionTracker::FinishSecondPass( void CleanUpForSecondPass(Thread* pThread, bool fIsSO, LPVOID MemoryStackFpForFrameChain, LPVOID MemoryStackFp); -// On CoreARM, the MemoryStackFp is ULONG when passed by RtlDispatchException, -// unlike its 64bit counterparts. EXTERN_C EXCEPTION_DISPOSITION -ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), +ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -861,7 +858,7 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord EXCEPTION_DISPOSITION returnDisposition = ExceptionContinueSearch; STRESS_LOG5(LF_EH, LL_INFO10, "Processing exception at establisher=%p, ip=%p disp->cxr: %p, sp: %p, cxr @ exception: %p\n", - MemoryStackFp, pDispatcherContext->ControlPc, + pEstablisherFrame, pDispatcherContext->ControlPc, pDispatcherContext->ContextRecord, GetSP(pDispatcherContext->ContextRecord), pContextRecord); AMD64_ONLY(STRESS_LOG3(LF_EH, LL_INFO10, " rbx=%p, rsi=%p, rdi=%p\n", pContextRecord->Rbx, pContextRecord->Rsi, pContextRecord->Rdi)); @@ -928,7 +925,7 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord } } - StackFrame sf((UINT_PTR)MemoryStackFp); + StackFrame sf((UINT_PTR)pEstablisherFrame); { @@ -954,7 +951,7 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord // { EH_LOG((LL_INFO100, "..................................................................................\n")); - EH_LOG((LL_INFO100, "ProcessCLRException enter, sp = 0x%p, ControlPc = 0x%p\n", MemoryStackFp, pDispatcherContext->ControlPc)); + EH_LOG((LL_INFO100, "ProcessCLRException enter, sp = 0x%p, ControlPc = 0x%p\n", pEstablisherFrame, pDispatcherContext->ControlPc)); DebugLogExceptionRecord(pExceptionRecord); if (STATUS_UNWIND_CONSOLIDATE == pExceptionRecord->ExceptionCode) @@ -1236,7 +1233,7 @@ lExit: ; // Exception is being propagated from a method marked UnmanagedCallersOnlyAttribute into its native caller. // The explicit frame chain needs to be unwound at this boundary. bool fIsSO = pExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW; - CleanUpForSecondPass(pThread, fIsSO, (void*)MemoryStackFp, (void*)MemoryStackFp); + CleanUpForSecondPass(pThread, fIsSO, pEstablisherFrame, pEstablisherFrame); } } } @@ -4453,7 +4450,7 @@ VOID UnwindManagedExceptionPass2(PAL_SEHException& ex, CONTEXT* unwindStartConte // Perform unwinding of the current frame disposition = ProcessCLRException(exceptionRecord, - establisherFrame, + (void*)establisherFrame, currentFrameContext, &dispatcherContext); @@ -4621,7 +4618,7 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex, CONTEXT // Find exception handler in the current frame disposition = ProcessCLRException(ex.GetExceptionRecord(), - establisherFrame, + (void*)establisherFrame, ex.GetContextRecord(), &dispatcherContext); @@ -5497,16 +5494,7 @@ void TrackerAllocator::FreeTrackerMemory(ExceptionTracker* pTracker) // specify pUnwindPersonalityRoutine. For instance the debugger uses this to unwind from ExceptionHijack back // to RaiseException in win32 and specifies an empty personality routine. For more details about this // see the comments in the code below. -// -// -// AMD64 is more "advanced", in that the DISPATCHER_CONTEXT contains a field for the TargetIp. So we don't have -// to use the control PC in pDispatcherContext->ContextRecord to indicate the target IP for the unwind. However, -// this also means that pDispatcherContext->ContextRecord is expected to be consistent. -// -// -// For more information, refer to vctools\crt\crtw32\misc\{ia64|amd64}\chandler.c for __C_specific_handler() and -// nt\base\ntos\rtl\{ia64|amd64}\exdsptch.c for RtlUnwindEx(). -void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pContext, LPVOID originalControlPC, PEXCEPTION_ROUTINE pUnwindPersonalityRoutine) +void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pContext, PEXCEPTION_ROUTINE pUnwindPersonalityRoutine = NULL) { if (pContext) { @@ -5514,7 +5502,7 @@ void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pCo CopyOSContext(pDispatcherContext->ContextRecord, pContext); } - pDispatcherContext->ControlPc = (UINT_PTR) GetIP(pDispatcherContext->ContextRecord); + pDispatcherContext->ControlPc = (UINT_PTR) GetIP(pDispatcherContext->ContextRecord); #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // Since this routine is used to fixup contexts for async exceptions, @@ -5634,14 +5622,6 @@ void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pCo } -// See the comment above for the overloaded version of this function. -void FixupDispatcherContext(DISPATCHER_CONTEXT* pDispatcherContext, CONTEXT* pContext, CONTEXT* pOriginalContext, PEXCEPTION_ROUTINE pUnwindPersonalityRoutine = NULL) -{ - _ASSERTE(pOriginalContext != NULL); - FixupDispatcherContext(pDispatcherContext, pContext, (LPVOID)::GetIP(pOriginalContext), pUnwindPersonalityRoutine); -} - - BOOL FirstCallToHandler ( DISPATCHER_CONTEXT *pDispatcherContext, CONTEXT **ppContextRecord) @@ -5673,9 +5653,8 @@ BOOL FirstCallToHandler ( EXTERN_C EXCEPTION_DISPOSITION -HijackHandler(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) -NOT_BIT64_ARG(IN ULONG MemoryStackFp), +HijackHandler(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -5716,7 +5695,7 @@ NOT_BIT64_ARG(IN ULONG MemoryStackFp), pThread->SetThrowControlForThread(Thread::InducedThreadStop); } - FixupDispatcherContext(pDispatcherContext, pNewContext, pContextRecord); + FixupDispatcherContext(pDispatcherContext, pNewContext); STRESS_LOG4(LF_EH, LL_INFO10, "HijackHandler: new establisher: %p, disp->cxr: %p, new ip: %p, new sp: %p\n", pDispatcherContext->EstablisherFrame, @@ -5803,7 +5782,7 @@ void CleanUpForSecondPass(Thread* pThread, bool fIsSO, LPVOID MemoryStackFpForFr EH_LOG((LL_INFO100, "Exception is going into unmanaged code, unwinding frame chain to %p\n", MemoryStackFpForFrameChain)); // On AMD64 the establisher pointer is the live stack pointer, but on - // IA64 and ARM it's the caller's stack pointer. It makes no difference, since there + // ARM and ARM64 it's the caller's stack pointer. It makes no difference, since there // is no Frame anywhere in CallDescrWorker's region of stack. // First make sure that unwinding the frame chain does not remove any transition frames @@ -5822,7 +5801,7 @@ void CleanUpForSecondPass(Thread* pThread, bool fIsSO, LPVOID MemoryStackFpForFr // (stack grows up). if (!fIsSO) { - ExceptionTracker::PopTrackerIfEscaping((void*)MemoryStackFp); + ExceptionTracker::PopTrackerIfEscaping(MemoryStackFp); } } @@ -5862,9 +5841,8 @@ UnhandledExceptionHandlerUnix( #else // TARGET_UNIX EXTERN_C EXCEPTION_DISPOSITION -UMThunkUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), +UMThunkUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -5885,7 +5863,7 @@ UMThunkUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord pThread->DisablePreemptiveGC(); } } - CleanUpForSecondPass(pThread, fIsSO, (void*)MemoryStackFp, (void*)MemoryStackFp); + CleanUpForSecondPass(pThread, fIsSO, pEstablisherFrame, pEstablisherFrame); } // The asm stub put us into COOP mode, but we're about to scan unmanaged call frames @@ -5908,16 +5886,15 @@ UMThunkUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord EXTERN_C EXCEPTION_DISPOSITION UMEntryPrestubUnwindFrameChainHandler( - IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), + IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) { EXCEPTION_DISPOSITION disposition = UMThunkUnwindFrameChainHandler( pExceptionRecord, - MemoryStackFp, + pEstablisherFrame, pContextRecord, pDispatcherContext ); @@ -5927,9 +5904,8 @@ UMEntryPrestubUnwindFrameChainHandler( EXTERN_C EXCEPTION_DISPOSITION UMThunkStubUnwindFrameChainHandler( - IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) -NOT_BIT64_ARG(IN ULONG MemoryStackFp), + IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -5944,14 +5920,14 @@ NOT_BIT64_ARG(IN ULONG MemoryStackFp), if (GetThreadNULLOk() != NULL) { SetReversePInvokeEscapingUnhandledExceptionStatus(IS_UNWINDING(pExceptionRecord->ExceptionFlags), - MemoryStackFp + pEstablisherFrame ); } #endif // _DEBUG EXCEPTION_DISPOSITION disposition = UMThunkUnwindFrameChainHandler( pExceptionRecord, - MemoryStackFp, + pEstablisherFrame, pContextRecord, pDispatcherContext ); @@ -5963,9 +5939,8 @@ NOT_BIT64_ARG(IN ULONG MemoryStackFp), // This is the personality routine setup for the assembly helper (CallDescrWorker) that calls into // managed code. EXTERN_C EXCEPTION_DISPOSITION -CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), +CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -5977,7 +5952,7 @@ CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionReco if (IS_UNWINDING(pExceptionRecord->ExceptionFlags)) { GCX_COOP_NO_DTOR(); - CleanUpForSecondPass(pThread, true, (void*)MemoryStackFp, (void*)MemoryStackFp); + CleanUpForSecondPass(pThread, true, pEstablisherFrame, pEstablisherFrame); } InterlockedAnd((LONG*)&pThread->m_fPreemptiveGCDisabled, 0); @@ -5987,7 +5962,7 @@ CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionReco } EXCEPTION_DISPOSITION retVal = ProcessCLRException(pExceptionRecord, - MemoryStackFp, + pEstablisherFrame, pContextRecord, pDispatcherContext); @@ -5996,7 +5971,7 @@ CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionReco if (IS_UNWINDING(pExceptionRecord->ExceptionFlags)) { - CleanUpForSecondPass(pThread, false, (void*)MemoryStackFp, (void*)MemoryStackFp); + CleanUpForSecondPass(pThread, false, pEstablisherFrame, pEstablisherFrame); } // We're scanning out from CallDescr and potentially through the EE and out to unmanaged. @@ -6011,9 +5986,8 @@ CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionReco #ifdef FEATURE_COMINTEROP EXTERN_C EXCEPTION_DISPOSITION -ReverseComUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), +ReverseComUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -6029,9 +6003,8 @@ ReverseComUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord #ifndef TARGET_UNIX EXTERN_C EXCEPTION_DISPOSITION FixRedirectContextHandler( - IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), + IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PCONTEXT pContextRecord, IN OUT PDISPATCHER_CONTEXT pDispatcherContext ) @@ -6052,7 +6025,7 @@ FixRedirectContextHandler( CONTEXT *pRedirectedContext = GetCONTEXTFromRedirectedStubStackFrame(pDispatcherContext); - FixupDispatcherContext(pDispatcherContext, pRedirectedContext, pContextRecord); + FixupDispatcherContext(pDispatcherContext, pRedirectedContext); // Returning ExceptionCollidedUnwind will cause the OS to take our new context record // and dispatcher context and restart the exception dispatching on this call frame, diff --git a/src/coreclr/vm/exceptionhandling.h b/src/coreclr/vm/exceptionhandling.h index a69740d175f4d1..a9c2086b8636c3 100644 --- a/src/coreclr/vm/exceptionhandling.h +++ b/src/coreclr/vm/exceptionhandling.h @@ -17,9 +17,8 @@ #define INVALID_RESUME_ADDRESS 0x000000000000bad0 EXTERN_C EXCEPTION_DISPOSITION -ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord - BIT64_ARG(IN ULONG64 MemoryStackFp) - NOT_BIT64_ARG(IN ULONG MemoryStackFp), +ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, IN OUT PT_CONTEXT pContextRecord, IN OUT PT_DISPATCHER_CONTEXT pDispatcherContext); diff --git a/src/coreclr/vm/exceptmacros.h b/src/coreclr/vm/exceptmacros.h index 3b33292044ddd4..1627e3d3d65cc4 100644 --- a/src/coreclr/vm/exceptmacros.h +++ b/src/coreclr/vm/exceptmacros.h @@ -240,7 +240,16 @@ VOID DECLSPEC_NORETURN RealCOMPlusThrowOM(); #endif // !defined(FEATURE_EH_FUNCLETS) -LONG WINAPI CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo); +enum VEH_ACTION +{ + VEH_NO_ACTION = -3, + VEH_EXECUTE_HANDLE_MANAGED_EXCEPTION = -2, + VEH_CONTINUE_EXECUTION = EXCEPTION_CONTINUE_EXECUTION, + VEH_CONTINUE_SEARCH = EXCEPTION_CONTINUE_SEARCH, + VEH_EXECUTE_HANDLER = EXCEPTION_EXECUTE_HANDLER +}; + +VEH_ACTION CLRVectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo); // Actual UEF worker prototype for use by GCUnhandledExceptionFilter. extern LONG InternalUnhandledExceptionFilter_Worker(PEXCEPTION_POINTERS pExceptionInfo); diff --git a/src/coreclr/vm/i386/excepx86.cpp b/src/coreclr/vm/i386/excepx86.cpp index 68c68f7f258a0e..51df72d448705e 100644 --- a/src/coreclr/vm/i386/excepx86.cpp +++ b/src/coreclr/vm/i386/excepx86.cpp @@ -1254,13 +1254,13 @@ CPFH_FirstPassHandler(EXCEPTION_RECORD *pExceptionRecord, // Call to the vectored handler to give other parts of the Runtime a chance to jump in and take over an // exception before we do too much with it. The most important point in the vectored handler is not to toggle // the GC mode. - DWORD filter = CLRVectoredExceptionHandler(&ptrs); + VEH_ACTION filter = CLRVectoredExceptionHandler(&ptrs); - if (filter == (DWORD) EXCEPTION_CONTINUE_EXECUTION) + if (filter == VEH_CONTINUE_EXECUTION) { return ExceptionContinueExecution; } - else if (filter == EXCEPTION_CONTINUE_SEARCH) + else if (filter == VEH_CONTINUE_SEARCH) { return ExceptionContinueSearch; } @@ -1300,22 +1300,16 @@ CPFH_FirstPassHandler(EXCEPTION_RECORD *pExceptionRecord, CPFH_VerifyThreadIsInValidState(pThread, exceptionCode, pEstablisherFrame); - // If we were in cooperative mode when we came in here, then its okay to see if we should do HandleManagedFault + // If we were in cooperative mode when we came in here, then it's okay to see if we should do HandleManagedFault // and push a FaultingExceptionFrame. If we weren't in coop mode coming in here, then it means that there's no - // way the exception could really be from managed code. I might look like it was from managed code, but in - // reality its a rethrow from unmanaged code, either unmanaged user code, or unmanaged EE implementation. + // way the exception could really be from managed code. It might look like it was from managed code, but in + // reality it's a rethrow from unmanaged code, either unmanaged user code, or unmanaged EE implementation. if (disabled && ShouldHandleManagedFault(pExceptionRecord, pContext, pEstablisherFrame, pThread)) { #if defined(USE_FEF) - HandleManagedFault(pExceptionRecord, pContext, pEstablisherFrame, pThread); + HandleManagedFault(pExceptionRecord, pContext); retval = ExceptionContinueExecution; goto exit; -#else // USE_FEF - // Save the context pointer in the Thread's EXInfo, so that a stack crawl can recover the - // register values from the fault. - - //@todo: I haven't yet found any case where we need to do anything here. If there are none, eliminate - // this entire if () {} block. #endif // USE_FEF }