diff options
Diffstat (limited to 'src/inc/palclr_win.h')
-rw-r--r-- | src/inc/palclr_win.h | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/inc/palclr_win.h b/src/inc/palclr_win.h new file mode 100644 index 0000000000..18edc6c8f5 --- /dev/null +++ b/src/inc/palclr_win.h @@ -0,0 +1,206 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// =========================================================================== +// File: palclr.h +// +// Various macros and constants that are necessary to make the CLR portable. +// + +// =========================================================================== + +#ifndef __PALCLR_WIN_H__ +#define __PALCLR_WIN_H__ + +// PAL SEH +// Macros for portable exception handling. The Win32 SEH is emulated using +// these macros and setjmp/longjmp on Unix +// +// Usage notes: +// +// - The filter has to be a function taking two parameters: +// LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) +// +// - It is not possible to directly use the local variables in the filter. +// All the local information that the filter has to need to know about should +// be passed through pv parameter +// +// - Do not use goto to jump out of the PAL_TRY block +// (jumping out of the try block is not a good idea even on Win32, because of +// it causes stack unwind) +// +// +// Simple examples: +// +// PAL_TRY { +// .... +// } WIN_PAL_FINALLY { +// .... +// } +// WIN_PAL_ENDTRY +// +// +// PAL_TRY { +// .... +// } WIN_PAL_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { +// .... +// } +// WIN_PAL_ENDTRY +// +// +// LONG MyFilter(PEXCEPTION_POINTERS *pExceptionInfo, PVOID pv) +// { +// ... +// } +// PAL_TRY { +// .... +// } WIN_PAL_EXCEPT_FILTER(MyFilter, NULL) { +// .... +// } +// WIN_PAL_ENDTRY +// +// +// Complex example: +// +// struct MyParams +// { +// ... +// } params; +// +// PAL_TRY { +// PAL_TRY { +// ... +// if (error) goto Done; +// ... +// Done: ; +// } WIN_PAL_EXCEPT_FILTER(OtherFilter, ¶ms) { +// ... +// } +// WIN_PAL_ENDTRY +// } +// WIN_PAL_FINALLY { +// } +// WIN_PAL_ENDTRY +// + +#if !defined(FEATURE_CORECLR) + +#include "staticcontract.h" + +#define WIN_PAL_TRY_NAKED \ + { \ + bool __exHandled; __exHandled = false; \ + DWORD __exCode; __exCode = 0; \ + __try \ + { + +#define WIN_PAL_TRY \ + { \ + WIN_PAL_TRY_NAKED \ + WIN_PAL_TRY_HANDLER_DBG_BEGIN + +#define WIN_PAL_TRY_FOR_DLLMAIN(_reason) \ + { \ + WIN_PAL_TRY_NAKED \ + WIN_PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) + +// Note: PAL_SEH_RESTORE_GUARD_PAGE is only ever defined in clrex.h, so we only restore guard pages automatically +// when these macros are used from within the VM. +#define WIN_PAL_SEH_RESTORE_GUARD_PAGE PAL_SEH_RESTORE_GUARD_PAGE + +#define WIN_PAL_EXCEPT_NAKED(Disposition) \ + } __except(__exCode = GetExceptionCode(), Disposition) { \ + __exHandled = true; \ + WIN_PAL_SEH_RESTORE_GUARD_PAGE + +#define WIN_PAL_EXCEPT(Disposition) \ + WIN_PAL_TRY_HANDLER_DBG_END \ + WIN_PAL_EXCEPT_NAKED(Disposition) + +#define WIN_PAL_EXCEPT_FILTER_NAKED(pfnFilter, pvFilterParameter) \ + } __except(__exCode = GetExceptionCode(), pfnFilter(GetExceptionInformation(), pvFilterParameter)) { \ + __exHandled = true; \ + WIN_PAL_SEH_RESTORE_GUARD_PAGE + +#define WIN_PAL_EXCEPT_FILTER(pfnFilter, pvFilterParameter) \ + WIN_PAL_TRY_HANDLER_DBG_END \ + WIN_PAL_EXCEPT_FILTER_NAKED(pfnFilter, pvFilterParameter) + +#define WIN_PAL_FINALLY_NAKED \ + } __finally { \ + +#define WIN_PAL_FINALLY \ + WIN_PAL_TRY_HANDLER_DBG_END \ + WIN_PAL_FINALLY_NAKED + +#define WIN_PAL_ENDTRY_NAKED \ + } \ + } \ + +#define WIN_PAL_ENDTRY \ + } \ + WIN_PAL_ENDTRY_NAKED_DBG \ + } \ + } + +#endif // !PAL_WIN_SEH + + +#if defined(_DEBUG_IMPL) && !defined(JIT_BUILD) && !defined(JIT64_BUILD) && !defined(_ARM_) // @ARMTODO +#define WIN_PAL_TRY_HANDLER_DBG_BEGIN \ + BOOL ___oldOkayToThrowValue = FALSE; \ + BOOL ___oldSOTolerantState = FALSE; \ + ClrDebugState *___pState = GetClrDebugState(); \ + __try \ + { \ + ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ + ___oldSOTolerantState = ___pState->IsSOTolerant(); \ + ___pState->SetOkToThrow(TRUE); \ + ANNOTATION_TRY_BEGIN; + +// Special version that avoids touching the debug state after doing work in a DllMain for process or thread detach. +#define WIN_PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) \ + BOOL ___oldOkayToThrowValue = FALSE; \ + BOOL ___oldSOTolerantState = FALSE; \ + ClrDebugState *___pState = CheckClrDebugState(); \ + __try \ + { \ + if (___pState) \ + { \ + ___oldOkayToThrowValue = ___pState->IsOkToThrow(); \ + ___oldSOTolerantState = ___pState->IsSOTolerant(); \ + ___pState->SetOkToThrow(TRUE); \ + } \ + if ((_reason == DLL_PROCESS_DETACH) || (_reason == DLL_THREAD_DETACH)) \ + { \ + ___pState = NULL; \ + } \ + ANNOTATION_TRY_BEGIN; + +#define WIN_PAL_TRY_HANDLER_DBG_END \ + ANNOTATION_TRY_END; \ + } \ + __finally \ + { \ + if (___pState != NULL) \ + { \ + _ASSERTE(___pState == CheckClrDebugState()); \ + ___pState->SetOkToThrow(___oldOkayToThrowValue); \ + ___pState->SetSOTolerance(___oldSOTolerantState); \ + } \ + } + +#define WIN_PAL_ENDTRY_NAKED_DBG \ + if (__exHandled) \ + { \ + RESTORE_SO_TOLERANCE_STATE; \ + } \ + +#else +#define WIN_PAL_TRY_HANDLER_DBG_BEGIN ANNOTATION_TRY_BEGIN; +#define WIN_PAL_TRY_HANDLER_DBG_BEGIN_DLLMAIN(_reason) ANNOTATION_TRY_BEGIN; +#define WIN_PAL_TRY_HANDLER_DBG_END ANNOTATION_TRY_END; +#define WIN_PAL_ENDTRY_NAKED_DBG +#endif // defined(ENABLE_CONTRACTS_IMPL) && !defined(JIT64_BUILD) + +#endif // __PALCLR_WIN_H__ |