1 | // Licensed to the .NET Foundation under one or more agreements. |
---|---|
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | // ==++== |
6 | // |
7 | |
8 | // |
9 | // |
10 | |
11 | // |
12 | // ==--== |
13 | |
14 | |
15 | #ifndef __eexcp_h__ |
16 | #define __eexcp_h__ |
17 | |
18 | #include "corhlpr.h" |
19 | #include "daccess.h" |
20 | |
21 | struct EE_ILEXCEPTION_CLAUSE; |
22 | typedef DPTR(EE_ILEXCEPTION_CLAUSE) PTR_EE_ILEXCEPTION_CLAUSE; |
23 | |
24 | // The exception handling sub-system needs to keep track of EH clause that is handling given exception. |
25 | // PTR_EXCEPTION_CLAUSE_TOKEN is opaque pointer that uniquely identifies |
26 | // exception handling clause. It abstracts away encoding differences of EH clauses between JIT and NGen. |
27 | typedef PTR_VOID PTR_EXCEPTION_CLAUSE_TOKEN; |
28 | |
29 | struct EE_ILEXCEPTION_CLAUSE { |
30 | //Flags is not marked as volatile since it is always accessed |
31 | // from within a critical section |
32 | CorExceptionFlag Flags; |
33 | DWORD TryStartPC; |
34 | DWORD TryEndPC; |
35 | DWORD HandlerStartPC; |
36 | DWORD HandlerEndPC; |
37 | union { |
38 | void* TypeHandle; |
39 | mdToken ClassToken; |
40 | DWORD FilterOffset; |
41 | }; |
42 | }; |
43 | |
44 | struct EE_ILEXCEPTION; |
45 | typedef DPTR(EE_ILEXCEPTION) PTR_EE_ILEXCEPTION; |
46 | |
47 | struct EE_ILEXCEPTION : public COR_ILMETHOD_SECT_FAT |
48 | { |
49 | EE_ILEXCEPTION_CLAUSE Clauses[1]; // actually variable size |
50 | |
51 | void Init(unsigned ehCount) |
52 | { |
53 | LIMITED_METHOD_CONTRACT; |
54 | |
55 | SetKind(CorILMethod_Sect_FatFormat); |
56 | SetDataSize((unsigned)sizeof(EE_ILEXCEPTION_CLAUSE) * ehCount); |
57 | } |
58 | |
59 | unsigned EHCount() const |
60 | { |
61 | LIMITED_METHOD_CONTRACT; |
62 | |
63 | return GetDataSize() / (DWORD) sizeof(EE_ILEXCEPTION_CLAUSE); |
64 | } |
65 | |
66 | static unsigned Size(unsigned ehCount) |
67 | { |
68 | LIMITED_METHOD_CONTRACT; |
69 | |
70 | _ASSERTE(ehCount > 0); |
71 | |
72 | return (offsetof(EE_ILEXCEPTION, Clauses) + sizeof(EE_ILEXCEPTION_CLAUSE) * ehCount); |
73 | } |
74 | EE_ILEXCEPTION_CLAUSE *EHClause(unsigned i) |
75 | { |
76 | LIMITED_METHOD_DAC_CONTRACT; |
77 | return &(PTR_EE_ILEXCEPTION_CLAUSE(PTR_HOST_MEMBER_TADDR(EE_ILEXCEPTION,this,Clauses))[i]); |
78 | } |
79 | }; |
80 | |
81 | #define COR_ILEXCEPTION_CLAUSE_CACHED_CLASS 0x10000000 |
82 | |
83 | inline BOOL HasCachedTypeHandle(EE_ILEXCEPTION_CLAUSE *EHClause) |
84 | { |
85 | _ASSERTE(sizeof(EHClause->Flags) == sizeof(DWORD)); |
86 | return (EHClause->Flags & COR_ILEXCEPTION_CLAUSE_CACHED_CLASS); |
87 | } |
88 | |
89 | inline void SetHasCachedTypeHandle(EE_ILEXCEPTION_CLAUSE *EHClause) |
90 | { |
91 | _ASSERTE(! HasCachedTypeHandle(EHClause)); |
92 | EHClause->Flags = (CorExceptionFlag)(EHClause->Flags | COR_ILEXCEPTION_CLAUSE_CACHED_CLASS); |
93 | } |
94 | |
95 | inline BOOL IsFinally(EE_ILEXCEPTION_CLAUSE *EHClause) |
96 | { |
97 | LIMITED_METHOD_CONTRACT; |
98 | |
99 | return (EHClause->Flags & COR_ILEXCEPTION_CLAUSE_FINALLY); |
100 | } |
101 | |
102 | inline BOOL IsFault(EE_ILEXCEPTION_CLAUSE *EHClause) |
103 | { |
104 | LIMITED_METHOD_CONTRACT; |
105 | |
106 | return (EHClause->Flags & COR_ILEXCEPTION_CLAUSE_FAULT); |
107 | } |
108 | |
109 | inline BOOL IsFaultOrFinally(EE_ILEXCEPTION_CLAUSE *EHClause) |
110 | { |
111 | return IsFault(EHClause) || IsFinally(EHClause); |
112 | } |
113 | |
114 | inline BOOL IsFilterHandler(EE_ILEXCEPTION_CLAUSE *EHClause) |
115 | { |
116 | LIMITED_METHOD_CONTRACT; |
117 | |
118 | return EHClause->Flags & COR_ILEXCEPTION_CLAUSE_FILTER; |
119 | } |
120 | |
121 | inline BOOL IsTypedHandler(EE_ILEXCEPTION_CLAUSE *EHClause) |
122 | { |
123 | return ! (IsFilterHandler(EHClause) || IsFaultOrFinally(EHClause)); |
124 | } |
125 | |
126 | inline BOOL IsDuplicateClause(EE_ILEXCEPTION_CLAUSE* pEHClause) |
127 | { |
128 | return pEHClause->Flags & COR_ILEXCEPTION_CLAUSE_DUPLICATED; |
129 | } |
130 | |
131 | #if defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) |
132 | // Finally is the only EH construct that can be part of the execution as being fall-through. |
133 | // |
134 | // "Cloned" finally is a contruct that represents a finally block that is used as |
135 | // fall through for normal try-block execution. Such a "cloned" finally will: |
136 | // |
137 | // 1) Have its try-clause's Start and End PC the same as its handler's start PC (i.e. will have |
138 | // zero length try block), AND |
139 | // 2) Is marked duplicate |
140 | // |
141 | // Because of their fall-through nature, JIT guarantees that only finally constructs can be cloned, |
142 | // and not catch or fault (since they cannot be fallen through but are invoked as funclets). |
143 | // |
144 | // The cloned finally construct is also used to mark "call to finally" thunks that are not within |
145 | // the EH region protected by the finally, and also not within the enclosing region. This is done |
146 | // to prevent ThreadAbortException from creating an infinite loop of calling the same finally. |
147 | inline BOOL IsClonedFinally(EE_ILEXCEPTION_CLAUSE* pEHClause) |
148 | { |
149 | return ((pEHClause->TryStartPC == pEHClause->TryEndPC) && |
150 | (pEHClause->TryStartPC == pEHClause->HandlerStartPC) && |
151 | IsFinally(pEHClause) && IsDuplicateClause(pEHClause)); |
152 | } |
153 | #endif // defined(_TARGET_AMD64_) || defined(_TARGET_ARM64_) |
154 | |
155 | #endif // __eexcp_h__ |
156 | |
157 |