summaryrefslogtreecommitdiff
path: root/src/inc/palclr_win.h
blob: 372f467cbd84c60194e9a3016d0a019962a03b60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// 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, &params) {
//   ...
//   }
//   WIN_PAL_ENDTRY
// }
// WIN_PAL_FINALLY {
// }
// WIN_PAL_ENDTRY
//



#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__