Merge pull request #14619 from briansull/emitter-cleanup
[platform/upstream/coreclr.git] / src / vm / excep.h
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 // EXCEP.H
5 //
6
7 //
8
9
10 #ifndef __excep_h__
11 #define __excep_h__
12
13 #include "exstatecommon.h"
14 #include "exceptmacros.h"
15 #include "corerror.h"  // HResults for the COM+ Runtime
16 #include "corexcep.h"  // Exception codes for the COM+ Runtime
17
18 class Thread;
19
20 #include "../dlls/mscorrc/resource.h"
21
22 #include <excepcpu.h>
23 #include "interoputil.h"
24
25 BOOL IsExceptionFromManagedCode(const EXCEPTION_RECORD * pExceptionRecord);
26 bool IsIPInMarkedJitHelper(UINT_PTR uControlPc);
27
28 #if defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK)
29
30 // General purpose functions for use on an IP in jitted code. 
31 bool IsIPInProlog(EECodeInfo *pCodeInfo);
32 bool IsIPInEpilog(PTR_CONTEXT pContextToCheck, EECodeInfo *pCodeInfo, BOOL *pSafeToInjectThreadAbort);
33
34 #endif // defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK)
35
36 void RaiseFailFastExceptionOnWin7(PEXCEPTION_RECORD pExceptionRecord, PT_CONTEXT pContext);
37
38 // Check if the Win32 Error code is an IO error.
39 BOOL IsWin32IOError(SCODE scode);
40
41 //******************************************************************************
42 //
43 //  SwallowUnhandledExceptions
44 //
45 //   Consult the EE policy and the app config to determine if the runtime should "swallow" unhandled exceptions.
46 //   Swallow if: the EEPolicy->UnhandledExceptionPolicy is "eHostDeterminedPolicy"
47 //           or: the app config value LegacyUnhandledExceptionPolicy() is set.
48 //
49 //  Parameters: 
50 //    none
51 //
52 //  Return value:
53 //    true - the runtime should "swallow" unhandled exceptions
54 //
55 inline bool SwallowUnhandledExceptions()
56 {
57     return (eHostDeterminedPolicy == GetEEPolicy()->GetUnhandledExceptionPolicy()) ||
58            g_pConfig->LegacyUnhandledExceptionPolicy();
59 }
60
61 // Enums
62 // return values of LookForHandler
63 enum LFH {
64     LFH_NOT_FOUND = 0,
65     LFH_FOUND = 1,
66 };
67
68 #include "runtimeexceptionkind.h"
69
70 class IJitManager;
71
72 //
73 // ThrowCallbackType is used to pass information to between various functions and the callbacks that they call
74 // during a managed stack walk.
75 //
76 struct ThrowCallbackType
77 {
78     MethodDesc * pFunc;     // the function containing a filter that returned catch indication
79     int     dHandler;       // the index of the handler whose filter returned catch indication
80     BOOL    bIsUnwind;      // are we currently unwinding an exception
81     BOOL    bUnwindStack;   // reset the stack before calling the handler? (Stack overflow only)
82     BOOL    bAllowAllocMem; // are we allowed to allocate memory?
83     BOOL    bDontCatch;     // can we catch this exception?
84     BYTE    *pStack;
85     Frame * pTopFrame;
86     Frame * pBottomFrame;
87     MethodDesc * pProfilerNotify;   // Context for profiler callbacks -- see COMPlusFrameHandler().
88     BOOL    bReplaceStack;  // Used to pass info to SaveStackTrace call
89     BOOL    bSkipLastElement;// Used to pass info to SaveStackTrace call
90 #ifdef _DEBUG
91     void * pCurrentExceptionRecord;
92     void * pPrevExceptionRecord;
93 #endif
94
95     // Is the current exception a longjmp?
96     CORRUPTING_EXCEPTIONS_ONLY(BOOL     m_fIsLongJump;)
97     void Init()
98     {
99         LIMITED_METHOD_CONTRACT;
100
101         pFunc = NULL;
102         dHandler = 0;
103         bIsUnwind = FALSE;
104         bUnwindStack = FALSE;
105         bAllowAllocMem = TRUE;
106         bDontCatch = FALSE;
107         pStack = NULL;
108         pTopFrame = (Frame *)-1;
109         pBottomFrame = (Frame *)-1;
110         pProfilerNotify = NULL;
111         bReplaceStack = FALSE;
112         bSkipLastElement = FALSE;
113 #ifdef _DEBUG
114         pCurrentExceptionRecord = 0;
115         pPrevExceptionRecord = 0;
116 #endif
117         // By default, the current exception is not a longjmp
118         CORRUPTING_EXCEPTIONS_ONLY(m_fIsLongJump = FALSE;)
119     }
120 };
121
122
123
124 struct EE_ILEXCEPTION_CLAUSE;
125
126 void InitializeExceptionHandling();
127 void CLRAddVectoredHandlers(void);
128 void CLRRemoveVectoredHandlers(void);
129 void TerminateExceptionHandling();
130
131 // Prototypes
132 EXTERN_C VOID STDCALL ResetCurrentContext();
133 #if !defined(WIN64EXCEPTIONS)
134 #ifdef _DEBUG
135 void CheckStackBarrier(EXCEPTION_REGISTRATION_RECORD *exRecord);
136 #endif
137 EXCEPTION_REGISTRATION_RECORD *FindNestedEstablisherFrame(EXCEPTION_REGISTRATION_RECORD *pEstablisherFrame);
138 LFH LookForHandler(const EXCEPTION_POINTERS *pExceptionPointers, Thread *pThread, ThrowCallbackType *tct);
139 StackWalkAction COMPlusThrowCallback (CrawlFrame *pCf, ThrowCallbackType *pData);
140 void UnwindFrames(Thread *pThread, ThrowCallbackType *tct);
141 #endif // !defined(WIN64EXCEPTIONS)
142
143 void UnwindFrameChain(Thread *pThread, LPVOID pvLimitSP);
144 DWORD MapWin32FaultToCOMPlusException(EXCEPTION_RECORD *pExceptionRecord);
145 DWORD ComputeEnclosingHandlerNestingLevel(IJitManager *pIJM, const METHODTOKEN& mdTok, SIZE_T offsNat);
146 BOOL IsException(MethodTable *pMT);
147 BOOL IsExceptionOfType(RuntimeExceptionKind reKind, OBJECTREF *pThrowable);
148 BOOL IsExceptionOfType(RuntimeExceptionKind reKind, Exception *pException);
149 BOOL IsAsyncThreadException(OBJECTREF *pThrowable);
150 BOOL IsUncatchable(OBJECTREF *pThrowable);
151 VOID FixupOnRethrow(Thread *pCurThread, EXCEPTION_POINTERS *pExceptionPointers);
152 BOOL UpdateCurrentThrowable(PEXCEPTION_RECORD pExceptionRecord);
153 BOOL IsStackOverflowException(Thread* pThread, EXCEPTION_RECORD* pExceptionRecord);
154 void WrapNonCompliantException(OBJECTREF *ppThrowable);
155 OBJECTREF PossiblyUnwrapThrowable(OBJECTREF throwable, Assembly *pAssembly);
156 BOOL ExceptionTypeOverridesStackTraceGetter(PTR_MethodTable pMT);
157
158 // Removes source file names/paths and line information from a stack trace.
159 void StripFileInfoFromStackTrace(SString &ssStackTrace); 
160
161 #ifdef _DEBUG
162 // C++ EH cracking material gleaned from the debugger:
163 // (DO NOT USE THIS KNOWLEDGE IN NON-DEBUG CODE!!!)
164 void *DebugGetCxxException(EXCEPTION_RECORD* pExceptionRecord);
165 #endif
166
167
168 #ifdef _DEBUG_IMPL
169 BOOL IsValidClause(EE_ILEXCEPTION_CLAUSE *EHClause);
170 BOOL IsCOMPlusExceptionHandlerInstalled();
171 #endif
172
173 BOOL InstallUnhandledExceptionFilter();
174 void UninstallUnhandledExceptionFilter();
175
176 #if !defined(FEATURE_PAL)
177 // Section naming is a strategy by itself. Ideally, we could have named the UEF section
178 // ".text$zzz" (lowercase after $ is important). What the linker does is look for the sections
179 // that has the same name before '$' sign. It combines them together but sorted in an alphabetical
180 // order. Thus, naming the UEF section ".text$zzz" would ensure that the UEF section is the last
181 // thing in the .text section. Reason for opting out of this approach was that BBT can move code
182 // within a section, no matter where it was located - and for this case, we need the UEF code
183 // at the right location to ensure that we can check the memory protection of its following
184 // section so that shouldnt affect UEF's memory protection. For details, read the comment in
185 // "CExecutionEngine::ClrVirtualProtect".
186 //
187 // Keeping UEF in its own section helps prevent code movement as BBT does not reorder
188 // sections. As per my understanding of the linker, ".text" section always comes first,
189 // followed by other "executable" sections (like our UEF section) and then ".data", etc.
190 // The order of user defined executable sections is typically defined by the linker
191 // in terms of which section it sees first. So, if there is another custom executable
192 // section that comes after UEF section, it can affect the UEF section and we will
193 // assert about it in "CExecutionEngine::ClrVirtualProtect".
194 #define CLR_UEF_SECTION_NAME ".CLR_UEF"
195 #endif //!defined(FEATURE_PAL)
196 LONG __stdcall COMUnhandledExceptionFilter(EXCEPTION_POINTERS *pExceptionInfo);
197
198
199 //////////////
200 // A list of places where we might have unhandled exceptions or other serious faults. These can be used as a mask in
201 // DbgJITDebuggerLaunchSetting to help control when we decide to ask the user about whether or not to launch a debugger.
202 //
203 enum UnhandledExceptionLocation
204     {
205     ProcessWideHandler    = 0x000001,
206     ManagedThread         = 0x000002, // Does not terminate the application. CLR swallows the unhandled exception.
207     ThreadPoolThread      = 0x000004, // ditto.
208     FinalizerThread       = 0x000008, // ditto.
209     FatalStackOverflow    = 0x000010,
210     SystemNotification    = 0x000020, // CLR will swallow after the notification occurs
211     FatalExecutionEngineException = 0x000040,
212     ClassInitUnhandledException   = 0x000080, // Does not terminate the application. CLR transforms this into TypeInitializationException
213
214     MaximumLocationValue  = 0x800000, // This is the maximum location value you're allowed to use. (Max 24 bits allowed.)
215
216     // This is a mask of all the locations that the debugger will attach to by default.
217     DefaultDebuggerAttach = ProcessWideHandler |
218                             FatalStackOverflow |
219                             FatalExecutionEngineException
220 };
221
222 struct ThreadBaseExceptionFilterParam
223 {
224     UnhandledExceptionLocation location;
225 };
226
227 LONG ThreadBaseExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pvParam);
228 LONG ThreadBaseExceptionSwallowingFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pvParam);
229 LONG ThreadBaseExceptionAppDomainFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pvParam);
230
231 // Filter for calls out from the 'vm' to native code, if there's a possibility of SEH exceptions
232 // in the native code.
233 struct CallOutFilterParam { BOOL OneShot; };
234 LONG CallOutFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pv);
235
236
237 void DECLSPEC_NORETURN RaiseDeadLockException();
238
239 void STDMETHODCALLTYPE DefaultCatchHandler(PEXCEPTION_POINTERS pExceptionInfo,
240                                            OBJECTREF *Throwable = NULL,
241                                            BOOL useLastThrownObject = FALSE,
242                                            BOOL isTerminating = FALSE,
243                                            BOOL isThreadBaseFilter = FALSE,
244                                            BOOL sendAppDomainEvents = TRUE);
245
246 void ReplaceExceptionContextRecord(T_CONTEXT *pTarget, T_CONTEXT *pSource);
247
248 // Localization helper function
249 void ResMgrGetString(LPCWSTR wszResourceName, STRINGREF * ppMessage);
250
251 // externs
252
253 //==========================================================================
254 // Various routines to throw COM+ objects.
255 //==========================================================================
256
257 //==========================================================================
258 // Throw an undecorated runtime exception with a specific string parameter
259 // that won't be localized.  If possible, try using
260 // COMPlusThrow(reKind, LPCWSTR wszResourceName) instead.
261 //==========================================================================
262
263 VOID DECLSPEC_NORETURN RealCOMPlusThrowNonLocalized(RuntimeExceptionKind reKind, LPCWSTR wszTag);
264
265 //==========================================================================
266 // Throw an object.
267 //==========================================================================
268
269 VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable 
270 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
271                                         , CorruptionSeverity severity = NotCorrupting
272 #endif // FEATURE_CORRUPTING_EXCEPTIONS
273                                         );
274
275 //==========================================================================
276 // Throw an undecorated runtime exception.
277 //==========================================================================
278
279 VOID DECLSPEC_NORETURN RealCOMPlusThrow(RuntimeExceptionKind reKind);
280
281 //==========================================================================
282 // Throw an undecorated runtime exception with a localized message.  Given
283 // a resource name, the ResourceManager will find the correct paired string
284 // in our .resources file.
285 //==========================================================================
286
287 VOID DECLSPEC_NORETURN RealCOMPlusThrow(RuntimeExceptionKind reKind, LPCWSTR wszResourceName, Exception * pInnerException = NULL);
288
289 //==========================================================================
290 // Throw a decorated runtime exception.
291 //==========================================================================
292
293 VOID DECLSPEC_NORETURN RealCOMPlusThrow(RuntimeExceptionKind  reKind, UINT resID, 
294                                         LPCWSTR wszArg1 = NULL, LPCWSTR wszArg2 = NULL, LPCWSTR wszArg3 = NULL, 
295                                         LPCWSTR wszArg4 = NULL, LPCWSTR wszArg5 = NULL, LPCWSTR wszArg6 = NULL);
296
297
298 //==========================================================================
299 // Throw a runtime exception based on an HResult. Note that for the version 
300 // of RealCOMPlusThrowHR that takes a resource ID, the HRESULT will be 
301 // passed as the first substitution string (%1).
302 //==========================================================================
303
304 enum tagGetErrorInfo
305 {
306     kGetErrorInfo
307 };
308
309 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, IErrorInfo* pErrInfo, Exception * pInnerException = NULL);
310 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, tagGetErrorInfo);
311 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr);
312 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, UINT resID, LPCWSTR wszArg1 = NULL, LPCWSTR wszArg2 = NULL, 
313                                           LPCWSTR wszArg3 = NULL, LPCWSTR wszArg4 = NULL, LPCWSTR wszArg5 = NULL, 
314                                           LPCWSTR wszArg6 = NULL);
315
316 #ifdef FEATURE_COMINTEROP
317
318 //==========================================================================
319 // Throw a runtime exception based on an HResult, check for error info
320 //==========================================================================
321
322 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, IUnknown *iface, REFIID riid);
323
324
325 //==========================================================================
326 // Throw a runtime exception based on an EXCEPINFO. This function will free
327 // the strings in the EXCEPINFO that is passed in.
328 //==========================================================================
329
330 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(EXCEPINFO *pExcepInfo);
331
332 #endif // FEATURE_COMINTEROP
333
334 //==========================================================================
335 // Throw a runtime exception based on the last Win32 error (GetLastError())
336 //==========================================================================
337
338 VOID DECLSPEC_NORETURN RealCOMPlusThrowWin32();
339 VOID DECLSPEC_NORETURN RealCOMPlusThrowWin32(HRESULT hr);
340
341
342 //==========================================================================
343 // Create an exception object
344 // Note that this may not succeed due to problems creating the exception
345 // object. On failure, it will set pInitException to the value of
346 // pInnerException, and will set pThrowable to the exception that got thrown
347 // while trying to create the TypeInitializationException object, which
348 // could be due to other type init issues, OOM, thread abort, etc.
349 // pInnerException (may be NULL) and pInitException and are IN params.
350 // pThrowable is an OUT param.
351 //==========================================================================
352 void CreateTypeInitializationExceptionObject(LPCWSTR pTypeThatFailed,
353                                              OBJECTREF *pInnerException, 
354                                              OBJECTREF *pInitException,
355                                              OBJECTREF *pThrowable);
356
357 //==========================================================================
358 // Examine an exception object
359 //==========================================================================
360
361 ULONG GetExceptionMessage(OBJECTREF throwable,
362                           __inout_ecount(bufferLength) LPWSTR buffer,
363                           ULONG bufferLength);
364 void GetExceptionMessage(OBJECTREF throwable, SString &result);
365 STRINGREF GetExceptionMessage(OBJECTREF throwable);
366 HRESULT GetExceptionHResult(OBJECTREF throwable);
367 DWORD GetExceptionXCode(OBJECTREF throwable);
368
369 void ExceptionPreserveStackTrace(OBJECTREF throwable);
370
371
372 //==========================================================================
373 // Create an exception object for an HRESULT
374 //==========================================================================
375
376 void GetExceptionForHR(HRESULT hr, IErrorInfo* pErrInfo, bool fUseCOMException, OBJECTREF* pProtectedThrowable, IRestrictedErrorInfo *pResErrorInfo = NULL, BOOL bHasLanguageRestrictedErrorInfo = FALSE);
377 void GetExceptionForHR(HRESULT hr, IErrorInfo* pErrInfo, OBJECTREF* pProtectedThrowable);
378 void GetExceptionForHR(HRESULT hr, OBJECTREF* pProtectedThrowable);
379 HRESULT GetHRFromThrowable(OBJECTREF throwable);
380
381 #if FEATURE_COMINTEROP
382 IRestrictedErrorInfo* GetRestrictedErrorInfoFromErrorObject(OBJECTREF throwable);
383 #endif
384 //==========================================================================
385 // Throw an ArithmeticException
386 //==========================================================================
387
388 VOID DECLSPEC_NORETURN RealCOMPlusThrowArithmetic();
389
390 //==========================================================================
391 // Throw an ArgumentNullException
392 //==========================================================================
393
394 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentNull(LPCWSTR argName, LPCWSTR wszResourceName);
395
396 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentNull(LPCWSTR argName);
397
398 //==========================================================================
399 // Throw an ArgumentOutOfRangeException
400 //==========================================================================
401
402 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentOutOfRange(LPCWSTR argName, LPCWSTR wszResourceName);
403
404 //==========================================================================
405 // Throw an ArgumentException
406 //==========================================================================
407 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentException(LPCWSTR argName, LPCWSTR wszResourceName);
408
409 //==========================================================================
410 // Throw an InvalidCastException
411 //==========================================================================
412 VOID DECLSPEC_NORETURN RealCOMPlusThrowInvalidCastException(TypeHandle thCastFrom, TypeHandle thCastTo);
413
414 VOID DECLSPEC_NORETURN RealCOMPlusThrowInvalidCastException(OBJECTREF *pObj, TypeHandle thCastTo);
415
416
417 #ifndef WIN64EXCEPTIONS
418
419 #include "eexcp.h"
420 #include "exinfo.h"
421
422 struct FrameHandlerExRecord
423 {
424     EXCEPTION_REGISTRATION_RECORD   m_ExReg;
425
426     Frame *m_pEntryFrame;
427
428     Frame *GetCurrFrame() 
429     {
430         LIMITED_METHOD_CONTRACT;
431         return m_pEntryFrame;
432     }
433 };
434
435 struct NestedHandlerExRecord : public FrameHandlerExRecord 
436 {
437     ExInfo m_handlerInfo;
438     BOOL   m_ActiveForUnwind;
439     ExInfo *m_pCurrentExInfo;
440     EXCEPTION_REGISTRATION_RECORD *m_pCurrentHandler;
441     NestedHandlerExRecord() : m_handlerInfo() {LIMITED_METHOD_CONTRACT;}
442     void Init(PEXCEPTION_ROUTINE pFrameHandler, Frame *pEntryFrame)
443     {
444         WRAPPER_NO_CONTRACT;
445
446         m_ExReg.Next=NULL;
447         m_ExReg.Handler=pFrameHandler;
448         m_pEntryFrame=pEntryFrame;
449         m_pCurrentExInfo = NULL;
450         m_pCurrentHandler = NULL;
451         m_handlerInfo.Init();
452         m_ActiveForUnwind = FALSE;
453     }
454 };
455
456 #endif // !WIN64EXCEPTIONS
457
458 #if defined(ENABLE_CONTRACTS_IMPL)
459
460 // Never call this class directly: Call it through CANNOTTHROWCOMPLUSEXCEPTION.
461 class COMPlusCannotThrowExceptionHelper
462 {
463 public:
464     DEBUG_NOINLINE COMPlusCannotThrowExceptionHelper(BOOL    fCond,
465                                       const char *szFunction,
466                                       const char *szFile,
467                                       int         linenum)
468     {
469         SCAN_SCOPE_BEGIN;
470         STATIC_CONTRACT_NOTHROW;  
471
472         m_fCond = fCond;
473         
474         if (m_fCond)
475         {
476             m_pClrDebugState = GetClrDebugState();
477             m_oldClrDebugState = *m_pClrDebugState;
478
479             m_ContractStackRecord.m_szFunction = szFunction;
480             m_ContractStackRecord.m_szFile     = szFile;
481             m_ContractStackRecord.m_lineNum    = linenum;
482             m_ContractStackRecord.m_testmask   = (Contract::ALL_Disabled & ~((UINT)(Contract::THROWS_Mask))) | Contract::THROWS_No;
483             m_ContractStackRecord.m_construct  = "CANNOTTHROW";
484             m_pClrDebugState->LinkContractStackTrace( &m_ContractStackRecord );
485
486             m_pClrDebugState->ViolationMaskReset( ThrowsViolation );
487             m_pClrDebugState->ResetOkToThrow();
488         }
489     }
490
491     DEBUG_NOINLINE ~COMPlusCannotThrowExceptionHelper()
492     {
493         SCAN_SCOPE_END;
494
495         if (m_fCond)
496         {
497             *m_pClrDebugState = m_oldClrDebugState;
498         }
499     }
500
501 private:
502     BOOL m_fCond;
503
504     ClrDebugState      *m_pClrDebugState;
505     ClrDebugState       m_oldClrDebugState;
506
507     ContractStackRecord   m_ContractStackRecord;
508 };
509
510 #endif // ENABLE_CONTRACTS_IMPL
511
512 //-------------------------------------------------------------------------------
513 // This simply tests to see if the exception object is a subclass of
514 // the descriminating class specified in the exception clause.
515 //-------------------------------------------------------------------------------
516 extern "C" BOOL ExceptionIsOfRightType(TypeHandle clauseType, TypeHandle thrownType);
517
518 //==========================================================================
519 // The stuff below is what works "behind the scenes" of the public macros.
520 //==========================================================================
521
522
523 // Specify NULL for uTryCatchResumeAddress when not checking for a InducedThreadRedirectAtEndOfCatch
524 EXTERN_C LPVOID COMPlusCheckForAbort(UINT_PTR uTryCatchResumeAddress = NULL);
525
526 BOOL        IsThreadHijackedForThreadStop(Thread* pThread, EXCEPTION_RECORD* pExceptionRecord);
527 void        AdjustContextForThreadStop(Thread* pThread, T_CONTEXT* pContext);
528 OBJECTREF   CreateCOMPlusExceptionObject(Thread* pThread, EXCEPTION_RECORD* pExceptionRecord, BOOL bAsynchronousThreadStop);
529
530 #if !defined(WIN64EXCEPTIONS)
531 EXCEPTION_HANDLER_DECL(COMPlusFrameHandler);
532 EXCEPTION_HANDLER_DECL(COMPlusNestedExceptionHandler);
533 #ifdef FEATURE_COMINTEROP
534 EXCEPTION_HANDLER_DECL(COMPlusFrameHandlerRevCom);
535 #endif // FEATURE_COMINTEROP
536
537 // Pop off any SEH handlers we have registered below pTargetSP
538 VOID __cdecl PopSEHRecords(LPVOID pTargetSP);
539
540 #if defined(_TARGET_X86_) && defined(DEBUGGING_SUPPORTED)
541 VOID UnwindExceptionTrackerAndResumeInInterceptionFrame(ExInfo* pExInfo, EHContext* context);
542 #endif // _TARGET_X86_ && DEBUGGING_SUPPORTED
543
544 BOOL PopNestedExceptionRecords(LPVOID pTargetSP, BOOL bCheckForUnknownHandlers = FALSE);
545 VOID PopNestedExceptionRecords(LPVOID pTargetSP, T_CONTEXT *pCtx, void *pSEH);
546
547 // Misc functions to access and update the SEH chain. Be very, very careful about updating the SEH chain.
548 // Frankly, if you think you need to use one of these function, please
549 // consult with the owner of the exception system.
550 PEXCEPTION_REGISTRATION_RECORD GetCurrentSEHRecord();
551 VOID SetCurrentSEHRecord(EXCEPTION_REGISTRATION_RECORD *pSEH);
552
553
554 #define STACK_OVERWRITE_BARRIER_SIZE 20
555 #define STACK_OVERWRITE_BARRIER_VALUE 0xabcdefab
556
557 #ifdef _DEBUG
558 #if defined(_TARGET_X86_)
559 struct FrameHandlerExRecordWithBarrier {
560     DWORD m_StackOverwriteBarrier[STACK_OVERWRITE_BARRIER_SIZE];
561     FrameHandlerExRecord m_ExRecord;
562 };
563
564 void VerifyValidTransitionFromManagedCode(Thread *pThread, CrawlFrame *pCF);
565 #endif // defined(_TARGET_X86_)
566 #endif // _DEBUG
567 #endif // !defined(WIN64EXCEPTIONS)
568
569 //==========================================================================
570 // This is a workaround designed to allow the use of the StubLinker object at bootup
571 // time where the EE isn't sufficient awake to create COM+ exception objects.
572 // Instead, COMPlusThrow(rexcep) does a simple RaiseException using this code.
573 // Or use COMPlusThrowBoot() to explicitly do so.
574 //==========================================================================
575 #define BOOTUP_EXCEPTION_COMPLUS  0xC0020001
576
577 void COMPlusThrowBoot(HRESULT hr);
578
579
580 //==========================================================================
581 // Used by the classloader to record a managed exception object to explain
582 // why a classload got botched.
583 //
584 // - Can be called with gc enabled or disabled.
585 //   This allows a catch-all error path to post a generic catchall error
586 //   message w/out bonking more specific error messages posted by inner functions.
587 //==========================================================================
588 VOID DECLSPEC_NORETURN ThrowTypeLoadException(LPCUTF8 pNameSpace, LPCUTF8 pTypeName,
589                            LPCWSTR pAssemblyName, LPCUTF8 pMessageArg,
590                            UINT resIDWhy);
591
592 VOID DECLSPEC_NORETURN ThrowTypeLoadException(LPCWSTR pFullTypeName,
593                                               LPCWSTR pAssemblyName,
594                                               LPCUTF8 pMessageArg,
595                                               UINT resIDWhy);
596
597 VOID DECLSPEC_NORETURN ThrowFieldLayoutError(mdTypeDef cl,                // cl of the NStruct being loaded
598                            Module* pModule,             // Module that defines the scope, loader and heap (for allocate FieldMarshalers)
599                            DWORD   dwOffset,            // Field offset
600                            DWORD   dwID);
601
602 UINT GetResourceIDForFileLoadExceptionHR(HRESULT hr);
603
604 FCDECL1(Object*, MissingMemberException_FormatSignature, I1Array* pPersistedSigUNSAFE);
605 FCDECL1(Object*, GetResourceFromDefault, StringObject* key);
606
607 #define EXCEPTION_NONCONTINUABLE 0x1    // Noncontinuable exception
608 #define EXCEPTION_UNWINDING 0x2         // Unwind is in progress
609 #define EXCEPTION_EXIT_UNWIND 0x4       // Exit unwind is in progress
610 #define EXCEPTION_STACK_INVALID 0x8     // Stack out of limits or unaligned
611 #define EXCEPTION_NESTED_CALL 0x10      // Nested exception handler call
612 #define EXCEPTION_TARGET_UNWIND 0x20    // Target unwind in progress
613 #define EXCEPTION_COLLIDED_UNWIND 0x40  // Collided exception handler call
614
615 #define EXCEPTION_UNWIND (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | \
616                           EXCEPTION_TARGET_UNWIND | EXCEPTION_COLLIDED_UNWIND)
617
618 #define IS_UNWINDING(Flag) ((Flag & EXCEPTION_UNWIND) != 0)
619
620 //#include "CodeMan.h"
621
622 class EHRangeTreeNode;
623 class EHRangeTree;
624
625 typedef CUnorderedArray<EHRangeTreeNode *, 7> EH_CLAUSE_UNORDERED_ARRAY;
626
627 class EHRangeTreeNode
628 {
629 public:
630     EHRangeTree                *m_pTree;
631     EE_ILEXCEPTION_CLAUSE      *m_clause;
632
633     EHRangeTreeNode            *m_pContainedBy;
634     EH_CLAUSE_UNORDERED_ARRAY   m_containees;
635
636     DWORD                       m_FilterEndPC;
637
638 private:
639     // A node can represent a range or a single offset.
640     // A node representing a range can either be the root node, which
641     // contains everything and has a NULL m_clause, or it can be
642     // a node mapping to an EH clause.
643     DWORD                       m_offset;
644     bool                        m_fIsRange;
645     bool                        m_fIsRoot;
646
647 public:
648     EHRangeTreeNode(void);
649     EHRangeTreeNode(DWORD offset, bool fIsRange = false);
650     void CommonCtor(DWORD offset, bool fIsRange);
651
652     bool IsRange();
653     void MarkAsRange();
654
655     bool IsRoot();
656     void MarkAsRoot(DWORD offset);
657
658     DWORD GetOffset();
659     DWORD GetTryStart();
660     DWORD GetTryEnd();
661     DWORD GetHandlerStart();
662     DWORD GetHandlerEnd();
663     DWORD GetFilterStart();
664     DWORD GetFilterEnd();
665
666     // These four functions may actually be called via FindContainer() while we are building the tree
667     // structure, in which case we shouldn't really check the tree recursively because the result is unreliable.
668     // Thus, they check m_pTree->m_fInitializing to see if they should call themselves recursively.
669     // Also, FindContainer() has extra logic to work around this boot-strapping problem.
670     bool Contains(EHRangeTreeNode* pNode);
671     bool TryContains(EHRangeTreeNode* pNode);
672     bool HandlerContains(EHRangeTreeNode* pNode);
673     bool FilterContains(EHRangeTreeNode* pNode);
674
675     // These are simple wrappers around the previous four.
676     bool Contains(DWORD offset);
677     bool TryContains(DWORD offset);
678     bool HandlerContains(DWORD offset);
679     bool FilterContains(DWORD offset);
680
681     EHRangeTreeNode* GetContainer();
682
683     HRESULT AddNode(EHRangeTreeNode *pNode);
684 } ;
685
686 class EHRangeTree
687 {
688     unsigned                m_EHCount;
689     EHRangeTreeNode        *m_rgNodes;
690     EE_ILEXCEPTION_CLAUSE  *m_rgClauses;
691
692 public:
693
694     EHRangeTreeNode        *m_root; // This is a sentinel, NOT an actual
695                                     // Exception Handler!
696     HRESULT                 m_hrInit; // Ctor fills this out.
697
698     bool                    m_fInitializing;
699
700     EHRangeTree(IJitManager* pIJM,
701                 const METHODTOKEN& methodToken,
702                 DWORD         methodSize,
703                 int           cFunclet,
704                 const DWORD * rgFuncletOffset);
705
706     ~EHRangeTree();
707
708     EHRangeTreeNode *FindContainer(EHRangeTreeNode *pNodeCur);
709     EHRangeTreeNode *FindMostSpecificContainer(DWORD addr);
710     EHRangeTreeNode *FindNextMostSpecificContainer(EHRangeTreeNode *pNodeCur,
711                                                    DWORD addr);
712
713     // <TODO> We shouldn't need this - instead, we
714     // should get sequence points annotated with whether they're STACK_EMPTY, etc,
715     // and then we'll figure out if the destination is ok based on that, instead.</TODO>
716     BOOL isAtStartOfCatch(DWORD offset);
717 } ;
718
719 HRESULT SetIPFromSrcToDst(Thread *pThread,
720                           SLOT addrStart,       // base address of method
721                           DWORD offFrom,        // native offset
722                           DWORD offTo,          // native offset
723                           bool fCanSetIPOnly,   // if true, don't do any real work
724                           PREGDISPLAY pReg,
725                           PT_CONTEXT pCtx,
726                           void *pDji,
727                           EHRangeTree *pEHRT);
728
729 BOOL IsInFirstFrameOfHandler(Thread *pThread,
730                              IJitManager *pJitManager,
731                              const METHODTOKEN& MethodToken,
732                              DWORD offSet);
733
734 //==========================================================================
735 // Handy helper functions
736 //==========================================================================
737 LONG FilterAccessViolation(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
738
739 bool IsContinuableException(Thread *pThread);
740
741 bool IsInterceptableException(Thread *pThread);
742
743 #ifdef DEBUGGING_SUPPORTED
744 // perform simple checking to see if the current exception is intercepted
745 bool CheckThreadExceptionStateForInterception();
746
747 #ifndef FEATURE_PAL
748 // Currently, only Windows supports ClrUnwindEx (used inside ClrDebuggerDoUnwindAndIntercept)
749 #define DEBUGGER_EXCEPTION_INTERCEPTION_SUPPORTED
750 #endif // !FEATURE_PAL
751
752 #ifdef DEBUGGER_EXCEPTION_INTERCEPTION_SUPPORTED
753 // Intercept the current exception and start an unwind.  This function may never return.
754 EXCEPTION_DISPOSITION ClrDebuggerDoUnwindAndIntercept(X86_FIRST_ARG(EXCEPTION_REGISTRATION_RECORD *pEstablisherFrame)
755                                                       EXCEPTION_RECORD *pExceptionRecord);
756 #endif // DEBUGGER_EXCEPTION_INTERCEPTION_SUPPORTED
757
758 LONG NotifyDebuggerLastChance(Thread *pThread,
759                               EXCEPTION_POINTERS *pExceptionInfo,
760                               BOOL jitAttachRequested);
761 #endif // DEBUGGING_SUPPORTED
762
763 #if defined(_TARGET_X86_)
764 void CPFH_AdjustContextForThreadSuspensionRace(T_CONTEXT *pContext, Thread *pThread);
765 #endif // _TARGET_X86_
766
767 DWORD GetGcMarkerExceptionCode(LPVOID ip);
768 bool IsGcMarker(DWORD exceptionCode, T_CONTEXT *pContext);
769
770 void InitSavedExceptionInfo();
771
772 bool ShouldHandleManagedFault(
773                         EXCEPTION_RECORD*               pExceptionRecord,
774                         T_CONTEXT*                        pContext,
775                         EXCEPTION_REGISTRATION_RECORD*  pEstablisherFrame,
776                         Thread*                         pThread);
777
778 void HandleManagedFault(EXCEPTION_RECORD*               pExceptionRecord,
779                         T_CONTEXT*                        pContext,
780                         EXCEPTION_REGISTRATION_RECORD*  pEstablisherFrame,
781                         Thread*                         pThread);
782
783 LONG WatsonLastChance(
784     Thread              *pThread,
785     EXCEPTION_POINTERS  *pExceptionInfo,
786     TypeOfReportedError tore);
787
788 bool DebugIsEECxxException(EXCEPTION_RECORD* pExceptionRecord);
789
790
791 inline void CopyOSContext(T_CONTEXT* pDest, T_CONTEXT* pSrc)
792 {
793     SIZE_T cbReadOnlyPost = 0;
794 #ifdef _TARGET_AMD64_
795     cbReadOnlyPost = sizeof(CONTEXT) - FIELD_OFFSET(CONTEXT, FltSave); // older OSes don't have the vector reg fields
796 #endif // _TARGET_AMD64_
797
798     memcpyNoGCRefs(pDest, pSrc, sizeof(T_CONTEXT) - cbReadOnlyPost);
799 }
800
801 void SaveCurrentExceptionInfo(PEXCEPTION_RECORD pRecord, PT_CONTEXT pContext);
802
803 #ifdef _DEBUG
804 void SetReversePInvokeEscapingUnhandledExceptionStatus(BOOL fIsUnwinding,
805 #ifdef _TARGET_X86_
806                                                        EXCEPTION_REGISTRATION_RECORD * pEstablisherFrame
807 #elif defined(WIN64EXCEPTIONS)
808                                                        ULONG64 pEstablisherFrame
809 #else
810 #error Unsupported platform
811 #endif
812                                                        );
813 #endif // _DEBUG
814
815 // See implementation for detailed comments in excep.cpp
816 LONG AppDomainTransitionExceptionFilter(
817     EXCEPTION_POINTERS *pExceptionInfo, // the pExceptionInfo passed to a filter function.
818     PVOID               pParam);         
819
820 // See implementation for detailed comments in excep.cpp
821 LONG ReflectionInvocationExceptionFilter(
822     EXCEPTION_POINTERS *pExceptionInfo, // the pExceptionInfo passed to a filter function.
823     PVOID               pParam);         
824
825 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
826 // -----------------------------------------------------------------------
827 // Support for Corrupted State Exceptions
828 // -----------------------------------------------------------------------
829 #ifndef HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE
830 #define HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE "System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute"
831 #endif // HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE
832
833 #ifndef HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME
834 #define HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME 2
835 #endif // HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME
836
837 // This helper class contains static method to support working with Corrupted State Exceptions, 
838 // including checking if a method can handle it or not, copy state across throwables, etc.
839 class CEHelper
840 {
841     BOOL static IsMethodInPreV4Assembly(PTR_MethodDesc pMethodDesc);
842     BOOL static CanMethodHandleCE(PTR_MethodDesc pMethodDesc, CorruptionSeverity severity, BOOL fCalculateSecurityInfo = TRUE);
843
844 public:
845     BOOL static CanMethodHandleException(CorruptionSeverity severity, PTR_MethodDesc pMethodDesc, BOOL fCalculateSecurityInfo = TRUE);
846     BOOL static CanIDispatchTargetHandleException();
847     BOOL static IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO = TRUE);
848     BOOL static IsProcessCorruptedStateException(OBJECTREF oThrowable);
849     BOOL static IsLastActiveExceptionCorrupting(BOOL fMarkForReuseIfCorrupting = FALSE);
850     BOOL static ShouldTreatActiveExceptionAsNonCorrupting();
851     void static MarkLastActiveExceptionCorruptionSeverityForReraiseReuse();
852     void static SetupCorruptionSeverityForActiveException(BOOL fIsRethrownException, BOOL fIsNestedException, BOOL fShouldTreatExceptionAsNonCorrupting = FALSE);
853 #ifdef WIN64EXCEPTIONS
854     typedef DPTR(class ExceptionTracker) PTR_ExceptionTracker;
855     void static SetupCorruptionSeverityForActiveExceptionInUnwindPass(Thread *pCurThread, PTR_ExceptionTracker pEHTracker, BOOL fIsFirstPass, 
856                                                                      DWORD dwExceptionCode);
857 #endif // WIN64EXCEPTIONS
858     void static ResetLastActiveCorruptionSeverityPostCatchHandler(Thread *pThread);
859 };
860
861 #endif // FEATURE_CORRUPTING_EXCEPTIONS
862
863 #ifndef DACCESS_COMPILE
864 // Switches to the previous AppDomain on the thread. See implementation for detailed comments.
865 BOOL ReturnToPreviousAppDomain();
866
867 // This is a generic holder that will enable you to revert to previous execution context (e.g. an AD).
868 // Set it up *once* you have transitioned to the target context.
869 class ReturnToPreviousAppDomainHolder
870 {
871 protected: // protected so that derived holder classes can also use them
872     BOOL        m_fShouldReturnToPreviousAppDomain;
873     Thread    * m_pThread;
874 #ifdef _DEBUG
875     AppDomain * m_pTransitionedToAD;
876 #endif // _DEBUG
877
878     void Init();
879     void ReturnToPreviousAppDomain();
880         
881 public:
882     ReturnToPreviousAppDomainHolder(); 
883     ~ReturnToPreviousAppDomainHolder();
884     void SuppressRelease();
885 };
886
887 // exception filter invoked for unhandled exceptions on the entry point thread (thread 0)
888 LONG EntryPointFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID _pData);
889
890 #endif // !DACCESS_COMPILE
891
892 // Enum that defines the types of exception notification handlers
893 // that we support.
894 enum ExceptionNotificationHandlerType
895 {
896     UnhandledExceptionHandler   = 0x1
897     ,
898     FirstChanceExceptionHandler = 0x2
899 };
900
901 // Defined in Frames.h
902 // class ContextTransitionFrame;
903
904 // This class contains methods to support delivering the various exception notifications.
905 class ExceptionNotifications
906 {
907 private:
908     void static GetEventArgsForNotification(ExceptionNotificationHandlerType notificationType,
909         OBJECTREF *pOutEventArgs, OBJECTREF *pThrowable);
910
911     void static DeliverNotificationInternal(ExceptionNotificationHandlerType notificationType,
912         OBJECTREF *pThrowable
913 #ifdef FEATURE_CORRUPTING_EXCEPTIONS        
914         , CorruptionSeverity severity
915 #endif // FEATURE_CORRUPTING_EXCEPTIONS
916         );
917
918     void static InvokeNotificationDelegate(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate, OBJECTREF *pEventArgs, 
919         OBJECTREF *pAppDomain
920 #ifdef FEATURE_CORRUPTING_EXCEPTIONS        
921         , CorruptionSeverity severity
922 #endif // FEATURE_CORRUPTING_EXCEPTIONS
923         );
924
925 public:
926     BOOL static CanDeliverNotificationToCurrentAppDomain(ExceptionNotificationHandlerType notificationType);
927     
928     void static DeliverNotification(ExceptionNotificationHandlerType notificationType,
929         OBJECTREF *pThrowable
930 #ifdef FEATURE_CORRUPTING_EXCEPTIONS        
931         , CorruptionSeverity severity
932 #endif // FEATURE_CORRUPTING_EXCEPTIONS
933         );
934
935 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
936     BOOL static CanDelegateBeInvokedForException(OBJECTREF *pDelegate, CorruptionSeverity severity);
937 #endif // FEATURE_CORRUPTING_EXCEPTIONS
938
939 public:
940     void static DeliverExceptionNotification(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate, 
941         OBJECTREF *pAppDomain, OBJECTREF *pEventArgs);
942     void static DeliverFirstChanceNotification();
943 };
944
945 #ifndef DACCESS_COMPILE
946
947 #ifndef WIN64EXCEPTIONS
948 void ResetThreadAbortState(PTR_Thread pThread, void *pEstablisherFrame);
949 #else
950 void ResetThreadAbortState(PTR_Thread pThread, CrawlFrame *pCf, StackFrame sfCurrentStackFrame);
951 #endif
952
953 X86_ONLY(EXCEPTION_REGISTRATION_RECORD* GetNextCOMPlusSEHRecord(EXCEPTION_REGISTRATION_RECORD* pRec);)
954
955 #endif // !DACCESS_COMPILE
956
957 #endif // __excep_h__