Fix hijacking for ARM/ARM64/x86 on Unix (#20042)
[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(FEATURE_HIJACK) && (!defined(_TARGET_X86_) || defined(FEATURE_PAL))
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 // FEATURE_HIJACK && (!_TARGET_X86_ || FEATURE_PAL)
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                                            BOOL sendWindowsEventLog = FALSE);
246
247 void ReplaceExceptionContextRecord(T_CONTEXT *pTarget, T_CONTEXT *pSource);
248
249 // Localization helper function
250 void ResMgrGetString(LPCWSTR wszResourceName, STRINGREF * ppMessage);
251
252 // externs
253
254 //==========================================================================
255 // Various routines to throw COM+ objects.
256 //==========================================================================
257
258 //==========================================================================
259 // Throw an undecorated runtime exception with a specific string parameter
260 // that won't be localized.  If possible, try using
261 // COMPlusThrow(reKind, LPCWSTR wszResourceName) instead.
262 //==========================================================================
263
264 VOID DECLSPEC_NORETURN RealCOMPlusThrowNonLocalized(RuntimeExceptionKind reKind, LPCWSTR wszTag);
265
266 //==========================================================================
267 // Throw an object.
268 //==========================================================================
269
270 VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable 
271 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
272                                         , CorruptionSeverity severity = NotCorrupting
273 #endif // FEATURE_CORRUPTING_EXCEPTIONS
274                                         );
275
276 //==========================================================================
277 // Throw an undecorated runtime exception.
278 //==========================================================================
279
280 VOID DECLSPEC_NORETURN RealCOMPlusThrow(RuntimeExceptionKind reKind);
281
282 //==========================================================================
283 // Throw an undecorated runtime exception with a localized message.  Given
284 // a resource name, the ResourceManager will find the correct paired string
285 // in our .resources file.
286 //==========================================================================
287
288 VOID DECLSPEC_NORETURN RealCOMPlusThrow(RuntimeExceptionKind reKind, LPCWSTR wszResourceName, Exception * pInnerException = NULL);
289
290 //==========================================================================
291 // Throw a decorated runtime exception.
292 //==========================================================================
293
294 VOID DECLSPEC_NORETURN RealCOMPlusThrow(RuntimeExceptionKind  reKind, UINT resID, 
295                                         LPCWSTR wszArg1 = NULL, LPCWSTR wszArg2 = NULL, LPCWSTR wszArg3 = NULL, 
296                                         LPCWSTR wszArg4 = NULL, LPCWSTR wszArg5 = NULL, LPCWSTR wszArg6 = NULL);
297
298
299 //==========================================================================
300 // Throw a runtime exception based on an HResult. Note that for the version 
301 // of RealCOMPlusThrowHR that takes a resource ID, the HRESULT will be 
302 // passed as the first substitution string (%1).
303 //==========================================================================
304
305 enum tagGetErrorInfo
306 {
307     kGetErrorInfo
308 };
309
310 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, IErrorInfo* pErrInfo, Exception * pInnerException = NULL);
311 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, tagGetErrorInfo);
312 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr);
313 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, UINT resID, LPCWSTR wszArg1 = NULL, LPCWSTR wszArg2 = NULL, 
314                                           LPCWSTR wszArg3 = NULL, LPCWSTR wszArg4 = NULL, LPCWSTR wszArg5 = NULL, 
315                                           LPCWSTR wszArg6 = NULL);
316
317 #ifdef FEATURE_COMINTEROP
318
319 //==========================================================================
320 // Throw a runtime exception based on an HResult, check for error info
321 //==========================================================================
322
323 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, IUnknown *iface, REFIID riid);
324
325
326 //==========================================================================
327 // Throw a runtime exception based on an EXCEPINFO. This function will free
328 // the strings in the EXCEPINFO that is passed in.
329 //==========================================================================
330
331 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(EXCEPINFO *pExcepInfo);
332
333 #endif // FEATURE_COMINTEROP
334
335 //==========================================================================
336 // Throw a runtime exception based on the last Win32 error (GetLastError())
337 //==========================================================================
338
339 VOID DECLSPEC_NORETURN RealCOMPlusThrowWin32();
340 VOID DECLSPEC_NORETURN RealCOMPlusThrowWin32(HRESULT hr);
341
342
343 //==========================================================================
344 // Create an exception object
345 // Note that this may not succeed due to problems creating the exception
346 // object. On failure, it will set pInitException to the value of
347 // pInnerException, and will set pThrowable to the exception that got thrown
348 // while trying to create the TypeInitializationException object, which
349 // could be due to other type init issues, OOM, thread abort, etc.
350 // pInnerException (may be NULL) and pInitException and are IN params.
351 // pThrowable is an OUT param.
352 //==========================================================================
353 void CreateTypeInitializationExceptionObject(LPCWSTR pTypeThatFailed,
354                                              OBJECTREF *pInnerException, 
355                                              OBJECTREF *pInitException,
356                                              OBJECTREF *pThrowable);
357
358 //==========================================================================
359 // Examine an exception object
360 //==========================================================================
361
362 ULONG GetExceptionMessage(OBJECTREF throwable,
363                           __inout_ecount(bufferLength) LPWSTR buffer,
364                           ULONG bufferLength);
365 void GetExceptionMessage(OBJECTREF throwable, SString &result);
366 STRINGREF GetExceptionMessage(OBJECTREF throwable);
367 HRESULT GetExceptionHResult(OBJECTREF throwable);
368 DWORD GetExceptionXCode(OBJECTREF throwable);
369
370 void ExceptionPreserveStackTrace(OBJECTREF throwable);
371
372
373 //==========================================================================
374 // Create an exception object for an HRESULT
375 //==========================================================================
376
377 void GetExceptionForHR(HRESULT hr, IErrorInfo* pErrInfo, bool fUseCOMException, OBJECTREF* pProtectedThrowable, IRestrictedErrorInfo *pResErrorInfo = NULL, BOOL bHasLanguageRestrictedErrorInfo = FALSE);
378 void GetExceptionForHR(HRESULT hr, IErrorInfo* pErrInfo, OBJECTREF* pProtectedThrowable);
379 void GetExceptionForHR(HRESULT hr, OBJECTREF* pProtectedThrowable);
380 HRESULT GetHRFromThrowable(OBJECTREF throwable);
381
382 #if FEATURE_COMINTEROP
383 IRestrictedErrorInfo* GetRestrictedErrorInfoFromErrorObject(OBJECTREF throwable);
384 #endif
385 //==========================================================================
386 // Throw an ArithmeticException
387 //==========================================================================
388
389 VOID DECLSPEC_NORETURN RealCOMPlusThrowArithmetic();
390
391 //==========================================================================
392 // Throw an ArgumentNullException
393 //==========================================================================
394
395 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentNull(LPCWSTR argName, LPCWSTR wszResourceName);
396
397 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentNull(LPCWSTR argName);
398
399 //==========================================================================
400 // Throw an ArgumentOutOfRangeException
401 //==========================================================================
402
403 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentOutOfRange(LPCWSTR argName, LPCWSTR wszResourceName);
404
405 //==========================================================================
406 // Throw an ArgumentException
407 //==========================================================================
408 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentException(LPCWSTR argName, LPCWSTR wszResourceName);
409
410 //==========================================================================
411 // Throw an InvalidCastException
412 //==========================================================================
413 VOID DECLSPEC_NORETURN RealCOMPlusThrowInvalidCastException(TypeHandle thCastFrom, TypeHandle thCastTo);
414
415 VOID DECLSPEC_NORETURN RealCOMPlusThrowInvalidCastException(OBJECTREF *pObj, TypeHandle thCastTo);
416
417
418 #ifndef WIN64EXCEPTIONS
419
420 #include "eexcp.h"
421 #include "exinfo.h"
422
423 struct FrameHandlerExRecord
424 {
425     EXCEPTION_REGISTRATION_RECORD   m_ExReg;
426
427     Frame *m_pEntryFrame;
428
429     Frame *GetCurrFrame() 
430     {
431         LIMITED_METHOD_CONTRACT;
432         return m_pEntryFrame;
433     }
434 };
435
436 struct NestedHandlerExRecord : public FrameHandlerExRecord 
437 {
438     ExInfo m_handlerInfo;
439     BOOL   m_ActiveForUnwind;
440     ExInfo *m_pCurrentExInfo;
441     EXCEPTION_REGISTRATION_RECORD *m_pCurrentHandler;
442     NestedHandlerExRecord() : m_handlerInfo() {LIMITED_METHOD_CONTRACT;}
443     void Init(PEXCEPTION_ROUTINE pFrameHandler, Frame *pEntryFrame)
444     {
445         WRAPPER_NO_CONTRACT;
446
447         m_ExReg.Next=NULL;
448         m_ExReg.Handler=pFrameHandler;
449         m_pEntryFrame=pEntryFrame;
450         m_pCurrentExInfo = NULL;
451         m_pCurrentHandler = NULL;
452         m_handlerInfo.Init();
453         m_ActiveForUnwind = FALSE;
454     }
455 };
456
457 #endif // !WIN64EXCEPTIONS
458
459 #if defined(ENABLE_CONTRACTS_IMPL)
460
461 // Never call this class directly: Call it through CANNOTTHROWCOMPLUSEXCEPTION.
462 class COMPlusCannotThrowExceptionHelper
463 {
464 public:
465     DEBUG_NOINLINE COMPlusCannotThrowExceptionHelper(BOOL    fCond,
466                                       const char *szFunction,
467                                       const char *szFile,
468                                       int         linenum)
469     {
470         SCAN_SCOPE_BEGIN;
471         STATIC_CONTRACT_NOTHROW;  
472
473         m_fCond = fCond;
474         
475         if (m_fCond)
476         {
477             m_pClrDebugState = GetClrDebugState();
478             m_oldClrDebugState = *m_pClrDebugState;
479
480             m_ContractStackRecord.m_szFunction = szFunction;
481             m_ContractStackRecord.m_szFile     = szFile;
482             m_ContractStackRecord.m_lineNum    = linenum;
483             m_ContractStackRecord.m_testmask   = (Contract::ALL_Disabled & ~((UINT)(Contract::THROWS_Mask))) | Contract::THROWS_No;
484             m_ContractStackRecord.m_construct  = "CANNOTTHROW";
485             m_pClrDebugState->LinkContractStackTrace( &m_ContractStackRecord );
486
487             m_pClrDebugState->ViolationMaskReset( ThrowsViolation );
488             m_pClrDebugState->ResetOkToThrow();
489         }
490     }
491
492     DEBUG_NOINLINE ~COMPlusCannotThrowExceptionHelper()
493     {
494         SCAN_SCOPE_END;
495
496         if (m_fCond)
497         {
498             *m_pClrDebugState = m_oldClrDebugState;
499         }
500     }
501
502 private:
503     BOOL m_fCond;
504
505     ClrDebugState      *m_pClrDebugState;
506     ClrDebugState       m_oldClrDebugState;
507
508     ContractStackRecord   m_ContractStackRecord;
509 };
510
511 #endif // ENABLE_CONTRACTS_IMPL
512
513 //-------------------------------------------------------------------------------
514 // This simply tests to see if the exception object is a subclass of
515 // the descriminating class specified in the exception clause.
516 //-------------------------------------------------------------------------------
517 extern "C" BOOL ExceptionIsOfRightType(TypeHandle clauseType, TypeHandle thrownType);
518
519 //==========================================================================
520 // The stuff below is what works "behind the scenes" of the public macros.
521 //==========================================================================
522
523
524 // Specify NULL for uTryCatchResumeAddress when not checking for a InducedThreadRedirectAtEndOfCatch
525 EXTERN_C LPVOID COMPlusCheckForAbort(UINT_PTR uTryCatchResumeAddress = NULL);
526
527 BOOL        IsThreadHijackedForThreadStop(Thread* pThread, EXCEPTION_RECORD* pExceptionRecord);
528 void        AdjustContextForThreadStop(Thread* pThread, T_CONTEXT* pContext);
529 OBJECTREF   CreateCOMPlusExceptionObject(Thread* pThread, EXCEPTION_RECORD* pExceptionRecord, BOOL bAsynchronousThreadStop);
530
531 #if !defined(WIN64EXCEPTIONS)
532 EXCEPTION_HANDLER_DECL(COMPlusFrameHandler);
533 EXCEPTION_HANDLER_DECL(COMPlusNestedExceptionHandler);
534 #ifdef FEATURE_COMINTEROP
535 EXCEPTION_HANDLER_DECL(COMPlusFrameHandlerRevCom);
536 #endif // FEATURE_COMINTEROP
537
538 // Pop off any SEH handlers we have registered below pTargetSP
539 VOID __cdecl PopSEHRecords(LPVOID pTargetSP);
540
541 #if defined(_TARGET_X86_) && defined(DEBUGGING_SUPPORTED)
542 VOID UnwindExceptionTrackerAndResumeInInterceptionFrame(ExInfo* pExInfo, EHContext* context);
543 #endif // _TARGET_X86_ && DEBUGGING_SUPPORTED
544
545 BOOL PopNestedExceptionRecords(LPVOID pTargetSP, BOOL bCheckForUnknownHandlers = FALSE);
546 VOID PopNestedExceptionRecords(LPVOID pTargetSP, T_CONTEXT *pCtx, void *pSEH);
547
548 // Misc functions to access and update the SEH chain. Be very, very careful about updating the SEH chain.
549 // Frankly, if you think you need to use one of these function, please
550 // consult with the owner of the exception system.
551 PEXCEPTION_REGISTRATION_RECORD GetCurrentSEHRecord();
552 VOID SetCurrentSEHRecord(EXCEPTION_REGISTRATION_RECORD *pSEH);
553
554
555 #define STACK_OVERWRITE_BARRIER_SIZE 20
556 #define STACK_OVERWRITE_BARRIER_VALUE 0xabcdefab
557
558 #ifdef _DEBUG
559 #if defined(_TARGET_X86_)
560 struct FrameHandlerExRecordWithBarrier {
561     DWORD m_StackOverwriteBarrier[STACK_OVERWRITE_BARRIER_SIZE];
562     FrameHandlerExRecord m_ExRecord;
563 };
564
565 void VerifyValidTransitionFromManagedCode(Thread *pThread, CrawlFrame *pCF);
566 #endif // defined(_TARGET_X86_)
567 #endif // _DEBUG
568 #endif // !defined(WIN64EXCEPTIONS)
569
570 //==========================================================================
571 // This is a workaround designed to allow the use of the StubLinker object at bootup
572 // time where the EE isn't sufficient awake to create COM+ exception objects.
573 // Instead, COMPlusThrow(rexcep) does a simple RaiseException using this code.
574 // Or use COMPlusThrowBoot() to explicitly do so.
575 //==========================================================================
576 #define BOOTUP_EXCEPTION_COMPLUS  0xC0020001
577
578 void COMPlusThrowBoot(HRESULT hr);
579
580
581 //==========================================================================
582 // Used by the classloader to record a managed exception object to explain
583 // why a classload got botched.
584 //
585 // - Can be called with gc enabled or disabled.
586 //   This allows a catch-all error path to post a generic catchall error
587 //   message w/out bonking more specific error messages posted by inner functions.
588 //==========================================================================
589 VOID DECLSPEC_NORETURN ThrowTypeLoadException(LPCUTF8 pNameSpace, LPCUTF8 pTypeName,
590                            LPCWSTR pAssemblyName, LPCUTF8 pMessageArg,
591                            UINT resIDWhy);
592
593 VOID DECLSPEC_NORETURN ThrowTypeLoadException(LPCWSTR pFullTypeName,
594                                               LPCWSTR pAssemblyName,
595                                               LPCUTF8 pMessageArg,
596                                               UINT resIDWhy);
597
598 VOID DECLSPEC_NORETURN ThrowFieldLayoutError(mdTypeDef cl,                // cl of the NStruct being loaded
599                            Module* pModule,             // Module that defines the scope, loader and heap (for allocate FieldMarshalers)
600                            DWORD   dwOffset,            // Field offset
601                            DWORD   dwID);
602
603 UINT GetResourceIDForFileLoadExceptionHR(HRESULT hr);
604
605 FCDECL1(Object*, MissingMemberException_FormatSignature, I1Array* pPersistedSigUNSAFE);
606 FCDECL1(Object*, GetResourceFromDefault, StringObject* key);
607
608 #define EXCEPTION_NONCONTINUABLE 0x1    // Noncontinuable exception
609 #define EXCEPTION_UNWINDING 0x2         // Unwind is in progress
610 #define EXCEPTION_EXIT_UNWIND 0x4       // Exit unwind is in progress
611 #define EXCEPTION_STACK_INVALID 0x8     // Stack out of limits or unaligned
612 #define EXCEPTION_NESTED_CALL 0x10      // Nested exception handler call
613 #define EXCEPTION_TARGET_UNWIND 0x20    // Target unwind in progress
614 #define EXCEPTION_COLLIDED_UNWIND 0x40  // Collided exception handler call
615
616 #define EXCEPTION_UNWIND (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | \
617                           EXCEPTION_TARGET_UNWIND | EXCEPTION_COLLIDED_UNWIND)
618
619 #define IS_UNWINDING(Flag) ((Flag & EXCEPTION_UNWIND) != 0)
620
621 //#include "CodeMan.h"
622
623 class EHRangeTreeNode;
624 class EHRangeTree;
625
626 typedef CUnorderedArray<EHRangeTreeNode *, 7> EH_CLAUSE_UNORDERED_ARRAY;
627
628 class EHRangeTreeNode
629 {
630 public:
631     EHRangeTree                *m_pTree;
632     EE_ILEXCEPTION_CLAUSE      *m_clause;
633
634     EHRangeTreeNode            *m_pContainedBy;
635     EH_CLAUSE_UNORDERED_ARRAY   m_containees;
636
637     DWORD                       m_FilterEndPC;
638
639 private:
640     // A node can represent a range or a single offset.
641     // A node representing a range can either be the root node, which
642     // contains everything and has a NULL m_clause, or it can be
643     // a node mapping to an EH clause.
644     DWORD                       m_offset;
645     bool                        m_fIsRange;
646     bool                        m_fIsRoot;
647
648 public:
649     EHRangeTreeNode(void);
650     EHRangeTreeNode(DWORD offset, bool fIsRange = false);
651     void CommonCtor(DWORD offset, bool fIsRange);
652
653     bool IsRange();
654     void MarkAsRange();
655
656     bool IsRoot();
657     void MarkAsRoot(DWORD offset);
658
659     DWORD GetOffset();
660     DWORD GetTryStart();
661     DWORD GetTryEnd();
662     DWORD GetHandlerStart();
663     DWORD GetHandlerEnd();
664     DWORD GetFilterStart();
665     DWORD GetFilterEnd();
666
667     // These four functions may actually be called via FindContainer() while we are building the tree
668     // structure, in which case we shouldn't really check the tree recursively because the result is unreliable.
669     // Thus, they check m_pTree->m_fInitializing to see if they should call themselves recursively.
670     // Also, FindContainer() has extra logic to work around this boot-strapping problem.
671     bool Contains(EHRangeTreeNode* pNode);
672     bool TryContains(EHRangeTreeNode* pNode);
673     bool HandlerContains(EHRangeTreeNode* pNode);
674     bool FilterContains(EHRangeTreeNode* pNode);
675
676     // These are simple wrappers around the previous four.
677     bool Contains(DWORD offset);
678     bool TryContains(DWORD offset);
679     bool HandlerContains(DWORD offset);
680     bool FilterContains(DWORD offset);
681
682     EHRangeTreeNode* GetContainer();
683
684     HRESULT AddNode(EHRangeTreeNode *pNode);
685 } ;
686
687 class EHRangeTree
688 {
689     unsigned                m_EHCount;
690     EHRangeTreeNode        *m_rgNodes;
691     EE_ILEXCEPTION_CLAUSE  *m_rgClauses;
692
693 public:
694
695     EHRangeTreeNode        *m_root; // This is a sentinel, NOT an actual
696                                     // Exception Handler!
697     HRESULT                 m_hrInit; // Ctor fills this out.
698
699     bool                    m_fInitializing;
700
701     EHRangeTree(IJitManager* pIJM,
702                 const METHODTOKEN& methodToken,
703                 DWORD         methodSize,
704                 int           cFunclet,
705                 const DWORD * rgFuncletOffset);
706
707     ~EHRangeTree();
708
709     EHRangeTreeNode *FindContainer(EHRangeTreeNode *pNodeCur);
710     EHRangeTreeNode *FindMostSpecificContainer(DWORD addr);
711     EHRangeTreeNode *FindNextMostSpecificContainer(EHRangeTreeNode *pNodeCur,
712                                                    DWORD addr);
713
714     // <TODO> We shouldn't need this - instead, we
715     // should get sequence points annotated with whether they're STACK_EMPTY, etc,
716     // and then we'll figure out if the destination is ok based on that, instead.</TODO>
717     BOOL isAtStartOfCatch(DWORD offset);
718 } ;
719
720 HRESULT SetIPFromSrcToDst(Thread *pThread,
721                           SLOT addrStart,       // base address of method
722                           DWORD offFrom,        // native offset
723                           DWORD offTo,          // native offset
724                           bool fCanSetIPOnly,   // if true, don't do any real work
725                           PREGDISPLAY pReg,
726                           PT_CONTEXT pCtx,
727                           void *pDji,
728                           EHRangeTree *pEHRT);
729
730 BOOL IsInFirstFrameOfHandler(Thread *pThread,
731                              IJitManager *pJitManager,
732                              const METHODTOKEN& MethodToken,
733                              DWORD offSet);
734
735 //==========================================================================
736 // Handy helper functions
737 //==========================================================================
738 LONG FilterAccessViolation(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
739
740 bool IsContinuableException(Thread *pThread);
741
742 bool IsInterceptableException(Thread *pThread);
743
744 #ifdef DEBUGGING_SUPPORTED
745 // perform simple checking to see if the current exception is intercepted
746 bool CheckThreadExceptionStateForInterception();
747
748 #ifndef FEATURE_PAL
749 // Currently, only Windows supports ClrUnwindEx (used inside ClrDebuggerDoUnwindAndIntercept)
750 #define DEBUGGER_EXCEPTION_INTERCEPTION_SUPPORTED
751 #endif // !FEATURE_PAL
752
753 #ifdef DEBUGGER_EXCEPTION_INTERCEPTION_SUPPORTED
754 // Intercept the current exception and start an unwind.  This function may never return.
755 EXCEPTION_DISPOSITION ClrDebuggerDoUnwindAndIntercept(X86_FIRST_ARG(EXCEPTION_REGISTRATION_RECORD *pEstablisherFrame)
756                                                       EXCEPTION_RECORD *pExceptionRecord);
757 #endif // DEBUGGER_EXCEPTION_INTERCEPTION_SUPPORTED
758
759 LONG NotifyDebuggerLastChance(Thread *pThread,
760                               EXCEPTION_POINTERS *pExceptionInfo,
761                               BOOL jitAttachRequested);
762 #endif // DEBUGGING_SUPPORTED
763
764 #if defined(_TARGET_X86_)
765 void CPFH_AdjustContextForThreadSuspensionRace(T_CONTEXT *pContext, Thread *pThread);
766 #endif // _TARGET_X86_
767
768 DWORD GetGcMarkerExceptionCode(LPVOID ip);
769 bool IsGcMarker(DWORD exceptionCode, T_CONTEXT *pContext);
770
771 void InitSavedExceptionInfo();
772
773 bool ShouldHandleManagedFault(
774                         EXCEPTION_RECORD*               pExceptionRecord,
775                         T_CONTEXT*                        pContext,
776                         EXCEPTION_REGISTRATION_RECORD*  pEstablisherFrame,
777                         Thread*                         pThread);
778
779 void HandleManagedFault(EXCEPTION_RECORD*               pExceptionRecord,
780                         T_CONTEXT*                        pContext,
781                         EXCEPTION_REGISTRATION_RECORD*  pEstablisherFrame,
782                         Thread*                         pThread);
783
784 LONG WatsonLastChance(
785     Thread              *pThread,
786     EXCEPTION_POINTERS  *pExceptionInfo,
787     TypeOfReportedError tore);
788
789 bool DebugIsEECxxException(EXCEPTION_RECORD* pExceptionRecord);
790
791
792 inline void CopyOSContext(T_CONTEXT* pDest, T_CONTEXT* pSrc)
793 {
794     SIZE_T cbReadOnlyPost = 0;
795 #ifdef _TARGET_AMD64_
796     cbReadOnlyPost = sizeof(CONTEXT) - FIELD_OFFSET(CONTEXT, FltSave); // older OSes don't have the vector reg fields
797 #endif // _TARGET_AMD64_
798
799     memcpyNoGCRefs(pDest, pSrc, sizeof(T_CONTEXT) - cbReadOnlyPost);
800 }
801
802 void SaveCurrentExceptionInfo(PEXCEPTION_RECORD pRecord, PT_CONTEXT pContext);
803
804 #ifdef _DEBUG
805 void SetReversePInvokeEscapingUnhandledExceptionStatus(BOOL fIsUnwinding,
806 #ifdef _TARGET_X86_
807                                                        EXCEPTION_REGISTRATION_RECORD * pEstablisherFrame
808 #elif defined(WIN64EXCEPTIONS)
809                                                        ULONG64 pEstablisherFrame
810 #else
811 #error Unsupported platform
812 #endif
813                                                        );
814 #endif // _DEBUG
815
816 // See implementation for detailed comments in excep.cpp
817 LONG AppDomainTransitionExceptionFilter(
818     EXCEPTION_POINTERS *pExceptionInfo, // the pExceptionInfo passed to a filter function.
819     PVOID               pParam);         
820
821 // See implementation for detailed comments in excep.cpp
822 LONG ReflectionInvocationExceptionFilter(
823     EXCEPTION_POINTERS *pExceptionInfo, // the pExceptionInfo passed to a filter function.
824     PVOID               pParam);         
825
826 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
827 // -----------------------------------------------------------------------
828 // Support for Corrupted State Exceptions
829 // -----------------------------------------------------------------------
830 #ifndef HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE
831 #define HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE "System.Runtime.ExceptionServices.HandleProcessCorruptedStateExceptionsAttribute"
832 #endif // HANDLE_PROCESS_CORRUPTED_STATE_EXCEPTION_ATTRIBUTE
833
834 #ifndef HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME
835 #define HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME 2
836 #endif // HIGHEST_MAJOR_VERSION_OF_PREV4_RUNTIME
837
838 // This helper class contains static method to support working with Corrupted State Exceptions, 
839 // including checking if a method can handle it or not, copy state across throwables, etc.
840 class CEHelper
841 {
842     BOOL static IsMethodInPreV4Assembly(PTR_MethodDesc pMethodDesc);
843     BOOL static CanMethodHandleCE(PTR_MethodDesc pMethodDesc, CorruptionSeverity severity, BOOL fCalculateSecurityInfo = TRUE);
844
845 public:
846     BOOL static CanMethodHandleException(CorruptionSeverity severity, PTR_MethodDesc pMethodDesc, BOOL fCalculateSecurityInfo = TRUE);
847     BOOL static CanIDispatchTargetHandleException();
848     BOOL static IsProcessCorruptedStateException(DWORD dwExceptionCode, BOOL fCheckForSO = TRUE);
849     BOOL static IsProcessCorruptedStateException(OBJECTREF oThrowable);
850     BOOL static IsLastActiveExceptionCorrupting(BOOL fMarkForReuseIfCorrupting = FALSE);
851     BOOL static ShouldTreatActiveExceptionAsNonCorrupting();
852     void static MarkLastActiveExceptionCorruptionSeverityForReraiseReuse();
853     void static SetupCorruptionSeverityForActiveException(BOOL fIsRethrownException, BOOL fIsNestedException, BOOL fShouldTreatExceptionAsNonCorrupting = FALSE);
854 #ifdef WIN64EXCEPTIONS
855     typedef DPTR(class ExceptionTracker) PTR_ExceptionTracker;
856     void static SetupCorruptionSeverityForActiveExceptionInUnwindPass(Thread *pCurThread, PTR_ExceptionTracker pEHTracker, BOOL fIsFirstPass, 
857                                                                      DWORD dwExceptionCode);
858 #endif // WIN64EXCEPTIONS
859     void static ResetLastActiveCorruptionSeverityPostCatchHandler(Thread *pThread);
860 };
861
862 #endif // FEATURE_CORRUPTING_EXCEPTIONS
863
864 #ifndef DACCESS_COMPILE
865 // Switches to the previous AppDomain on the thread. See implementation for detailed comments.
866 BOOL ReturnToPreviousAppDomain();
867
868 // This is a generic holder that will enable you to revert to previous execution context (e.g. an AD).
869 // Set it up *once* you have transitioned to the target context.
870 class ReturnToPreviousAppDomainHolder
871 {
872 protected: // protected so that derived holder classes can also use them
873     BOOL        m_fShouldReturnToPreviousAppDomain;
874     Thread    * m_pThread;
875 #ifdef _DEBUG
876     AppDomain * m_pTransitionedToAD;
877 #endif // _DEBUG
878
879     void Init();
880     void ReturnToPreviousAppDomain();
881         
882 public:
883     ReturnToPreviousAppDomainHolder(); 
884     ~ReturnToPreviousAppDomainHolder();
885     void SuppressRelease();
886 };
887
888 // exception filter invoked for unhandled exceptions on the entry point thread (thread 0)
889 LONG EntryPointFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID _pData);
890
891 #endif // !DACCESS_COMPILE
892
893 // Enum that defines the types of exception notification handlers
894 // that we support.
895 enum ExceptionNotificationHandlerType
896 {
897     UnhandledExceptionHandler   = 0x1
898     ,
899     FirstChanceExceptionHandler = 0x2
900 };
901
902 // Defined in Frames.h
903 // class ContextTransitionFrame;
904
905 // This class contains methods to support delivering the various exception notifications.
906 class ExceptionNotifications
907 {
908 private:
909     void static GetEventArgsForNotification(ExceptionNotificationHandlerType notificationType,
910         OBJECTREF *pOutEventArgs, OBJECTREF *pThrowable);
911
912     void static DeliverNotificationInternal(ExceptionNotificationHandlerType notificationType,
913         OBJECTREF *pThrowable
914 #ifdef FEATURE_CORRUPTING_EXCEPTIONS        
915         , CorruptionSeverity severity
916 #endif // FEATURE_CORRUPTING_EXCEPTIONS
917         );
918
919     void static InvokeNotificationDelegate(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate, OBJECTREF *pEventArgs, 
920         OBJECTREF *pAppDomain
921 #ifdef FEATURE_CORRUPTING_EXCEPTIONS        
922         , CorruptionSeverity severity
923 #endif // FEATURE_CORRUPTING_EXCEPTIONS
924         );
925
926 public:
927     BOOL static CanDeliverNotificationToCurrentAppDomain(ExceptionNotificationHandlerType notificationType);
928     
929     void static DeliverNotification(ExceptionNotificationHandlerType notificationType,
930         OBJECTREF *pThrowable
931 #ifdef FEATURE_CORRUPTING_EXCEPTIONS        
932         , CorruptionSeverity severity
933 #endif // FEATURE_CORRUPTING_EXCEPTIONS
934         );
935
936 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
937     BOOL static CanDelegateBeInvokedForException(OBJECTREF *pDelegate, CorruptionSeverity severity);
938 #endif // FEATURE_CORRUPTING_EXCEPTIONS
939
940 public:
941     void static DeliverExceptionNotification(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate, 
942         OBJECTREF *pAppDomain, OBJECTREF *pEventArgs);
943     void static DeliverFirstChanceNotification();
944 };
945
946 #ifndef DACCESS_COMPILE
947
948 #ifndef WIN64EXCEPTIONS
949 void ResetThreadAbortState(PTR_Thread pThread, void *pEstablisherFrame);
950 #else
951 void ResetThreadAbortState(PTR_Thread pThread, CrawlFrame *pCf, StackFrame sfCurrentStackFrame);
952 #endif
953
954 X86_ONLY(EXCEPTION_REGISTRATION_RECORD* GetNextCOMPlusSEHRecord(EXCEPTION_REGISTRATION_RECORD* pRec);)
955
956 #endif // !DACCESS_COMPILE
957
958 #endif // __excep_h__