2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
5 //*****************************************************************************
9 // This file has the definition of ICodeManager and EECodeManager.
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
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).
23 //*****************************************************************************
27 //*****************************************************************************
31 #include "corjit.h" // For NativeVarInfo
32 #include "stackwalktypes.h"
33 #include "bitvector.h"
35 #if !defined(_TARGET_X86_)
36 #define USE_GC_INFO_DECODER
40 #if CHECK_APP_DOMAIN_LEAKS
41 #define CHECK_APP_DOMAIN GC_CALL_CHECK_APP_DOMAIN
43 #define CHECK_APP_DOMAIN 0
48 #ifdef DACCESS_COMPILE
49 typedef struct _DAC_SLOT_LOCATION
55 _DAC_SLOT_LOCATION(int _reg, int _regOffset, bool _targetPtr)
56 : reg(_reg), regOffset(_regOffset), targetPtr(_targetPtr)
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
69 /******************************************************************************
70 The stackwalker maintains some state on behalf of ICodeManager.
73 const int CODEMAN_STATE_SIZE = 512;
77 DWORD dwIsSet; // Is set to 0 by the stackwalk as appropriate
78 BYTE stateBuf[CODEMAN_STATE_SIZE];
81 /******************************************************************************
82 These flags are used by some functions, although not all combinations might
83 make sense for all functions.
86 enum ICodeManagerFlags
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
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
98 = 0x0020, // we're in the middle of a stackwalk seeded
99 // by an untrusted source (e.g., sampling profiler)
101 ParentOfFuncletStackFrame
102 = 0x0040, // A funclet for this frame was previously reported
104 = 0x0080, // EnumGCRefs/EnumerateLiveSlots should *not* include
105 // any untracked slots
108 //*****************************************************************************
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.
118 enum GenericParamContextType
120 GENERIC_PARAM_CONTEXT_NONE = 0,
121 GENERIC_PARAM_CONTEXT_THIS = 1,
122 GENERIC_PARAM_CONTEXT_METHODDESC = 2,
123 GENERIC_PARAM_CONTEXT_METHODTABLE = 3
126 //*****************************************************************************
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.
132 //*****************************************************************************
136 VPTR_BASE_VTABLE_CLASS_AND_CTOR(ICodeManager)
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
152 /* Type of funclet corresponding to a shadow stack-pointer */
156 SHADOW_SP_IN_FILTER = 0x1,
157 SHADOW_SP_FILTER_DONE = 0x2,
161 #ifndef DACCESS_COMPILE
163 virtual void FixContext(ContextType ctxType,
165 EECodeInfo *pCodeInfo,
168 OBJECTREF thrownObject,
169 CodeManState *pState,
170 size_t ** ppShadowSP, // OUT
171 size_t ** ppEndRegion) = 0; // OUT
173 #endif // #ifndef DACCESS_COMPILE
176 Gets the ambient stack pointer value at the given nesting level within
179 virtual TADDR GetAmbientSP(PREGDISPLAY pContext,
180 EECodeInfo *pCodeInfo,
183 CodeManState *pState) = 0;
186 Get the number of bytes used for stack parameters.
187 This is currently only used on x86.
189 virtual ULONG32 GetStackParameterSize(EECodeInfo* pCodeInfo) = 0;
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.
199 virtual bool UnwindStackFrame(PREGDISPLAY pContext,
200 EECodeInfo *pCodeInfo,
202 CodeManState *pState,
203 StackwalkCacheUnwindInfo *pUnwindInfo) = 0;
206 Is the function currently at a "GC safe point" ?
207 Can call EnumGcRefs() successfully
209 virtual bool IsGcSafe(EECodeInfo *pCodeInfo,
210 DWORD dwRelOffset) = 0;
212 #if defined(_TARGET_AMD64_) && defined(_DEBUG)
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.
218 virtual unsigned FindEndOfLastInterruptibleRegion(unsigned curOffset,
220 PTR_VOID methodInfoPtr) = 0;
221 #endif // _TARGET_AMD64_ && _DEBUG
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.
230 virtual bool EnumGcRefs(PREGDISPLAY pContext,
231 EECodeInfo *pCodeInfo,
233 GCEnumCallback pCallback,
234 LPVOID hCallBack) = 0;
237 Return the address of the local security object reference
240 virtual OBJECTREF* GetAddrOfSecurityObject(CrawlFrame *pCF) = 0;
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.)
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.
252 virtual OBJECTREF GetInstance(PREGDISPLAY pContext,
253 EECodeInfo* pCodeInfo) = 0;
256 Returns the extra argument passed to to shared generic code if it is still alive.
257 Returns NULL in all other cases.
259 virtual PTR_VOID GetParamTypeArg(PREGDISPLAY pContext,
260 EECodeInfo * pCodeInfo) = 0;
262 // Returns the type of the context parameter (this, methodtable, methoddesc, or none)
263 virtual GenericParamContextType GetParamContextType(PREGDISPLAY pContext,
264 EECodeInfo * pCodeInfo) = 0;
267 Returns the offset of the GuardStack cookie if it exists.
268 Returns NULL if there is no cookie.
270 virtual void * GetGSCookieAddr(PREGDISPLAY pContext,
271 EECodeInfo * pCodeInfo,
272 CodeManState * pState) = 0;
275 Returns true if the given IP is in the given method's prolog or an epilog.
277 virtual bool IsInPrologOrEpilog(DWORD relPCOffset,
278 PTR_VOID methodInfoPtr,
279 size_t* prologSize) = 0;
282 Returns true if the given IP is in the synchronized region of the method (valid for synchronized methods only)
284 virtual bool IsInSynchronizedRegion(
286 PTR_VOID methodInfoPtr,
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.
294 virtual size_t GetFunctionSize(PTR_VOID methodInfoPtr) = 0;
297 Returns the size of the frame (barring localloc)
299 virtual unsigned int GetFrameSize(PTR_VOID methodInfoPtr) = 0;
301 #ifndef DACCESS_COMPILE
305 virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg)=0;
307 virtual BOOL IsInFilter(void *methodInfoPtr,
310 DWORD curNestLevel) = 0;
312 virtual BOOL LeaveFinally(void *methodInfoPtr,
316 virtual void LeaveCatch(void *methodInfoPtr,
323 Last chance for the runtime support to do fixups in the context
324 before execution continues inside an EnC updated function.
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;
335 #endif // EnC_SUPPORTED
337 #endif // #ifndef DACCESS_COMPILE
340 #ifdef DACCESS_COMPILE
341 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags) = 0;
345 //*****************************************************************************
347 // EECodeManager is the EE's implementation of the ICodeManager which
348 // supports the default format of GCInfo.
350 //*****************************************************************************
354 class EECodeManager : public ICodeManager {
356 VPTR_VTABLE_CLASS_AND_CTOR(EECodeManager, ICodeManager)
361 #ifndef DACCESS_COMPILE
364 Last chance for the runtime support to do fixups in the context
365 before execution continues inside a filter, catch handler, or finally
368 void FixContext(ContextType ctxType,
370 EECodeInfo *pCodeInfo,
373 OBJECTREF thrownObject,
374 CodeManState *pState,
375 size_t ** ppShadowSP, // OUT
376 size_t ** ppEndRegion); // OUT
378 #endif // #ifndef DACCESS_COMPILE
381 Gets the ambient stack pointer value at the given nesting level within
385 TADDR GetAmbientSP(PREGDISPLAY pContext,
386 EECodeInfo *pCodeInfo,
389 CodeManState *pState);
392 Get the number of bytes used for stack parameters.
393 This is currently only used on x86.
396 ULONG32 GetStackParameterSize(EECodeInfo* pCodeInfo);
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.
407 bool UnwindStackFrame(
408 PREGDISPLAY pContext,
409 EECodeInfo *pCodeInfo,
411 CodeManState *pState,
412 StackwalkCacheUnwindInfo *pUnwindInfo);
416 UnwindCurrentStackFrame,
417 EnsureCallerStackFrameIsValid
421 * Light unwind the current stack frame, using provided cache entry.
422 * only pPC and Esp of pContext are updated. And pEbp if necessary.
426 void QuickUnwindStackFrame(
428 StackwalkCacheEntry *pCacheEntry,
429 QuickUnwindFlag flag);
432 Is the function currently at a "GC safe point" ?
433 Can call EnumGcRefs() successfully
436 bool IsGcSafe( EECodeInfo *pCodeInfo,
439 #if defined(_TARGET_AMD64_) && defined(_DEBUG)
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.
446 unsigned FindEndOfLastInterruptibleRegion(unsigned curOffset,
448 PTR_VOID methodInfoPtr);
449 #endif // _TARGET_AMD64_ && _DEBUG
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.
459 bool EnumGcRefs(PREGDISPLAY pContext,
460 EECodeInfo *pCodeInfo,
462 GCEnumCallback pCallback,
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,
471 GCEnumCallback pCallBack,
473 #endif // FEATURE_CONSERVATIVE_GC
476 Return the address of the local security object reference
477 using data that was previously cached before in UnwindStackFrame
478 using StackwalkCacheUnwindInfo
480 static OBJECTREF* GetAddrOfSecurityObjectFromCachedInfo(
482 StackwalkCacheUnwindInfo * stackwalkCacheUnwindInfo);
485 OBJECTREF* GetAddrOfSecurityObject(CrawlFrame *pCF) DAC_UNEXPECTED();
488 OBJECTREF GetInstance(
489 PREGDISPLAY pContext,
490 EECodeInfo * pCodeInfo);
493 Returns the extra argument passed to to shared generic code if it is still alive.
494 Returns NULL in all other cases.
497 PTR_VOID GetParamTypeArg(PREGDISPLAY pContext,
498 EECodeInfo * pCodeInfo);
500 // Returns the type of the context parameter (this, methodtable, methoddesc, or none)
501 virtual GenericParamContextType GetParamContextType(PREGDISPLAY pContext,
502 EECodeInfo * pCodeInfo);
504 #if defined(WIN64EXCEPTIONS) && !defined(CROSSGEN_COMPILE)
506 Returns the generics token. This is used by GetInstance() and GetParamTypeArg() on WIN64.
509 PTR_VOID GetExactGenericsToken(PREGDISPLAY pContext,
510 EECodeInfo * pCodeInfo);
513 PTR_VOID GetExactGenericsToken(SIZE_T baseStackSlot,
514 EECodeInfo * pCodeInfo);
517 #endif // WIN64EXCEPTIONS && !CROSSGEN_COMPILE
520 Returns the offset of the GuardStack cookie if it exists.
521 Returns NULL if there is no cookie.
524 void * GetGSCookieAddr(PREGDISPLAY pContext,
525 EECodeInfo * pCodeInfo,
526 CodeManState * pState);
530 Returns true if the given IP is in the given method's prolog or an epilog.
533 bool IsInPrologOrEpilog(
535 PTR_VOID methodInfoPtr,
539 Returns true if the given IP is in the synchronized region of the method (valid for synchronized functions only)
542 bool IsInSynchronizedRegion(
544 PTR_VOID methodInfoPtr,
548 Returns the size of a given function.
551 size_t GetFunctionSize(
552 PTR_VOID methodInfoPtr);
555 Returns the size of the frame (barring localloc)
558 unsigned int GetFrameSize(
559 PTR_VOID methodInfoPtr);
561 #ifndef DACCESS_COMPILE
563 virtual const BYTE* GetFinallyReturnAddr(PREGDISPLAY pReg);
564 virtual BOOL LeaveFinally(void *methodInfoPtr,
567 virtual BOOL IsInFilter(void *methodInfoPtr,
571 virtual void LeaveCatch(void *methodInfoPtr,
577 Last chance for the runtime support to do fixups in the context
578 before execution continues inside an EnC updated function.
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
590 #endif // #ifndef DACCESS_COMPILE
593 static void EnsureCallerContextIsValid( PREGDISPLAY pRD, StackwalkCacheEntry* pCacheEntry, EECodeInfo * pCodeInfo = NULL );
594 static size_t GetCallerSp( PREGDISPLAY pRD );
597 #ifdef DACCESS_COMPILE
598 virtual void EnumMemoryRegions(CLRDataEnumMemoryFlags flags);
604 /*****************************************************************************
605 <TODO>ToDo: Do we want to include JIT/IL/target.h? </TODO>
610 REGI_EAX, REGI_ECX, REGI_EDX, REGI_EBX,
611 REGI_ESP, REGI_EBP, REGI_ESI, REGI_EDI,
616 /*****************************************************************************
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),
637 /*****************************************************************************
639 * Helper to extract basic info from a method info block.
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 */
649 unsigned int prologSize;
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;
657 unsigned char epilogCnt;
658 bool epilogEnd; // is the epilog at the end of the method
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
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)?
674 // These always includes EBP for EBP-frames and double-aligned-frames
675 RegMask savedRegMask:8; // which callee-saved regs are saved on stack
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;
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
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.
690 enum { NOT_IN_PROLOG = -1, NOT_IN_EPILOG = -1 };
692 int prologOffs; // NOT_IN_PROLOG if not in prolog
693 int epilogOffs; // NOT_IN_EPILOG if not in epilog. It is never 0
696 // Results passed back from scanArgRegTable
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[]
705 // These next two are now large structs (i.e 132 bytes each)
707 ptrArgTP argMaskResult; // pending arguments mask
708 ptrArgTP iargMaskResult; // iptr qualifier for argMaskResult
711 /*****************************************************************************
712 How the stackwalkers buffer will be interpreted
715 struct CodeManStateBuf
720 //*****************************************************************************
722 //*****************************************************************************