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// File: debugger.inl
6//
7
8//
9// Inline definitions for the Left-Side of the CLR debugging services
10// This is logically part of the header file.
11//
12//*****************************************************************************
13
14#ifndef DEBUGGER_INL_
15#define DEBUGGER_INL_
16
17//=============================================================================
18// Inlined methods for Debugger.
19//=============================================================================
20inline bool Debugger::HasLazyData()
21{
22 LIMITED_METHOD_CONTRACT;
23 return (m_pLazyData != NULL);
24}
25inline RCThreadLazyInit *Debugger::GetRCThreadLazyData()
26{
27 LIMITED_METHOD_CONTRACT;
28 return &(GetLazyData()->m_RCThread);
29}
30
31inline DebuggerLazyInit *Debugger::GetLazyData()
32{
33 LIMITED_METHOD_DAC_CONTRACT;
34 _ASSERTE(m_pLazyData != NULL);
35 return m_pLazyData;
36}
37
38inline DebuggerModuleTable * Debugger::GetModuleTable()
39{
40 LIMITED_METHOD_CONTRACT;
41
42 return m_pModules;
43}
44
45
46//=============================================================================
47// Inlined methods for DebuggerModule.
48//=============================================================================
49
50
51//-----------------------------------------------------------------------------
52// Constructor for a Debugger-Module.
53// @dbgtodo inspection - get rid of this entire class as we move things out-of-proc.
54//-----------------------------------------------------------------------------
55inline DebuggerModule::DebuggerModule(Module * pRuntimeModule,
56 DomainFile * pDomainFile,
57 AppDomain * pAppDomain) :
58 m_enableClassLoadCallbacks(FALSE),
59 m_pPrimaryModule(NULL),
60 m_pRuntimeModule(pRuntimeModule),
61 m_pRuntimeDomainFile(pDomainFile),
62 m_pAppDomain(pAppDomain)
63{
64 LOG((LF_CORDB,LL_INFO10000, "DM::DM this:0x%x Module:0x%x DF:0x%x AD:0x%x\n",
65 this, pRuntimeModule, pDomainFile, pAppDomain));
66
67 // Pick a primary module.
68 // Arguably, this could be in DebuggerModuleTable::AddModule
69 PickPrimaryModule();
70
71
72 // Do we have any optimized code?
73 DWORD dwDebugBits = pRuntimeModule->GetDebuggerInfoBits();
74 m_fHasOptimizedCode = CORDebuggerAllowJITOpts(dwDebugBits);
75
76 // Dynamic modules must receive ClassLoad callbacks in order to receive metadata updates as the module
77 // evolves. So we force this on here and refuse to change it for all dynamic modules.
78 if (pRuntimeModule->IsReflection())
79 {
80 EnableClassLoadCallbacks(TRUE);
81 }
82}
83
84//-----------------------------------------------------------------------------
85// Returns true if we have any optimized code in the module.
86//
87// Notes:
88// JMC-probes aren't emitted in optimized code.
89// <TODO> Life would be nice if the Jit tracked this. </TODO>
90//-----------------------------------------------------------------------------
91inline bool DebuggerModule::HasAnyOptimizedCode()
92{
93 LIMITED_METHOD_CONTRACT;
94 Module * pModule = this->GetPrimaryModule()->GetRuntimeModule();
95 DWORD dwDebugBits = pModule->GetDebuggerInfoBits();
96 return CORDebuggerAllowJITOpts(dwDebugBits);
97}
98
99//-----------------------------------------------------------------------------
100// Return true if we've enabled class-load callbacks.
101//-----------------------------------------------------------------------------
102inline BOOL DebuggerModule::ClassLoadCallbacksEnabled(void)
103{
104 return m_enableClassLoadCallbacks;
105}
106
107//-----------------------------------------------------------------------------
108// Set whether we should enable class-load callbacks for this module.
109//-----------------------------------------------------------------------------
110inline void DebuggerModule::EnableClassLoadCallbacks(BOOL f)
111{
112 if (m_enableClassLoadCallbacks != f)
113 {
114 if (f)
115 {
116 _ASSERTE(g_pDebugger != NULL);
117 g_pDebugger->IncrementClassLoadCallbackCount();
118 }
119 else
120 {
121 _ASSERTE(g_pDebugger != NULL);
122 g_pDebugger->DecrementClassLoadCallbackCount();
123 }
124
125 m_enableClassLoadCallbacks = f;
126 }
127}
128
129//-----------------------------------------------------------------------------
130// Return the appdomain that this module exists in.
131//-----------------------------------------------------------------------------
132inline AppDomain* DebuggerModule::GetAppDomain()
133{
134 return m_pAppDomain;
135}
136
137//-----------------------------------------------------------------------------
138// Return the EE module that this module corresponds to.
139//-----------------------------------------------------------------------------
140inline Module * DebuggerModule::GetRuntimeModule()
141{
142 LIMITED_METHOD_DAC_CONTRACT;
143 return m_pRuntimeModule;
144}
145
146//-----------------------------------------------------------------------------
147// <TODO> (8/12/2002)
148// Currently we create a new DebuggerModules for each appdomain a shared
149// module lives in. We then pretend there aren't any shared modules.
150// This is bad. We need to move away from this.
151// Once we stop lying, then every module will be it's own PrimaryModule. :)
152//
153// Currently, Module* is 1:n w/ DebuggerModule.
154// We add a notion of PrimaryModule so that:
155// Module* is 1:1 w/ DebuggerModule::GetPrimaryModule();
156// This should help transition towards exposing shared modules.
157// If the Runtime module is shared, then this gives a common DM.
158// If the runtime module is not shared, then this is an identity function.
159// </TODO>
160//-----------------------------------------------------------------------------
161inline DebuggerModule * DebuggerModule::GetPrimaryModule()
162{
163 _ASSERTE(m_pPrimaryModule != NULL);
164 return m_pPrimaryModule;
165}
166
167//-----------------------------------------------------------------------------
168// This is called by DebuggerModuleTable to set our primary module.
169//-----------------------------------------------------------------------------
170inline void DebuggerModule::SetPrimaryModule(DebuggerModule * pPrimary)
171{
172 _ASSERTE(pPrimary != NULL);
173 // Our primary module must by definition refer to the same runtime module as us
174 _ASSERTE(pPrimary->GetRuntimeModule() == this->GetRuntimeModule());
175
176 LOG((LF_CORDB, LL_EVERYTHING, "DM::SetPrimaryModule - this=%p, pPrimary=%p\n", this, pPrimary));
177 m_pPrimaryModule = pPrimary;
178}
179
180inline DebuggerEval * FuncEvalFrame::GetDebuggerEval()
181{
182 LIMITED_METHOD_DAC_CONTRACT;
183 return m_pDebuggerEval;
184}
185
186inline unsigned FuncEvalFrame::GetFrameAttribs(void)
187{
188 LIMITED_METHOD_DAC_CONTRACT;
189
190 if (GetDebuggerEval()->m_evalDuringException)
191 {
192 return FRAME_ATTR_NONE;
193 }
194 else
195 {
196 return FRAME_ATTR_RESUMABLE; // Treat the next frame as the top frame.
197 }
198}
199
200inline TADDR FuncEvalFrame::GetReturnAddressPtr()
201{
202 LIMITED_METHOD_DAC_CONTRACT;
203
204 if (GetDebuggerEval()->m_evalDuringException)
205 {
206 return NULL;
207 }
208 else
209 {
210 return PTR_HOST_MEMBER_TADDR(FuncEvalFrame, this, m_ReturnAddress);
211 }
212}
213
214//
215// This updates the register display for a FuncEvalFrame.
216//
217inline void FuncEvalFrame::UpdateRegDisplay(const PREGDISPLAY pRD)
218{
219 SUPPORTS_DAC;
220 DebuggerEval * pDE = GetDebuggerEval();
221
222 // No context to update if we're doing a func eval from within exception processing.
223 if (pDE->m_evalDuringException)
224 {
225 return;
226 }
227
228#ifndef WIN64EXCEPTIONS
229 // Reset pContext; it's only valid for active (top-most) frame.
230 pRD->pContext = NULL;
231#endif // !_WIN64
232
233
234#ifdef _TARGET_X86_
235 // Update all registers in the reg display from the CONTEXT we stored when the thread was hijacked for this func
236 // eval. We have to update all registers, not just the callee saved registers, because we can hijack a thread at any
237 // point for a func eval, not just at a call site.
238 pRD->SetEdiLocation(&(pDE->m_context.Edi));
239 pRD->SetEsiLocation(&(pDE->m_context.Esi));
240 pRD->SetEbxLocation(&(pDE->m_context.Ebx));
241 pRD->SetEdxLocation(&(pDE->m_context.Edx));
242 pRD->SetEcxLocation(&(pDE->m_context.Ecx));
243 pRD->SetEaxLocation(&(pDE->m_context.Eax));
244 pRD->SetEbpLocation(&(pDE->m_context.Ebp));
245 pRD->SP = (DWORD)GetSP(&pDE->m_context);
246 pRD->PCTAddr = GetReturnAddressPtr();
247 pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr);
248
249#elif defined(_TARGET_AMD64_)
250 pRD->IsCallerContextValid = FALSE;
251 pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary.
252
253 memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(CONTEXT));
254
255 pRD->pCurrentContextPointers->Rax = &(pDE->m_context.Rax);
256 pRD->pCurrentContextPointers->Rcx = &(pDE->m_context.Rcx);
257 pRD->pCurrentContextPointers->Rdx = &(pDE->m_context.Rdx);
258 pRD->pCurrentContextPointers->R8 = &(pDE->m_context.R8);
259 pRD->pCurrentContextPointers->R9 = &(pDE->m_context.R9);
260 pRD->pCurrentContextPointers->R10 = &(pDE->m_context.R10);
261 pRD->pCurrentContextPointers->R11 = &(pDE->m_context.R11);
262
263 pRD->pCurrentContextPointers->Rbx = &(pDE->m_context.Rbx);
264 pRD->pCurrentContextPointers->Rsi = &(pDE->m_context.Rsi);
265 pRD->pCurrentContextPointers->Rdi = &(pDE->m_context.Rdi);
266 pRD->pCurrentContextPointers->Rbp = &(pDE->m_context.Rbp);
267 pRD->pCurrentContextPointers->R12 = &(pDE->m_context.R12);
268 pRD->pCurrentContextPointers->R13 = &(pDE->m_context.R13);
269 pRD->pCurrentContextPointers->R14 = &(pDE->m_context.R14);
270 pRD->pCurrentContextPointers->R15 = &(pDE->m_context.R15);
271
272 // SyncRegDisplayToCurrentContext() sets the pRD->SP and pRD->ControlPC on AMD64.
273 SyncRegDisplayToCurrentContext(pRD);
274
275#elif defined(_TARGET_ARM_)
276 pRD->IsCallerContextValid = FALSE;
277 pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary.
278
279 memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT));
280
281 pRD->pCurrentContextPointers->R4 = &(pDE->m_context.R4);
282 pRD->pCurrentContextPointers->R5 = &(pDE->m_context.R5);
283 pRD->pCurrentContextPointers->R6 = &(pDE->m_context.R6);
284 pRD->pCurrentContextPointers->R7 = &(pDE->m_context.R7);
285 pRD->pCurrentContextPointers->R8 = &(pDE->m_context.R8);
286 pRD->pCurrentContextPointers->R9 = &(pDE->m_context.R9);
287 pRD->pCurrentContextPointers->R10 = &(pDE->m_context.R10);
288 pRD->pCurrentContextPointers->R11 = &(pDE->m_context.R11);
289 pRD->pCurrentContextPointers->Lr = &(pDE->m_context.Lr);
290
291 pRD->volatileCurrContextPointers.R0 = &(pDE->m_context.R0);
292 pRD->volatileCurrContextPointers.R1 = &(pDE->m_context.R1);
293 pRD->volatileCurrContextPointers.R2 = &(pDE->m_context.R2);
294 pRD->volatileCurrContextPointers.R3 = &(pDE->m_context.R3);
295 pRD->volatileCurrContextPointers.R12 = &(pDE->m_context.R12);
296
297 SyncRegDisplayToCurrentContext(pRD);
298
299#elif defined(_TARGET_ARM64_)
300 pRD->IsCallerContextValid = FALSE;
301 pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary.
302
303 memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT));
304
305 pRD->pCurrentContextPointers->X19 = &(pDE->m_context.X19);
306 pRD->pCurrentContextPointers->X20 = &(pDE->m_context.X20);
307 pRD->pCurrentContextPointers->X21 = &(pDE->m_context.X21);
308 pRD->pCurrentContextPointers->X22 = &(pDE->m_context.X22);
309 pRD->pCurrentContextPointers->X23 = &(pDE->m_context.X23);
310 pRD->pCurrentContextPointers->X24 = &(pDE->m_context.X24);
311 pRD->pCurrentContextPointers->X25 = &(pDE->m_context.X25);
312 pRD->pCurrentContextPointers->X26 = &(pDE->m_context.X26);
313 pRD->pCurrentContextPointers->X27 = &(pDE->m_context.X27);
314 pRD->pCurrentContextPointers->X28 = &(pDE->m_context.X28);
315 pRD->pCurrentContextPointers->Lr = &(pDE->m_context.Lr);
316 pRD->pCurrentContextPointers->Fp = &(pDE->m_context.Fp);
317
318 pRD->volatileCurrContextPointers.X0 = &(pDE->m_context.X0);
319 pRD->volatileCurrContextPointers.X1 = &(pDE->m_context.X1);
320 pRD->volatileCurrContextPointers.X2 = &(pDE->m_context.X2);
321 pRD->volatileCurrContextPointers.X3 = &(pDE->m_context.X3);
322 pRD->volatileCurrContextPointers.X4 = &(pDE->m_context.X4);
323 pRD->volatileCurrContextPointers.X5 = &(pDE->m_context.X5);
324 pRD->volatileCurrContextPointers.X6 = &(pDE->m_context.X6);
325 pRD->volatileCurrContextPointers.X7 = &(pDE->m_context.X7);
326 pRD->volatileCurrContextPointers.X8 = &(pDE->m_context.X8);
327 pRD->volatileCurrContextPointers.X9 = &(pDE->m_context.X9);
328 pRD->volatileCurrContextPointers.X10 = &(pDE->m_context.X10);
329 pRD->volatileCurrContextPointers.X11 = &(pDE->m_context.X11);
330 pRD->volatileCurrContextPointers.X12 = &(pDE->m_context.X12);
331 pRD->volatileCurrContextPointers.X13 = &(pDE->m_context.X13);
332 pRD->volatileCurrContextPointers.X14 = &(pDE->m_context.X14);
333 pRD->volatileCurrContextPointers.X15 = &(pDE->m_context.X15);
334 pRD->volatileCurrContextPointers.X16 = &(pDE->m_context.X16);
335 pRD->volatileCurrContextPointers.X17 = &(pDE->m_context.X17);
336
337 SyncRegDisplayToCurrentContext(pRD);
338#else
339 PORTABILITY_ASSERT("FuncEvalFrame::UpdateRegDisplay is not implemented on this platform.");
340#endif
341}
342
343#endif // DEBUGGER_INL_
344