Add a fourth parameter to the DEFINE_DACVAR macro that is the actual fully qualified...
[platform/upstream/coreclr.git] / src / vm / stackwalktypes.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 // File: stackwalktypes.h
7 //
8
9 // ============================================================================
10 // Contains types used by stackwalk.h.
11
12
13 #ifndef __STACKWALKTYPES_H__
14 #define __STACKWALKTYPES_H__
15
16 class CrawlFrame;
17 struct RangeSection;
18 struct StackwalkCacheEntry;
19
20 //
21 // This type should be used internally inside the code manager only. EECodeInfo should 
22 // be used in general code instead. Ideally, we would replace all uses of METHODTOKEN 
23 // with EECodeInfo.
24 //
25 struct METHODTOKEN
26 {
27     METHODTOKEN(RangeSection * pRangeSection, TADDR pCodeHeader)
28         : m_pRangeSection(pRangeSection), m_pCodeHeader(pCodeHeader)
29     {
30     }
31
32     METHODTOKEN()
33     {
34     }
35
36     // Cache of RangeSection containing the code to avoid redundant lookups.
37     RangeSection * m_pRangeSection;
38
39     // CodeHeader* for EEJitManager
40     // PTR_RUNTIME_FUNCTION for managed native code
41     TADDR m_pCodeHeader;
42
43     BOOL IsNull() const
44     {
45         return m_pCodeHeader == NULL;
46     }
47 };
48
49 //************************************************************************
50 // Stack walking
51 //************************************************************************
52 enum StackCrawlMark
53 {
54     LookForMe = 0,
55     LookForMyCaller = 1,
56     LookForMyCallersCaller = 2,
57     LookForThread = 3
58 };
59
60 enum StackWalkAction 
61 {
62     SWA_CONTINUE    = 0,    // continue walking
63     SWA_ABORT       = 1,    // stop walking, early out in "failure case"
64     SWA_FAILED      = 2     // couldn't walk stack
65 };
66
67 #define SWA_DONE SWA_CONTINUE
68
69
70 // Pointer to the StackWalk callback function.
71 typedef StackWalkAction (*PSTACKWALKFRAMESCALLBACK)(
72     CrawlFrame       *pCF,      //
73     VOID*             pData     // Caller's private data
74
75 );
76
77 /******************************************************************************
78    StackwalkCache: new class implements stackwalk perf optimization features.
79    StackwalkCacheEntry array: very simple per thread hash table, keeping cached data.
80    StackwalkCacheUnwindInfo: used by EECodeManager::UnwindStackFrame to return
81    stackwalk cache flags.
82    Cf. Ilyakoz for any questions.
83 */
84
85 struct StackwalkCacheUnwindInfo
86 {
87 #if defined(_TARGET_AMD64_)
88     ULONG RBPOffset;
89     ULONG RSPOffsetFromUnwindInfo;
90 #else  // !_TARGET_AMD64_
91     size_t securityObjectOffset;    // offset of SecurityObject. 0 if there is no security object
92     BOOL fUseEbp;                   // Is EBP modified by the method - either for a frame-pointer or for a scratch-register?
93     BOOL fUseEbpAsFrameReg;         // use EBP as the frame pointer?
94 #endif // !_TARGET_AMD64_
95
96     inline StackwalkCacheUnwindInfo() { SUPPORTS_DAC; ZeroMemory(this, sizeof(StackwalkCacheUnwindInfo)); }
97     StackwalkCacheUnwindInfo(StackwalkCacheEntry * pCacheEntry);
98 };
99
100 //************************************************************************
101
102 #if defined(_WIN64)
103     #define STACKWALK_CACHE_ENTRY_ALIGN_BOUNDARY 0x10
104 #else  // !_WIN64
105     #define STACKWALK_CACHE_ENTRY_ALIGN_BOUNDARY 0x8
106 #endif // !_WIN64
107
108 DECLSPEC_ALIGN(STACKWALK_CACHE_ENTRY_ALIGN_BOUNDARY) 
109 struct StackwalkCacheEntry
110 {
111     //
112     //  don't rearrange the fields, so that invalid value 0x8000000000000000 will never appear
113     //  as StackwalkCacheEntry, it's required for atomicMOVQ using FILD/FISTP instructions
114     //
115     UINT_PTR IP;
116 #if !defined(_TARGET_AMD64_)
117     WORD ESPOffset:15;          // stack offset (frame size + pending arguments + etc)
118     WORD securityObjectOffset:3;// offset of SecurityObject. 0 if there is no security object
119     WORD fUseEbp:1;             // For ESP methods, is EBP touched at all?
120     WORD fUseEbpAsFrameReg:1;   // use EBP as the frame register?
121     WORD argSize:11;            // size of args pushed on stack
122 #else  // _TARGET_AMD64_
123     DWORD RSPOffset;
124     DWORD RBPOffset;
125 #endif // _TARGET_AMD64_
126
127     inline BOOL Init(UINT_PTR   IP,
128                      UINT_PTR   SPOffset,
129                      StackwalkCacheUnwindInfo *pUnwindInfo,
130                      UINT_PTR   argSize)
131     {
132         LIMITED_METHOD_CONTRACT;
133
134         this->IP              = IP;
135
136 #if defined(_TARGET_X86_)
137         this->ESPOffset         = SPOffset;
138         this->argSize           = argSize;
139         
140         this->securityObjectOffset = (WORD)pUnwindInfo->securityObjectOffset;
141         _ASSERTE(this->securityObjectOffset == pUnwindInfo->securityObjectOffset);
142         
143         this->fUseEbp           = pUnwindInfo->fUseEbp;
144         this->fUseEbpAsFrameReg = pUnwindInfo->fUseEbpAsFrameReg;
145         _ASSERTE(!fUseEbpAsFrameReg || fUseEbp);
146
147         // return success if we fit SPOffset and argSize into
148         return ((this->ESPOffset == SPOffset) && 
149                 (this->argSize == argSize));
150 #elif defined(_TARGET_AMD64_)
151         // The size of a stack frame is guaranteed to fit in 4 bytes, so we don't need to check RSPOffset and RBPOffset.
152
153         // The actual SP offset may be bigger than the offset we get from the unwind info because of stack allocations.
154         _ASSERTE(SPOffset >= pUnwindInfo->RSPOffsetFromUnwindInfo);
155
156         _ASSERTE(FitsIn<DWORD>(SPOffset));
157         this->RSPOffset  = static_cast<DWORD>(SPOffset);
158         _ASSERTE(FitsIn<DWORD>(pUnwindInfo->RBPOffset + (SPOffset - pUnwindInfo->RSPOffsetFromUnwindInfo)));
159         this->RBPOffset  = static_cast<DWORD>(pUnwindInfo->RBPOffset + (SPOffset - pUnwindInfo->RSPOffsetFromUnwindInfo));
160         return TRUE;
161 #else  // !_TARGET_X86_ && !_TARGET_AMD64_
162         return FALSE;
163 #endif // !_TARGET_X86_ && !_TARGET_AMD64_
164     }
165
166     inline BOOL HasSecurityObject()
167     {
168         LIMITED_METHOD_CONTRACT;
169
170 #if defined(_TARGET_X86_)
171         return securityObjectOffset != 0;
172 #else  // !_TARGET_X86_
173         // On AMD64 we don't save anything by grabbing the security object before it is needed.  This is because
174         // we need to crack the GC info in order to find the security object, and to unwind we only need to
175         // crack the unwind info.
176         return FALSE;
177 #endif // !_TARGET_X86_
178     }
179
180     inline BOOL IsSafeToUseCache()
181     {
182         LIMITED_METHOD_CONTRACT;
183
184 #if defined(_TARGET_X86_)
185         return (!fUseEbp || fUseEbpAsFrameReg);
186 #elif defined(_TARGET_AMD64_)
187         return TRUE;
188 #else  // !_TARGET_X86_ && !_TARGET_AMD64_
189         return FALSE;
190 #endif // !_TARGET_X86_ && !_TARGET_AMD64_
191     }
192 };
193
194 #if defined(_TARGET_X86_) || defined(_TARGET_AMD64_)
195 static_assert_no_msg(sizeof(StackwalkCacheEntry) == 2 * sizeof(UINT_PTR));
196 #endif // _TARGET_X86_ || _TARGET_AMD64_
197
198 //************************************************************************
199
200 class StackwalkCache 
201 {
202     friend struct _DacGlobals;
203
204     public:
205         BOOL Lookup(UINT_PTR IP);
206         void Insert(StackwalkCacheEntry *pCacheEntry);
207         inline void ClearEntry () { LIMITED_METHOD_DAC_CONTRACT; m_CacheEntry.IP = 0; }
208         inline BOOL Enabled() { LIMITED_METHOD_DAC_CONTRACT;  return s_Enabled; };
209         inline BOOL IsEmpty () { LIMITED_METHOD_CONTRACT;  return m_CacheEntry.IP == 0; }
210
211 #ifndef DACCESS_COMPILE
212         StackwalkCache();
213 #endif
214         static void Init();
215
216         StackwalkCacheEntry m_CacheEntry; // local copy of Global Cache entry for current IP
217         
218         static void Invalidate(LoaderAllocator * pLoaderAllocator);
219         
220     private:
221         unsigned GetKey(UINT_PTR IP);
222         
223 #ifdef DACCESS_COMPILE
224         // DAC can't rely on the cache here
225         const static BOOL s_Enabled;
226 #else
227         static BOOL s_Enabled;
228 #endif
229 };
230
231 //************************************************************************
232
233 inline StackwalkCacheUnwindInfo::StackwalkCacheUnwindInfo(StackwalkCacheEntry * pCacheEntry) 
234 {
235     LIMITED_METHOD_CONTRACT;
236     
237 #if defined(_TARGET_AMD64_)
238     RBPOffset = pCacheEntry->RBPOffset;
239 #else  // !_TARGET_AMD64_
240     securityObjectOffset = pCacheEntry->securityObjectOffset;
241     fUseEbp = pCacheEntry->fUseEbp;
242     fUseEbpAsFrameReg = pCacheEntry->fUseEbpAsFrameReg;
243 #endif // !_TARGET_AMD64_
244 }
245
246 #endif  // __STACKWALKTYPES_H__