Add a fourth parameter to the DEFINE_DACVAR macro that is the actual fully qualified...
[platform/upstream/coreclr.git] / src / inc / eetwain.h
1 //
2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
4 //
5 //*****************************************************************************
6 //
7 // EETwain.h
8 //
9 // This file has the definition of ICodeManager and EECodeManager.
10 //
11 // ICorJitCompiler compiles the IL of a method to native code, and stores
12 // auxilliary data called as GCInfo (via ICorJitInfo::allocGCInfo()).
13 // The data is used by the EE to manage the method's garbage collection,
14 // exception handling, stack-walking etc.
15 // This data can be parsed by an ICodeManager corresponding to that
16 // ICorJitCompiler.
17 //
18 // EECodeManager is an implementation of ICodeManager for a default format
19 // of GCInfo. Various ICorJitCompiler's are free to share this format so that
20 // they do not need to provide their own implementation of ICodeManager
21 // (though they are permitted to, if they want).
22 //
23 //*****************************************************************************
24
25 #ifndef _EETWAIN_H
26 #define _EETWAIN_H
27 //*****************************************************************************
28
29 #include <daccess.h>
30 #include "regdisp.h"
31 #include "corjit.h"     // For NativeVarInfo
32 #include "stackwalktypes.h"
33 #include "bitvector.h"
34
35 #if !defined(_TARGET_X86_)
36 #define USE_GC_INFO_DECODER
37 #endif
38
39
40 #if CHECK_APP_DOMAIN_LEAKS
41 #define CHECK_APP_DOMAIN    GC_CALL_CHECK_APP_DOMAIN
42 #else
43 #define CHECK_APP_DOMAIN    0
44 #endif
45
46 struct EHContext;
47
48 #ifdef DACCESS_COMPILE
49 typedef struct _DAC_SLOT_LOCATION
50 {
51     int reg;
52     int regOffset;
53     bool targetPtr;
54     
55     _DAC_SLOT_LOCATION(int _reg, int _regOffset, bool _targetPtr)
56         : reg(_reg), regOffset(_regOffset), targetPtr(_targetPtr)
57     {
58     }
59 } DacSlotLocation;
60 #endif
61
62 typedef void (*GCEnumCallback)(
63     LPVOID          hCallback,      // callback data
64     OBJECTREF*      pObject,        // address of obect-reference we are reporting
65     DWORD           flags           // is this a pinned and/or interior pointer
66     DAC_ARG(DacSlotLocation loc)    // where the reference came from
67 );
68
69 /******************************************************************************
70   The stackwalker maintains some state on behalf of ICodeManager.
71 */
72
73 const int CODEMAN_STATE_SIZE = 512;
74
75 struct CodeManState
76 {
77     DWORD       dwIsSet; // Is set to 0 by the stackwalk as appropriate
78     BYTE        stateBuf[CODEMAN_STATE_SIZE];
79 };
80
81 /******************************************************************************
82    These flags are used by some functions, although not all combinations might
83    make sense for all functions.
84 */
85
86 enum ICodeManagerFlags
87 {
88     ActiveStackFrame =  0x0001, // this is the currently active function
89     ExecutionAborted =  0x0002, // execution of this function has been aborted
90                                     // (i.e. it will not continue execution at the
91                                     // current location)
92     AbortingCall    =   0x0004, // The current call will never return
93     UpdateAllRegs   =   0x0008, // update full register set
94     CodeAltered     =   0x0010, // code of that function might be altered
95                                     // (e.g. by debugger), need to call EE
96                                     // for original code
97     SpeculativeStackwalk
98                     =   0x0020, // we're in the middle of a stackwalk seeded
99                                     // by an untrusted source (e.g., sampling profiler)
100
101     ParentOfFuncletStackFrame
102                     =   0x0040, // A funclet for this frame was previously reported
103     NoReportUntracked
104                     =   0x0080, // EnumGCRefs/EnumerateLiveSlots should *not* include
105                                 // any untracked slots
106 };
107
108 //*****************************************************************************
109 //
110 // EECodeInfo is used by ICodeManager to get information about the
111 // method whose GCInfo is being processed.
112 // It is useful so that some information which is available elsewhere does
113 // not need to be cached in the GCInfo.
114 //
115
116 class EECodeInfo;
117
118 enum GenericParamContextType
119 {
120     GENERIC_PARAM_CONTEXT_NONE = 0,
121     GENERIC_PARAM_CONTEXT_THIS = 1,
122     GENERIC_PARAM_CONTEXT_METHODDESC = 2,
123     GENERIC_PARAM_CONTEXT_METHODTABLE = 3
124 };
125
126 //*****************************************************************************
127 //
128 // ICodeManager is the abstract class that all CodeManagers
129 // must inherit from.  This will probably need to move into
130 // cor.h and become a real com interface.
131 //
132 //*****************************************************************************
133
134 class ICodeManager
135 {
136     VPTR_BASE_VTABLE_CLASS_AND_CTOR(ICodeManager)
137
138 public:
139
140 /*
141     Last chance for the runtime support to do fixups in the context
142     before execution continues inside a filter, catch handler, or fault/finally
143 */
144
145 enum ContextType
146 {
147     FILTER_CONTEXT,
148     CATCH_CONTEXT,
149     FINALLY_CONTEXT
150 };
151
152 /* Type of funclet corresponding to a shadow stack-pointer */
153
154 enum
155 {
156     SHADOW_SP_IN_FILTER = 0x1,
157     SHADOW_SP_FILTER_DONE = 0x2,
158     SHADOW_SP_BITS = 0x3
159 };
160
161 #ifndef DACCESS_COMPILE
162
163 virtual void FixContext(ContextType     ctxType,
164                         EHContext      *ctx,
165                         EECodeInfo     *pCodeInfo,
166                         DWORD           dwRelOffset,
167                         DWORD           nestingLevel,
168                         OBJECTREF       thrownObject,
169                         CodeManState   *pState,
170                         size_t       ** ppShadowSP,             // OUT
171                         size_t       ** ppEndRegion) = 0;       // OUT
172
173 #endif // #ifndef DACCESS_COMPILE
174
175 /*
176     Gets the ambient stack pointer value at the given nesting level within
177     the method.
178 */
179 virtual TADDR GetAmbientSP(PREGDISPLAY     pContext,
180                            EECodeInfo     *pCodeInfo,
181                            DWORD           dwRelOffset,
182                            DWORD           nestingLevel,
183                            CodeManState   *pState) = 0;
184
185 /*
186     Get the number of bytes used for stack parameters.
187     This is currently only used on x86.
188 */
189 virtual ULONG32 GetStackParameterSize(EECodeInfo* pCodeInfo) = 0;
190
191 /*
192     Unwind the current stack frame, i.e. update the virtual register
193     set in pContext. This will be similar to the state after the function
194     returns back to caller (IP points to after the call, Frame and Stack
195     pointer has been reset, callee-saved registers restored
196     (if UpdateAllRegs), callee-UNsaved registers are trashed)
197     Returns success of operation.
198 */
199 virtual bool UnwindStackFrame(PREGDISPLAY     pContext,
200                               EECodeInfo     *pCodeInfo,
201                               unsigned        flags,
202                               CodeManState   *pState,
203                               StackwalkCacheUnwindInfo  *pUnwindInfo) = 0;
204
205 /*
206     Is the function currently at a "GC safe point" ?
207     Can call EnumGcRefs() successfully
208 */
209 virtual bool IsGcSafe(EECodeInfo     *pCodeInfo,
210                       DWORD           dwRelOffset) = 0;
211
212 #if defined(_TARGET_AMD64_) && defined(_DEBUG)
213 /*
214     Locates the end of the last interruptible region in the given code range.
215     Returns 0 if the entire range is uninterruptible.  Returns the end point
216     if the entire range is interruptible.
217 */
218 virtual unsigned FindEndOfLastInterruptibleRegion(unsigned curOffset,
219                                                   unsigned endOffset,
220                                                   PTR_VOID methodInfoPtr) = 0;
221 #endif // _TARGET_AMD64_ && _DEBUG
222
223 /*
224     Enumerate all live object references in that function using
225     the virtual register set. Same reference location cannot be enumerated
226     multiple times (but all differenct references pointing to the same
227     object have to be individually enumerated).
228     Returns success of operation.
229 */
230 virtual bool EnumGcRefs(PREGDISPLAY     pContext,
231                         EECodeInfo     *pCodeInfo,
232                         unsigned        flags,
233                         GCEnumCallback  pCallback,
234                         LPVOID          hCallBack) = 0;
235
236 /*
237     Return the address of the local security object reference
238     (if available).
239 */
240 virtual OBJECTREF* GetAddrOfSecurityObject(CrawlFrame *pCF) = 0;
241
242 /*
243     For a non-static method, "this" pointer is passed in as argument 0.
244     However, if there is a "ldarga 0" or "starg 0" in the IL, 
245     JIT will create a copy of arg0 and redirect all "ldarg(a) 0" and "starg 0" to this copy.
246     (See Compiler::lvaArg0Var for more details.)
247     
248     The following method returns the original "this" argument, i.e. the one that is passed in,
249     if it is a non-static method AND the object is still alive. 
250     Returns NULL in all other cases.
251 */
252 virtual OBJECTREF GetInstance(PREGDISPLAY     pContext,
253                               EECodeInfo*     pCodeInfo) = 0;
254
255 /*
256     Returns the extra argument passed to to shared generic code if it is still alive.
257     Returns NULL in all other cases.
258 */
259 virtual PTR_VOID GetParamTypeArg(PREGDISPLAY     pContext,
260                                  EECodeInfo *    pCodeInfo) = 0;
261
262 // Returns the type of the context parameter (this, methodtable, methoddesc, or none)
263 virtual GenericParamContextType GetParamContextType(PREGDISPLAY     pContext,
264                                                     EECodeInfo *    pCodeInfo) = 0;
265
266 /*
267     Returns the offset of the GuardStack cookie if it exists.
268     Returns NULL if there is no cookie.
269 */
270 virtual void * GetGSCookieAddr(PREGDISPLAY     pContext,
271                                EECodeInfo    * pCodeInfo,
272                                CodeManState  * pState) = 0;
273
274 /*
275   Returns true if the given IP is in the given method's prolog or an epilog.
276 */
277 virtual bool IsInPrologOrEpilog(DWORD  relPCOffset,
278                                 PTR_VOID methodInfoPtr,
279                                 size_t* prologSize) = 0;
280
281 /*
282   Returns true if the given IP is in the synchronized region of the method (valid for synchronized methods only)
283 */
284 virtual bool IsInSynchronizedRegion(
285                 DWORD           relOffset,
286                 PTR_VOID        methodInfoPtr,
287                 unsigned        flags) = 0;
288
289 /*
290   Returns the size of a given function as reported in the GC info (does
291   not take procedure splitting into account).  For the actual size of
292   the hot region call IJitManager::JitTokenToMethodHotSize.
293 */
294 virtual size_t GetFunctionSize(PTR_VOID methodInfoPtr) = 0;
295
296 /*
297   Returns the size of the frame (barring localloc)
298 */
299 virtual unsigned int GetFrameSize(PTR_VOID methodInfoPtr) = 0;
300
301 #ifndef DACCESS_COMPILE
302
303 /* Debugger API */
304
305 virtual const BYTE*     GetFinallyReturnAddr(PREGDISPLAY pReg)=0;
306
307 virtual BOOL            IsInFilter(void *methodInfoPtr,
308                                    unsigned offset,
309                                    PCONTEXT pCtx,
310                                    DWORD curNestLevel) = 0;
311
312 virtual BOOL            LeaveFinally(void *methodInfoPtr,
313                                      unsigned offset,
314                                      PCONTEXT pCtx) = 0;
315
316 virtual void            LeaveCatch(void *methodInfoPtr,
317                                    unsigned offset,
318                                    PCONTEXT pCtx)=0;
319
320 #ifdef EnC_SUPPORTED
321
322 /*
323     Last chance for the runtime support to do fixups in the context
324     before execution continues inside an EnC updated function.
325 */
326
327 virtual HRESULT FixContextForEnC(PCONTEXT        pCtx,
328                                     EECodeInfo    * pOldCodeInfo,
329                const ICorDebugInfo::NativeVarInfo * oldMethodVars,
330                                     SIZE_T          oldMethodVarsCount,
331                                     EECodeInfo    * pNewCodeInfo,
332                const ICorDebugInfo::NativeVarInfo * newMethodVars,
333                                     SIZE_T          newMethodVarsCount) = 0;
334
335 #endif // EnC_SUPPORTED
336
337 #endif // #ifndef DACCESS_COMPILE
338
339
340 #ifdef DACCESS_COMPILE
341     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) = 0;
342 #endif
343 };
344
345 //*****************************************************************************
346 //
347 // EECodeManager is the EE's implementation of the ICodeManager which
348 // supports the default format of GCInfo.
349 //
350 //*****************************************************************************
351
352 struct hdrInfo;
353
354 class EECodeManager : public ICodeManager {
355
356     VPTR_VTABLE_CLASS_AND_CTOR(EECodeManager, ICodeManager)
357
358 public:
359
360
361 #ifndef DACCESS_COMPILE
362
363 /*
364     Last chance for the runtime support to do fixups in the context
365     before execution continues inside a filter, catch handler, or finally
366 */
367 virtual
368 void FixContext(ContextType     ctxType,
369                 EHContext      *ctx,
370                 EECodeInfo     *pCodeInfo,
371                 DWORD           dwRelOffset,
372                 DWORD           nestingLevel,
373                 OBJECTREF       thrownObject,
374                 CodeManState   *pState,
375                 size_t       ** ppShadowSP,             // OUT
376                 size_t       ** ppEndRegion);           // OUT
377
378 #endif // #ifndef DACCESS_COMPILE
379
380 /*
381     Gets the ambient stack pointer value at the given nesting level within
382     the method.
383 */
384 virtual
385 TADDR GetAmbientSP(PREGDISPLAY     pContext,
386                    EECodeInfo     *pCodeInfo,
387                    DWORD           dwRelOffset,
388                    DWORD           nestingLevel,
389                    CodeManState   *pState);
390
391 /*
392     Get the number of bytes used for stack parameters.
393     This is currently only used on x86.
394 */
395 virtual 
396 ULONG32 GetStackParameterSize(EECodeInfo* pCodeInfo);
397
398 /*
399     Unwind the current stack frame, i.e. update the virtual register
400     set in pContext. This will be similar to the state after the function
401     returns back to caller (IP points to after the call, Frame and Stack
402     pointer has been reset, callee-saved registers restored
403     (if UpdateAllRegs), callee-UNsaved registers are trashed)
404     Returns success of operation.
405 */
406 virtual
407 bool UnwindStackFrame(
408                 PREGDISPLAY     pContext,
409                 EECodeInfo     *pCodeInfo,
410                 unsigned        flags,
411                 CodeManState   *pState,
412                 StackwalkCacheUnwindInfo  *pUnwindInfo);
413
414 enum QuickUnwindFlag
415 {
416     UnwindCurrentStackFrame,
417     EnsureCallerStackFrameIsValid
418 };
419
420 /*
421   *  Light unwind the current stack frame, using provided cache entry.
422   *  only pPC and Esp of pContext are updated. And pEbp if necessary.
423   */
424
425 static
426 void QuickUnwindStackFrame(
427              PREGDISPLAY pRD,
428              StackwalkCacheEntry *pCacheEntry,
429              QuickUnwindFlag flag);
430
431 /*
432     Is the function currently at a "GC safe point" ?
433     Can call EnumGcRefs() successfully
434 */
435 virtual
436 bool IsGcSafe(  EECodeInfo     *pCodeInfo,
437                 DWORD           dwRelOffset);
438
439 #if defined(_TARGET_AMD64_) && defined(_DEBUG)
440 /*
441     Locates the end of the last interruptible region in the given code range.
442     Returns 0 if the entire range is uninterruptible.  Returns the end point
443     if the entire range is interruptible.
444 */
445 virtual
446 unsigned FindEndOfLastInterruptibleRegion(unsigned curOffset,
447                                           unsigned endOffset,
448                                           PTR_VOID methodInfoPtr);
449 #endif // _TARGET_AMD64_ && _DEBUG
450
451 /*
452     Enumerate all live object references in that function using
453     the virtual register set. Same reference location cannot be enumerated
454     multiple times (but all differenct references pointing to the same
455     object have to be individually enumerated).
456     Returns success of operation.
457 */
458 virtual
459 bool EnumGcRefs(PREGDISPLAY     pContext,
460                 EECodeInfo     *pCodeInfo,
461                 unsigned        flags,
462                 GCEnumCallback  pCallback,
463                 LPVOID          hCallBack);
464
465 #ifdef FEATURE_CONSERVATIVE_GC
466 // Temporary conservative collection, for testing purposes, until we have
467 // accurate gc info from the JIT.
468 bool EECodeManager::EnumGcRefsConservative(PREGDISPLAY     pRD,
469                                            EECodeInfo     *pCodeInfo,
470                                            unsigned        flags,
471                                            GCEnumCallback  pCallBack,
472                                            LPVOID          hCallBack);
473 #endif // FEATURE_CONSERVATIVE_GC
474
475 /*
476    Return the address of the local security object reference
477    using data that was previously cached before in UnwindStackFrame
478    using StackwalkCacheUnwindInfo
479 */
480 static OBJECTREF* GetAddrOfSecurityObjectFromCachedInfo(
481         PREGDISPLAY pRD,
482         StackwalkCacheUnwindInfo * stackwalkCacheUnwindInfo);
483
484 virtual
485 OBJECTREF* GetAddrOfSecurityObject(CrawlFrame *pCF) DAC_UNEXPECTED();
486
487 virtual
488 OBJECTREF GetInstance(
489                 PREGDISPLAY     pContext,
490                 EECodeInfo *    pCodeInfo);
491
492 /*
493     Returns the extra argument passed to to shared generic code if it is still alive.
494     Returns NULL in all other cases.
495 */
496 virtual
497 PTR_VOID GetParamTypeArg(PREGDISPLAY     pContext,
498                          EECodeInfo *    pCodeInfo);
499
500 // Returns the type of the context parameter (this, methodtable, methoddesc, or none)
501 virtual GenericParamContextType GetParamContextType(PREGDISPLAY     pContext,
502                                                     EECodeInfo *    pCodeInfo);
503
504 #if defined(WIN64EXCEPTIONS) && !defined(CROSSGEN_COMPILE)
505 /*
506     Returns the generics token.  This is used by GetInstance() and GetParamTypeArg() on WIN64.
507 */
508 static 
509 PTR_VOID GetExactGenericsToken(PREGDISPLAY     pContext,
510                                EECodeInfo *    pCodeInfo);
511
512 static 
513 PTR_VOID GetExactGenericsToken(SIZE_T          baseStackSlot,
514                                EECodeInfo *    pCodeInfo);
515
516
517 #endif // WIN64EXCEPTIONS && !CROSSGEN_COMPILE
518
519 /*
520     Returns the offset of the GuardStack cookie if it exists.
521     Returns NULL if there is no cookie.
522 */
523 virtual
524 void * GetGSCookieAddr(PREGDISPLAY     pContext,
525                        EECodeInfo    * pCodeInfo,
526                        CodeManState  * pState);
527
528
529 /*
530   Returns true if the given IP is in the given method's prolog or an epilog.
531 */
532 virtual
533 bool IsInPrologOrEpilog(
534                 DWORD           relOffset,
535                 PTR_VOID        methodInfoPtr,
536                 size_t*         prologSize);
537
538 /*
539   Returns true if the given IP is in the synchronized region of the method (valid for synchronized functions only)
540 */
541 virtual
542 bool IsInSynchronizedRegion(
543                 DWORD           relOffset,
544                 PTR_VOID        methodInfoPtr,
545                 unsigned        flags);
546
547 /*
548   Returns the size of a given function.
549 */
550 virtual
551 size_t GetFunctionSize(
552                 PTR_VOID        methodInfoPtr);
553
554 /*
555   Returns the size of the frame (barring localloc)
556 */
557 virtual
558 unsigned int GetFrameSize(
559                 PTR_VOID        methodInfoPtr);
560
561 #ifndef DACCESS_COMPILE
562
563 virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg);
564 virtual BOOL LeaveFinally(void *methodInfoPtr,
565                           unsigned offset,
566                           PCONTEXT pCtx);
567 virtual BOOL IsInFilter(void *methodInfoPtr,
568                         unsigned offset,
569                         PCONTEXT pCtx,
570                           DWORD curNestLevel);
571 virtual void LeaveCatch(void *methodInfoPtr,
572                          unsigned offset,
573                          PCONTEXT pCtx);
574
575 #ifdef EnC_SUPPORTED
576 /*
577     Last chance for the runtime support to do fixups in the context
578     before execution continues inside an EnC updated function.
579 */
580 virtual
581 HRESULT FixContextForEnC(PCONTEXT        pCtx,
582                             EECodeInfo    * pOldCodeInfo,
583        const ICorDebugInfo::NativeVarInfo * oldMethodVars,
584                             SIZE_T          oldMethodVarsCount,
585                             EECodeInfo    * pNewCodeInfo,
586        const ICorDebugInfo::NativeVarInfo * newMethodVars,
587                             SIZE_T          newMethodVarsCount);
588 #endif // EnC_SUPPORTED
589
590 #endif // #ifndef DACCESS_COMPILE
591
592 #ifndef _TARGET_X86_
593     static void EnsureCallerContextIsValid( PREGDISPLAY pRD, StackwalkCacheEntry* pCacheEntry, EECodeInfo * pCodeInfo = NULL );
594     static size_t GetCallerSp( PREGDISPLAY  pRD );
595 #endif
596
597 #ifdef DACCESS_COMPILE
598     virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
599 #endif
600
601 };
602
603
604 /*****************************************************************************
605  <TODO>ToDo: Do we want to include JIT/IL/target.h? </TODO>
606  */
607
608 enum regNum
609 {
610         REGI_EAX, REGI_ECX, REGI_EDX, REGI_EBX,
611         REGI_ESP, REGI_EBP, REGI_ESI, REGI_EDI,
612         REGI_COUNT,
613         REGI_NA = REGI_COUNT
614 };
615
616 /*****************************************************************************
617  Register masks
618  */
619
620 enum RegMask
621 {
622     RM_EAX = 0x01,
623     RM_ECX = 0x02,
624     RM_EDX = 0x04,
625     RM_EBX = 0x08,
626     RM_ESP = 0x10,
627     RM_EBP = 0x20,
628     RM_ESI = 0x40,
629     RM_EDI = 0x80,
630
631     RM_NONE = 0x00,
632     RM_ALL = (RM_EAX|RM_ECX|RM_EDX|RM_EBX|RM_ESP|RM_EBP|RM_ESI|RM_EDI),
633     RM_CALLEE_SAVED = (RM_EBP|RM_EBX|RM_ESI|RM_EDI),
634     RM_CALLEE_TRASHED = (RM_ALL & ~RM_CALLEE_SAVED),
635 };
636
637 /*****************************************************************************
638  *
639  *  Helper to extract basic info from a method info block.
640  */
641
642 struct hdrInfo
643 {
644     unsigned int        methodSize;     // native code bytes
645     unsigned int        argSize;        // in bytes
646     unsigned int        stackSize;      /* including callee saved registers */
647     unsigned int        rawStkSize;     /* excluding callee saved registers */
648
649     unsigned int        prologSize;
650
651     // Size of the epilogs in the method.
652     // For methods which use CEE_JMP, some epilogs may end with a "ret" instruction
653     // and some may end with a "jmp". The epilogSize reported should be for the 
654     // epilog with the smallest size.
655     unsigned int        epilogSize;
656
657     unsigned char       epilogCnt;
658     bool                epilogEnd;      // is the epilog at the end of the method
659     
660     bool                ebpFrame;       // locals and arguments addressed relative to EBP
661     bool                doubleAlign;    // is the stack double-aligned? locals addressed relative to ESP, and arguments relative to EBP
662     bool                interruptible;  // intr. at all times (excluding prolog/epilog), not just call sites
663
664     bool                securityCheck;  // has a slot for security object
665     bool                handlers;       // has callable handlers
666     bool                localloc;       // uses localloc
667     bool                editNcontinue;  // has been compiled in EnC mode
668     bool                varargs;        // is this a varargs routine
669     bool                profCallbacks;  // does the method have Enter-Leave callbacks
670     bool                genericsContext;// has a reported generic context paramter
671     bool                genericsContextIsMethodDesc;// reported generic context parameter is methoddesc
672     bool                isSpeculativeStackWalk; // is the stackwalk seeded by an untrusted source (e.g., sampling profiler)?
673
674     // These always includes EBP for EBP-frames and double-aligned-frames
675     RegMask             savedRegMask:8; // which callee-saved regs are saved on stack
676
677     // Count of the callee-saved registers, excluding the frame pointer.
678     // This does not include EBP for EBP-frames and double-aligned-frames.
679     unsigned int        savedRegsCountExclFP;
680
681     unsigned int        untrackedCnt;
682     unsigned int        varPtrTableSize;
683     unsigned int        argTabOffset;   // INVALID_ARGTAB_OFFSET if argtab must be reached by stepping through ptr tables
684     unsigned int        gsCookieOffset; // INVALID_GS_COOKIE_OFFSET if there is no GuardStack cookie
685
686     unsigned int        syncStartOffset; // start/end code offset of the protected region in synchronized methods.
687     unsigned int        syncEndOffset;   // INVALID_SYNC_OFFSET if there not synchronized method
688     unsigned int        syncEpilogStart; // The start of the epilog. Synchronized methods are guaranteed to have no more than one epilog.
689
690     enum { NOT_IN_PROLOG = -1, NOT_IN_EPILOG = -1 };
691     
692     int                 prologOffs;     // NOT_IN_PROLOG if not in prolog
693     int                 epilogOffs;     // NOT_IN_EPILOG if not in epilog. It is never 0
694
695     //
696     // Results passed back from scanArgRegTable
697     //
698     regNum              thisPtrResult;  // register holding "this"
699     RegMask             regMaskResult;  // registers currently holding GC ptrs
700     RegMask            iregMaskResult;  // iptr qualifier for regMaskResult
701     unsigned            argHnumResult;
702     PTR_CBYTE            argTabResult;  // Table of encoded offsets of pending ptr args
703     unsigned              argTabBytes;  // Number of bytes in argTabResult[]
704
705     // These next two are now large structs (i.e 132 bytes each)
706
707     ptrArgTP            argMaskResult;  // pending arguments mask
708     ptrArgTP           iargMaskResult;  // iptr qualifier for argMaskResult
709 };
710
711 /*****************************************************************************
712   How the stackwalkers buffer will be interpreted
713 */
714
715 struct CodeManStateBuf
716 {
717     DWORD       hdrInfoSize;
718     hdrInfo     hdrInfoBody;
719 };
720 //*****************************************************************************
721 #endif // _EETWAIN_H
722 //*****************************************************************************