From: Andrew Au Date: Tue, 26 Jun 2018 17:31:07 +0000 (-0700) Subject: Hacking CordbProcess::GetThreadContext / SetThreadContext to retrieve/modify managed... X-Git-Tag: submit/tizen/20210909.063632~11030^2~3475 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=76569b21b8ba4e8ec6a55a39f80a767a31faeeaf;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Hacking CordbProcess::GetThreadContext / SetThreadContext to retrieve/modify managed ThreadContext Commit migrated from https://github.com/dotnet/coreclr/commit/f72bba95b01c790f92641b9d7d96bf23a014dd3e --- diff --git a/src/coreclr/src/debug/di/process.cpp b/src/coreclr/src/debug/di/process.cpp index 1ab0724..64446cd 100644 --- a/src/coreclr/src/debug/di/process.cpp +++ b/src/coreclr/src/debug/di/process.cpp @@ -6454,12 +6454,9 @@ HRESULT CordbProcess::GetThreadContext(DWORD threadID, ULONG32 contextSize, BYTE { PUBLIC_REENTRANT_API_ENTRY(this); FAIL_IF_NEUTERED(this); - FAIL_IF_MANAGED_ONLY(this); - - DT_CONTEXT * pContext; LOG((LF_CORDB, LL_INFO10000, "CP::GTC: thread=0x%x\n", threadID)); - RSLockHolder lockHolder(GetProcessLock()); + DT_CONTEXT * pContext; if (contextSize != sizeof(DT_CONTEXT)) { @@ -6471,21 +6468,52 @@ HRESULT CordbProcess::GetThreadContext(DWORD threadID, ULONG32 contextSize, BYTE VALIDATE_POINTER_TO_OBJECT_ARRAY(context, BYTE, contextSize, true, true); -#if !defined(FEATURE_INTEROP_DEBUGGING) - return E_NOTIMPL; -#else - // Find the unmanaged thread - CordbUnmanagedThread *ut = GetUnmanagedThread(threadID); - - if (ut == NULL) + if (this->IsInteropDebugging()) { - LOG((LF_CORDB, LL_INFO10000, "CP::GTC: thread=0x%x, thread id is invalid.\n", threadID)); + RSLockHolder lockHolder(GetProcessLock()); - return E_INVALIDARG; + // Find the unmanaged thread + CordbUnmanagedThread *ut = GetUnmanagedThread(threadID); + + if (ut == NULL) + { + LOG((LF_CORDB, LL_INFO10000, "CP::GTC: thread=0x%x, thread id is invalid.\n", threadID)); + + return E_INVALIDARG; + } + + return ut->GetThreadContext((DT_CONTEXT*)context); } + else + { + RSLockHolder ch(GetProcess()->GetStopGoLock()); + RSLockHolder lockHolder(GetProcessLock()); - return ut->GetThreadContext((DT_CONTEXT*)context); -#endif // FEATURE_INTEROP_DEBUGGING + HRESULT hr = S_OK; + EX_TRY + { + CordbThread* thread = this->TryLookupThreadByVolatileOSId(threadID); + if (thread == NULL) + { + LOG((LF_CORDB, LL_INFO10000, "CP::GTC: thread=0x%x, thread id is invalid.\n", threadID)); + + hr = E_INVALIDARG; + } + else + { + DT_CONTEXT* managedContext; + hr = thread->GetManagedContext(&managedContext); + *pContext = *managedContext; + } + } + EX_CATCH + { + hr = E_FAIL; + } + EX_END_CATCH(SwallowAllExceptions) + + return hr; + } } // Public implementation of ICorDebugProcess::SetThreadContext. @@ -6494,67 +6522,86 @@ HRESULT CordbProcess::GetThreadContext(DWORD threadID, ULONG32 contextSize, BYTE HRESULT CordbProcess::SetThreadContext(DWORD threadID, ULONG32 contextSize, BYTE context[]) { PUBLIC_REENTRANT_API_ENTRY(this); - FAIL_IF_MANAGED_ONLY(this); -#if !defined(FEATURE_INTEROP_DEBUGGING) - return E_NOTIMPL; -#else HRESULT hr = S_OK; - RSLockHolder lockHolder(GetProcessLock()); - - CordbUnmanagedThread *ut = NULL; + // @todo - could we look at the context flags and return E_INVALIDARG if they're bad? + FAIL_IF_NEUTERED(this); + VALIDATE_POINTER_TO_OBJECT_ARRAY(context, BYTE, contextSize, true, true); if (contextSize != sizeof(DT_CONTEXT)) { LOG((LF_CORDB, LL_INFO10000, "CP::STC: thread=0x%x, context size is invalid.\n", threadID)); - hr = E_INVALIDARG; - goto Label_Done; + return E_INVALIDARG; } - // @todo - could we look at the context flags and return E_INVALIDARG if they're bad? - FAIL_IF_NEUTERED(this); - VALIDATE_POINTER_TO_OBJECT_ARRAY(context, BYTE, contextSize, true, true); + DT_CONTEXT* pContext = (DT_CONTEXT*)context; - // Find the unmanaged thread - ut = GetUnmanagedThread(threadID); - - if (ut == NULL) + if (this->IsInteropDebugging()) { - LOG((LF_CORDB, LL_INFO10000, "CP::STC: thread=0x%x, thread is invalid.\n", threadID)); - hr = E_INVALIDARG; - goto Label_Done; - } + RSLockHolder lockHolder(GetProcessLock()); - hr = ut->SetThreadContext((DT_CONTEXT*)context); + CordbUnmanagedThread *ut = NULL; + // Find the unmanaged thread + ut = GetUnmanagedThread(threadID); - // Update the register set for the leaf-unmanaged chain so that it's consistent w/ the context. - // We may not necessarily be synchronized, and so these frames may be stale. Even so, no harm done. - if (SUCCEEDED(hr)) - { - // @dbgtodo stackwalk: this should all disappear with V3 stackwalker and getting rid of SetThreadContext. - EX_TRY + if (ut == NULL) { - // Find the managed thread. Returns NULL if thread is not managed. - // If we don't have a thread prveiously cached, then there's no state to update. - CordbThread * pThread = TryLookupThreadByVolatileOSId(threadID); + LOG((LF_CORDB, LL_INFO10000, "CP::STC: thread=0x%x, thread is invalid.\n", threadID)); + return E_INVALIDARG; + } - if (pThread != NULL) + hr = ut->SetThreadContext(pContext); + + // Update the register set for the leaf-unmanaged chain so that it's consistent w/ the context. + // We may not necessarily be synchronized, and so these frames may be stale. Even so, no harm done. + if (SUCCEEDED(hr)) + { + // @dbgtodo stackwalk: this should all disappear with V3 stackwalker and getting rid of SetThreadContext. + EX_TRY { - // In V2, we used to update the CONTEXT of the leaf chain if the chain is an unmanaged chain. - // In Arrowhead, we just force a cleanup of the stackwalk cache. This is a more correct - // thing to do anyway, since the CONTEXT being set could be anything. - pThread->CleanupStack(); + // Find the managed thread. Returns NULL if thread is not managed. + // If we don't have a thread prveiously cached, then there's no state to update. + CordbThread * pThread = TryLookupThreadByVolatileOSId(threadID); + + if (pThread != NULL) + { + // In V2, we used to update the CONTEXT of the leaf chain if the chain is an unmanaged chain. + // In Arrowhead, we just force a cleanup of the stackwalk cache. This is a more correct + // thing to do anyway, since the CONTEXT being set could be anything. + pThread->CleanupStack(); + } } + EX_CATCH_HRESULT(hr); } - EX_CATCH_HRESULT(hr); } + else + { + RSLockHolder ch(GetProcess()->GetStopGoLock()); + RSLockHolder lockHolder(GetProcessLock()); + + EX_TRY + { + CordbThread* thread = this->TryLookupThreadByVolatileOSId(threadID); + if (thread == NULL) + { + LOG((LF_CORDB, LL_INFO10000, "CP::GTC: thread=0x%x, thread id is invalid.\n", threadID)); -Label_Done: - return ErrWrapper(hr); + hr = E_INVALIDARG; + } -#endif // FEATURE_INTEROP_DEBUGGING + hr = thread->SetManagedContext(pContext); + } + EX_CATCH + { + hr = E_FAIL; + } + EX_END_CATCH(SwallowAllExceptions) + + + } + return hr; } diff --git a/src/coreclr/src/debug/ee/controller.cpp b/src/coreclr/src/debug/ee/controller.cpp index 5ae9a95..c4b2927 100644 --- a/src/coreclr/src/debug/ee/controller.cpp +++ b/src/coreclr/src/debug/ee/controller.cpp @@ -3017,15 +3017,15 @@ DPOSS_ACTION DebuggerController::DispatchPatchOrSingleStep(Thread *thread, CONTE reabort = thread->m_StateNC & Thread::TSNC_DebuggerReAbort; SENDIPCEVENT_END; - CONTEXT c; - c.ContextFlags = CONTEXT_DEBUG_REGISTERS; - thread->GetThreadContext(&c); - - context->Dr7 = c.Dr7; - context->Dr0 = c.Dr0; - context->Dr1 = c.Dr1; - context->Dr2 = c.Dr2; - context->Dr3 = c.Dr3; + // CONTEXT c; + // c.ContextFlags = CONTEXT_DEBUG_REGISTERS; + // thread->GetThreadContext(&c); + + // context->Dr7 = c.Dr7; + // context->Dr0 = c.Dr0; + // context->Dr1 = c.Dr1; + // context->Dr2 = c.Dr2; + // context->Dr3 = c.Dr3; if (!atSafePlace) g_pDebugger->DecThreadsAtUnsafePlaces();