9a95af12986fa6c32b3623a2dc9a3b3137861a25
[platform/upstream/coreclr.git] / src / vm / eedbginterfaceimpl.cpp
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 /*
7  *
8  * COM+99 EE to Debugger Interface Implementation
9  *
10  */
11
12 #include "common.h"
13 #include "dbginterface.h"
14 #include "eedbginterfaceimpl.h"
15 #include "virtualcallstub.h"
16 #include "contractimpl.h"
17
18 #ifdef DEBUGGING_SUPPORTED
19
20 #ifndef DACCESS_COMPILE
21
22 //
23 // Cleanup any global data used by this interface.
24 //
25 void EEDbgInterfaceImpl::Terminate(void)
26 {
27     CONTRACTL
28     {
29         SO_INTOLERANT;
30         NOTHROW;
31         GC_NOTRIGGER;
32     } 
33     CONTRACTL_END;
34
35     if (g_pEEDbgInterfaceImpl)
36     {
37         delete g_pEEDbgInterfaceImpl;
38         g_pEEDbgInterfaceImpl = NULL;
39     }
40 }
41
42 #endif // #ifndef DACCESS_COMPILE
43
44 Thread* EEDbgInterfaceImpl::GetThread(void) 
45
46     LIMITED_METHOD_CONTRACT;
47 // Since this may be called from a Debugger Interop Hijack, the EEThread may be bogus.
48 // Thus we can't use contracts. If we do fix that, then the contract below would be nice...
49 #if 0
50     CONTRACT(Thread *)
51     {
52         NOTHROW;
53         GC_NOTRIGGER;
54         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
55     }
56     CONTRACT_END;
57 #endif
58
59     return ::GetThread(); 
60 }
61
62 #ifndef DACCESS_COMPILE
63
64 StackWalkAction EEDbgInterfaceImpl::StackWalkFramesEx(Thread* pThread,
65                                                       PREGDISPLAY pRD,
66                                                       PSTACKWALKFRAMESCALLBACK pCallback,
67                                                       VOID* pData,
68                                                       unsigned int flags)
69
70     CONTRACTL
71     {
72         DISABLED(NOTHROW); // FIX THIS when StackWalkFramesEx gets fixed.
73         DISABLED(GC_TRIGGERS); // We cannot predict if pCallback will trigger or not. 
74                                // Disabled is not a bug in this case.
75         PRECONDITION(CheckPointer(pThread));
76     }
77     CONTRACTL_END;
78
79     return pThread->StackWalkFramesEx(pRD, pCallback, pData, flags); 
80 }
81
82 Frame *EEDbgInterfaceImpl::GetFrame(CrawlFrame *pCF)
83
84     CONTRACT(Frame *)
85     {
86         SO_NOT_MAINLINE;
87         NOTHROW;
88         GC_NOTRIGGER;
89         PRECONDITION(CheckPointer(pCF));
90         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
91     }
92     CONTRACT_END;
93
94     RETURN pCF->GetFrame(); 
95 }
96
97 bool EEDbgInterfaceImpl::InitRegDisplay(Thread* pThread, 
98                                         const PREGDISPLAY pRD,
99                                         const PCONTEXT pctx, 
100                                         bool validContext)
101
102     CONTRACTL
103     {
104         SO_NOT_MAINLINE;
105         NOTHROW;
106         GC_NOTRIGGER;
107         PRECONDITION(CheckPointer(pThread));
108         PRECONDITION(CheckPointer(pRD));
109         if (validContext)
110         {
111             PRECONDITION(CheckPointer(pctx));
112         }
113     }
114     CONTRACTL_END;
115
116     return pThread->InitRegDisplay(pRD, pctx, validContext); 
117 }
118
119 BOOL EEDbgInterfaceImpl::IsStringObject(Object* o)
120
121     CONTRACTL
122     {
123         SO_NOT_MAINLINE;
124         THROWS;
125         GC_NOTRIGGER;
126         PRECONDITION(CheckPointer(o));
127     }
128     CONTRACTL_END;
129
130     return o->GetMethodTable() == g_pStringClass;
131 }
132
133 BOOL EEDbgInterfaceImpl::IsTypedReference(MethodTable* pMT)
134
135     CONTRACTL
136     {
137         SO_NOT_MAINLINE;
138         THROWS;
139         GC_NOTRIGGER;
140         PRECONDITION(CheckPointer(pMT));
141     }
142     CONTRACTL_END;
143
144     return pMT == g_TypedReferenceMT; 
145 }
146
147 WCHAR* EEDbgInterfaceImpl::StringObjectGetBuffer(StringObject* so)
148
149     CONTRACTL
150     {
151         SO_NOT_MAINLINE;
152         NOTHROW;
153         GC_NOTRIGGER;
154         PRECONDITION(CheckPointer(so));
155     }
156     CONTRACTL_END;
157
158     return so->GetBuffer(); 
159 }
160
161 DWORD EEDbgInterfaceImpl::StringObjectGetStringLength(StringObject* so)
162
163     CONTRACTL
164     {
165         SO_NOT_MAINLINE;
166         NOTHROW;
167         GC_NOTRIGGER;
168         PRECONDITION(CheckPointer(so));
169     }
170     CONTRACTL_END;
171
172     return so->GetStringLength(); 
173 }
174
175 void* EEDbgInterfaceImpl::GetObjectFromHandle(OBJECTHANDLE handle)
176 {
177     CONTRACTL
178     {
179         SO_NOT_MAINLINE;
180         NOTHROW;
181         GC_NOTRIGGER;
182     }
183     CONTRACTL_END;
184
185     void *v;
186
187     *((OBJECTREF *)&v) = *(OBJECTREF *)handle;
188
189     return v;
190 }
191
192 OBJECTHANDLE EEDbgInterfaceImpl::GetHandleFromObject(void *obj, 
193                                               bool fStrongNewRef, 
194                                               AppDomain *pAppDomain)
195 {
196     CONTRACTL
197     {
198         SO_NOT_MAINLINE;
199         THROWS;  // From CreateHandle
200         GC_NOTRIGGER;
201         PRECONDITION(CheckPointer(pAppDomain));
202     }
203     CONTRACTL_END;
204
205     OBJECTHANDLE oh;
206
207     if (fStrongNewRef)
208     {
209         oh = pAppDomain->CreateStrongHandle(ObjectToOBJECTREF((Object *)obj));
210
211         LOG((LF_CORDB, LL_INFO1000, "EEI::GHFO: Given objectref 0x%x,"
212             "created strong handle 0x%x!\n", obj, oh));
213     }
214     else
215     {
216         oh = pAppDomain->CreateLongWeakHandle( ObjectToOBJECTREF((Object *)obj));
217
218         LOG((LF_CORDB, LL_INFO1000, "EEI::GHFO: Given objectref 0x%x,"
219             "created long weak handle 0x%x!\n", obj, oh));
220     }
221
222     return oh;
223 }
224
225 void EEDbgInterfaceImpl::DbgDestroyHandle(OBJECTHANDLE oh, 
226                                           bool fStrongNewRef)
227 {
228     CONTRACTL
229     {
230         SO_NOT_MAINLINE;
231         NOTHROW;
232         GC_NOTRIGGER;
233     }
234     CONTRACTL_END;
235
236     LOG((LF_CORDB, LL_INFO1000, "EEI::GHFO: Destroyed given handle 0x%x,"
237         "fStrong: 0x%x!\n", oh, fStrongNewRef));
238
239     if (fStrongNewRef)
240     {
241         DestroyStrongHandle(oh);
242     }
243     else
244     {
245         DestroyLongWeakHandle(oh);
246     }
247 }
248
249     
250 OBJECTHANDLE EEDbgInterfaceImpl::GetThreadException(Thread *pThread)   
251 {   
252     CONTRACTL
253     {
254         NOTHROW;
255         GC_NOTRIGGER;
256         PRECONDITION(CheckPointer(pThread));
257     }
258     CONTRACTL_END;
259
260     OBJECTHANDLE oh = pThread->GetThrowableAsHandle();  
261
262     if (oh != NULL)
263     {
264         return oh;
265     }
266
267     // Return the last thrown object if there's no current throwable.
268     // This logic is similar to UpdateCurrentThrowable().
269     return pThread->m_LastThrownObjectHandle;
270 }   
271
272 bool EEDbgInterfaceImpl::IsThreadExceptionNull(Thread *pThread) 
273 {
274     CONTRACTL
275     {
276         SO_TOLERANT;
277         NOTHROW;
278         GC_NOTRIGGER;
279         PRECONDITION(CheckPointer(pThread));
280     }
281     CONTRACTL_END;
282
283     //
284     // We're assuming that the handle on the
285     // thread is a strong handle and we're goona check it for
286     // NULL. We're also assuming something about the
287     // implementation of the handle here, too.
288     //
289     OBJECTHANDLE h = pThread->GetThrowableAsHandle();
290     if (h == NULL)
291     {
292         return true;
293     }
294
295     void *pThrowable = *((void**)h);
296
297     return (pThrowable == NULL);
298 }   
299
300 void EEDbgInterfaceImpl::ClearThreadException(Thread *pThread)  
301 {
302     //
303     // If one day there is a continuable exception, then this will have to be
304     // implemented properly. 
305     //
306     //
307     LIMITED_METHOD_CONTRACT;
308 }   
309
310 bool EEDbgInterfaceImpl::StartSuspendForDebug(AppDomain *pAppDomain, 
311                                               BOOL fHoldingThreadStoreLock) 
312 {
313     CONTRACTL
314     {
315         SO_NOT_MAINLINE;
316         NOTHROW;
317         GC_NOTRIGGER;
318     }
319     CONTRACTL_END;
320
321     LOG((LF_CORDB,LL_INFO1000, "EEDbgII:SSFD: start suspend on AD:0x%x\n",
322         pAppDomain));
323
324     bool result = Thread::SysStartSuspendForDebug(pAppDomain);
325
326     return result;  
327 }
328
329 bool EEDbgInterfaceImpl::SweepThreadsForDebug(bool forceSync)
330 {
331     CONTRACTL
332     {
333         SO_NOT_MAINLINE;
334         NOTHROW;
335         DISABLED(GC_TRIGGERS);  // Called by unmanaged threads.
336     }
337     CONTRACTL_END;
338
339     return Thread::SysSweepThreadsForDebug(forceSync);
340 }
341
342 void EEDbgInterfaceImpl::ResumeFromDebug(AppDomain *pAppDomain) 
343 {
344     CONTRACTL
345     {
346         SO_NOT_MAINLINE;
347         NOTHROW;
348         GC_NOTRIGGER;
349     }
350     CONTRACTL_END;
351
352     Thread::SysResumeFromDebug(pAppDomain);
353 }
354
355 void EEDbgInterfaceImpl::MarkThreadForDebugSuspend(Thread* pRuntimeThread)
356 {
357     CONTRACTL
358     {
359         SO_NOT_MAINLINE;
360         NOTHROW;
361         GC_NOTRIGGER;
362         PRECONDITION(CheckPointer(pRuntimeThread));
363     }
364     CONTRACTL_END;
365
366     pRuntimeThread->MarkForDebugSuspend();
367 }
368
369 void EEDbgInterfaceImpl::MarkThreadForDebugStepping(Thread* pRuntimeThread, 
370                                                     bool onOff)
371 {
372     CONTRACTL
373     {
374         SO_NOT_MAINLINE;
375         NOTHROW;
376         GC_NOTRIGGER;
377         PRECONDITION(CheckPointer(pRuntimeThread));
378     }
379     CONTRACTL_END;
380
381     pRuntimeThread->MarkDebuggerIsStepping(onOff);
382 }
383     
384 void EEDbgInterfaceImpl::SetThreadFilterContext(Thread *thread, 
385                                                 CONTEXT *context)   
386 {   
387     CONTRACTL
388     {
389         SO_NOT_MAINLINE;
390         NOTHROW;
391         GC_NOTRIGGER;
392         PRECONDITION(CheckPointer(thread));
393     }
394     CONTRACTL_END;
395
396     thread->SetFilterContext(context); 
397 }   
398
399 CONTEXT *EEDbgInterfaceImpl::GetThreadFilterContext(Thread *thread) 
400 {   
401     CONTRACT(CONTEXT *)
402     {
403         NOTHROW;
404         GC_NOTRIGGER;
405         PRECONDITION(CheckPointer(thread));
406         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
407     }
408     CONTRACT_END;
409
410     RETURN thread->GetFilterContext();    
411 }
412
413 #ifdef FEATURE_INTEROP_DEBUGGING
414
415 VOID * EEDbgInterfaceImpl::GetThreadDebuggerWord()
416 {
417     return UnsafeTlsGetValue(g_debuggerWordTLSIndex);
418 }
419
420 void EEDbgInterfaceImpl::SetThreadDebuggerWord(VOID *dw)
421 {
422     UnsafeTlsSetValue(g_debuggerWordTLSIndex, dw);
423 }
424
425 #endif
426
427 BOOL EEDbgInterfaceImpl::IsManagedNativeCode(const BYTE *address)
428
429     WRAPPER_NO_CONTRACT;
430     return ExecutionManager::IsManagedCode((PCODE)address);
431 }
432
433 PCODE EEDbgInterfaceImpl::GetNativeCodeStartAddress(PCODE address)
434 {
435     WRAPPER_NO_CONTRACT;
436     _ASSERTE(address != NULL);
437
438     return ExecutionManager::GetCodeStartAddress(address);
439 }
440
441 MethodDesc *EEDbgInterfaceImpl::GetNativeCodeMethodDesc(const PCODE address)
442
443     CONTRACT(MethodDesc *)
444     {
445         NOTHROW;
446         GC_NOTRIGGER;
447         PRECONDITION(address != NULL);
448         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
449     }
450     CONTRACT_END;
451
452     RETURN ExecutionManager::GetCodeMethodDesc(address);
453 }
454
455 #ifndef USE_GC_INFO_DECODER
456 // IsInPrologOrEpilog doesn't seem to be used for code that uses GC_INFO_DECODER
457 BOOL EEDbgInterfaceImpl::IsInPrologOrEpilog(const BYTE *address,
458                                             size_t* prologSize)
459 {
460     CONTRACTL
461     {
462         SO_NOT_MAINLINE;
463         NOTHROW;
464         GC_NOTRIGGER;
465     }
466     CONTRACTL_END;
467
468     *prologSize = 0;
469
470     EECodeInfo codeInfo((PCODE)address);
471
472     if (codeInfo.IsValid())
473     {
474         GCInfoToken gcInfoToken = codeInfo.GetGCInfoToken();
475
476         if (codeInfo.GetCodeManager()->IsInPrologOrEpilog(codeInfo.GetRelOffset(), gcInfoToken, prologSize))
477         {
478             return TRUE;
479         }
480     }
481
482     return FALSE;
483 }
484 #endif // USE_GC_INFO_DECODER
485
486 // 
487 // Given a collection of native offsets of a certain function, determine if each falls
488 // within an exception filter or handler.
489 //
490 void EEDbgInterfaceImpl::DetermineIfOffsetsInFilterOrHandler(const BYTE *functionAddress,
491                                                                   DebugOffsetToHandlerInfo *pOffsetToHandlerInfo, 
492                                                                   unsigned offsetToHandlerInfoLength)
493 {
494     CONTRACTL
495     {
496         SO_NOT_MAINLINE;
497         NOTHROW;
498         GC_NOTRIGGER;
499     }
500     CONTRACTL_END;
501
502     EECodeInfo codeInfo((PCODE)functionAddress);
503
504     if (!codeInfo.IsValid())
505     {
506         return;
507     }
508
509     // Loop through all the exception handling clause information for the method
510     EH_CLAUSE_ENUMERATOR pEnumState;
511     unsigned EHCount = codeInfo.GetJitManager()->InitializeEHEnumeration(codeInfo.GetMethodToken(), &pEnumState);
512     if (EHCount == 0)
513     {
514         return;
515     }
516     
517     for (ULONG i=0; i < EHCount; i++)
518     {
519         EE_ILEXCEPTION_CLAUSE EHClause;
520         codeInfo.GetJitManager()->GetNextEHClause(&pEnumState, &EHClause);
521
522         // Check each EH clause against each offset of interest.  
523         // Note that this could be time consuming for very long methods ( O(n^2) ).
524         // We could make this linear if we could guarentee that the two lists are sorted.               
525         for (ULONG j=0; j < offsetToHandlerInfoLength; j++)
526         {
527             SIZE_T offs = pOffsetToHandlerInfo[j].offset;
528
529             // those with -1 indicate slots to skip
530             if (offs == (SIZE_T) -1)
531             {
532                 continue;
533             }
534             // For a filter, the handler comes directly after it so check from start of filter 
535             // to end of handler
536             if (IsFilterHandler(&EHClause))
537             {
538                 if (offs >= EHClause.FilterOffset && offs < EHClause.HandlerEndPC)
539                 {
540                     pOffsetToHandlerInfo[j].isInFilterOrHandler = TRUE;
541                 }
542             }
543             // For anything else, only care about handler range
544             else if (offs >= EHClause.HandlerStartPC && offs < EHClause.HandlerEndPC)
545             {
546                 pOffsetToHandlerInfo[j].isInFilterOrHandler = TRUE;
547             }
548         }
549     }
550 }
551 #endif // #ifndef DACCESS_COMPILE
552
553 void EEDbgInterfaceImpl::GetMethodRegionInfo(const PCODE    pStart, 
554                                              PCODE        * pCold, 
555                                              size_t *hotSize, 
556                                              size_t *coldSize)
557 {
558     CONTRACTL
559     {
560         SO_INTOLERANT;
561         NOTHROW;
562         GC_NOTRIGGER;
563         PRECONDITION(CheckPointer(pCold));
564         PRECONDITION(CheckPointer(hotSize));
565         PRECONDITION(CheckPointer(coldSize));
566         SUPPORTS_DAC;
567     }
568     CONTRACTL_END;
569
570     IJitManager::MethodRegionInfo methodRegionInfo = {NULL, 0, NULL, 0};
571
572     EECodeInfo codeInfo(pStart);
573
574     if (codeInfo.IsValid() != NULL)
575     {
576         codeInfo.GetMethodRegionInfo(&methodRegionInfo);
577     }
578
579     *pCold    = methodRegionInfo.coldStartAddress;
580     *hotSize  = methodRegionInfo.hotSize;
581     *coldSize = methodRegionInfo.coldSize;
582 }
583
584 #if defined(WIN64EXCEPTIONS)
585 DWORD EEDbgInterfaceImpl::GetFuncletStartOffsets(const BYTE *pStart, DWORD* pStartOffsets, DWORD dwLength)
586 {
587     CONTRACTL
588     {
589         NOTHROW;
590         GC_NOTRIGGER;
591         PRECONDITION(CheckPointer(pStart));
592     }
593     CONTRACTL_END;
594
595     EECodeInfo codeInfo((PCODE)pStart);
596     _ASSERTE(codeInfo.IsValid());
597
598     return codeInfo.GetJitManager()->GetFuncletStartOffsets(codeInfo.GetMethodToken(), pStartOffsets, dwLength);
599 }
600
601 StackFrame EEDbgInterfaceImpl::FindParentStackFrame(CrawlFrame* pCF)
602 {
603     CONTRACTL
604     {
605         NOTHROW;
606         GC_NOTRIGGER;
607         PRECONDITION(CheckPointer(pCF));
608     }
609     CONTRACTL_END;
610
611 #if defined(DACCESS_COMPILE)
612     DacNotImpl();
613     return StackFrame();
614
615 #else  // !DACCESS_COMPILE
616     return ExceptionTracker::FindParentStackFrameForStackWalk(pCF);
617
618 #endif // !DACCESS_COMPILE
619 }
620 #endif // WIN64EXCEPTIONS
621
622 #ifndef DACCESS_COMPILE
623 size_t EEDbgInterfaceImpl::GetFunctionSize(MethodDesc *pFD)
624 {
625     CONTRACTL
626     {
627         NOTHROW;
628         GC_NOTRIGGER;
629         PRECONDITION(CheckPointer(pFD));
630     }
631     CONTRACTL_END;
632
633     PCODE methodStart = pFD->GetNativeCode();
634
635     if (methodStart == NULL)
636         return 0;
637
638     EECodeInfo codeInfo(methodStart);
639     GCInfoToken gcInfoToken = codeInfo.GetGCInfoToken();
640     return codeInfo.GetCodeManager()->GetFunctionSize(gcInfoToken);
641 }
642 #endif //!DACCESS_COMPILE
643
644 const PCODE EEDbgInterfaceImpl::GetFunctionAddress(MethodDesc *pFD)
645
646     CONTRACTL
647     {
648         NOTHROW;
649         GC_NOTRIGGER;
650         PRECONDITION(CheckPointer(pFD));
651         SUPPORTS_DAC;
652     }
653     CONTRACTL_END;
654
655     return pFD->GetNativeCode();
656 }
657
658 #ifndef DACCESS_COMPILE
659
660 void EEDbgInterfaceImpl::DisablePreemptiveGC(void) 
661
662     CONTRACTL
663     {
664         SO_INTOLERANT;
665         NOTHROW;
666         DISABLED(GC_TRIGGERS); // Disabled because disabled in RareDisablePreemptiveGC()
667     }
668     CONTRACTL_END;
669
670     ::GetThread()->DisablePreemptiveGC(); 
671 }    
672
673 void EEDbgInterfaceImpl::EnablePreemptiveGC(void) 
674
675     CONTRACTL
676     {
677         SO_INTOLERANT;
678         NOTHROW;
679         DISABLED(GC_TRIGGERS); // Disabled because disabled in RareEnablePreemptiveGC()
680     }
681     CONTRACTL_END;
682
683     ::GetThread()->EnablePreemptiveGC(); 
684 }  
685
686 bool EEDbgInterfaceImpl::IsPreemptiveGCDisabled(void)   
687
688     CONTRACTL
689     {
690         SO_TOLERANT;
691         NOTHROW;
692         GC_NOTRIGGER;
693     }
694     CONTRACTL_END;
695
696     return ::GetThread()->PreemptiveGCDisabled() != 0; 
697 }   
698
699 DWORD EEDbgInterfaceImpl::MethodDescIsStatic(MethodDesc *pFD)
700 {
701     CONTRACTL
702     {
703         NOTHROW;
704         GC_NOTRIGGER;
705         PRECONDITION(CheckPointer(pFD));
706     }
707     CONTRACTL_END;
708     
709     return pFD->IsStatic();
710 }
711
712 #endif // #ifndef DACCESS_COMPILE
713
714 Module *EEDbgInterfaceImpl::MethodDescGetModule(MethodDesc *pFD)
715 {
716     CONTRACT(Module *)
717     {
718         NOTHROW;
719         GC_NOTRIGGER;
720         PRECONDITION(CheckPointer(pFD));
721         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
722     }
723     CONTRACT_END;
724     
725     RETURN pFD->GetModule();
726 }
727
728 #ifndef DACCESS_COMPILE
729
730 COR_ILMETHOD* EEDbgInterfaceImpl::MethodDescGetILHeader(MethodDesc *pFD)
731 {
732     CONTRACT(COR_ILMETHOD *)
733     {
734         THROWS; 
735         GC_NOTRIGGER;
736         PRECONDITION(CheckPointer(pFD));
737         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
738     }
739     CONTRACT_END;
740     
741     if (pFD->IsIL())
742     {
743         RETURN pFD->GetILHeader();
744     }
745
746     RETURN NULL;
747 }
748
749 ULONG EEDbgInterfaceImpl::MethodDescGetRVA(MethodDesc *pFD)
750 {
751     CONTRACTL
752     {
753         SO_NOT_MAINLINE;
754         NOTHROW;
755         GC_NOTRIGGER;
756         PRECONDITION(CheckPointer(pFD));
757     }
758     CONTRACTL_END;
759
760     return pFD->GetRVA();
761 }
762
763 MethodDesc *EEDbgInterfaceImpl::FindLoadedMethodRefOrDef(Module* pModule,
764                                                           mdToken memberRef)
765 {
766     CONTRACT(MethodDesc *)
767     {
768         NOTHROW;
769         GC_NOTRIGGER;
770         PRECONDITION(CheckPointer(pModule));
771         POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
772     }
773     CONTRACT_END;
774     
775     // Must have a MemberRef or a MethodDef
776     mdToken tkType = TypeFromToken(memberRef);
777     _ASSERTE((tkType == mdtMemberRef) || (tkType == mdtMethodDef));
778
779     if (tkType == mdtMemberRef) 
780     {
781         RETURN pModule->LookupMemberRefAsMethod(memberRef);
782     }
783
784     RETURN pModule->LookupMethodDef(memberRef);
785 }
786
787 MethodDesc *EEDbgInterfaceImpl::LoadMethodDef(Module* pModule,
788                                               mdMethodDef methodDef, 
789                                               DWORD numGenericArgs, 
790                                               TypeHandle *pGenericArgs,
791                                               TypeHandle *pOwnerType)
792 {
793     CONTRACT(MethodDesc *)
794     {
795         THROWS;
796         GC_TRIGGERS;
797         PRECONDITION(CheckPointer(pModule));
798         POSTCONDITION(CheckPointer(RETVAL));
799     }
800     CONTRACT_END;
801
802     _ASSERTE(TypeFromToken(methodDef) == mdtMethodDef);
803
804     // The generic class and method args are sent as one array
805     // by the debugger.  We now split this into two by finding out how
806     // many generic args are for the class and how many for the 
807     // method.  The actual final checks are done in MemberLoader::GetMethodDescFromMethodDef.
808
809     DWORD numGenericClassArgs = 0;
810     TypeHandle *pGenericClassArgs = NULL;
811     DWORD nGenericMethodArgs = 0;
812     TypeHandle *pGenericMethodArgs = NULL;
813     mdTypeDef typeDef = 0;
814
815     TypeHandle thOwner;
816
817     BOOL forceRemotable = FALSE;
818     if (numGenericArgs != 0)
819     {
820         HRESULT hr = pModule->GetMDImport()->GetParentToken(methodDef, &typeDef); 
821         if (FAILED(hr)) 
822             COMPlusThrowHR(E_INVALIDARG);
823
824         TypeHandle thClass = LoadClass(pModule, typeDef);
825         _ASSERTE(!thClass.IsNull());
826
827         numGenericClassArgs = thClass.GetNumGenericArgs();
828         if (numGenericArgs < numGenericClassArgs)
829         {
830             COMPlusThrowHR(COR_E_TARGETPARAMCOUNT);
831         }
832         pGenericClassArgs = (numGenericClassArgs > 0) ? pGenericArgs : NULL;
833         nGenericMethodArgs = (numGenericArgs >= numGenericClassArgs) ? (numGenericArgs - numGenericClassArgs) : 0;
834         pGenericMethodArgs = (nGenericMethodArgs > 0) ? (pGenericArgs + numGenericClassArgs) : NULL;
835
836 #ifdef FEATURE_COMINTEROP
837         if (numGenericClassArgs > 0)
838         {
839             thOwner = ClassLoader::LoadGenericInstantiationThrowing(pModule, typeDef, Instantiation(pGenericClassArgs, numGenericClassArgs));
840             // for classes supporting generic interop force remotable method descs
841             forceRemotable = thOwner.GetMethodTable()->SupportsGenericInterop(TypeHandle::Interop_ManagedToNative);
842         }
843 #endif // FEATURE_COMINTEROP
844     }
845
846     MethodDesc *pRes = MemberLoader::GetMethodDescFromMethodDef(pModule, 
847                                                                 methodDef, 
848                                                                 Instantiation(pGenericClassArgs, numGenericClassArgs),
849                                                                 Instantiation(pGenericMethodArgs, nGenericMethodArgs),
850                                                                 forceRemotable);
851
852     // The ownerType is extra information that augments the specification of an interface MD.
853     // It is only needed if generics code sharing is supported, because otherwise MDs are
854     // fully self-describing.
855     if (pOwnerType != NULL)
856     {
857         if (numGenericClassArgs != 0)
858         {
859             if (thOwner.IsNull())
860                 *pOwnerType = ClassLoader::LoadGenericInstantiationThrowing(pModule, typeDef, Instantiation(pGenericClassArgs, numGenericClassArgs));
861             else
862                 *pOwnerType = thOwner;
863         }
864         else
865         {
866             *pOwnerType = TypeHandle(pRes->GetMethodTable());
867         }
868     }
869     RETURN (pRes);
870
871 }
872
873
874 TypeHandle EEDbgInterfaceImpl::FindLoadedClass(Module *pModule, 
875                                              mdTypeDef classToken)
876 {
877     CONTRACT(TypeHandle)
878     {
879         NOTHROW;
880         GC_NOTRIGGER;
881         PRECONDITION(CheckPointer(pModule));
882     }
883     CONTRACT_END;
884     
885     RETURN ClassLoader::LookupTypeDefOrRefInModule(pModule, classToken);
886
887 }
888
889 TypeHandle EEDbgInterfaceImpl::FindLoadedInstantiation(Module *pModule,
890                                                        mdTypeDef typeDef,
891                                                        DWORD ntypars,
892                                                        TypeHandle *inst)
893 {
894     // Lookup operations run the class loader in non-load mode.
895     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
896
897
898     // scan violation:  asserts that this can be suppressed since there is currently
899     // work on dac-izing all this code and as a result the issue will become moot.
900     CONTRACT_VIOLATION(FaultViolation);
901
902     return ClassLoader::LoadGenericInstantiationThrowing(pModule, typeDef, Instantiation(inst, ntypars),
903                                                         ClassLoader::DontLoadTypes);
904 }
905
906 TypeHandle EEDbgInterfaceImpl::FindLoadedFnptrType(TypeHandle *inst, 
907                                                    DWORD ntypars)
908 {
909     // Lookup operations run the class loader in non-load mode.
910     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
911
912     //<TODO> : CALLCONV? </TODO>
913     return ClassLoader::LoadFnptrTypeThrowing(0, ntypars, inst, 
914                                               // <TODO> should this be FailIfNotLoaded? - NO - although we may 
915                                               // want to debug unrestored VCs, we can't do it because the debug API 
916                                               // is not set up to handle them </TODO>
917                                               // == FailIfNotLoadedOrNotRestored
918                                               ClassLoader::DontLoadTypes);
919 }
920
921 TypeHandle EEDbgInterfaceImpl::FindLoadedPointerOrByrefType(CorElementType et, 
922                                                             TypeHandle elemtype)
923 {
924     // Lookup operations run the class loader in non-load mode.
925     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
926
927     return ClassLoader::LoadPointerOrByrefTypeThrowing(et, elemtype, 
928                                                        // <TODO> should this be FailIfNotLoaded? - NO - although we may 
929                                                        // want to debug unrestored VCs, we can't do it because the debug API 
930                                                        // is not set up to handle them </TODO>
931                                                        // == FailIfNotLoadedOrNotRestored
932                                                        ClassLoader::DontLoadTypes);
933 }
934
935 TypeHandle EEDbgInterfaceImpl::FindLoadedArrayType(CorElementType et, 
936                                                    TypeHandle elemtype, 
937                                                    unsigned rank)
938 {
939     // Lookup operations run the class loader in non-load mode.
940     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
941
942     if (elemtype.IsNull())
943         return TypeHandle();
944     else
945         return ClassLoader::LoadArrayTypeThrowing(elemtype, et, rank, 
946                                                   // <TODO> should this be FailIfNotLoaded? - NO - although we may 
947                                                   // want to debug unrestored VCs, we can't do it because the debug API 
948                                                   // is not set up to handle them </TODO>
949                                                   // == FailIfNotLoadedOrNotRestored
950                                                   ClassLoader::DontLoadTypes );
951 }
952
953
954 TypeHandle EEDbgInterfaceImpl::FindLoadedElementType(CorElementType et) 
955 {
956     // Lookup operations run the class loader in non-load mode.
957     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
958
959     MethodTable *m = MscorlibBinder::GetElementType(et);
960
961     return TypeHandle(m);
962 }
963     
964 TypeHandle EEDbgInterfaceImpl::LoadClass(Module *pModule, 
965                                        mdTypeDef classToken)
966 {
967     CONTRACT(TypeHandle)
968     {
969         THROWS;
970         GC_TRIGGERS;
971         PRECONDITION(CheckPointer(pModule));
972     }
973     CONTRACT_END;
974     
975     RETURN ClassLoader::LoadTypeDefOrRefThrowing(pModule, classToken, 
976                                                           ClassLoader::ThrowIfNotFound, 
977                                                           ClassLoader::PermitUninstDefOrRef);
978
979 }
980
981 TypeHandle EEDbgInterfaceImpl::LoadInstantiation(Module *pModule,
982                                                  mdTypeDef typeDef,
983                                                  DWORD ntypars,
984                                                  TypeHandle *inst)
985 {
986     CONTRACT(TypeHandle)
987     {
988         THROWS;
989         GC_TRIGGERS;
990         PRECONDITION(CheckPointer(pModule));
991     }
992     CONTRACT_END;
993     
994     RETURN ClassLoader::LoadGenericInstantiationThrowing(pModule, typeDef, Instantiation(inst, ntypars));
995 }
996
997 TypeHandle EEDbgInterfaceImpl::LoadArrayType(CorElementType et,
998                                              TypeHandle elemtype, 
999                                              unsigned rank)
1000 {
1001     CONTRACT(TypeHandle)
1002     {
1003         THROWS;
1004         GC_TRIGGERS;
1005     }
1006     CONTRACT_END;
1007     
1008     if (elemtype.IsNull())
1009         RETURN TypeHandle();
1010     else
1011         RETURN ClassLoader::LoadArrayTypeThrowing(elemtype, et, rank);
1012 }
1013
1014 TypeHandle EEDbgInterfaceImpl::LoadPointerOrByrefType(CorElementType et, 
1015                                                       TypeHandle elemtype)
1016 {
1017     CONTRACTL
1018     {
1019         SO_NOT_MAINLINE;
1020         THROWS;
1021         GC_TRIGGERS;
1022     }
1023     CONTRACTL_END;
1024     
1025     return ClassLoader::LoadPointerOrByrefTypeThrowing(et, elemtype);
1026 }
1027
1028 TypeHandle EEDbgInterfaceImpl::LoadFnptrType(TypeHandle *inst, 
1029                                              DWORD ntypars)
1030 {
1031     CONTRACTL
1032     {
1033         SO_NOT_MAINLINE;
1034         THROWS;
1035         GC_TRIGGERS;
1036     }
1037     CONTRACTL_END;
1038     
1039     /* @TODO : CALLCONV? */
1040     return ClassLoader::LoadFnptrTypeThrowing(0, ntypars, inst);
1041 }
1042
1043 TypeHandle EEDbgInterfaceImpl::LoadElementType(CorElementType et) 
1044 {
1045     CONTRACTL
1046     {
1047         SO_NOT_MAINLINE;
1048         THROWS;
1049         GC_TRIGGERS;
1050     }
1051     CONTRACTL_END;
1052     
1053     MethodTable *m = MscorlibBinder::GetElementType(et);
1054     
1055     if (m == NULL)
1056     {
1057         return TypeHandle();
1058     }
1059
1060     return TypeHandle(m);
1061 }
1062
1063
1064 HRESULT EEDbgInterfaceImpl::GetMethodImplProps(Module *pModule, 
1065                                                mdToken tk,
1066                                                DWORD *pRVA, 
1067                                                DWORD *pImplFlags)
1068 {
1069     CONTRACTL
1070     {
1071         SO_NOT_MAINLINE;
1072         NOTHROW;
1073         GC_NOTRIGGER;
1074         PRECONDITION(CheckPointer(pModule));
1075     }
1076     CONTRACTL_END;
1077     
1078     return pModule->GetMDImport()->GetMethodImplProps(tk, pRVA, pImplFlags);
1079 }
1080
1081 HRESULT EEDbgInterfaceImpl::GetParentToken(Module *pModule, 
1082                                            mdToken tk, 
1083                                            mdToken *pParentToken)
1084 {
1085     CONTRACTL
1086     {
1087         SO_NOT_MAINLINE;
1088         NOTHROW;
1089         GC_NOTRIGGER;
1090         PRECONDITION(CheckPointer(pModule));
1091     }
1092     CONTRACTL_END;
1093     
1094     return pModule->GetMDImport()->GetParentToken(tk, pParentToken);
1095 }
1096     
1097 void EEDbgInterfaceImpl::MarkDebuggerAttached(void)
1098 {
1099     CONTRACTL
1100     {
1101         SO_NOT_MAINLINE;
1102         NOTHROW;
1103         GC_NOTRIGGER;
1104     }
1105     CONTRACTL_END;
1106     
1107     g_CORDebuggerControlFlags |= DBCF_ATTACHED;
1108     g_CORDebuggerControlFlags &= ~DBCF_PENDING_ATTACH;
1109 }
1110
1111 void EEDbgInterfaceImpl::MarkDebuggerUnattached(void)
1112 {
1113     CONTRACTL
1114     {
1115         SO_NOT_MAINLINE;
1116         NOTHROW;
1117         GC_NOTRIGGER;
1118     }
1119     CONTRACTL_END;
1120     
1121     g_CORDebuggerControlFlags &= ~DBCF_ATTACHED;
1122 }
1123
1124
1125 #ifdef EnC_SUPPORTED
1126
1127 // Apply an EnC edit to the specified module
1128 HRESULT EEDbgInterfaceImpl::EnCApplyChanges(EditAndContinueModule *pModule,
1129                                             DWORD cbMetadata,
1130                                             BYTE *pMetadata,
1131                                             DWORD cbIL,
1132                                             BYTE *pIL)
1133 {
1134     LOG((LF_ENC, LL_INFO100, "EncApplyChanges\n"));
1135     CONTRACTL
1136     {
1137         SO_NOT_MAINLINE;
1138         DISABLED(THROWS);
1139         DISABLED(GC_TRIGGERS);
1140         PRECONDITION(CheckPointer(pModule));
1141     }
1142     CONTRACTL_END;
1143     
1144     return pModule->ApplyEditAndContinue(cbMetadata, pMetadata, cbIL, pIL);
1145 }
1146
1147 // Remap execution to the latest version of an edited method
1148 // This function should never return.
1149 void EEDbgInterfaceImpl::ResumeInUpdatedFunction(EditAndContinueModule *pModule,
1150                                                  MethodDesc *pFD, 
1151                                                  void *debuggerFuncHandle,
1152                                                  SIZE_T resumeIP,
1153                                                  CONTEXT *pContext)
1154 {
1155     CONTRACTL
1156     {
1157         SO_NOT_MAINLINE;
1158         DISABLED(THROWS);
1159         DISABLED(GC_TRIGGERS);
1160         PRECONDITION(CheckPointer(pModule));
1161     }
1162     CONTRACTL_END;
1163     
1164     pModule->ResumeInUpdatedFunction(pFD, 
1165                                      debuggerFuncHandle,
1166                                      resumeIP, 
1167                                      pContext);
1168 }
1169
1170 #endif // EnC_SUPPORTED
1171
1172 bool EEDbgInterfaceImpl::CrawlFrameIsGcSafe(CrawlFrame *pCF)
1173 {
1174     CONTRACTL
1175     {
1176         SO_NOT_MAINLINE;
1177         SO_NOT_MAINLINE;
1178         NOTHROW;
1179         GC_NOTRIGGER;
1180         PRECONDITION(CheckPointer(pCF));
1181     }
1182     CONTRACTL_END;
1183     
1184     return pCF->IsGcSafe();
1185 }
1186
1187 bool EEDbgInterfaceImpl::IsStub(const BYTE *ip)
1188 {
1189     CONTRACTL
1190     {
1191         SO_NOT_MAINLINE;
1192         NOTHROW;
1193         GC_NOTRIGGER;
1194     }
1195     CONTRACTL_END;
1196
1197     // IsStub will catch any exceptions and return false.
1198     return StubManager::IsStub((PCODE) ip) != FALSE;
1199 }
1200
1201 #endif // #ifndef DACCESS_COMPILE
1202
1203 // static
1204 bool EEDbgInterfaceImpl::DetectHandleILStubs(Thread *thread)
1205 {
1206     CONTRACTL
1207     {
1208         NOTHROW;
1209         GC_NOTRIGGER;
1210     }
1211     CONTRACTL_END;
1212
1213     return thread->DetectHandleILStubsForDebugger();
1214 }
1215
1216 bool EEDbgInterfaceImpl::TraceStub(const BYTE *ip, 
1217                                    TraceDestination *trace)
1218 {
1219 #ifndef DACCESS_COMPILE
1220     CONTRACTL
1221     {
1222         SO_NOT_MAINLINE;
1223         NOTHROW;
1224         GC_NOTRIGGER;
1225     }
1226     CONTRACTL_END;
1227     
1228     return StubManager::TraceStub((PCODE) ip, trace) != FALSE;
1229 #else
1230     DacNotImpl();
1231     return false;
1232 #endif // #ifndef DACCESS_COMPILE
1233 }
1234
1235 #ifndef DACCESS_COMPILE
1236
1237 bool EEDbgInterfaceImpl::FollowTrace(TraceDestination *trace)
1238 {
1239     CONTRACTL
1240     {
1241         SO_NOT_MAINLINE;
1242         NOTHROW;
1243         GC_NOTRIGGER;
1244     }
1245     CONTRACTL_END;
1246     
1247     return StubManager::FollowTrace(trace) != FALSE;
1248 }
1249
1250 bool EEDbgInterfaceImpl::TraceFrame(Thread *thread, 
1251                                     Frame *frame, 
1252                                     BOOL fromPatch, 
1253                                     TraceDestination *trace, 
1254                                     REGDISPLAY *regs)
1255 {
1256     CONTRACTL
1257     {
1258         SO_NOT_MAINLINE;
1259         THROWS;
1260         DISABLED(GC_TRIGGERS);  // This is not a bug - the debugger can call this on an un-managed thread.
1261         PRECONDITION(CheckPointer(frame));
1262     }
1263     CONTRACTL_END;
1264
1265     bool fResult = frame->TraceFrame(thread, fromPatch, trace, regs) != FALSE;
1266
1267 #ifdef _DEBUG
1268     StubManager::DbgWriteLog("Doing TraceFrame on frame=0x%p (fromPatch=%d), yeilds:\n", frame, fromPatch);
1269     if (fResult)
1270     {
1271         SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE;    
1272         FAULT_NOT_FATAL();
1273         SString buffer;
1274         StubManager::DbgWriteLog("  td=%S\n", trace->DbgToString(buffer));
1275     }
1276     else
1277     {
1278         StubManager::DbgWriteLog("  false (this frame does not expect to call managed code).\n");
1279     }
1280 #endif        
1281     return fResult;
1282 }
1283
1284 bool EEDbgInterfaceImpl::TraceManager(Thread *thread, 
1285                                       StubManager *stubManager,
1286                                       TraceDestination *trace, 
1287                                       CONTEXT *context,
1288                                       BYTE **pRetAddr)
1289 {
1290     CONTRACTL
1291     {
1292         SO_NOT_MAINLINE;
1293         NOTHROW;
1294         GC_TRIGGERS;
1295         PRECONDITION(CheckPointer(stubManager));
1296     }
1297     CONTRACTL_END;
1298
1299     bool fResult = false;
1300
1301     EX_TRY
1302     {
1303         fResult =  stubManager->TraceManager(thread, trace, context, pRetAddr) != FALSE;
1304     }
1305     EX_CATCH
1306     {
1307         // We never expect TraceManager() to fail and throw an exception, 
1308         // so we should never hit this assertion.
1309         _ASSERTE(!"Fail to trace a stub through TraceManager()");
1310         fResult = false;
1311     }
1312     EX_END_CATCH(SwallowAllExceptions);
1313
1314 #ifdef _DEBUG
1315     StubManager::DbgWriteLog("Doing TraceManager on %s (0x%p) for IP=0x%p, yields:\n", stubManager->DbgGetName(), stubManager, GetIP(context));
1316     if (fResult)
1317     {
1318         // Should never be on helper thread
1319         FAULT_NOT_FATAL();
1320         SString buffer;
1321         StubManager::DbgWriteLog("  td=%S\n", trace->DbgToString(buffer));
1322     }
1323     else
1324     {
1325         StubManager::DbgWriteLog("  false (this stub does not expect to call managed code).\n");
1326     }
1327 #endif    
1328     return fResult;
1329 }
1330
1331 void EEDbgInterfaceImpl::EnableTraceCall(Thread *thread)
1332 {
1333     CONTRACTL
1334     {
1335         SO_NOT_MAINLINE;
1336         NOTHROW;
1337         GC_NOTRIGGER;
1338         PRECONDITION(CheckPointer(thread));
1339     }
1340     CONTRACTL_END;
1341     
1342     thread->IncrementTraceCallCount();
1343 }
1344
1345 void EEDbgInterfaceImpl::DisableTraceCall(Thread *thread)
1346 {
1347     CONTRACTL
1348     {
1349         SO_NOT_MAINLINE;
1350         NOTHROW;
1351         GC_NOTRIGGER;
1352         PRECONDITION(CheckPointer(thread));
1353     }
1354     CONTRACTL_END;
1355     
1356     thread->DecrementTraceCallCount();
1357 }
1358
1359 EXTERN_C UINT32 _tls_index;
1360
1361 void EEDbgInterfaceImpl::GetRuntimeOffsets(SIZE_T *pTLSIndex,
1362                                            SIZE_T *pTLSIsSpecialIndex,
1363                                            SIZE_T *pTLSCantStopIndex,
1364                                            SIZE_T *pEEThreadStateOffset,
1365                                            SIZE_T *pEEThreadStateNCOffset,
1366                                            SIZE_T *pEEThreadPGCDisabledOffset,
1367                                            DWORD  *pEEThreadPGCDisabledValue,
1368                                            SIZE_T *pEEThreadFrameOffset,
1369                                            SIZE_T *pEEThreadMaxNeededSize,
1370                                            DWORD  *pEEThreadSteppingStateMask,
1371                                            DWORD  *pEEMaxFrameValue,
1372                                            SIZE_T *pEEThreadDebuggerFilterContextOffset,
1373                                            SIZE_T *pEEThreadCantStopOffset,
1374                                            SIZE_T *pEEFrameNextOffset,
1375                                            DWORD  *pEEIsManagedExceptionStateMask)
1376 {
1377     CONTRACTL
1378     {
1379         SO_INTOLERANT;
1380         NOTHROW;
1381         GC_NOTRIGGER;
1382         PRECONDITION(CheckPointer(pTLSIndex));
1383         PRECONDITION(CheckPointer(pTLSIsSpecialIndex));
1384         PRECONDITION(CheckPointer(pEEThreadStateOffset));
1385         PRECONDITION(CheckPointer(pEEThreadStateNCOffset));
1386         PRECONDITION(CheckPointer(pEEThreadPGCDisabledOffset));
1387         PRECONDITION(CheckPointer(pEEThreadPGCDisabledValue));
1388         PRECONDITION(CheckPointer(pEEThreadFrameOffset));
1389         PRECONDITION(CheckPointer(pEEThreadMaxNeededSize));
1390         PRECONDITION(CheckPointer(pEEThreadSteppingStateMask));
1391         PRECONDITION(CheckPointer(pEEMaxFrameValue));
1392         PRECONDITION(CheckPointer(pEEThreadDebuggerFilterContextOffset));
1393         PRECONDITION(CheckPointer(pEEThreadCantStopOffset));
1394         PRECONDITION(CheckPointer(pEEFrameNextOffset));
1395         PRECONDITION(CheckPointer(pEEIsManagedExceptionStateMask));
1396     }
1397     CONTRACTL_END;
1398     
1399     *pTLSIndex = g_TlsIndex;
1400     *pTLSIsSpecialIndex = TlsIdx_ThreadType;
1401     *pTLSCantStopIndex = TlsIdx_CantStopCount;
1402     *pEEThreadStateOffset = Thread::GetOffsetOfState();
1403     *pEEThreadStateNCOffset = Thread::GetOffsetOfStateNC();
1404     *pEEThreadPGCDisabledOffset = Thread::GetOffsetOfGCFlag();
1405     *pEEThreadPGCDisabledValue = 1; // A little obvious, but just in case...
1406     *pEEThreadFrameOffset = Thread::GetOffsetOfCurrentFrame();
1407     *pEEThreadMaxNeededSize = sizeof(Thread);
1408     *pEEThreadDebuggerFilterContextOffset = Thread::GetOffsetOfDebuggerFilterContext();
1409     *pEEThreadCantStopOffset = Thread::GetOffsetOfCantStop();
1410     *pEEThreadSteppingStateMask = Thread::TSNC_DebuggerIsStepping;
1411     *pEEMaxFrameValue = (DWORD)(size_t)FRAME_TOP; // <TODO> should this be size_t for 64bit?</TODO>
1412     *pEEFrameNextOffset = Frame::GetOffsetOfNextLink();
1413     *pEEIsManagedExceptionStateMask = Thread::TSNC_DebuggerIsManagedException;
1414 }
1415
1416 void EEDbgInterfaceImpl::DebuggerModifyingLogSwitch (int iNewLevel, 
1417                                                      const WCHAR *pLogSwitchName)
1418 {
1419     CONTRACTL
1420     {
1421         SO_NOT_MAINLINE;
1422         THROWS;
1423         GC_NOTRIGGER;
1424     }
1425     CONTRACTL_END;
1426 }
1427
1428
1429 HRESULT EEDbgInterfaceImpl::SetIPFromSrcToDst(Thread *pThread,
1430                                               SLOT addrStart,      
1431                                               DWORD offFrom,        
1432                                               DWORD offTo,          
1433                                               bool fCanSetIPOnly,   
1434                                               PREGDISPLAY pReg,
1435                                               PCONTEXT pCtx,
1436                                               void *pDji,
1437                                               EHRangeTree *pEHRT)
1438 {
1439     CONTRACTL
1440     {
1441         SO_NOT_MAINLINE;
1442         THROWS;
1443         GC_TRIGGERS;
1444     }
1445     CONTRACTL_END;
1446
1447     return ::SetIPFromSrcToDst(pThread,
1448                                addrStart,      
1449                                offFrom,        
1450                                offTo,          
1451                                fCanSetIPOnly,   
1452                                pReg,
1453                                pCtx,
1454                                pDji,
1455                                pEHRT);
1456
1457 }
1458
1459 void EEDbgInterfaceImpl::SetDebugState(Thread *pThread, 
1460                                        CorDebugThreadState state)
1461 {
1462     CONTRACTL
1463     {
1464         SO_NOT_MAINLINE;
1465         NOTHROW;
1466         GC_NOTRIGGER;
1467         PRECONDITION(CheckPointer(pThread));
1468     }
1469     CONTRACTL_END;
1470     
1471     _ASSERTE(state == THREAD_SUSPEND || state == THREAD_RUN);
1472
1473     LOG((LF_CORDB,LL_INFO10000,"EEDbg:Setting thread 0x%x (ID:0x%x) to 0x%x\n", pThread, pThread->GetThreadId(), state));
1474
1475     if (state == THREAD_SUSPEND)
1476     {
1477         pThread->SetThreadStateNC(Thread::TSNC_DebuggerUserSuspend);
1478     }
1479     else
1480     {
1481         pThread->ResetThreadStateNC(Thread::TSNC_DebuggerUserSuspend);
1482     }
1483 }
1484
1485 void EEDbgInterfaceImpl::SetAllDebugState(Thread *et, 
1486                                           CorDebugThreadState state)
1487 {
1488     CONTRACTL
1489     {
1490         SO_NOT_MAINLINE;
1491         NOTHROW;
1492         GC_NOTRIGGER;
1493     }
1494     CONTRACTL_END;
1495     
1496     Thread *pThread = NULL;
1497
1498     while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
1499     {
1500         if (pThread != et)
1501         {
1502             SetDebugState(pThread, state);
1503         }
1504     }
1505 }
1506
1507 // This is pretty much copied from VM\COMSynchronizable's
1508 // INT32 __stdcall ThreadNative::GetThreadState, so propogate changes
1509 // to both functions
1510 // This just gets the user state from the EE's perspective (hence "partial").
1511 CorDebugUserState EEDbgInterfaceImpl::GetPartialUserState(Thread *pThread)
1512 {
1513     CONTRACTL
1514     {
1515         SO_NOT_MAINLINE;
1516         NOTHROW;
1517         GC_NOTRIGGER;
1518         PRECONDITION(CheckPointer(pThread));
1519     }
1520     CONTRACTL_END;
1521     
1522     Thread::ThreadState ts = pThread->GetSnapshotState();
1523     unsigned ret = 0;
1524
1525     if (ts & Thread::TS_Background)
1526     {
1527         ret |= (unsigned)USER_BACKGROUND;
1528     }
1529
1530     if (ts & Thread::TS_Unstarted)
1531     {
1532         ret |= (unsigned)USER_UNSTARTED;            
1533     }
1534
1535     // Don't report a StopRequested if the thread has actually stopped.
1536     if (ts & Thread::TS_Dead)
1537     {
1538         ret |= (unsigned)USER_STOPPED;           
1539     }
1540
1541     if (ts & Thread::TS_Interruptible)
1542     {
1543         ret |= (unsigned)USER_WAIT_SLEEP_JOIN;          
1544     }
1545
1546     // CoreCLR does not support user-requested thread suspension
1547     _ASSERTE(!(ts & Thread::TS_UserSuspendPending));
1548
1549     LOG((LF_CORDB,LL_INFO1000, "EEDbgII::GUS: thread 0x%x (id:0x%x)"
1550         " userThreadState is 0x%x\n", pThread, pThread->GetThreadId(), ret));
1551
1552     return (CorDebugUserState)ret;
1553 }
1554
1555 #endif // #ifndef DACCESS_COMPILE
1556
1557 #ifdef DACCESS_COMPILE
1558
1559 void
1560 EEDbgInterfaceImpl::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
1561 {
1562     DAC_ENUM_VTHIS();
1563 }
1564
1565 #endif
1566
1567 unsigned EEDbgInterfaceImpl::GetSizeForCorElementType(CorElementType etyp)
1568 {
1569     WRAPPER_NO_CONTRACT;
1570
1571     return (::GetSizeForCorElementType(etyp));
1572 }
1573
1574
1575 #ifndef DACCESS_COMPILE
1576 /*
1577  * ObjIsInstanceOf
1578  *
1579  * This method supplies the internal VM implementation of this method to the 
1580  * debugger left-side.
1581  *
1582  */
1583 BOOL EEDbgInterfaceImpl::ObjIsInstanceOf(Object *pElement, TypeHandle toTypeHnd)
1584 {
1585     WRAPPER_NO_CONTRACT;
1586
1587     return (::ObjIsInstanceOf(pElement, toTypeHnd));
1588 }
1589 #endif
1590     
1591 /*
1592  * ClearAllDebugInterfaceReferences
1593  *
1594  * This method is called by the debugging part of the runtime to notify
1595  * that the debugger resources are no longer valid and any internal references
1596  * to it must be null'ed out.
1597  *
1598  * Parameters:
1599  *   None.
1600  *
1601  * Returns:
1602  *   None.
1603  *
1604  */
1605 void EEDbgInterfaceImpl::ClearAllDebugInterfaceReferences()
1606 {
1607     LIMITED_METHOD_CONTRACT;
1608 }
1609
1610 #ifndef DACCESS_COMPILE
1611 #ifdef _DEBUG
1612 /*
1613  * ObjectRefFlush
1614  *
1615  * Flushes all debug tracking information for object referencing.
1616  *
1617  * Parameters:
1618  *   pThread - The target thread to flush object references of.
1619  *
1620  * Returns:
1621  *   None.
1622  *
1623  */
1624 void EEDbgInterfaceImpl::ObjectRefFlush(Thread *pThread)
1625 {
1626     WRAPPER_NO_CONTRACT;
1627
1628     Thread::ObjectRefFlush(pThread);
1629 }
1630 #endif
1631 #endif
1632
1633 #endif // DEBUGGING_SUPPORTED