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/* This is a poor man's implementation of virtual methods. */
7/* The purpose of pCrawlFrame is to abstract (at least for the most common cases
8 from the fact that not all methods are "framed" (basically all methods in
9 "native" code are "unframed"). That way the job for the enumerator callbacks
10 becomes much simpler (i.e. more transparent and hopefully less error prone).
11 Two call-backs still need to distinguish between the two types: GC and exception.
12 Both of these call-backs need to do really different things; for frameless methods
13 they need to go through the codemanager and use the resp. apis.
14
15 The reason for not implementing virtual methods on crawlFrame is solely because of
16 the way exception handling is implemented (it does a "long jump" and bypasses
17 the enumerator (stackWalker) when it finds a matching frame. By doing so couldn't
18 properly destruct the dynamically created instance of CrawlFrame.
19*/
20
21#ifndef __stackwalk_h__
22#define __stackwalk_h__
23
24#include "eetwain.h"
25#include "stackwalktypes.h"
26
27class Frame;
28class CrawlFrame;
29class ICodeManager;
30class IJitManager;
31struct EE_ILEXCEPTION;
32class AppDomain;
33
34// This define controls handling of faults in managed code. If it is defined,
35// the exception is handled (retried, actually), with a FaultingExceptionFrame
36// on the stack. The FEF is used for unwinding. If not defined, the unwinding
37// uses the exception context.
38#define USE_FEF // to mark where code needs to be changed to eliminate the FEF
39#if defined(_TARGET_X86_) && !defined(FEATURE_PAL)
40 #undef USE_FEF // Turn off the FEF use on x86.
41 #define ELIMINATE_FEF
42#else
43 #if defined(ELIMINATE_FEF)
44 #undef ELIMINATE_FEF
45 #endif
46#endif // _TARGET_X86_ && !FEATURE_PAL
47
48#if defined(WIN64EXCEPTIONS)
49#define RECORD_RESUMABLE_FRAME_SP
50#endif
51
52//************************************************************************
53// Enumerate all functions.
54//************************************************************************
55
56/* This enumerator is meant to be used for the most common cases, i.e. to
57 enumerate just all the functions of the requested thread. It is just a
58 cover for the "real" enumerator.
59 */
60
61StackWalkAction StackWalkFunctions(Thread * thread, PSTACKWALKFRAMESCALLBACK pCallback, VOID * pData);
62
63/*<TODO>@ISSUE: Maybe use a define instead?</TODO>
64#define StackWalkFunctions(thread, callBack, userdata) thread->StackWalkFrames(METHODSONLY, (callBack),(userData))
65*/
66
67
68class CrawlFrame
69{
70public:
71
72#ifdef _TARGET_X86_
73 friend StackWalkAction TAStackCrawlCallBack(CrawlFrame* pCf, void* data);
74#endif // _TARGET_X86_
75
76 //************************************************************************
77 // Functions available for the callbacks (using the current pCrawlFrame)
78 //************************************************************************
79
80 /* Widely used/benign functions */
81
82 /* Is this a function? */
83 /* Returns either a MethodDesc* or NULL for "non-function" frames */
84 //<TODO>@TODO: what will it return for transition frames?</TODO>
85
86#ifdef FEATURE_INTERPRETER
87 MethodDesc *GetFunction();
88#else // FEATURE_INTERPRETER
89 inline MethodDesc *GetFunction()
90 {
91 LIMITED_METHOD_DAC_CONTRACT;
92 return pFunc;
93 }
94#endif
95
96
97 Assembly *GetAssembly();
98
99 /* Returns either a Frame * (for "framed items) or
100 Returns NULL for frameless functions
101 */
102 inline Frame* GetFrame() // will return NULL for "frameless methods"
103 {
104 LIMITED_METHOD_DAC_CONTRACT;
105
106 if (isFrameless)
107 return NULL;
108 else
109 return pFrame;
110 }
111
112 BOOL IsInCalleesFrames(LPVOID stackPointer);
113
114#ifndef DACCESS_COMPILE
115 /* Returns address of the securityobject stored in the current function (method?)
116 Returns NULL if
117 - not a function OR
118 - function (method?) hasn't reserved any room for it
119 (which is an error)
120 */
121 OBJECTREF * GetAddrOfSecurityObject();
122#endif // DACCESS_COMPILE
123
124 // Fetch the extra type argument passed in some cases
125 PTR_VOID GetParamTypeArg();
126
127 /* Returns the "this" pointer of the method of the current frame -- at least in some cases.
128 Returns NULL if the current frame does not have a method, or that method is not an instance method of a class type.
129 Otherwise, the semantics currently depend, unfortunately, on the architecture. On non-x86 architectures,
130 should only be called for methods where the generic instantiation context is found via the this pointer (so that
131 this information will be encoded in the GC Info). On x86, can be called for this case, or if the method
132 is synchronized.
133 */
134 OBJECTREF GetThisPointer();
135
136 /*
137 Returns ambient Stack pointer for this crawlframe.
138 Must be a frameless method.
139 Returns NULL if not available (includes prolog + epilog).
140 This is safe to call on all methods, but it may return
141 garbage if the method does not have an ambient SP (eg, ebp-based methods).
142 x86 is the only platform using ambient SP.
143 */
144 TADDR GetAmbientSPFromCrawlFrame();
145
146 void GetExactGenericInstantiations(Instantiation *pClassInst,
147 Instantiation *pMethodInst);
148
149 /* Returns extra information required to reconstruct exact generic parameters,
150 if any.
151 Returns NULL if
152 - no extra information is required (i.e. the code is non-shared, which
153 you can tell from the MethodDesc)
154 - the extra information is not available (i.e. optimized away or codegen problem)
155 Returns a MethodTable if the pMD returned by GetFunction satisfies RequiresInstMethodTableArg,
156 and returns a MethodDesc if the pMD returned by GetFunction satisfies RequiresInstMethodDescArg.
157 These together carry the exact instantiation information.
158 */
159 PTR_VOID GetExactGenericArgsToken();
160
161 inline CodeManState * GetCodeManState() { LIMITED_METHOD_DAC_CONTRACT; return & codeManState; }
162 /*
163 IF YOU USE ANY OF THE SUBSEQUENT FUNCTIONS, YOU NEED TO REALLY UNDERSTAND THE
164 STACK-WALKER (INCLUDING UNWINDING OF METHODS IN MANAGED NATIVE CODE)!
165 YOU ALSO NEED TO UNDERSTAND THAT THESE FUNCTIONS MIGHT CHANGE ON AN AS-NEED BASIS.
166 */
167
168 /* The rest are meant to be used only by the exception catcher and the GC call-back */
169
170 /* Is currently a frame available? */
171 /* conceptually returns (GetFrame(pCrawlFrame) == NULL)
172 */
173 inline bool IsFrameless()
174 {
175 LIMITED_METHOD_DAC_CONTRACT;
176
177 return isFrameless;
178 }
179
180
181 /* Is it the current active (top-most) frame
182 */
183 inline bool IsActiveFrame()
184 {
185 LIMITED_METHOD_DAC_CONTRACT;
186
187 return isFirst;
188 }
189
190 /* Is it the current active function (top-most frame)
191 asserts for non-functions, should be used for managed native code only
192 */
193 inline bool IsActiveFunc()
194 {
195 LIMITED_METHOD_DAC_CONTRACT;
196
197 return (pFunc && isFirst);
198 }
199
200 /* Is it the current active function (top-most frame)
201 which faulted or threw an exception ?
202 asserts for non-functions, should be used for managed native code only
203 */
204 bool IsInterrupted()
205 {
206 LIMITED_METHOD_DAC_CONTRACT;
207
208 return (pFunc && isInterrupted /* && isFrameless?? */);
209 }
210
211 /* Is it the current active function (top-most frame) which faulted ?
212 asserts for non-functions, should be used for managed native code only
213 */
214 bool HasFaulted()
215 {
216 LIMITED_METHOD_DAC_CONTRACT;
217
218 return (pFunc && hasFaulted /* && isFrameless?? */);
219 }
220
221 /* Is this CrawlFrame just marking that we're in native code?
222 Such frames are only provided when the stackwalk is inited w/ NOTIFY_ON_U2M_TRANSITIONS.
223 The only use of these crawlframes is to get the Regdisplay.
224 */
225 bool IsNativeMarker()
226 {
227 LIMITED_METHOD_DAC_CONTRACT;
228 return isNativeMarker;
229 }
230
231 /* x86 does not always push a FaultingExceptionFrame on the stack when there is a native exception
232 (e.g. a breakpoint). In this case, it relies on the CONTEXT stored on the ExInfo to resume
233 the stackwalk at the managed stack frame which has faulted.
234
235 This flag is set when the stackwalker is stopped at such a no-explicit-frame transition. Conceptually
236 this is just like stopping at a transition frame. Note that the stackwalker only stops at no-frame
237 transition if NOTIFY_ON_NO_FRAME_TRANSITIONS is set.
238 */
239 bool IsNoFrameTransition()
240 {
241 LIMITED_METHOD_DAC_CONTRACT;
242 return isNoFrameTransition;
243 }
244
245 // A no-frame transition is one protected by an ExInfo. It's an optimization on x86 to avoid pushing a
246 // FaultingExceptionFrame (FEF). Thus, for all intents and purposes, we should treat a no-frame
247 // transition as a FEF. This function returns a stack address for the no-frame transition to substitute
248 // as the frame address of a FEF. It's currently only used by the debugger stackwalker.
249 TADDR GetNoFrameTransitionMarker()
250 {
251 LIMITED_METHOD_DAC_CONTRACT;
252 return (isNoFrameTransition ? taNoFrameTransitionMarker : NULL);
253 }
254
255 /* Has the IP been adjusted to a point where it is safe to do GC ?
256 (for OutOfLineThrownExceptionFrame)
257 asserts for non-functions, should be used for managed native code only
258 */
259 bool IsIPadjusted()
260 {
261 LIMITED_METHOD_DAC_CONTRACT;
262
263 return (pFunc && isIPadjusted /* && isFrameless?? */);
264 }
265
266 /* Gets the ICodeMangerFlags for the current frame */
267
268 unsigned GetCodeManagerFlags()
269 {
270 CONTRACTL {
271 NOTHROW;
272 GC_NOTRIGGER;
273 SUPPORTS_DAC;
274 } CONTRACTL_END;
275
276 unsigned flags = 0;
277
278 if (IsActiveFunc())
279 flags |= ActiveStackFrame;
280
281 if (IsInterrupted())
282 {
283 flags |= ExecutionAborted;
284
285 if (!HasFaulted() && !IsIPadjusted())
286 {
287 _ASSERTE(!(flags & ActiveStackFrame));
288 flags |= AbortingCall;
289 }
290 }
291
292#if defined(WIN64EXCEPTIONS)
293 if (ShouldParentToFuncletSkipReportingGCReferences())
294 {
295 flags |= ParentOfFuncletStackFrame;
296 }
297#endif // defined(WIN64EXCEPTIONS)
298
299 return flags;
300 }
301
302 AppDomain *GetAppDomain()
303 {
304 LIMITED_METHOD_DAC_CONTRACT;
305
306 return pAppDomain;
307 }
308
309 /* Is this frame at a safe spot for GC?
310 */
311 bool IsGcSafe();
312
313#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
314 bool HasTailCalls();
315#endif // _TARGET_ARM_ || _TARGET_ARM64_
316
317 PREGDISPLAY GetRegisterSet()
318 {
319 LIMITED_METHOD_DAC_CONTRACT;
320
321 // We would like to make the following assertion, but it is legitimately
322 // violated when we perform a crawl to find the return address for a hijack.
323 // _ASSERTE(isFrameless);
324 return pRD;
325 }
326
327 EECodeInfo * GetCodeInfo()
328 {
329 LIMITED_METHOD_DAC_CONTRACT;
330
331 // This assumes that CrawlFrame is host-only structure with DACCESS_COMPILE
332 // and thus it always returns the host address.
333 return &codeInfo;
334 }
335
336 GCInfoToken GetGCInfoToken()
337 {
338 LIMITED_METHOD_DAC_CONTRACT;
339 _ASSERTE(isFrameless);
340 return codeInfo.GetGCInfoToken();
341 }
342
343 PTR_VOID GetGCInfo()
344 {
345 LIMITED_METHOD_DAC_CONTRACT;
346 _ASSERTE(isFrameless);
347 return codeInfo.GetGCInfo();
348 }
349
350 const METHODTOKEN& GetMethodToken()
351 {
352 LIMITED_METHOD_DAC_CONTRACT;
353 _ASSERTE(isFrameless);
354 return codeInfo.GetMethodToken();
355 }
356
357 unsigned GetRelOffset()
358 {
359 LIMITED_METHOD_DAC_CONTRACT;
360 _ASSERTE(isFrameless);
361 return codeInfo.GetRelOffset();
362 }
363
364 IJitManager* GetJitManager()
365 {
366 LIMITED_METHOD_DAC_CONTRACT;
367 _ASSERTE(isFrameless);
368 return codeInfo.GetJitManager();
369 }
370
371 ICodeManager* GetCodeManager()
372 {
373 LIMITED_METHOD_DAC_CONTRACT;
374 _ASSERTE(isFrameless);
375 return codeInfo.GetCodeManager();
376 }
377
378 inline StackwalkCacheEntry* GetStackwalkCacheEntry()
379 {
380 LIMITED_METHOD_CONTRACT;
381 _ASSERTE (isCachedMethod != stackWalkCache.IsEmpty());
382 if (isCachedMethod && stackWalkCache.m_CacheEntry.IsSafeToUseCache())
383 {
384 return &(stackWalkCache.m_CacheEntry);
385 }
386 else
387 {
388 return NULL;
389 }
390 }
391
392 void CheckGSCookies();
393
394#if defined(WIN64EXCEPTIONS)
395 bool IsFunclet()
396 {
397 WRAPPER_NO_CONTRACT;
398
399 if (!IsFrameless())
400 return false;
401
402 return !!codeInfo.IsFunclet();
403 }
404
405 bool IsFilterFunclet();
406
407 // Indicates if the funclet has already reported GC
408 // references (or not). This will return true if
409 // we come across the parent frame of a funclet
410 // that is active on the stack.
411 bool ShouldParentToFuncletSkipReportingGCReferences()
412 {
413 LIMITED_METHOD_CONTRACT;
414 return fShouldParentToFuncletSkipReportingGCReferences;
415 }
416
417 bool ShouldCrawlframeReportGCReferences()
418 {
419 LIMITED_METHOD_CONTRACT;
420
421 return fShouldCrawlframeReportGCReferences;
422 }
423
424 bool ShouldParentToFuncletUseUnwindTargetLocationForGCReporting()
425 {
426 LIMITED_METHOD_CONTRACT;
427 return fShouldParentFrameUseUnwindTargetPCforGCReporting;
428 }
429
430 const EE_ILEXCEPTION_CLAUSE& GetEHClauseForCatch()
431 {
432 return ehClauseForCatch;
433 }
434
435#endif // WIN64EXCEPTIONS
436
437protected:
438 // CrawlFrames are temporarily created by the enumerator.
439 // Do not create one from C++. This protected constructor polices this rule.
440 CrawlFrame();
441
442 void SetCurGSCookie(GSCookie * pGSCookie);
443
444private:
445
446 friend class Thread;
447 friend class EECodeManager;
448 friend class StackFrameIterator;
449#ifdef WIN64EXCEPTIONS
450 friend class ExceptionTracker;
451#endif // WIN64EXCEPTIONS
452
453 CodeManState codeManState;
454
455 bool isFrameless;
456 bool isFirst;
457
458 // The next three fields are only valid for managed stack frames. They are set using attributes
459 // on explicit frames, and they are reset after processing each managed stack frame.
460 bool isInterrupted;
461 bool hasFaulted;
462 bool isIPadjusted;
463
464 bool isNativeMarker;
465 bool isProfilerDoStackSnapshot;
466 bool isNoFrameTransition;
467 TADDR taNoFrameTransitionMarker; // see code:CrawlFrame.GetNoFrameTransitionMarker
468 PTR_Frame pFrame;
469 MethodDesc *pFunc;
470
471 // the rest is only used for "frameless methods"
472 AppDomain *pAppDomain;
473 PREGDISPLAY pRD; // "thread context"/"virtual register set"
474
475 EECodeInfo codeInfo;
476#if defined(WIN64EXCEPTIONS)
477 bool isFilterFunclet;
478 bool isFilterFuncletCached;
479 bool fShouldParentToFuncletSkipReportingGCReferences;
480 bool fShouldCrawlframeReportGCReferences;
481 bool fShouldParentFrameUseUnwindTargetPCforGCReporting;
482 EE_ILEXCEPTION_CLAUSE ehClauseForCatch;
483#endif //WIN64EXCEPTIONS
484 Thread* pThread;
485
486 // fields used for stackwalk cache
487 OBJECTREF *pSecurityObject;
488 BOOL isCachedMethod;
489 StackwalkCache stackWalkCache;
490
491 GSCookie *pCurGSCookie;
492 GSCookie *pFirstGSCookie;
493
494 friend class Frame; // added to allow 'friend void CrawlFrame::GotoNextFrame();' declaration in class Frame, frames.h
495 void GotoNextFrame();
496};
497
498void GcEnumObject(LPVOID pData, OBJECTREF *pObj);
499StackWalkAction GcStackCrawlCallBack(CrawlFrame* pCF, VOID* pData);
500
501#if defined(ELIMINATE_FEF)
502//******************************************************************************
503// This class is used to help use exception context records to resync a
504// stackwalk, when managed code has generated an exception (eg, AV, zerodiv.,,)
505// Such an exception causes a transition from the managed code into unmanaged
506// OS and runtime code, but without the benefit of any Frame. This code helps
507// the stackwalker simulate the effect that such a frame would have.
508// In particular, this class has methods to walk the chain of ExInfos, looking
509// for records with pContext pointers with certain characteristics. The
510// characteristics that are important are the location in the stack (ie, is a
511// given pContext relevant at a particular point in the stack walk), and
512// whether the pContext was generated in managed code.
513//******************************************************************************
514class ExInfoWalker
515{
516public:
517 ExInfoWalker() : m_pExInfo(0) { SUPPORTS_DAC; }
518 void Init (ExInfo *pExInfo) { SUPPORTS_DAC; m_pExInfo = pExInfo; }
519 // Skip one ExInfo.
520 void WalkOne();
521 // Attempt to find an ExInfo with a pContext that is higher (older) than
522 // a given minimum location.
523 void WalkToPosition(TADDR taMinimum, BOOL bPopFrames);
524 // Attempt to find an ExInfo with a pContext that has an IP in managed code.
525 void WalkToManaged();
526 // Return current ExInfo's m_pContext, or NULL if no m_pExInfo.
527 PTR_CONTEXT GetContext() { SUPPORTS_DAC; return m_pExInfo ? m_pExInfo->m_pContext : NULL; }
528 // Useful to see if there is more on the ExInfo chain.
529 ExInfo* GetExInfo() { SUPPORTS_DAC; return m_pExInfo; }
530
531 // helper functions for retrieving information from the exception CONTEXT
532 TADDR GetSPFromContext()
533 {
534 LIMITED_METHOD_CONTRACT;
535 SUPPORTS_DAC;
536 return dac_cast<TADDR>((m_pExInfo && m_pExInfo->m_pContext) ? GetSP(m_pExInfo->m_pContext) : PTR_NULL);
537 }
538
539 TADDR GetEBPFromContext()
540 {
541 LIMITED_METHOD_CONTRACT;
542 SUPPORTS_DAC;
543 return dac_cast<TADDR>((m_pExInfo && m_pExInfo->m_pContext) ? GetFP(m_pExInfo->m_pContext) : PTR_NULL);
544 }
545
546 DWORD GetFault() { SUPPORTS_DAC; return m_pExInfo ? m_pExInfo->m_pExceptionRecord->ExceptionCode : 0; }
547
548private:
549 ExInfo *m_pExInfo;
550}; // class ExInfoWalker
551#endif // ELIMINATE_FEF
552
553
554//---------------------------------------------------------------------------------------
555//
556// This iterator class walks the stack of a managed thread. Where the iterator stops depends on the
557// stackwalk flags.
558//
559// Notes:
560// This class works both in-process and out-of-process (e.g. DAC).
561//
562
563class StackFrameIterator
564{
565public:
566 // This constructor is for the usage pattern of creating an uninitialized StackFrameIterator and then
567 // calling Init() on it.
568 StackFrameIterator(void);
569
570 // This constructor is for the usage pattern of creating an initialized StackFrameIterator and then
571 // calling ResetRegDisp() on it.
572 StackFrameIterator(Thread * pThread, PTR_Frame pFrame, ULONG32 flags);
573
574 //
575 // We should consider merging Init() and ResetRegDisp().
576 //
577
578 // Initialize the iterator. Note that the iterator has thread-affinity,
579 // and the stackwalk flags cannot be changed once the iterator is created.
580 BOOL Init(Thread * pThread,
581 PTR_Frame pFrame,
582 PREGDISPLAY pRegDisp,
583 ULONG32 flags);
584
585 // Reset the iterator to the specified REGDISPLAY. The caller must ensure that the REGDISPLAY is valid.
586 BOOL ResetRegDisp(PREGDISPLAY pRegDisp,
587 bool fIsFirst);
588
589 // @dbgtodo inspection - This function should be removed once the Windows debuggers stop using the old DAC API.
590 void SetIsFirstFrame(bool isFirst)
591 {
592 LIMITED_METHOD_CONTRACT;
593 m_crawl.isFirst = isFirst;
594 }
595
596 // whether the iterator has reached the root of the stack or not
597 BOOL IsValid(void);
598
599 // advance to the next frame according to the stackwalk flags
600 StackWalkAction Next(void);
601
602 enum FrameState
603 {
604 SFITER_UNINITIALIZED, // uninitialized
605 SFITER_FRAMELESS_METHOD, // managed stack frame
606 SFITER_FRAME_FUNCTION, // explicit frame
607 SFITER_SKIPPED_FRAME_FUNCTION, // skipped explicit frame
608 SFITER_NO_FRAME_TRANSITION, // no-frame transition (currently used for ExInfo only)
609 SFITER_NATIVE_MARKER_FRAME, // the native stack frame immediately below (stack grows up)
610 // a managed stack region
611 SFITER_INITIAL_NATIVE_CONTEXT, // initial native seed CONTEXT
612 SFITER_DONE, // the iterator has reached the end of the stack
613 };
614 FrameState GetFrameState() {LIMITED_METHOD_DAC_CONTRACT; return m_frameState;}
615
616 CrawlFrame m_crawl;
617
618#if defined(_DEBUG)
619 // used in logging
620 UINT32 m_uFramesProcessed;
621#endif // _DEBUG
622
623private:
624 // This is a helper for the two constructors.
625 void CommonCtor(Thread * pThread, PTR_Frame pFrame, ULONG32 flags);
626
627 // Reset the CrawlFrame owned by the iterator. Used by both Init() and ResetRegDisp().
628 void ResetCrawlFrame(void);
629
630 // Check whether we should stop at the current frame given the stackwalk flags.
631 // If not, continue advancing to the next frame.
632 StackWalkAction Filter(void);
633
634 // Advance to the next frame regardless of the stackwalk flags. This is used by Next() and Filter().
635 StackWalkAction NextRaw(void);
636
637 // sync the REGDISPLAY to the current CONTEXT
638 void UpdateRegDisp(void);
639
640 // Check whether the IP is managed code. This function updates the following fields on CrawlFrame:
641 // JitManagerInstance and isFrameless.
642 void ProcessIp(PCODE Ip);
643
644 // Update the CrawlFrame to represent where we have stopped.
645 // This is called after advancing to a new frame.
646 void ProcessCurrentFrame(void);
647
648 // If an explicit frame is allocated in a managed stack frame (e.g. an inlined pinvoke call),
649 // we may have skipped an explicit frame. This function checks for them.
650 BOOL CheckForSkippedFrames(void);
651
652 // Perform the necessary tasks before stopping at a managed stack frame. This is mostly validation work.
653 void PreProcessingForManagedFrames(void);
654
655 // Perform the necessary tasks after stopping at a managed stack frame and unwinding to its caller.
656 // This includes advancing the ExInfo and checking whether the new IP is managed.
657 void PostProcessingForManagedFrames(void);
658
659 // Perform the necessary tasks after stopping at a no-frame transition. This includes loading
660 // the CONTEXT stored in the ExInfo and updating the REGDISPLAY to the faulting managed stack frame.
661 void PostProcessingForNoFrameTransition(void);
662
663#if defined(WIN64EXCEPTIONS)
664 void ResetGCRefReportingState(bool ResetOnlyIntermediaryState = false)
665 {
666 LIMITED_METHOD_CONTRACT;
667
668 if (!ResetOnlyIntermediaryState)
669 {
670 m_sfFuncletParent = StackFrame();
671 m_fProcessNonFilterFunclet = false;
672 }
673
674 m_sfIntermediaryFuncletParent = StackFrame();
675 m_fProcessIntermediaryNonFilterFunclet = false;
676 }
677#endif // defined(WIN64EXCEPTIONS)
678
679 // Iteration state.
680 FrameState m_frameState;
681
682 // Initial state. Must be preserved for restarting.
683 Thread * m_pThread; // Thread on which to walk.
684
685 PTR_Frame m_pStartFrame; // Frame* passed to Init
686
687 // This is the real starting explicit frame. If m_pStartFrame is NULL,
688 // then this is equal to m_pThread->GetFrame(). Otherwise this is equal to m_pStartFrame.
689 INDEBUG(PTR_Frame m_pRealStartFrame);
690
691 ULONG32 m_flags; // StackWalkFrames flags.
692 ICodeManagerFlags m_codeManFlags;
693 ExecutionManager::ScanFlag m_scanFlag;
694
695 // the following fields are used to cache information about a managed stack frame
696 // when we need to stop for skipped explicit frames
697 EECodeInfo m_cachedCodeInfo;
698
699 GSCookie * m_pCachedGSCookie;
700
701#if defined(ELIMINATE_FEF)
702 ExInfoWalker m_exInfoWalk;
703#endif // ELIMINATE_FEF
704
705#if defined(WIN64EXCEPTIONS)
706 // used in funclet-skipping
707 StackFrame m_sfParent;
708
709 // Used in GC reference enumeration mode
710 StackFrame m_sfFuncletParent;
711 bool m_fProcessNonFilterFunclet;
712 StackFrame m_sfIntermediaryFuncletParent;
713 bool m_fProcessIntermediaryNonFilterFunclet;
714 bool m_fDidFuncletReportGCReferences;
715#endif // WIN64EXCEPTIONS
716
717#if defined(RECORD_RESUMABLE_FRAME_SP)
718 LPVOID m_pvResumableFrameTargetSP;
719#endif // RECORD_RESUMABLE_FRAME_SP
720};
721
722void SetUpRegdisplayForStackWalk(Thread * pThread, T_CONTEXT * pContext, REGDISPLAY * pRegdisplay);
723
724#endif
725