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 | // |
5 | |
6 | // |
7 | |
8 | #ifndef __ExStateCommon_h__ |
9 | #define __ExStateCommon_h__ |
10 | |
11 | #include "stackframe.h" |
12 | |
13 | class ExceptionFlags; |
14 | |
15 | #ifdef DEBUGGING_SUPPORTED |
16 | //--------------------------------------------------------------------------------------- |
17 | // |
18 | // This class stores information necessary to intercept an exception. It's basically a communication channel |
19 | // between the debugger and the EH subsystem. Each internal exception tracking structure |
20 | // (ExInfo on x86 and ExceptionTracker on WIN64) contains one DebuggerExState. |
21 | // |
22 | // Notes: |
23 | // This class actually stores more information on x86 than on WIN64 because the x86 EH subsystem |
24 | // has more work to do when unwinding the stack. WIN64 just asks the OS to do it. |
25 | // |
26 | |
27 | class DebuggerExState |
28 | { |
29 | public: |
30 | |
31 | //--------------------------------------------------------------------------------------- |
32 | // |
33 | // constructor |
34 | // |
35 | |
36 | DebuggerExState() |
37 | { |
38 | Init(); |
39 | } |
40 | |
41 | //--------------------------------------------------------------------------------------- |
42 | // |
43 | // This function is simply used to initialize all the fields in the DebuggerExState. |
44 | // |
45 | |
46 | void Init() |
47 | { |
48 | m_sfDebuggerIndicatedFramePointer = StackFrame(); |
49 | m_pDebuggerInterceptFunc = NULL; |
50 | m_sfDebuggerInterceptFramePointer = StackFrame(); |
51 | m_pDebuggerContext = NULL; |
52 | m_pDebuggerInterceptNativeOffset = 0; |
53 | |
54 | #ifndef WIN64EXCEPTIONS |
55 | // x86-specific fields |
56 | m_pDebuggerInterceptFrame = EXCEPTION_CHAIN_END; |
57 | #endif // !WIN64EXCEPTIONS |
58 | m_dDebuggerInterceptHandlerDepth = 0; |
59 | } |
60 | |
61 | //--------------------------------------------------------------------------------------- |
62 | // |
63 | // Retrieves the opaque token stored by the debugger. |
64 | // |
65 | // Return Value: |
66 | // the stored opaque token for the debugger |
67 | // |
68 | |
69 | void* GetDebuggerInterceptContext() |
70 | { |
71 | LIMITED_METHOD_CONTRACT; |
72 | return m_pDebuggerContext; |
73 | } |
74 | |
75 | //--------------------------------------------------------------------------------------- |
76 | // |
77 | // Stores an opaque token which is only used by the debugger. |
78 | // |
79 | // Arguments: |
80 | // pContext - the token to be stored |
81 | // |
82 | |
83 | void SetDebuggerInterceptContext(void* pContext) |
84 | { |
85 | LIMITED_METHOD_CONTRACT; |
86 | m_pDebuggerContext = pContext; |
87 | } |
88 | |
89 | //--------------------------------------------------------------------------------------- |
90 | // |
91 | // Marks the current stack frame visited by the EH subsystem during the first pass. |
92 | // This marker moves closer to the root of the stack while each stack frame is examined in the first pass. |
93 | // This continues until the end of the first pass. |
94 | // |
95 | // Arguments: |
96 | // stackPointer - SP of the current stack frame |
97 | // bStorePointer - BSP of the current stack frame |
98 | // |
99 | |
100 | void SetDebuggerIndicatedFramePointer(void* stackPointer) |
101 | { |
102 | LIMITED_METHOD_CONTRACT; |
103 | m_sfDebuggerIndicatedFramePointer = StackFrame((UINT_PTR)stackPointer); |
104 | } |
105 | |
106 | // This function stores the information necessary to intercept an exception in the DebuggerExState. |
107 | BOOL SetDebuggerInterceptInfo(IJitManager *pJitManager, |
108 | Thread *pThread, |
109 | const METHODTOKEN& methodToken, |
110 | MethodDesc *pMethDesc, |
111 | ULONG_PTR natOffset, |
112 | StackFrame sfDebuggerInterceptFramePointer, |
113 | ExceptionFlags* pFlags); |
114 | |
115 | //--------------------------------------------------------------------------------------- |
116 | // |
117 | // This function is basically just a getter to retrieve the information stored on the DebuggerExState. |
118 | // Refer to the comments for individual fields for more information. |
119 | // |
120 | // Arguments: |
121 | // pEstablisherFrame - m_pDebuggerInterceptFrame |
122 | // ppFunc - m_pDebuggerInterceptFunc |
123 | // pdHandler - m_dDebuggerInterceptHandlerDepth |
124 | // ppStack - the SP of m_sfDebuggerInterceptFramePointer |
125 | // ppBStore - the BSP of m_sfDebuggerInterceptFramePointer |
126 | // pNativeOffset - m_pDebuggerInterceptNativeOffset; |
127 | // ppFrame - always set to NULL |
128 | // |
129 | // Notes: |
130 | // Everything is an out parameter. |
131 | // |
132 | // Apparently ppFrame is actually used on x86 to set tct.pBottomFrame to NULL. |
133 | // |
134 | |
135 | void GetDebuggerInterceptInfo( |
136 | #ifndef WIN64EXCEPTIONS |
137 | PEXCEPTION_REGISTRATION_RECORD *pEstablisherFrame, |
138 | #endif // !WIN64EXCEPTIONS |
139 | MethodDesc **ppFunc, |
140 | int *pdHandler, |
141 | BYTE **ppStack, |
142 | ULONG_PTR *pNativeOffset, |
143 | Frame **ppFrame) |
144 | { |
145 | LIMITED_METHOD_CONTRACT; |
146 | |
147 | #ifndef WIN64EXCEPTIONS |
148 | if (pEstablisherFrame != NULL) |
149 | { |
150 | *pEstablisherFrame = m_pDebuggerInterceptFrame; |
151 | } |
152 | #endif // !WIN64EXCEPTIONS |
153 | |
154 | if (ppFunc != NULL) |
155 | { |
156 | *ppFunc = m_pDebuggerInterceptFunc; |
157 | } |
158 | |
159 | if (pdHandler != NULL) |
160 | { |
161 | *pdHandler = m_dDebuggerInterceptHandlerDepth; |
162 | } |
163 | |
164 | if (ppStack != NULL) |
165 | { |
166 | *ppStack = (BYTE *)m_sfDebuggerInterceptFramePointer.SP; |
167 | } |
168 | |
169 | if (pNativeOffset != NULL) |
170 | { |
171 | *pNativeOffset = m_pDebuggerInterceptNativeOffset; |
172 | } |
173 | |
174 | if (ppFrame != NULL) |
175 | { |
176 | *ppFrame = NULL; |
177 | } |
178 | } |
179 | |
180 | private: |
181 | // This frame pointer marks the latest stack frame examined by the EH subsystem in the first pass. |
182 | // An exception cannot be intercepted closer to the root than this frame pointer. |
183 | StackFrame m_sfDebuggerIndicatedFramePointer; |
184 | |
185 | // the method in which we are going to resume execution |
186 | MethodDesc* m_pDebuggerInterceptFunc; |
187 | |
188 | // the frame pointer of the stack frame where we are intercepting the exception |
189 | StackFrame m_sfDebuggerInterceptFramePointer; |
190 | |
191 | // opaque token used by the debugger |
192 | void* m_pDebuggerContext; |
193 | |
194 | // the native offset at which to resume execution |
195 | ULONG_PTR m_pDebuggerInterceptNativeOffset; |
196 | |
197 | // The remaining fields are only used on x86. |
198 | #ifndef WIN64EXCEPTIONS |
199 | // the exception registration record covering the stack range containing the interception point |
200 | PEXCEPTION_REGISTRATION_RECORD m_pDebuggerInterceptFrame; |
201 | #endif // !WIN64EXCEPTIONS |
202 | |
203 | // the nesting level at which we want to resume execution |
204 | int m_dDebuggerInterceptHandlerDepth; |
205 | }; |
206 | #endif // DEBUGGING_SUPPORTED |
207 | |
208 | class EHClauseInfo |
209 | { |
210 | public: |
211 | EHClauseInfo() |
212 | { |
213 | LIMITED_METHOD_CONTRACT; |
214 | |
215 | // For the profiler, other clause fields are not valid if m_ClauseType is COR_PRF_CLAUSE_NONE. |
216 | m_ClauseType = COR_PRF_CLAUSE_NONE; |
217 | m_IPForEHClause = 0; |
218 | m_sfForEHClause.Clear(); |
219 | m_csfEHClause.Clear(); |
220 | m_fManagedCodeEntered = FALSE; |
221 | } |
222 | |
223 | void SetEHClauseType(COR_PRF_CLAUSE_TYPE EHClauseType) |
224 | { |
225 | LIMITED_METHOD_CONTRACT; |
226 | m_ClauseType = EHClauseType; |
227 | } |
228 | |
229 | void SetInfo(COR_PRF_CLAUSE_TYPE EHClauseType, |
230 | UINT_PTR uIPForEHClause, |
231 | StackFrame sfForEHClause) |
232 | { |
233 | LIMITED_METHOD_CONTRACT; |
234 | |
235 | m_ClauseType = EHClauseType; |
236 | m_IPForEHClause = uIPForEHClause; |
237 | m_sfForEHClause = sfForEHClause; |
238 | } |
239 | |
240 | void ResetInfo() |
241 | { |
242 | LIMITED_METHOD_CONTRACT; |
243 | |
244 | // For the profiler, other clause fields are not valid if m_ClauseType is COR_PRF_CLAUSE_NONE. |
245 | m_ClauseType = COR_PRF_CLAUSE_NONE; |
246 | m_IPForEHClause = 0; |
247 | m_sfForEHClause.Clear(); |
248 | m_csfEHClause.Clear(); |
249 | } |
250 | |
251 | void SetManagedCodeEntered(BOOL fEntered) |
252 | { |
253 | LIMITED_METHOD_CONTRACT; |
254 | m_fManagedCodeEntered = fEntered; |
255 | } |
256 | |
257 | void SetCallerStackFrame(CallerStackFrame csfEHClause) |
258 | { |
259 | LIMITED_METHOD_CONTRACT; |
260 | m_csfEHClause = csfEHClause; |
261 | } |
262 | |
263 | COR_PRF_CLAUSE_TYPE GetClauseType() { LIMITED_METHOD_CONTRACT; return m_ClauseType; } |
264 | |
265 | UINT_PTR GetIPForEHClause() { LIMITED_METHOD_CONTRACT; return m_IPForEHClause; } |
266 | UINT_PTR GetFramePointerForEHClause() { LIMITED_METHOD_CONTRACT; return m_sfForEHClause.SP; } |
267 | |
268 | BOOL IsManagedCodeEntered() { LIMITED_METHOD_CONTRACT; return m_fManagedCodeEntered; } |
269 | |
270 | StackFrame GetStackFrameForEHClause() { LIMITED_METHOD_CONTRACT; return m_sfForEHClause; } |
271 | CallerStackFrame GetCallerStackFrameForEHClause(){ LIMITED_METHOD_CONTRACT; return m_csfEHClause; } |
272 | |
273 | // On some platforms, we make the call to the funclets via an assembly helper. The reference to the field |
274 | // containing the stack pointer is passed to the assembly helper so that it can update |
275 | // it with correct SP value once its prolog has executed. |
276 | // |
277 | // This method is used to get the field reference |
278 | CallerStackFrame* GetCallerStackFrameForEHClauseReference() |
279 | { |
280 | LIMITED_METHOD_CONTRACT; |
281 | return &m_csfEHClause; |
282 | } |
283 | |
284 | private: |
285 | UINT_PTR m_IPForEHClause; // the entry point of the current notified exception clause |
286 | StackFrame m_sfForEHClause; // the assocated frame pointer of the current notified exception clause |
287 | CallerStackFrame m_csfEHClause; // the caller SP of the funclet; only used on WIN64 |
288 | |
289 | COR_PRF_CLAUSE_TYPE m_ClauseType; // this has a value from COR_PRF_CLAUSE_TYPE while an exception notification is pending |
290 | BOOL m_fManagedCodeEntered; // this flag indicates that we have called the managed code for the current EH clause |
291 | }; |
292 | |
293 | class ExceptionFlags |
294 | { |
295 | public: |
296 | ExceptionFlags() |
297 | { |
298 | Init(); |
299 | } |
300 | |
301 | #if defined(WIN64EXCEPTIONS) |
302 | ExceptionFlags(bool fReadOnly) |
303 | { |
304 | Init(); |
305 | #ifdef _DEBUG |
306 | if (fReadOnly) |
307 | { |
308 | m_flags |= Ex_FlagsAreReadOnly; |
309 | m_debugFlags |= Ex_FlagsAreReadOnly; |
310 | } |
311 | #endif // _DEBUG |
312 | } |
313 | #endif // defined(WIN64EXCEPTIONS) |
314 | |
315 | void AssertIfReadOnly() |
316 | { |
317 | SUPPORTS_DAC; |
318 | |
319 | #if defined(WIN64EXCEPTIONS) && defined(_DEBUG) |
320 | if ((m_flags & Ex_FlagsAreReadOnly) || (m_debugFlags & Ex_FlagsAreReadOnly)) |
321 | { |
322 | _ASSERTE(!"Tried to update read-only flags!" ); |
323 | } |
324 | #endif // defined(WIN64EXCEPTIONS) && defined(_DEBUG) |
325 | } |
326 | |
327 | void Init() |
328 | { |
329 | m_flags = 0; |
330 | #ifdef _DEBUG |
331 | m_debugFlags = 0; |
332 | #endif // _DEBUG |
333 | } |
334 | |
335 | BOOL IsRethrown() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_IsRethrown; } |
336 | void SetIsRethrown() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_IsRethrown; } |
337 | void ResetIsRethrown() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags &= ~Ex_IsRethrown; } |
338 | |
339 | BOOL UnwindHasStarted() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_UnwindHasStarted; } |
340 | void SetUnwindHasStarted() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_UnwindHasStarted; } |
341 | void ResetUnwindHasStarted() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags &= ~Ex_UnwindHasStarted; } |
342 | |
343 | BOOL UnwindingToFindResumeFrame() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_UnwindingToFindResumeFrame; } |
344 | void SetUnwindingToFindResumeFrame() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_UnwindingToFindResumeFrame; } |
345 | void ResetUnwindingToFindResumeFrame() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags &= ~Ex_UnwindingToFindResumeFrame; } |
346 | |
347 | BOOL UseExInfoForStackwalk() { LIMITED_METHOD_DAC_CONTRACT; return m_flags & Ex_UseExInfoForStackwalk; } |
348 | void SetUseExInfoForStackwalk() { LIMITED_METHOD_DAC_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_UseExInfoForStackwalk; } |
349 | void ResetUseExInfoForStackwalk() { LIMITED_METHOD_DAC_CONTRACT; AssertIfReadOnly(); m_flags &= ~Ex_UseExInfoForStackwalk; } |
350 | |
351 | #ifdef _DEBUG |
352 | BOOL ReversePInvokeEscapingException() { LIMITED_METHOD_DAC_CONTRACT; return m_debugFlags & Ex_RPInvokeEscapingException; } |
353 | void SetReversePInvokeEscapingException() { LIMITED_METHOD_DAC_CONTRACT; AssertIfReadOnly(); m_debugFlags |= Ex_RPInvokeEscapingException; } |
354 | void ResetReversePInvokeEscapingException() { LIMITED_METHOD_DAC_CONTRACT; AssertIfReadOnly(); m_debugFlags &= ~Ex_RPInvokeEscapingException; } |
355 | #endif // _DEBUG |
356 | |
357 | #ifdef DEBUGGING_SUPPORTED |
358 | BOOL SentDebugUserFirstChance() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_SentDebugUserFirstChance; } |
359 | void SetSentDebugUserFirstChance() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_SentDebugUserFirstChance; } |
360 | |
361 | BOOL SentDebugFirstChance() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_SentDebugFirstChance; } |
362 | void SetSentDebugFirstChance() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_SentDebugFirstChance; } |
363 | |
364 | BOOL SentDebugUnwindBegin() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_SentDebugUnwindBegin; } |
365 | void SetSentDebugUnwindBegin() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_SentDebugUnwindBegin; } |
366 | |
367 | BOOL DebugCatchHandlerFound() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_DebugCatchHandlerFound; } |
368 | void SetDebugCatchHandlerFound() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_DebugCatchHandlerFound; } |
369 | |
370 | BOOL SentDebugUnhandled() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_SentDebugUnhandled; } |
371 | void SetSentDebugUnhandled() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_SentDebugUnhandled; } |
372 | |
373 | BOOL IsUnhandled() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_IsUnhandled; } |
374 | void SetUnhandled() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_IsUnhandled; } |
375 | |
376 | BOOL DebuggerInterceptNotPossible() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_DebuggerInterceptNotPossible; } |
377 | void SetDebuggerInterceptNotPossible() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_DebuggerInterceptNotPossible; } |
378 | |
379 | BOOL DebuggerInterceptInfo() { LIMITED_METHOD_DAC_CONTRACT; return m_flags & Ex_DebuggerInterceptInfo; } |
380 | void SetDebuggerInterceptInfo() { LIMITED_METHOD_DAC_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_DebuggerInterceptInfo; } |
381 | #endif |
382 | |
383 | BOOL WasThrownByUs() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_WasThrownByUs; } |
384 | void SetWasThrownByUs() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_WasThrownByUs; } |
385 | void ResetWasThrownByUs() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags &= ~Ex_WasThrownByUs; } |
386 | |
387 | BOOL GotWatsonBucketDetails() { LIMITED_METHOD_CONTRACT; return m_flags & Ex_GotWatsonBucketInfo; } |
388 | void SetGotWatsonBucketDetails() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags |= Ex_GotWatsonBucketInfo; } |
389 | void ResetGotWatsonBucketDetails() { LIMITED_METHOD_CONTRACT; AssertIfReadOnly(); m_flags &= ~Ex_GotWatsonBucketInfo; } |
390 | |
391 | private: |
392 | enum |
393 | { |
394 | Ex_IsRethrown = 0x00000001, |
395 | Ex_UnwindingToFindResumeFrame = 0x00000002, |
396 | Ex_UnwindHasStarted = 0x00000004, |
397 | Ex_UseExInfoForStackwalk = 0x00000008, // Use this ExInfo to unwind a fault (AV, zerodiv) back to managed code? |
398 | |
399 | #ifdef DEBUGGING_SUPPORTED |
400 | Ex_SentDebugUserFirstChance = 0x00000010, |
401 | Ex_SentDebugFirstChance = 0x00000020, |
402 | Ex_SentDebugUnwindBegin = 0x00000040, |
403 | Ex_DebugCatchHandlerFound = 0x00000080, |
404 | Ex_SentDebugUnhandled = 0x00000100, |
405 | Ex_DebuggerInterceptInfo = 0x00000200, |
406 | Ex_DebuggerInterceptNotPossible = 0x00000400, |
407 | Ex_IsUnhandled = 0x00000800, |
408 | #endif |
409 | // Unused = 0x00001000, |
410 | |
411 | Ex_WasThrownByUs = 0x00002000, |
412 | |
413 | Ex_GotWatsonBucketInfo = 0x00004000, |
414 | |
415 | #if defined(WIN64EXCEPTIONS) && defined(_DEBUG) |
416 | Ex_FlagsAreReadOnly = 0x80000000 |
417 | #endif // defined(WIN64EXCEPTIONS) && defined(_DEBUG) |
418 | |
419 | }; |
420 | |
421 | UINT32 m_flags; |
422 | |
423 | #ifdef _DEBUG |
424 | enum |
425 | { |
426 | Ex_RPInvokeEscapingException = 0x40000000 |
427 | }; |
428 | UINT32 m_debugFlags; |
429 | #endif // _DEBUG |
430 | }; |
431 | |
432 | //------------------------------------------------------------------------------ |
433 | // Error reporting (unhandled exception, fatal error, user breakpoint |
434 | class TypeOfReportedError |
435 | { |
436 | public: |
437 | enum Type {INVALID, UnhandledException, FatalError, UserBreakpoint, NativeThreadUnhandledException, NativeBreakpoint, StackOverflowException}; |
438 | |
439 | TypeOfReportedError(Type t) : m_type(t) {} |
440 | |
441 | BOOL IsUnhandledException() { LIMITED_METHOD_CONTRACT; return (m_type == UnhandledException) || (m_type == NativeThreadUnhandledException) || (m_type == StackOverflowException); } |
442 | BOOL IsFatalError() { return (m_type == FatalError); } |
443 | BOOL IsUserBreakpoint() {return (m_type == UserBreakpoint); } |
444 | BOOL IsBreakpoint() {return (m_type == UserBreakpoint) || (m_type == NativeBreakpoint); } |
445 | BOOL IsException() { LIMITED_METHOD_CONTRACT; return IsUnhandledException() || (m_type == NativeBreakpoint) || (m_type == StackOverflowException); } |
446 | |
447 | Type GetType() { return m_type; } |
448 | void SetType(Type t) { m_type = t; } |
449 | |
450 | private: |
451 | Type m_type; |
452 | }; |
453 | |
454 | |
455 | #ifndef FEATURE_PAL |
456 | // This class is used to track Watson bucketing information for an exception. |
457 | typedef DPTR(class EHWatsonBucketTracker) PTR_EHWatsonBucketTracker; |
458 | class EHWatsonBucketTracker |
459 | { |
460 | private: |
461 | struct |
462 | { |
463 | PTR_VOID m_pUnhandledBuckets; |
464 | UINT_PTR m_UnhandledIp; |
465 | } m_WatsonUnhandledInfo; |
466 | |
467 | #ifdef _DEBUG |
468 | enum |
469 | { |
470 | // Bucket details were captured for ThreadAbort |
471 | Wb_CapturedForThreadAbort = 1, |
472 | |
473 | // Bucket details were captured at AD Transition |
474 | Wb_CapturedAtADTransition = 2, |
475 | |
476 | // Bucket details were captured during Reflection invocation |
477 | Wb_CapturedAtReflectionInvocation = 4 |
478 | }; |
479 | |
480 | DWORD m_DebugFlags; |
481 | #endif // _DEBUG |
482 | |
483 | public: |
484 | EHWatsonBucketTracker(); |
485 | void Init(); |
486 | void CopyEHWatsonBucketTracker(const EHWatsonBucketTracker& srcTracker); |
487 | void CopyBucketsFromThrowable(OBJECTREF oThrowable); |
488 | void SaveIpForWatsonBucket(UINT_PTR ip); |
489 | UINT_PTR RetrieveWatsonBucketIp(); |
490 | PTR_VOID RetrieveWatsonBuckets(); |
491 | void ClearWatsonBucketDetails(); |
492 | void CaptureUnhandledInfoForWatson(TypeOfReportedError tore, Thread * pThread, OBJECTREF * pThrowable); |
493 | |
494 | #ifdef _DEBUG |
495 | void ResetFlags() { LIMITED_METHOD_CONTRACT; m_DebugFlags = 0; } |
496 | BOOL CapturedForThreadAbort() { LIMITED_METHOD_CONTRACT; return m_DebugFlags & Wb_CapturedForThreadAbort; } |
497 | void SetCapturedForThreadAbort() { LIMITED_METHOD_CONTRACT; m_DebugFlags |= Wb_CapturedForThreadAbort; } |
498 | void ResetCapturedForThreadAbort() { LIMITED_METHOD_CONTRACT; m_DebugFlags &= ~Wb_CapturedForThreadAbort; } |
499 | |
500 | BOOL CapturedAtADTransition() { LIMITED_METHOD_CONTRACT; return m_DebugFlags & Wb_CapturedAtADTransition; } |
501 | void SetCapturedAtADTransition() { LIMITED_METHOD_CONTRACT; m_DebugFlags |= Wb_CapturedAtADTransition; } |
502 | void ResetCapturedAtADTransition() { LIMITED_METHOD_CONTRACT; m_DebugFlags &= ~Wb_CapturedAtADTransition; } |
503 | |
504 | BOOL CapturedAtReflectionInvocation() { LIMITED_METHOD_CONTRACT; return m_DebugFlags & Wb_CapturedAtReflectionInvocation; } |
505 | void SetCapturedAtReflectionInvocation() { LIMITED_METHOD_CONTRACT; m_DebugFlags |= Wb_CapturedAtReflectionInvocation; } |
506 | void ResetCapturedAtReflectionInvocation() { LIMITED_METHOD_CONTRACT; m_DebugFlags &= ~Wb_CapturedAtReflectionInvocation; } |
507 | #endif // _DEBUG |
508 | }; |
509 | |
510 | void SetStateForWatsonBucketing(BOOL fIsRethrownException, OBJECTHANDLE ohOriginalException); |
511 | BOOL CopyWatsonBucketsToThrowable(PTR_VOID pUnmanagedBuckets, OBJECTREF oTargetThrowable = NULL); |
512 | void CopyWatsonBucketsFromThrowableToCurrentThrowable(OBJECTREF oThrowableFrom); |
513 | void CopyWatsonBucketsBetweenThrowables(OBJECTREF oThrowableFrom, OBJECTREF oThrowableTo = NULL); |
514 | void SetupInitialThrowBucketDetails(UINT_PTR adjustedIp); |
515 | BOOL SetupWatsonBucketsForFailFast(EXCEPTIONREF refException); |
516 | void SetupWatsonBucketsForUEF(BOOL fUseLastThrownObject); |
517 | BOOL SetupWatsonBucketsForEscapingPreallocatedExceptions(); |
518 | BOOL SetupWatsonBucketsForNonPreallocatedExceptions(OBJECTREF oThrowable = NULL); |
519 | PTR_EHWatsonBucketTracker GetWatsonBucketTrackerForPreallocatedException(OBJECTREF oPreAllocThrowable, BOOL fCaptureBucketsIfNotPresent, |
520 | BOOL fStartSearchFromPreviousTracker = FALSE); |
521 | BOOL IsThrowableThreadAbortException(OBJECTREF oThrowable); |
522 | #endif // !FEATURE_PAL |
523 | |
524 | #endif // __ExStateCommon_h__ |
525 | |