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
21struct EE_ILEXCEPTION_CLAUSE;
22typedef 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.
27typedef PTR_VOID PTR_EXCEPTION_CLAUSE_TOKEN;
28
29struct 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
44struct EE_ILEXCEPTION;
45typedef DPTR(EE_ILEXCEPTION) PTR_EE_ILEXCEPTION;
46
47struct 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
83inline 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
89inline void SetHasCachedTypeHandle(EE_ILEXCEPTION_CLAUSE *EHClause)
90{
91 _ASSERTE(! HasCachedTypeHandle(EHClause));
92 EHClause->Flags = (CorExceptionFlag)(EHClause->Flags | COR_ILEXCEPTION_CLAUSE_CACHED_CLASS);
93}
94
95inline BOOL IsFinally(EE_ILEXCEPTION_CLAUSE *EHClause)
96{
97 LIMITED_METHOD_CONTRACT;
98
99 return (EHClause->Flags & COR_ILEXCEPTION_CLAUSE_FINALLY);
100}
101
102inline BOOL IsFault(EE_ILEXCEPTION_CLAUSE *EHClause)
103{
104 LIMITED_METHOD_CONTRACT;
105
106 return (EHClause->Flags & COR_ILEXCEPTION_CLAUSE_FAULT);
107}
108
109inline BOOL IsFaultOrFinally(EE_ILEXCEPTION_CLAUSE *EHClause)
110{
111 return IsFault(EHClause) || IsFinally(EHClause);
112}
113
114inline BOOL IsFilterHandler(EE_ILEXCEPTION_CLAUSE *EHClause)
115{
116 LIMITED_METHOD_CONTRACT;
117
118 return EHClause->Flags & COR_ILEXCEPTION_CLAUSE_FILTER;
119}
120
121inline BOOL IsTypedHandler(EE_ILEXCEPTION_CLAUSE *EHClause)
122{
123 return ! (IsFilterHandler(EHClause) || IsFaultOrFinally(EHClause));
124}
125
126inline 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.
147inline 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