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.
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
20 #include "../dlls/mscorrc/resource.h"
23 #include "interoputil.h"
25 BOOL IsExceptionFromManagedCode(const EXCEPTION_RECORD * pExceptionRecord);
26 bool IsIPInMarkedJitHelper(UINT_PTR uControlPc);
28 #if defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK)
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);
34 #endif // defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK)
36 void RaiseFailFastExceptionOnWin7(PEXCEPTION_RECORD pExceptionRecord, PT_CONTEXT pContext);
38 // Check if the Win32 Error code is an IO error.
39 BOOL IsWin32IOError(SCODE scode);
41 //******************************************************************************
43 // SwallowUnhandledExceptions
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.
53 // true - the runtime should "swallow" unhandled exceptions
55 inline bool SwallowUnhandledExceptions()
57 return (eHostDeterminedPolicy == GetEEPolicy()->GetUnhandledExceptionPolicy()) ||
58 g_pConfig->LegacyUnhandledExceptionPolicy();
62 // return values of LookForHandler
68 #include "runtimeexceptionkind.h"
73 // ThrowCallbackType is used to pass information to between various functions and the callbacks that they call
74 // during a managed stack walk.
76 struct ThrowCallbackType
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?
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
91 void * pCurrentExceptionRecord;
92 void * pPrevExceptionRecord;
95 // Is the current exception a longjmp?
96 CORRUPTING_EXCEPTIONS_ONLY(BOOL m_fIsLongJump;)
99 LIMITED_METHOD_CONTRACT;
104 bUnwindStack = FALSE;
105 bAllowAllocMem = TRUE;
108 pTopFrame = (Frame *)-1;
109 pBottomFrame = (Frame *)-1;
110 pProfilerNotify = NULL;
111 bReplaceStack = FALSE;
112 bSkipLastElement = FALSE;
114 pCurrentExceptionRecord = 0;
115 pPrevExceptionRecord = 0;
117 // By default, the current exception is not a longjmp
118 CORRUPTING_EXCEPTIONS_ONLY(m_fIsLongJump = FALSE;)
124 struct EE_ILEXCEPTION_CLAUSE;
126 void InitializeExceptionHandling();
127 void CLRAddVectoredHandlers(void);
128 void CLRRemoveVectoredHandlers(void);
129 void TerminateExceptionHandling();
132 EXTERN_C VOID STDCALL ResetCurrentContext();
133 #if !defined(WIN64EXCEPTIONS)
135 void CheckStackBarrier(EXCEPTION_REGISTRATION_RECORD *exRecord);
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)
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);
158 // Removes source file names/paths and line information from a stack trace.
159 void StripFileInfoFromStackTrace(SString &ssStackTrace);
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);
169 BOOL IsValidClause(EE_ILEXCEPTION_CLAUSE *EHClause);
170 BOOL IsCOMPlusExceptionHandlerInstalled();
173 BOOL InstallUnhandledExceptionFilter();
174 void UninstallUnhandledExceptionFilter();
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".
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);
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.
203 enum UnhandledExceptionLocation
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
214 MaximumLocationValue = 0x800000, // This is the maximum location value you're allowed to use. (Max 24 bits allowed.)
216 // This is a mask of all the locations that the debugger will attach to by default.
217 DefaultDebuggerAttach = ProcessWideHandler |
219 FatalExecutionEngineException
222 struct ThreadBaseExceptionFilterParam
224 UnhandledExceptionLocation location;
227 LONG ThreadBaseExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pvParam);
228 LONG ThreadBaseExceptionSwallowingFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pvParam);
229 LONG ThreadBaseExceptionAppDomainFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID pvParam);
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);
237 void DECLSPEC_NORETURN RaiseDeadLockException();
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);
246 void ReplaceExceptionContextRecord(T_CONTEXT *pTarget, T_CONTEXT *pSource);
248 // Localization helper function
249 void ResMgrGetString(LPCWSTR wszResourceName, STRINGREF * ppMessage);
253 //==========================================================================
254 // Various routines to throw COM+ objects.
255 //==========================================================================
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 //==========================================================================
263 VOID DECLSPEC_NORETURN RealCOMPlusThrowNonLocalized(RuntimeExceptionKind reKind, LPCWSTR wszTag);
265 //==========================================================================
267 //==========================================================================
269 VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable
270 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
271 , CorruptionSeverity severity = NotCorrupting
272 #endif // FEATURE_CORRUPTING_EXCEPTIONS
275 //==========================================================================
276 // Throw an undecorated runtime exception.
277 //==========================================================================
279 VOID DECLSPEC_NORETURN RealCOMPlusThrow(RuntimeExceptionKind reKind);
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 //==========================================================================
287 VOID DECLSPEC_NORETURN RealCOMPlusThrow(RuntimeExceptionKind reKind, LPCWSTR wszResourceName, Exception * pInnerException = NULL);
289 //==========================================================================
290 // Throw a decorated runtime exception.
291 //==========================================================================
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);
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 //==========================================================================
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);
316 #ifdef FEATURE_COMINTEROP
318 //==========================================================================
319 // Throw a runtime exception based on an HResult, check for error info
320 //==========================================================================
322 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, IUnknown *iface, REFIID riid);
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 //==========================================================================
330 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(EXCEPINFO *pExcepInfo);
332 #endif // FEATURE_COMINTEROP
334 //==========================================================================
335 // Throw a runtime exception based on the last Win32 error (GetLastError())
336 //==========================================================================
338 VOID DECLSPEC_NORETURN RealCOMPlusThrowWin32();
339 VOID DECLSPEC_NORETURN RealCOMPlusThrowWin32(HRESULT hr);
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);
357 //==========================================================================
358 // Examine an exception object
359 //==========================================================================
361 ULONG GetExceptionMessage(OBJECTREF throwable,
362 __inout_ecount(bufferLength) LPWSTR buffer,
364 void GetExceptionMessage(OBJECTREF throwable, SString &result);
365 STRINGREF GetExceptionMessage(OBJECTREF throwable);
366 HRESULT GetExceptionHResult(OBJECTREF throwable);
367 DWORD GetExceptionXCode(OBJECTREF throwable);
369 void ExceptionPreserveStackTrace(OBJECTREF throwable);
372 //==========================================================================
373 // Create an exception object for an HRESULT
374 //==========================================================================
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);
381 #if FEATURE_COMINTEROP
382 IRestrictedErrorInfo* GetRestrictedErrorInfoFromErrorObject(OBJECTREF throwable);
384 //==========================================================================
385 // Throw an ArithmeticException
386 //==========================================================================
388 VOID DECLSPEC_NORETURN RealCOMPlusThrowArithmetic();
390 //==========================================================================
391 // Throw an ArgumentNullException
392 //==========================================================================
394 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentNull(LPCWSTR argName, LPCWSTR wszResourceName);
396 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentNull(LPCWSTR argName);
398 //==========================================================================
399 // Throw an ArgumentOutOfRangeException
400 //==========================================================================
402 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentOutOfRange(LPCWSTR argName, LPCWSTR wszResourceName);
404 //==========================================================================
405 // Throw an ArgumentException
406 //==========================================================================
407 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentException(LPCWSTR argName, LPCWSTR wszResourceName);
409 //==========================================================================
410 // Throw an InvalidCastException
411 //==========================================================================
412 VOID DECLSPEC_NORETURN RealCOMPlusThrowInvalidCastException(TypeHandle thCastFrom, TypeHandle thCastTo);
414 VOID DECLSPEC_NORETURN RealCOMPlusThrowInvalidCastException(OBJECTREF *pObj, TypeHandle thCastTo);
417 #ifndef WIN64EXCEPTIONS
422 struct FrameHandlerExRecord
424 EXCEPTION_REGISTRATION_RECORD m_ExReg;
426 Frame *m_pEntryFrame;
428 Frame *GetCurrFrame()
430 LIMITED_METHOD_CONTRACT;
431 return m_pEntryFrame;
435 struct NestedHandlerExRecord : public FrameHandlerExRecord
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)
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;
456 #endif // !WIN64EXCEPTIONS
458 #if defined(ENABLE_CONTRACTS_IMPL)
460 // Never call this class directly: Call it through CANNOTTHROWCOMPLUSEXCEPTION.
461 class COMPlusCannotThrowExceptionHelper
464 DEBUG_NOINLINE COMPlusCannotThrowExceptionHelper(BOOL fCond,
465 const char *szFunction,
470 STATIC_CONTRACT_NOTHROW;
476 m_pClrDebugState = GetClrDebugState();
477 m_oldClrDebugState = *m_pClrDebugState;
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 );
486 m_pClrDebugState->ViolationMaskReset( ThrowsViolation );
487 m_pClrDebugState->ResetOkToThrow();
491 DEBUG_NOINLINE ~COMPlusCannotThrowExceptionHelper()
497 *m_pClrDebugState = m_oldClrDebugState;
504 ClrDebugState *m_pClrDebugState;
505 ClrDebugState m_oldClrDebugState;
507 ContractStackRecord m_ContractStackRecord;
510 #endif // ENABLE_CONTRACTS_IMPL
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);
518 //==========================================================================
519 // The stuff below is what works "behind the scenes" of the public macros.
520 //==========================================================================
523 // Specify NULL for uTryCatchResumeAddress when not checking for a InducedThreadRedirectAtEndOfCatch
524 EXTERN_C LPVOID COMPlusCheckForAbort(UINT_PTR uTryCatchResumeAddress = NULL);
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);
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
537 // Pop off any SEH handlers we have registered below pTargetSP
538 VOID __cdecl PopSEHRecords(LPVOID pTargetSP);
540 #if defined(_TARGET_X86_) && defined(DEBUGGING_SUPPORTED)
541 VOID UnwindExceptionTrackerAndResumeInInterceptionFrame(ExInfo* pExInfo, EHContext* context);
542 #endif // _TARGET_X86_ && DEBUGGING_SUPPORTED
544 BOOL PopNestedExceptionRecords(LPVOID pTargetSP, BOOL bCheckForUnknownHandlers = FALSE);
545 VOID PopNestedExceptionRecords(LPVOID pTargetSP, T_CONTEXT *pCtx, void *pSEH);
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);
554 #define STACK_OVERWRITE_BARRIER_SIZE 20
555 #define STACK_OVERWRITE_BARRIER_VALUE 0xabcdefab
558 #if defined(_TARGET_X86_)
559 struct FrameHandlerExRecordWithBarrier {
560 DWORD m_StackOverwriteBarrier[STACK_OVERWRITE_BARRIER_SIZE];
561 FrameHandlerExRecord m_ExRecord;
564 void VerifyValidTransitionFromManagedCode(Thread *pThread, CrawlFrame *pCF);
565 #endif // defined(_TARGET_X86_)
567 #endif // !defined(WIN64EXCEPTIONS)
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
577 void COMPlusThrowBoot(HRESULT hr);
580 //==========================================================================
581 // Used by the classloader to record a managed exception object to explain
582 // why a classload got botched.
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,
592 VOID DECLSPEC_NORETURN ThrowTypeLoadException(LPCWSTR pFullTypeName,
593 LPCWSTR pAssemblyName,
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
602 UINT GetResourceIDForFileLoadExceptionHR(HRESULT hr);
604 FCDECL1(Object*, MissingMemberException_FormatSignature, I1Array* pPersistedSigUNSAFE);
605 FCDECL1(Object*, GetResourceFromDefault, StringObject* key);
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
615 #define EXCEPTION_UNWIND (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | \
616 EXCEPTION_TARGET_UNWIND | EXCEPTION_COLLIDED_UNWIND)
618 #define IS_UNWINDING(Flag) ((Flag & EXCEPTION_UNWIND) != 0)
620 //#include "CodeMan.h"
622 class EHRangeTreeNode;
625 typedef CUnorderedArray<EHRangeTreeNode *, 7> EH_CLAUSE_UNORDERED_ARRAY;
627 class EHRangeTreeNode
630 EHRangeTree *m_pTree;
631 EE_ILEXCEPTION_CLAUSE *m_clause;
633 EHRangeTreeNode *m_pContainedBy;
634 EH_CLAUSE_UNORDERED_ARRAY m_containees;
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.
648 EHRangeTreeNode(void);
649 EHRangeTreeNode(DWORD offset, bool fIsRange = false);
650 void CommonCtor(DWORD offset, bool fIsRange);
656 void MarkAsRoot(DWORD offset);
661 DWORD GetHandlerStart();
662 DWORD GetHandlerEnd();
663 DWORD GetFilterStart();
664 DWORD GetFilterEnd();
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);
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);
681 EHRangeTreeNode* GetContainer();
683 HRESULT AddNode(EHRangeTreeNode *pNode);
689 EHRangeTreeNode *m_rgNodes;
690 EE_ILEXCEPTION_CLAUSE *m_rgClauses;
694 EHRangeTreeNode *m_root; // This is a sentinel, NOT an actual
695 // Exception Handler!
696 HRESULT m_hrInit; // Ctor fills this out.
698 bool m_fInitializing;
700 EHRangeTree(IJitManager* pIJM,
701 const METHODTOKEN& methodToken,
704 const DWORD * rgFuncletOffset);
708 EHRangeTreeNode *FindContainer(EHRangeTreeNode *pNodeCur);
709 EHRangeTreeNode *FindMostSpecificContainer(DWORD addr);
710 EHRangeTreeNode *FindNextMostSpecificContainer(EHRangeTreeNode *pNodeCur,
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);
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
729 BOOL IsInFirstFrameOfHandler(Thread *pThread,
730 IJitManager *pJitManager,
731 const METHODTOKEN& MethodToken,
734 //==========================================================================
735 // Handy helper functions
736 //==========================================================================
737 LONG FilterAccessViolation(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
739 bool IsContinuableException(Thread *pThread);
741 bool IsInterceptableException(Thread *pThread);
743 #ifdef DEBUGGING_SUPPORTED
744 // perform simple checking to see if the current exception is intercepted
745 bool CheckThreadExceptionStateForInterception();
748 // Currently, only Windows supports ClrUnwindEx (used inside ClrDebuggerDoUnwindAndIntercept)
749 #define DEBUGGER_EXCEPTION_INTERCEPTION_SUPPORTED
750 #endif // !FEATURE_PAL
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
758 LONG NotifyDebuggerLastChance(Thread *pThread,
759 EXCEPTION_POINTERS *pExceptionInfo,
760 BOOL jitAttachRequested);
761 #endif // DEBUGGING_SUPPORTED
763 #if defined(_TARGET_X86_)
764 void CPFH_AdjustContextForThreadSuspensionRace(T_CONTEXT *pContext, Thread *pThread);
765 #endif // _TARGET_X86_
767 DWORD GetGcMarkerExceptionCode(LPVOID ip);
768 bool IsGcMarker(DWORD exceptionCode, T_CONTEXT *pContext);
770 void InitSavedExceptionInfo();
772 bool ShouldHandleManagedFault(
773 EXCEPTION_RECORD* pExceptionRecord,
775 EXCEPTION_REGISTRATION_RECORD* pEstablisherFrame,
778 void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord,
780 EXCEPTION_REGISTRATION_RECORD* pEstablisherFrame,
783 LONG WatsonLastChance(
785 EXCEPTION_POINTERS *pExceptionInfo,
786 TypeOfReportedError tore);
788 bool DebugIsEECxxException(EXCEPTION_RECORD* pExceptionRecord);
791 inline void CopyOSContext(T_CONTEXT* pDest, T_CONTEXT* pSrc)
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_
798 memcpyNoGCRefs(pDest, pSrc, sizeof(T_CONTEXT) - cbReadOnlyPost);
801 void SaveCurrentExceptionInfo(PEXCEPTION_RECORD pRecord, PT_CONTEXT pContext);
804 void SetReversePInvokeEscapingUnhandledExceptionStatus(BOOL fIsUnwinding,
806 EXCEPTION_REGISTRATION_RECORD * pEstablisherFrame
807 #elif defined(WIN64EXCEPTIONS)
808 ULONG64 pEstablisherFrame
810 #error Unsupported platform
815 // See implementation for detailed comments in excep.cpp
816 LONG AppDomainTransitionExceptionFilter(
817 EXCEPTION_POINTERS *pExceptionInfo, // the pExceptionInfo passed to a filter function.
820 // See implementation for detailed comments in excep.cpp
821 LONG ReflectionInvocationExceptionFilter(
822 EXCEPTION_POINTERS *pExceptionInfo, // the pExceptionInfo passed to a filter function.
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
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
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.
841 BOOL static IsMethodInPreV4Assembly(PTR_MethodDesc pMethodDesc);
842 BOOL static CanMethodHandleCE(PTR_MethodDesc pMethodDesc, CorruptionSeverity severity, BOOL fCalculateSecurityInfo = TRUE);
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);
861 #endif // FEATURE_CORRUPTING_EXCEPTIONS
863 #ifndef DACCESS_COMPILE
864 // Switches to the previous AppDomain on the thread. See implementation for detailed comments.
865 BOOL ReturnToPreviousAppDomain();
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
871 protected: // protected so that derived holder classes can also use them
872 BOOL m_fShouldReturnToPreviousAppDomain;
875 AppDomain * m_pTransitionedToAD;
879 void ReturnToPreviousAppDomain();
882 ReturnToPreviousAppDomainHolder();
883 ~ReturnToPreviousAppDomainHolder();
884 void SuppressRelease();
887 // exception filter invoked for unhandled exceptions on the entry point thread (thread 0)
888 LONG EntryPointFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID _pData);
890 #endif // !DACCESS_COMPILE
892 // Enum that defines the types of exception notification handlers
894 enum ExceptionNotificationHandlerType
896 UnhandledExceptionHandler = 0x1
898 FirstChanceExceptionHandler = 0x2
901 // Defined in Frames.h
902 // class ContextTransitionFrame;
904 // This class contains methods to support delivering the various exception notifications.
905 class ExceptionNotifications
908 void static GetEventArgsForNotification(ExceptionNotificationHandlerType notificationType,
909 OBJECTREF *pOutEventArgs, OBJECTREF *pThrowable);
911 void static DeliverNotificationInternal(ExceptionNotificationHandlerType notificationType,
912 OBJECTREF *pThrowable
913 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
914 , CorruptionSeverity severity
915 #endif // FEATURE_CORRUPTING_EXCEPTIONS
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
926 BOOL static CanDeliverNotificationToCurrentAppDomain(ExceptionNotificationHandlerType notificationType);
928 void static DeliverNotification(ExceptionNotificationHandlerType notificationType,
929 OBJECTREF *pThrowable
930 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
931 , CorruptionSeverity severity
932 #endif // FEATURE_CORRUPTING_EXCEPTIONS
935 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
936 BOOL static CanDelegateBeInvokedForException(OBJECTREF *pDelegate, CorruptionSeverity severity);
937 #endif // FEATURE_CORRUPTING_EXCEPTIONS
940 void static DeliverExceptionNotification(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate,
941 OBJECTREF *pAppDomain, OBJECTREF *pEventArgs);
942 void static DeliverFirstChanceNotification();
945 #ifndef DACCESS_COMPILE
947 #ifndef WIN64EXCEPTIONS
948 void ResetThreadAbortState(PTR_Thread pThread, void *pEstablisherFrame);
950 void ResetThreadAbortState(PTR_Thread pThread, CrawlFrame *pCf, StackFrame sfCurrentStackFrame);
953 X86_ONLY(EXCEPTION_REGISTRATION_RECORD* GetNextCOMPlusSEHRecord(EXCEPTION_REGISTRATION_RECORD* pRec);)
955 #endif // !DACCESS_COMPILE
957 #endif // __excep_h__