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.
8 * COM+99 EE to Debugger Interface Implementation
13 #include "dbginterface.h"
14 #include "eedbginterfaceimpl.h"
15 #include "virtualcallstub.h"
16 #include "contractimpl.h"
18 #ifdef DEBUGGING_SUPPORTED
20 #ifndef DACCESS_COMPILE
23 // Cleanup any global data used by this interface.
25 void EEDbgInterfaceImpl::Terminate(void)
35 if (g_pEEDbgInterfaceImpl)
37 delete g_pEEDbgInterfaceImpl;
38 g_pEEDbgInterfaceImpl = NULL;
42 #endif // #ifndef DACCESS_COMPILE
44 Thread* EEDbgInterfaceImpl::GetThread(void)
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...
54 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
62 #ifndef DACCESS_COMPILE
64 StackWalkAction EEDbgInterfaceImpl::StackWalkFramesEx(Thread* pThread,
66 PSTACKWALKFRAMESCALLBACK pCallback,
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));
79 return pThread->StackWalkFramesEx(pRD, pCallback, pData, flags);
82 Frame *EEDbgInterfaceImpl::GetFrame(CrawlFrame *pCF)
89 PRECONDITION(CheckPointer(pCF));
90 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
94 RETURN pCF->GetFrame();
97 bool EEDbgInterfaceImpl::InitRegDisplay(Thread* pThread,
98 const PREGDISPLAY pRD,
107 PRECONDITION(CheckPointer(pThread));
108 PRECONDITION(CheckPointer(pRD));
111 PRECONDITION(CheckPointer(pctx));
116 return pThread->InitRegDisplay(pRD, pctx, validContext);
119 BOOL EEDbgInterfaceImpl::IsStringObject(Object* o)
126 PRECONDITION(CheckPointer(o));
130 return o->GetMethodTable() == g_pStringClass;
133 BOOL EEDbgInterfaceImpl::IsTypedReference(MethodTable* pMT)
140 PRECONDITION(CheckPointer(pMT));
144 return pMT == g_TypedReferenceMT;
147 WCHAR* EEDbgInterfaceImpl::StringObjectGetBuffer(StringObject* so)
154 PRECONDITION(CheckPointer(so));
158 return so->GetBuffer();
161 DWORD EEDbgInterfaceImpl::StringObjectGetStringLength(StringObject* so)
168 PRECONDITION(CheckPointer(so));
172 return so->GetStringLength();
175 void* EEDbgInterfaceImpl::GetObjectFromHandle(OBJECTHANDLE handle)
187 *((OBJECTREF *)&v) = *(OBJECTREF *)handle;
192 OBJECTHANDLE EEDbgInterfaceImpl::GetHandleFromObject(void *obj,
194 AppDomain *pAppDomain)
199 THROWS; // From CreateHandle
201 PRECONDITION(CheckPointer(pAppDomain));
209 oh = pAppDomain->CreateStrongHandle(ObjectToOBJECTREF((Object *)obj));
211 LOG((LF_CORDB, LL_INFO1000, "EEI::GHFO: Given objectref 0x%x,"
212 "created strong handle 0x%x!\n", obj, oh));
216 oh = pAppDomain->CreateLongWeakHandle( ObjectToOBJECTREF((Object *)obj));
218 LOG((LF_CORDB, LL_INFO1000, "EEI::GHFO: Given objectref 0x%x,"
219 "created long weak handle 0x%x!\n", obj, oh));
225 void EEDbgInterfaceImpl::DbgDestroyHandle(OBJECTHANDLE oh,
236 LOG((LF_CORDB, LL_INFO1000, "EEI::GHFO: Destroyed given handle 0x%x,"
237 "fStrong: 0x%x!\n", oh, fStrongNewRef));
241 DestroyStrongHandle(oh);
245 DestroyLongWeakHandle(oh);
250 OBJECTHANDLE EEDbgInterfaceImpl::GetThreadException(Thread *pThread)
256 PRECONDITION(CheckPointer(pThread));
260 OBJECTHANDLE oh = pThread->GetThrowableAsHandle();
267 // Return the last thrown object if there's no current throwable.
268 // This logic is similar to UpdateCurrentThrowable().
269 return pThread->m_LastThrownObjectHandle;
272 bool EEDbgInterfaceImpl::IsThreadExceptionNull(Thread *pThread)
279 PRECONDITION(CheckPointer(pThread));
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.
289 OBJECTHANDLE h = pThread->GetThrowableAsHandle();
295 void *pThrowable = *((void**)h);
297 return (pThrowable == NULL);
300 void EEDbgInterfaceImpl::ClearThreadException(Thread *pThread)
303 // If one day there is a continuable exception, then this will have to be
304 // implemented properly.
307 LIMITED_METHOD_CONTRACT;
310 bool EEDbgInterfaceImpl::StartSuspendForDebug(AppDomain *pAppDomain,
311 BOOL fHoldingThreadStoreLock)
321 LOG((LF_CORDB,LL_INFO1000, "EEDbgII:SSFD: start suspend on AD:0x%x\n",
324 bool result = Thread::SysStartSuspendForDebug(pAppDomain);
329 bool EEDbgInterfaceImpl::SweepThreadsForDebug(bool forceSync)
335 DISABLED(GC_TRIGGERS); // Called by unmanaged threads.
339 return Thread::SysSweepThreadsForDebug(forceSync);
342 void EEDbgInterfaceImpl::ResumeFromDebug(AppDomain *pAppDomain)
352 Thread::SysResumeFromDebug(pAppDomain);
355 void EEDbgInterfaceImpl::MarkThreadForDebugSuspend(Thread* pRuntimeThread)
362 PRECONDITION(CheckPointer(pRuntimeThread));
366 pRuntimeThread->MarkForDebugSuspend();
369 void EEDbgInterfaceImpl::MarkThreadForDebugStepping(Thread* pRuntimeThread,
377 PRECONDITION(CheckPointer(pRuntimeThread));
381 pRuntimeThread->MarkDebuggerIsStepping(onOff);
384 void EEDbgInterfaceImpl::SetThreadFilterContext(Thread *thread,
392 PRECONDITION(CheckPointer(thread));
396 thread->SetFilterContext(context);
399 CONTEXT *EEDbgInterfaceImpl::GetThreadFilterContext(Thread *thread)
405 PRECONDITION(CheckPointer(thread));
406 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
410 RETURN thread->GetFilterContext();
413 #ifdef FEATURE_INTEROP_DEBUGGING
415 VOID * EEDbgInterfaceImpl::GetThreadDebuggerWord()
417 return UnsafeTlsGetValue(g_debuggerWordTLSIndex);
420 void EEDbgInterfaceImpl::SetThreadDebuggerWord(VOID *dw)
422 UnsafeTlsSetValue(g_debuggerWordTLSIndex, dw);
427 BOOL EEDbgInterfaceImpl::IsManagedNativeCode(const BYTE *address)
430 return ExecutionManager::IsManagedCode((PCODE)address);
433 PCODE EEDbgInterfaceImpl::GetNativeCodeStartAddress(PCODE address)
436 _ASSERTE(address != NULL);
438 return ExecutionManager::GetCodeStartAddress(address);
441 MethodDesc *EEDbgInterfaceImpl::GetNativeCodeMethodDesc(const PCODE address)
443 CONTRACT(MethodDesc *)
447 PRECONDITION(address != NULL);
448 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
452 RETURN ExecutionManager::GetCodeMethodDesc(address);
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,
470 EECodeInfo codeInfo((PCODE)address);
472 if (codeInfo.IsValid())
474 GCInfoToken gcInfoToken = codeInfo.GetGCInfoToken();
476 if (codeInfo.GetCodeManager()->IsInPrologOrEpilog(codeInfo.GetRelOffset(), gcInfoToken, prologSize))
484 #endif // USE_GC_INFO_DECODER
487 // Given a collection of native offsets of a certain function, determine if each falls
488 // within an exception filter or handler.
490 void EEDbgInterfaceImpl::DetermineIfOffsetsInFilterOrHandler(const BYTE *functionAddress,
491 DebugOffsetToHandlerInfo *pOffsetToHandlerInfo,
492 unsigned offsetToHandlerInfoLength)
502 EECodeInfo codeInfo((PCODE)functionAddress);
504 if (!codeInfo.IsValid())
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);
517 for (ULONG i=0; i < EHCount; i++)
519 EE_ILEXCEPTION_CLAUSE EHClause;
520 codeInfo.GetJitManager()->GetNextEHClause(&pEnumState, &EHClause);
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++)
527 SIZE_T offs = pOffsetToHandlerInfo[j].offset;
529 // those with -1 indicate slots to skip
530 if (offs == (SIZE_T) -1)
534 // For a filter, the handler comes directly after it so check from start of filter
536 if (IsFilterHandler(&EHClause))
538 if (offs >= EHClause.FilterOffset && offs < EHClause.HandlerEndPC)
540 pOffsetToHandlerInfo[j].isInFilterOrHandler = TRUE;
543 // For anything else, only care about handler range
544 else if (offs >= EHClause.HandlerStartPC && offs < EHClause.HandlerEndPC)
546 pOffsetToHandlerInfo[j].isInFilterOrHandler = TRUE;
551 #endif // #ifndef DACCESS_COMPILE
553 void EEDbgInterfaceImpl::GetMethodRegionInfo(const PCODE pStart,
563 PRECONDITION(CheckPointer(pCold));
564 PRECONDITION(CheckPointer(hotSize));
565 PRECONDITION(CheckPointer(coldSize));
570 IJitManager::MethodRegionInfo methodRegionInfo = {NULL, 0, NULL, 0};
572 EECodeInfo codeInfo(pStart);
574 if (codeInfo.IsValid() != NULL)
576 codeInfo.GetMethodRegionInfo(&methodRegionInfo);
579 *pCold = methodRegionInfo.coldStartAddress;
580 *hotSize = methodRegionInfo.hotSize;
581 *coldSize = methodRegionInfo.coldSize;
584 #if defined(WIN64EXCEPTIONS)
585 DWORD EEDbgInterfaceImpl::GetFuncletStartOffsets(const BYTE *pStart, DWORD* pStartOffsets, DWORD dwLength)
591 PRECONDITION(CheckPointer(pStart));
595 EECodeInfo codeInfo((PCODE)pStart);
596 _ASSERTE(codeInfo.IsValid());
598 return codeInfo.GetJitManager()->GetFuncletStartOffsets(codeInfo.GetMethodToken(), pStartOffsets, dwLength);
601 StackFrame EEDbgInterfaceImpl::FindParentStackFrame(CrawlFrame* pCF)
607 PRECONDITION(CheckPointer(pCF));
611 #if defined(DACCESS_COMPILE)
615 #else // !DACCESS_COMPILE
616 return ExceptionTracker::FindParentStackFrameForStackWalk(pCF);
618 #endif // !DACCESS_COMPILE
620 #endif // WIN64EXCEPTIONS
622 #ifndef DACCESS_COMPILE
623 size_t EEDbgInterfaceImpl::GetFunctionSize(MethodDesc *pFD)
629 PRECONDITION(CheckPointer(pFD));
633 PCODE methodStart = pFD->GetNativeCode();
635 if (methodStart == NULL)
638 EECodeInfo codeInfo(methodStart);
639 GCInfoToken gcInfoToken = codeInfo.GetGCInfoToken();
640 return codeInfo.GetCodeManager()->GetFunctionSize(gcInfoToken);
642 #endif //!DACCESS_COMPILE
644 PCODE EEDbgInterfaceImpl::GetFunctionAddress(MethodDesc *pFD)
650 PRECONDITION(CheckPointer(pFD));
655 return pFD->GetNativeCode();
658 #ifndef DACCESS_COMPILE
660 void EEDbgInterfaceImpl::DisablePreemptiveGC(void)
666 DISABLED(GC_TRIGGERS); // Disabled because disabled in RareDisablePreemptiveGC()
670 ::GetThread()->DisablePreemptiveGC();
673 void EEDbgInterfaceImpl::EnablePreemptiveGC(void)
679 DISABLED(GC_TRIGGERS); // Disabled because disabled in RareEnablePreemptiveGC()
683 ::GetThread()->EnablePreemptiveGC();
686 bool EEDbgInterfaceImpl::IsPreemptiveGCDisabled(void)
696 return ::GetThread()->PreemptiveGCDisabled() != 0;
699 DWORD EEDbgInterfaceImpl::MethodDescIsStatic(MethodDesc *pFD)
705 PRECONDITION(CheckPointer(pFD));
709 return pFD->IsStatic();
712 #endif // #ifndef DACCESS_COMPILE
714 Module *EEDbgInterfaceImpl::MethodDescGetModule(MethodDesc *pFD)
720 PRECONDITION(CheckPointer(pFD));
721 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
725 RETURN pFD->GetModule();
728 #ifndef DACCESS_COMPILE
730 COR_ILMETHOD* EEDbgInterfaceImpl::MethodDescGetILHeader(MethodDesc *pFD)
732 CONTRACT(COR_ILMETHOD *)
736 PRECONDITION(CheckPointer(pFD));
737 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
743 RETURN pFD->GetILHeader();
749 ULONG EEDbgInterfaceImpl::MethodDescGetRVA(MethodDesc *pFD)
756 PRECONDITION(CheckPointer(pFD));
760 return pFD->GetRVA();
763 MethodDesc *EEDbgInterfaceImpl::FindLoadedMethodRefOrDef(Module* pModule,
766 CONTRACT(MethodDesc *)
770 PRECONDITION(CheckPointer(pModule));
771 POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
775 // Must have a MemberRef or a MethodDef
776 mdToken tkType = TypeFromToken(memberRef);
777 _ASSERTE((tkType == mdtMemberRef) || (tkType == mdtMethodDef));
779 if (tkType == mdtMemberRef)
781 RETURN pModule->LookupMemberRefAsMethod(memberRef);
784 RETURN pModule->LookupMethodDef(memberRef);
787 MethodDesc *EEDbgInterfaceImpl::LoadMethodDef(Module* pModule,
788 mdMethodDef methodDef,
789 DWORD numGenericArgs,
790 TypeHandle *pGenericArgs,
791 TypeHandle *pOwnerType)
793 CONTRACT(MethodDesc *)
797 PRECONDITION(CheckPointer(pModule));
798 POSTCONDITION(CheckPointer(RETVAL));
802 _ASSERTE(TypeFromToken(methodDef) == mdtMethodDef);
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.
809 DWORD numGenericClassArgs = 0;
810 TypeHandle *pGenericClassArgs = NULL;
811 DWORD nGenericMethodArgs = 0;
812 TypeHandle *pGenericMethodArgs = NULL;
813 mdTypeDef typeDef = 0;
817 BOOL forceRemotable = FALSE;
818 if (numGenericArgs != 0)
820 HRESULT hr = pModule->GetMDImport()->GetParentToken(methodDef, &typeDef);
822 COMPlusThrowHR(E_INVALIDARG);
824 TypeHandle thClass = LoadClass(pModule, typeDef);
825 _ASSERTE(!thClass.IsNull());
827 numGenericClassArgs = thClass.GetNumGenericArgs();
828 if (numGenericArgs < numGenericClassArgs)
830 COMPlusThrowHR(COR_E_TARGETPARAMCOUNT);
832 pGenericClassArgs = (numGenericClassArgs > 0) ? pGenericArgs : NULL;
833 nGenericMethodArgs = (numGenericArgs >= numGenericClassArgs) ? (numGenericArgs - numGenericClassArgs) : 0;
834 pGenericMethodArgs = (nGenericMethodArgs > 0) ? (pGenericArgs + numGenericClassArgs) : NULL;
836 #ifdef FEATURE_COMINTEROP
837 if (numGenericClassArgs > 0)
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);
843 #endif // FEATURE_COMINTEROP
846 MethodDesc *pRes = MemberLoader::GetMethodDescFromMethodDef(pModule,
848 Instantiation(pGenericClassArgs, numGenericClassArgs),
849 Instantiation(pGenericMethodArgs, nGenericMethodArgs),
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)
857 if (numGenericClassArgs != 0)
859 if (thOwner.IsNull())
860 *pOwnerType = ClassLoader::LoadGenericInstantiationThrowing(pModule, typeDef, Instantiation(pGenericClassArgs, numGenericClassArgs));
862 *pOwnerType = thOwner;
866 *pOwnerType = TypeHandle(pRes->GetMethodTable());
874 TypeHandle EEDbgInterfaceImpl::FindLoadedClass(Module *pModule,
875 mdTypeDef classToken)
881 PRECONDITION(CheckPointer(pModule));
885 RETURN ClassLoader::LookupTypeDefOrRefInModule(pModule, classToken);
889 TypeHandle EEDbgInterfaceImpl::FindLoadedInstantiation(Module *pModule,
894 // Lookup operations run the class loader in non-load mode.
895 ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
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);
902 return ClassLoader::LoadGenericInstantiationThrowing(pModule, typeDef, Instantiation(inst, ntypars),
903 ClassLoader::DontLoadTypes);
906 TypeHandle EEDbgInterfaceImpl::FindLoadedFnptrType(TypeHandle *inst,
909 // Lookup operations run the class loader in non-load mode.
910 ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
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);
921 TypeHandle EEDbgInterfaceImpl::FindLoadedPointerOrByrefType(CorElementType et,
924 // Lookup operations run the class loader in non-load mode.
925 ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
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);
935 TypeHandle EEDbgInterfaceImpl::FindLoadedArrayType(CorElementType et,
939 // Lookup operations run the class loader in non-load mode.
940 ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
942 if (elemtype.IsNull())
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 );
954 TypeHandle EEDbgInterfaceImpl::FindLoadedElementType(CorElementType et)
956 // Lookup operations run the class loader in non-load mode.
957 ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
959 MethodTable *m = MscorlibBinder::GetElementType(et);
961 return TypeHandle(m);
964 TypeHandle EEDbgInterfaceImpl::LoadClass(Module *pModule,
965 mdTypeDef classToken)
971 PRECONDITION(CheckPointer(pModule));
975 RETURN ClassLoader::LoadTypeDefOrRefThrowing(pModule, classToken,
976 ClassLoader::ThrowIfNotFound,
977 ClassLoader::PermitUninstDefOrRef);
981 TypeHandle EEDbgInterfaceImpl::LoadInstantiation(Module *pModule,
990 PRECONDITION(CheckPointer(pModule));
994 RETURN ClassLoader::LoadGenericInstantiationThrowing(pModule, typeDef, Instantiation(inst, ntypars));
997 TypeHandle EEDbgInterfaceImpl::LoadArrayType(CorElementType et,
1001 CONTRACT(TypeHandle)
1008 if (elemtype.IsNull())
1009 RETURN TypeHandle();
1011 RETURN ClassLoader::LoadArrayTypeThrowing(elemtype, et, rank);
1014 TypeHandle EEDbgInterfaceImpl::LoadPointerOrByrefType(CorElementType et,
1015 TypeHandle elemtype)
1025 return ClassLoader::LoadPointerOrByrefTypeThrowing(et, elemtype);
1028 TypeHandle EEDbgInterfaceImpl::LoadFnptrType(TypeHandle *inst,
1039 /* @TODO : CALLCONV? */
1040 return ClassLoader::LoadFnptrTypeThrowing(0, ntypars, inst);
1043 TypeHandle EEDbgInterfaceImpl::LoadElementType(CorElementType et)
1053 MethodTable *m = MscorlibBinder::GetElementType(et);
1057 return TypeHandle();
1060 return TypeHandle(m);
1064 HRESULT EEDbgInterfaceImpl::GetMethodImplProps(Module *pModule,
1074 PRECONDITION(CheckPointer(pModule));
1078 return pModule->GetMDImport()->GetMethodImplProps(tk, pRVA, pImplFlags);
1081 HRESULT EEDbgInterfaceImpl::GetParentToken(Module *pModule,
1083 mdToken *pParentToken)
1090 PRECONDITION(CheckPointer(pModule));
1094 return pModule->GetMDImport()->GetParentToken(tk, pParentToken);
1097 void EEDbgInterfaceImpl::MarkDebuggerAttached(void)
1107 g_CORDebuggerControlFlags |= DBCF_ATTACHED;
1108 g_CORDebuggerControlFlags &= ~DBCF_PENDING_ATTACH;
1111 void EEDbgInterfaceImpl::MarkDebuggerUnattached(void)
1121 g_CORDebuggerControlFlags &= ~DBCF_ATTACHED;
1125 #ifdef EnC_SUPPORTED
1127 // Apply an EnC edit to the specified module
1128 HRESULT EEDbgInterfaceImpl::EnCApplyChanges(EditAndContinueModule *pModule,
1134 LOG((LF_ENC, LL_INFO100, "EncApplyChanges\n"));
1139 DISABLED(GC_TRIGGERS);
1140 PRECONDITION(CheckPointer(pModule));
1144 return pModule->ApplyEditAndContinue(cbMetadata, pMetadata, cbIL, pIL);
1147 // Remap execution to the latest version of an edited method
1148 // This function should never return.
1149 void EEDbgInterfaceImpl::ResumeInUpdatedFunction(EditAndContinueModule *pModule,
1151 void *debuggerFuncHandle,
1159 DISABLED(GC_TRIGGERS);
1160 PRECONDITION(CheckPointer(pModule));
1164 pModule->ResumeInUpdatedFunction(pFD,
1170 #endif // EnC_SUPPORTED
1172 bool EEDbgInterfaceImpl::CrawlFrameIsGcSafe(CrawlFrame *pCF)
1180 PRECONDITION(CheckPointer(pCF));
1184 return pCF->IsGcSafe();
1187 bool EEDbgInterfaceImpl::IsStub(const BYTE *ip)
1197 // IsStub will catch any exceptions and return false.
1198 return StubManager::IsStub((PCODE) ip) != FALSE;
1201 #endif // #ifndef DACCESS_COMPILE
1204 bool EEDbgInterfaceImpl::DetectHandleILStubs(Thread *thread)
1213 return thread->DetectHandleILStubsForDebugger();
1216 bool EEDbgInterfaceImpl::TraceStub(const BYTE *ip,
1217 TraceDestination *trace)
1219 #ifndef DACCESS_COMPILE
1228 return StubManager::TraceStub((PCODE) ip, trace) != FALSE;
1232 #endif // #ifndef DACCESS_COMPILE
1235 #ifndef DACCESS_COMPILE
1237 bool EEDbgInterfaceImpl::FollowTrace(TraceDestination *trace)
1247 return StubManager::FollowTrace(trace) != FALSE;
1250 bool EEDbgInterfaceImpl::TraceFrame(Thread *thread,
1253 TraceDestination *trace,
1260 DISABLED(GC_TRIGGERS); // This is not a bug - the debugger can call this on an un-managed thread.
1261 PRECONDITION(CheckPointer(frame));
1265 bool fResult = frame->TraceFrame(thread, fromPatch, trace, regs) != FALSE;
1268 StubManager::DbgWriteLog("Doing TraceFrame on frame=0x%p (fromPatch=%d), yeilds:\n", frame, fromPatch);
1271 SUPPRESS_ALLOCATION_ASSERTS_IN_THIS_SCOPE;
1274 StubManager::DbgWriteLog(" td=%S\n", trace->DbgToString(buffer));
1278 StubManager::DbgWriteLog(" false (this frame does not expect to call managed code).\n");
1284 bool EEDbgInterfaceImpl::TraceManager(Thread *thread,
1285 StubManager *stubManager,
1286 TraceDestination *trace,
1295 PRECONDITION(CheckPointer(stubManager));
1299 bool fResult = false;
1303 fResult = stubManager->TraceManager(thread, trace, context, pRetAddr) != FALSE;
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()");
1312 EX_END_CATCH(SwallowAllExceptions);
1315 StubManager::DbgWriteLog("Doing TraceManager on %s (0x%p) for IP=0x%p, yields:\n", stubManager->DbgGetName(), stubManager, GetIP(context));
1318 // Should never be on helper thread
1321 StubManager::DbgWriteLog(" td=%S\n", trace->DbgToString(buffer));
1325 StubManager::DbgWriteLog(" false (this stub does not expect to call managed code).\n");
1331 void EEDbgInterfaceImpl::EnableTraceCall(Thread *thread)
1338 PRECONDITION(CheckPointer(thread));
1342 thread->IncrementTraceCallCount();
1345 void EEDbgInterfaceImpl::DisableTraceCall(Thread *thread)
1352 PRECONDITION(CheckPointer(thread));
1356 thread->DecrementTraceCallCount();
1359 EXTERN_C UINT32 _tls_index;
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)
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));
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;
1416 void EEDbgInterfaceImpl::DebuggerModifyingLogSwitch (int iNewLevel,
1417 const WCHAR *pLogSwitchName)
1429 HRESULT EEDbgInterfaceImpl::SetIPFromSrcToDst(Thread *pThread,
1447 return ::SetIPFromSrcToDst(pThread,
1459 void EEDbgInterfaceImpl::SetDebugState(Thread *pThread,
1460 CorDebugThreadState state)
1467 PRECONDITION(CheckPointer(pThread));
1471 _ASSERTE(state == THREAD_SUSPEND || state == THREAD_RUN);
1473 LOG((LF_CORDB,LL_INFO10000,"EEDbg:Setting thread 0x%x (ID:0x%x) to 0x%x\n", pThread, pThread->GetThreadId(), state));
1475 if (state == THREAD_SUSPEND)
1477 pThread->SetThreadStateNC(Thread::TSNC_DebuggerUserSuspend);
1481 pThread->ResetThreadStateNC(Thread::TSNC_DebuggerUserSuspend);
1485 void EEDbgInterfaceImpl::SetAllDebugState(Thread *et,
1486 CorDebugThreadState state)
1496 Thread *pThread = NULL;
1498 while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
1502 SetDebugState(pThread, state);
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)
1518 PRECONDITION(CheckPointer(pThread));
1522 Thread::ThreadState ts = pThread->GetSnapshotState();
1525 if (ts & Thread::TS_Background)
1527 ret |= (unsigned)USER_BACKGROUND;
1530 if (ts & Thread::TS_Unstarted)
1532 ret |= (unsigned)USER_UNSTARTED;
1535 // Don't report a StopRequested if the thread has actually stopped.
1536 if (ts & Thread::TS_Dead)
1538 ret |= (unsigned)USER_STOPPED;
1541 if (ts & Thread::TS_Interruptible)
1543 ret |= (unsigned)USER_WAIT_SLEEP_JOIN;
1546 // CoreCLR does not support user-requested thread suspension
1547 _ASSERTE(!(ts & Thread::TS_UserSuspendPending));
1549 LOG((LF_CORDB,LL_INFO1000, "EEDbgII::GUS: thread 0x%x (id:0x%x)"
1550 " userThreadState is 0x%x\n", pThread, pThread->GetThreadId(), ret));
1552 return (CorDebugUserState)ret;
1555 #endif // #ifndef DACCESS_COMPILE
1557 #ifdef DACCESS_COMPILE
1560 EEDbgInterfaceImpl::EnumMemoryRegions(CLRDataEnumMemoryFlags flags)
1567 unsigned EEDbgInterfaceImpl::GetSizeForCorElementType(CorElementType etyp)
1569 WRAPPER_NO_CONTRACT;
1571 return (::GetSizeForCorElementType(etyp));
1575 #ifndef DACCESS_COMPILE
1579 * This method supplies the internal VM implementation of this method to the
1580 * debugger left-side.
1583 BOOL EEDbgInterfaceImpl::ObjIsInstanceOf(Object *pElement, TypeHandle toTypeHnd)
1585 WRAPPER_NO_CONTRACT;
1587 return (::ObjIsInstanceOf(pElement, toTypeHnd));
1592 * ClearAllDebugInterfaceReferences
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.
1605 void EEDbgInterfaceImpl::ClearAllDebugInterfaceReferences()
1607 LIMITED_METHOD_CONTRACT;
1610 #ifndef DACCESS_COMPILE
1615 * Flushes all debug tracking information for object referencing.
1618 * pThread - The target thread to flush object references of.
1624 void EEDbgInterfaceImpl::ObjectRefFlush(Thread *pThread)
1626 WRAPPER_NO_CONTRACT;
1628 Thread::ObjectRefFlush(pThread);
1633 #endif // DEBUGGING_SUPPORTED