diff --git a/src/coreclr/vm/exceptionhandling.h b/src/coreclr/vm/exceptionhandling.h index 8668b787280008..cd6e1bb8de8b08 100644 --- a/src/coreclr/vm/exceptionhandling.h +++ b/src/coreclr/vm/exceptionhandling.h @@ -22,6 +22,12 @@ ProcessCLRException(IN PEXCEPTION_RECORD pExceptionRecord, IN OUT PT_CONTEXT pContextRecord, IN OUT PT_DISPATCHER_CONTEXT pDispatcherContext); +EXTERN_C EXCEPTION_DISPOSITION __cdecl +CallDescrWorkerUnwindFrameChainHandler(IN PEXCEPTION_RECORD pExceptionRecord, + IN PVOID pEstablisherFrame, + IN OUT PT_CONTEXT pContextRecord, + IN OUT PT_DISPATCHER_CONTEXT pDispatcherContext); + VOID DECLSPEC_NORETURN DispatchManagedException(OBJECTREF throwable, CONTEXT *pExceptionContext, EXCEPTION_RECORD *pExceptionRecord = NULL); VOID DECLSPEC_NORETURN DispatchManagedException(OBJECTREF throwable); VOID DECLSPEC_NORETURN DispatchManagedException(RuntimeExceptionKind reKind); diff --git a/src/coreclr/vm/exceptmacros.h b/src/coreclr/vm/exceptmacros.h index ff3eafd842da4c..2f0ff66e2384b2 100644 --- a/src/coreclr/vm/exceptmacros.h +++ b/src/coreclr/vm/exceptmacros.h @@ -322,6 +322,41 @@ VOID DECLSPEC_NORETURN DispatchManagedException(PAL_SEHException& ex, bool isHar UNREACHABLE(); \ } +#elif defined(TARGET_X86) && defined(TARGET_WINDOWS) && defined(FEATURE_EH_FUNCLETS) + +#define INSTALL_MANAGED_EXCEPTION_DISPATCHER +#define UNINSTALL_MANAGED_EXCEPTION_DISPATCHER + +#define INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP +#define UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP + +// We use [UN]INSTALL_MANAGED_EXCEPTION_DISPATCHER_EX to backpatch the SEH record installed +// in CallDescrWorkerInternal from ProcessCLRException to CallDescrWorkerUnwindFrameChainHandler +// when throwing an exception. This ensures that class loading exceptions are propagated through +// unmanaged code before being forwarded to the managed one. + +#define INSTALL_MANAGED_EXCEPTION_DISPATCHER_EX \ + try \ + { + +#define UNINSTALL_MANAGED_EXCEPTION_DISPATCHER_EX(nativeRethrow) \ + } \ + catch (...) \ + { \ + if (nativeRethrow) \ + { \ + PEXCEPTION_REGISTRATION_RECORD pExceptionRecord = GetCurrentSEHRecord(); \ + _ASSERTE(pExceptionRecord != EXCEPTION_CHAIN_END); \ + while (pExceptionRecord->Handler != (PEXCEPTION_ROUTINE)ProcessCLRException) \ + { \ + pExceptionRecord = pExceptionRecord->Next; \ + _ASSERTE(pExceptionRecord != EXCEPTION_CHAIN_END); \ + } \ + pExceptionRecord->Handler = (PEXCEPTION_ROUTINE)CallDescrWorkerUnwindFrameChainHandler; \ + } \ + throw; \ + } + #else // TARGET_UNIX #define INSTALL_MANAGED_EXCEPTION_DISPATCHER diff --git a/src/coreclr/vm/i386/asmhelpers.asm b/src/coreclr/vm/i386/asmhelpers.asm index 5656aee6c1e230..e64931d6405882 100644 --- a/src/coreclr/vm/i386/asmhelpers.asm +++ b/src/coreclr/vm/i386/asmhelpers.asm @@ -1215,30 +1215,8 @@ _ThePreStub@0 proc public push esi -ifdef FEATURE_EH_FUNCLETS - cmp [esi + 24], CallDescrWorkerInternalReturnAddress - jne NoSEHReplace - - ; If we were called from CallDescrWorkerInternal then swap the last - ; SEH registration for _CallDescrWorkerUnwindFrameChainHandler to ensure - ; that class loading exceptions are propagated through unmanaged code - ; before being forwarded to the managed one. - mov edi, fs:[0] - ; mov esi, [edi] - ; mov fs:[0], esi - mov [edi + 4], _CallDescrWorkerUnwindFrameChainHandler - call _PreStubWorker@8 - mov [edi + 4], _ProcessCLRException - ; mov fs:[0], edi - jmp AfterPreStubWorker - -NoSEHReplace: -endif ; FEATURE_EH_FUNCLETS - call _PreStubWorker@8 -AfterPreStubWorker: - ; eax now contains replacement stub. PreStubWorker will never return ; NULL (it throws an exception if stub creation fails.)