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(FEATURE_HIJACK) && (!defined(_TARGET_X86_) || defined(FEATURE_PAL))
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 // FEATURE_HIJACK && (!_TARGET_X86_ || FEATURE_PAL)
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,
245 BOOL sendWindowsEventLog = FALSE);
247 void ReplaceExceptionContextRecord(T_CONTEXT *pTarget, T_CONTEXT *pSource);
249 // Localization helper function
250 void ResMgrGetString(LPCWSTR wszResourceName, STRINGREF * ppMessage);
254 //==========================================================================
255 // Various routines to throw COM+ objects.
256 //==========================================================================
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 //==========================================================================
264 VOID DECLSPEC_NORETURN RealCOMPlusThrowNonLocalized(RuntimeExceptionKind reKind, LPCWSTR wszTag);
266 //==========================================================================
268 //==========================================================================
270 VOID DECLSPEC_NORETURN RealCOMPlusThrow(OBJECTREF throwable
271 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
272 , CorruptionSeverity severity = NotCorrupting
273 #endif // FEATURE_CORRUPTING_EXCEPTIONS
276 //==========================================================================
277 // Throw an undecorated runtime exception.
278 //==========================================================================
280 VOID DECLSPEC_NORETURN RealCOMPlusThrow(RuntimeExceptionKind reKind);
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 //==========================================================================
288 VOID DECLSPEC_NORETURN RealCOMPlusThrow(RuntimeExceptionKind reKind, LPCWSTR wszResourceName, Exception * pInnerException = NULL);
290 //==========================================================================
291 // Throw a decorated runtime exception.
292 //==========================================================================
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);
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 //==========================================================================
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);
317 #ifdef FEATURE_COMINTEROP
319 //==========================================================================
320 // Throw a runtime exception based on an HResult, check for error info
321 //==========================================================================
323 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(HRESULT hr, IUnknown *iface, REFIID riid);
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 //==========================================================================
331 VOID DECLSPEC_NORETURN RealCOMPlusThrowHR(EXCEPINFO *pExcepInfo);
333 #endif // FEATURE_COMINTEROP
335 //==========================================================================
336 // Throw a runtime exception based on the last Win32 error (GetLastError())
337 //==========================================================================
339 VOID DECLSPEC_NORETURN RealCOMPlusThrowWin32();
340 VOID DECLSPEC_NORETURN RealCOMPlusThrowWin32(HRESULT hr);
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);
358 //==========================================================================
359 // Examine an exception object
360 //==========================================================================
362 ULONG GetExceptionMessage(OBJECTREF throwable,
363 __inout_ecount(bufferLength) LPWSTR buffer,
365 void GetExceptionMessage(OBJECTREF throwable, SString &result);
366 STRINGREF GetExceptionMessage(OBJECTREF throwable);
367 HRESULT GetExceptionHResult(OBJECTREF throwable);
368 DWORD GetExceptionXCode(OBJECTREF throwable);
370 void ExceptionPreserveStackTrace(OBJECTREF throwable);
373 //==========================================================================
374 // Create an exception object for an HRESULT
375 //==========================================================================
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);
382 #if FEATURE_COMINTEROP
383 IRestrictedErrorInfo* GetRestrictedErrorInfoFromErrorObject(OBJECTREF throwable);
385 //==========================================================================
386 // Throw an ArithmeticException
387 //==========================================================================
389 VOID DECLSPEC_NORETURN RealCOMPlusThrowArithmetic();
391 //==========================================================================
392 // Throw an ArgumentNullException
393 //==========================================================================
395 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentNull(LPCWSTR argName, LPCWSTR wszResourceName);
397 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentNull(LPCWSTR argName);
399 //==========================================================================
400 // Throw an ArgumentOutOfRangeException
401 //==========================================================================
403 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentOutOfRange(LPCWSTR argName, LPCWSTR wszResourceName);
405 //==========================================================================
406 // Throw an ArgumentException
407 //==========================================================================
408 VOID DECLSPEC_NORETURN RealCOMPlusThrowArgumentException(LPCWSTR argName, LPCWSTR wszResourceName);
410 //==========================================================================
411 // Throw an InvalidCastException
412 //==========================================================================
413 VOID DECLSPEC_NORETURN RealCOMPlusThrowInvalidCastException(TypeHandle thCastFrom, TypeHandle thCastTo);
415 VOID DECLSPEC_NORETURN RealCOMPlusThrowInvalidCastException(OBJECTREF *pObj, TypeHandle thCastTo);
418 #ifndef WIN64EXCEPTIONS
423 struct FrameHandlerExRecord
425 EXCEPTION_REGISTRATION_RECORD m_ExReg;
427 Frame *m_pEntryFrame;
429 Frame *GetCurrFrame()
431 LIMITED_METHOD_CONTRACT;
432 return m_pEntryFrame;
436 struct NestedHandlerExRecord : public FrameHandlerExRecord
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)
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;
457 #endif // !WIN64EXCEPTIONS
459 #if defined(ENABLE_CONTRACTS_IMPL)
461 // Never call this class directly: Call it through CANNOTTHROWCOMPLUSEXCEPTION.
462 class COMPlusCannotThrowExceptionHelper
465 DEBUG_NOINLINE COMPlusCannotThrowExceptionHelper(BOOL fCond,
466 const char *szFunction,
471 STATIC_CONTRACT_NOTHROW;
477 m_pClrDebugState = GetClrDebugState();
478 m_oldClrDebugState = *m_pClrDebugState;
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 );
487 m_pClrDebugState->ViolationMaskReset( ThrowsViolation );
488 m_pClrDebugState->ResetOkToThrow();
492 DEBUG_NOINLINE ~COMPlusCannotThrowExceptionHelper()
498 *m_pClrDebugState = m_oldClrDebugState;
505 ClrDebugState *m_pClrDebugState;
506 ClrDebugState m_oldClrDebugState;
508 ContractStackRecord m_ContractStackRecord;
511 #endif // ENABLE_CONTRACTS_IMPL
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);
519 //==========================================================================
520 // The stuff below is what works "behind the scenes" of the public macros.
521 //==========================================================================
524 // Specify NULL for uTryCatchResumeAddress when not checking for a InducedThreadRedirectAtEndOfCatch
525 EXTERN_C LPVOID COMPlusCheckForAbort(UINT_PTR uTryCatchResumeAddress = NULL);
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);
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
538 // Pop off any SEH handlers we have registered below pTargetSP
539 VOID __cdecl PopSEHRecords(LPVOID pTargetSP);
541 #if defined(_TARGET_X86_) && defined(DEBUGGING_SUPPORTED)
542 VOID UnwindExceptionTrackerAndResumeInInterceptionFrame(ExInfo* pExInfo, EHContext* context);
543 #endif // _TARGET_X86_ && DEBUGGING_SUPPORTED
545 BOOL PopNestedExceptionRecords(LPVOID pTargetSP, BOOL bCheckForUnknownHandlers = FALSE);
546 VOID PopNestedExceptionRecords(LPVOID pTargetSP, T_CONTEXT *pCtx, void *pSEH);
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);
555 #define STACK_OVERWRITE_BARRIER_SIZE 20
556 #define STACK_OVERWRITE_BARRIER_VALUE 0xabcdefab
559 #if defined(_TARGET_X86_)
560 struct FrameHandlerExRecordWithBarrier {
561 DWORD m_StackOverwriteBarrier[STACK_OVERWRITE_BARRIER_SIZE];
562 FrameHandlerExRecord m_ExRecord;
565 void VerifyValidTransitionFromManagedCode(Thread *pThread, CrawlFrame *pCF);
566 #endif // defined(_TARGET_X86_)
568 #endif // !defined(WIN64EXCEPTIONS)
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
578 void COMPlusThrowBoot(HRESULT hr);
581 //==========================================================================
582 // Used by the classloader to record a managed exception object to explain
583 // why a classload got botched.
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,
593 VOID DECLSPEC_NORETURN ThrowTypeLoadException(LPCWSTR pFullTypeName,
594 LPCWSTR pAssemblyName,
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
603 UINT GetResourceIDForFileLoadExceptionHR(HRESULT hr);
605 FCDECL1(Object*, MissingMemberException_FormatSignature, I1Array* pPersistedSigUNSAFE);
606 FCDECL1(Object*, GetResourceFromDefault, StringObject* key);
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
616 #define EXCEPTION_UNWIND (EXCEPTION_UNWINDING | EXCEPTION_EXIT_UNWIND | \
617 EXCEPTION_TARGET_UNWIND | EXCEPTION_COLLIDED_UNWIND)
619 #define IS_UNWINDING(Flag) ((Flag & EXCEPTION_UNWIND) != 0)
621 //#include "CodeMan.h"
623 class EHRangeTreeNode;
626 typedef CUnorderedArray<EHRangeTreeNode *, 7> EH_CLAUSE_UNORDERED_ARRAY;
628 class EHRangeTreeNode
631 EHRangeTree *m_pTree;
632 EE_ILEXCEPTION_CLAUSE *m_clause;
634 EHRangeTreeNode *m_pContainedBy;
635 EH_CLAUSE_UNORDERED_ARRAY m_containees;
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.
649 EHRangeTreeNode(void);
650 EHRangeTreeNode(DWORD offset, bool fIsRange = false);
651 void CommonCtor(DWORD offset, bool fIsRange);
657 void MarkAsRoot(DWORD offset);
662 DWORD GetHandlerStart();
663 DWORD GetHandlerEnd();
664 DWORD GetFilterStart();
665 DWORD GetFilterEnd();
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);
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);
682 EHRangeTreeNode* GetContainer();
684 HRESULT AddNode(EHRangeTreeNode *pNode);
690 EHRangeTreeNode *m_rgNodes;
691 EE_ILEXCEPTION_CLAUSE *m_rgClauses;
695 EHRangeTreeNode *m_root; // This is a sentinel, NOT an actual
696 // Exception Handler!
697 HRESULT m_hrInit; // Ctor fills this out.
699 bool m_fInitializing;
701 EHRangeTree(IJitManager* pIJM,
702 const METHODTOKEN& methodToken,
705 const DWORD * rgFuncletOffset);
709 EHRangeTreeNode *FindContainer(EHRangeTreeNode *pNodeCur);
710 EHRangeTreeNode *FindMostSpecificContainer(DWORD addr);
711 EHRangeTreeNode *FindNextMostSpecificContainer(EHRangeTreeNode *pNodeCur,
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);
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
730 BOOL IsInFirstFrameOfHandler(Thread *pThread,
731 IJitManager *pJitManager,
732 const METHODTOKEN& MethodToken,
735 //==========================================================================
736 // Handy helper functions
737 //==========================================================================
738 LONG FilterAccessViolation(PEXCEPTION_POINTERS pExceptionPointers, LPVOID lpvParam);
740 bool IsContinuableException(Thread *pThread);
742 bool IsInterceptableException(Thread *pThread);
744 #ifdef DEBUGGING_SUPPORTED
745 // perform simple checking to see if the current exception is intercepted
746 bool CheckThreadExceptionStateForInterception();
749 // Currently, only Windows supports ClrUnwindEx (used inside ClrDebuggerDoUnwindAndIntercept)
750 #define DEBUGGER_EXCEPTION_INTERCEPTION_SUPPORTED
751 #endif // !FEATURE_PAL
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
759 LONG NotifyDebuggerLastChance(Thread *pThread,
760 EXCEPTION_POINTERS *pExceptionInfo,
761 BOOL jitAttachRequested);
762 #endif // DEBUGGING_SUPPORTED
764 #if defined(_TARGET_X86_)
765 void CPFH_AdjustContextForThreadSuspensionRace(T_CONTEXT *pContext, Thread *pThread);
766 #endif // _TARGET_X86_
768 DWORD GetGcMarkerExceptionCode(LPVOID ip);
769 bool IsGcMarker(DWORD exceptionCode, T_CONTEXT *pContext);
771 void InitSavedExceptionInfo();
773 bool ShouldHandleManagedFault(
774 EXCEPTION_RECORD* pExceptionRecord,
776 EXCEPTION_REGISTRATION_RECORD* pEstablisherFrame,
779 void HandleManagedFault(EXCEPTION_RECORD* pExceptionRecord,
781 EXCEPTION_REGISTRATION_RECORD* pEstablisherFrame,
784 LONG WatsonLastChance(
786 EXCEPTION_POINTERS *pExceptionInfo,
787 TypeOfReportedError tore);
789 bool DebugIsEECxxException(EXCEPTION_RECORD* pExceptionRecord);
792 inline void CopyOSContext(T_CONTEXT* pDest, T_CONTEXT* pSrc)
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_
799 memcpyNoGCRefs(pDest, pSrc, sizeof(T_CONTEXT) - cbReadOnlyPost);
802 void SaveCurrentExceptionInfo(PEXCEPTION_RECORD pRecord, PT_CONTEXT pContext);
805 void SetReversePInvokeEscapingUnhandledExceptionStatus(BOOL fIsUnwinding,
807 EXCEPTION_REGISTRATION_RECORD * pEstablisherFrame
808 #elif defined(WIN64EXCEPTIONS)
809 ULONG64 pEstablisherFrame
811 #error Unsupported platform
816 // See implementation for detailed comments in excep.cpp
817 LONG AppDomainTransitionExceptionFilter(
818 EXCEPTION_POINTERS *pExceptionInfo, // the pExceptionInfo passed to a filter function.
821 // See implementation for detailed comments in excep.cpp
822 LONG ReflectionInvocationExceptionFilter(
823 EXCEPTION_POINTERS *pExceptionInfo, // the pExceptionInfo passed to a filter function.
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
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
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.
842 BOOL static IsMethodInPreV4Assembly(PTR_MethodDesc pMethodDesc);
843 BOOL static CanMethodHandleCE(PTR_MethodDesc pMethodDesc, CorruptionSeverity severity, BOOL fCalculateSecurityInfo = TRUE);
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);
862 #endif // FEATURE_CORRUPTING_EXCEPTIONS
864 #ifndef DACCESS_COMPILE
865 // Switches to the previous AppDomain on the thread. See implementation for detailed comments.
866 BOOL ReturnToPreviousAppDomain();
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
872 protected: // protected so that derived holder classes can also use them
873 BOOL m_fShouldReturnToPreviousAppDomain;
876 AppDomain * m_pTransitionedToAD;
880 void ReturnToPreviousAppDomain();
883 ReturnToPreviousAppDomainHolder();
884 ~ReturnToPreviousAppDomainHolder();
885 void SuppressRelease();
888 // exception filter invoked for unhandled exceptions on the entry point thread (thread 0)
889 LONG EntryPointFilter(PEXCEPTION_POINTERS pExceptionInfo, PVOID _pData);
891 #endif // !DACCESS_COMPILE
893 // Enum that defines the types of exception notification handlers
895 enum ExceptionNotificationHandlerType
897 UnhandledExceptionHandler = 0x1
899 FirstChanceExceptionHandler = 0x2
902 // Defined in Frames.h
903 // class ContextTransitionFrame;
905 // This class contains methods to support delivering the various exception notifications.
906 class ExceptionNotifications
909 void static GetEventArgsForNotification(ExceptionNotificationHandlerType notificationType,
910 OBJECTREF *pOutEventArgs, OBJECTREF *pThrowable);
912 void static DeliverNotificationInternal(ExceptionNotificationHandlerType notificationType,
913 OBJECTREF *pThrowable
914 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
915 , CorruptionSeverity severity
916 #endif // FEATURE_CORRUPTING_EXCEPTIONS
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
927 BOOL static CanDeliverNotificationToCurrentAppDomain(ExceptionNotificationHandlerType notificationType);
929 void static DeliverNotification(ExceptionNotificationHandlerType notificationType,
930 OBJECTREF *pThrowable
931 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
932 , CorruptionSeverity severity
933 #endif // FEATURE_CORRUPTING_EXCEPTIONS
936 #ifdef FEATURE_CORRUPTING_EXCEPTIONS
937 BOOL static CanDelegateBeInvokedForException(OBJECTREF *pDelegate, CorruptionSeverity severity);
938 #endif // FEATURE_CORRUPTING_EXCEPTIONS
941 void static DeliverExceptionNotification(ExceptionNotificationHandlerType notificationType, OBJECTREF *pDelegate,
942 OBJECTREF *pAppDomain, OBJECTREF *pEventArgs);
943 void static DeliverFirstChanceNotification();
946 #ifndef DACCESS_COMPILE
948 #ifndef WIN64EXCEPTIONS
949 void ResetThreadAbortState(PTR_Thread pThread, void *pEstablisherFrame);
951 void ResetThreadAbortState(PTR_Thread pThread, CrawlFrame *pCf, StackFrame sfCurrentStackFrame);
954 X86_ONLY(EXCEPTION_REGISTRATION_RECORD* GetNextCOMPlusSEHRecord(EXCEPTION_REGISTRATION_RECORD* pRec);)
956 #endif // !DACCESS_COMPILE
958 #endif // __excep_h__