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