@@ -7661,6 +7661,8 @@ HRESULT CordbProcess::GetRuntimeOffsets()
7661
7661
m_runtimeOffsets.m_debuggerWordTLSIndex));
7662
7662
#endif // FEATURE_INTEROP_DEBUGGING
7663
7663
7664
+ LOG((LF_CORDB, LL_INFO10000, " m_setThreadContextNeededAddr= 0x%p\n",
7665
+ m_runtimeOffsets.m_setThreadContextNeededAddr));
7664
7666
LOG((LF_CORDB, LL_INFO10000, " m_TLSIndex= 0x%08x\n",
7665
7667
m_runtimeOffsets.m_TLSIndex));
7666
7668
LOG((LF_CORDB, LL_INFO10000, " m_EEThreadStateOffset= 0x%08x\n",
@@ -7719,6 +7721,7 @@ HRESULT CordbProcess::GetRuntimeOffsets()
7719
7721
m_runtimeOffsets.m_signalHijackCompleteBPAddr,
7720
7722
m_runtimeOffsets.m_excepNotForRuntimeBPAddr,
7721
7723
m_runtimeOffsets.m_notifyRSOfSyncCompleteBPAddr,
7724
+ m_runtimeOffsets.m_setThreadContextNeededAddr,
7722
7725
};
7723
7726
7724
7727
const int NumFlares = ARRAY_SIZE(flares);
@@ -11152,7 +11155,162 @@ void CordbProcess::FilterClrNotification(
11152
11155
}
11153
11156
}
11154
11157
11158
+ #ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
11159
+ void CordbProcess::HandleSetThreadContextNeeded(DWORD dwThreadId)
11160
+ {
11161
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded\n"));
11162
+
11163
+ #if defined(TARGET_WINDOWS) && defined(TARGET_AMD64)
11164
+ HandleHolder hThread = OpenThread(
11165
+ THREAD_GET_CONTEXT | THREAD_SET_CONTEXT | THREAD_QUERY_INFORMATION | THREAD_SUSPEND_RESUME,
11166
+ FALSE, // thread handle is not inheritable.
11167
+ dwThreadId);
11168
+
11169
+ if (hThread == NULL)
11170
+ {
11171
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from OpenThread\n"));
11172
+ ThrowHR(E_UNEXPECTED);
11173
+ }
11174
+
11175
+ DWORD previousSuspendCount = ::SuspendThread(hThread);
11176
+ if (previousSuspendCount == (DWORD)-1)
11177
+ {
11178
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from SuspendThread\n"));
11179
+ ThrowHR(HRESULT_FROM_GetLastError());
11180
+ }
11181
+
11182
+ CONTEXT context = { 0 };
11183
+ context.ContextFlags = CONTEXT_FULL;
11184
+
11185
+ HRESULT hr = GetDataTarget()->GetThreadContext(dwThreadId, CONTEXT_FULL, sizeof(CONTEXT), reinterpret_cast<BYTE*> (&context));
11186
+ IfFailThrow(hr);
11187
+
11188
+ TADDR lsContextAddr = (TADDR)context.Rcx;
11189
+ DWORD contextSize = (DWORD)context.Rdx;
11190
+
11191
+ TADDR expectedRip = (TADDR)context.R8;
11192
+ TADDR expectedRsp = (TADDR)context.R9;
11193
+
11194
+ if (contextSize == 0 || contextSize > sizeof(CONTEXT) + 25000)
11195
+ {
11196
+ _ASSERTE(!"Corrupted HandleSetThreadContextNeeded message received");
11197
+
11198
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Corrupted HandleSetThreadContextNeeded message received\n"));
11199
+
11200
+ ThrowHR(E_UNEXPECTED);
11201
+ }
11202
+
11203
+ PCONTEXT pContext = (PCONTEXT)_alloca(contextSize);
11204
+ ULONG32 cbRead;
11205
+ hr = GetDataTarget()->ReadVirtual(lsContextAddr, reinterpret_cast<BYTE*>(pContext), contextSize, &cbRead);
11206
+ if (FAILED(hr))
11207
+ {
11208
+ _ASSERTE(!"ReadVirtual failed");
11209
+
11210
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - ReadVirtual (error: 0x%X).\n", hr));
11211
+
11212
+ ThrowHR(CORDBG_E_READVIRTUAL_FAILURE);
11213
+ }
11214
+
11215
+ if (cbRead != contextSize)
11216
+ {
11217
+ _ASSERTE(!"ReadVirtual context size mismatch");
11155
11218
11219
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - ReadVirtual context size mismatch\n"));
11220
+
11221
+ ThrowHR(ERROR_PARTIAL_COPY);
11222
+ }
11223
+
11224
+ if (pContext->Rip != expectedRip || pContext->Rsp != expectedRsp)
11225
+ {
11226
+ _ASSERTE(!"ReadVirtual unexpectedly returned mismatched Rip and Rsp registers");
11227
+
11228
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - ReadVirtual unexpectedly returned mismatched Rip and Rsp registers\n"));
11229
+
11230
+ ThrowHR(E_UNEXPECTED);
11231
+ }
11232
+
11233
+ // TODO: Ideally we would use ICorDebugMutableDataTarget::SetThreadContext however this API currently only handles the legacy context.
11234
+ // We should combine the following code with the shared implementation
11235
+
11236
+ // The initialize call should fail but return contextSize
11237
+ contextSize = 0;
11238
+ DWORD contextFlags = pContext->ContextFlags;
11239
+ BOOL success = InitializeContext(NULL, contextFlags, NULL, &contextSize);
11240
+
11241
+ if(success || GetLastError() != ERROR_INSUFFICIENT_BUFFER)
11242
+ {
11243
+ _ASSERTE(!"InitializeContext unexpectedly succeeded or didn't return ERROR_INSUFFICIENT_BUFFER");
11244
+
11245
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - InitializeContext unexpectedly succeeded or didn't return ERROR_INSUFFICIENT_BUFFER\n"));
11246
+
11247
+ ThrowHR(E_UNEXPECTED);
11248
+ }
11249
+
11250
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - InitializeContext ContextSize %d\n", contextSize));
11251
+
11252
+ PVOID pBuffer = _alloca(contextSize);
11253
+ PCONTEXT pFrameContext = NULL;
11254
+ success = InitializeContext(pBuffer, contextFlags, &pFrameContext, &contextSize);
11255
+ if (!success)
11256
+ {
11257
+ HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
11258
+ _ASSERTE(!"InitializeContext failed");
11259
+
11260
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from InitializeContext (error: 0x%X [%d]).\n", hr, GetLastError()));
11261
+
11262
+ ThrowHR(hr);
11263
+ }
11264
+
11265
+ _ASSERTE((BYTE*)pFrameContext == pBuffer);
11266
+
11267
+ success = CopyContext(pFrameContext, contextFlags, pContext);
11268
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - CopyContext=%s %d\n", success?"SUCCESS":"FAIL", GetLastError()));
11269
+ if (!success)
11270
+ {
11271
+ HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
11272
+ _ASSERTE(!"CopyContext failed");
11273
+
11274
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from CopyContext (error: 0x%X [%d]).\n", hr, GetLastError()));
11275
+
11276
+ ThrowHR(hr);
11277
+ }
11278
+
11279
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Set Thread Context - ID = 0x%X, SS enabled = %d\n", dwThreadId, /*(uint64_t)hThread,*/ (pContext->EFlags & 0x100) != 0));
11280
+
11281
+ DWORD lastError = 0;
11282
+
11283
+ success = ::SetThreadContext(hThread, pFrameContext);
11284
+ if (!success)
11285
+ {
11286
+ lastError = ::GetLastError();
11287
+ }
11288
+
11289
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Set Thread Context Completed: Success=%d GetLastError=%d hr=0x%X\n", success, lastError, HRESULT_FROM_WIN32(lastError)));
11290
+ _ASSERTE(success);
11291
+
11292
+ DWORD suspendCount = ::ResumeThread(hThread);
11293
+ if (suspendCount == (DWORD)-1)
11294
+ {
11295
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from ResumeThread\n"));
11296
+ ThrowHR(HRESULT_FROM_GetLastError());
11297
+ }
11298
+ if (suspendCount != previousSuspendCount + 1)
11299
+ {
11300
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from ResumeThread\n"));
11301
+ ThrowHR(E_UNEXPECTED);
11302
+ }
11303
+
11304
+ if (!success)
11305
+ {
11306
+ LOG((LF_CORDB, LL_INFO10000, "RS HandleSetThreadContextNeeded - Unexpected result from SetThreadContext\n"));
11307
+ ThrowHR(HRESULT_FROM_WIN32(lastError));
11308
+ }
11309
+ #else
11310
+ #error Platform not supported
11311
+ #endif
11312
+ }
11313
+ #endif // OUT_OF_PROCESS_SETTHREADCONTEXT
11156
11314
11157
11315
//
11158
11316
// If the thread has an unhandled managed exception, hijack it.
@@ -11377,7 +11535,15 @@ HRESULT CordbProcess::Filter(
11377
11535
11378
11536
// holder will invoke DeleteIPCEventHelper(pManagedEvent).
11379
11537
}
11538
+ #ifdef OUT_OF_PROCESS_SETTHREADCONTEXT
11539
+ else if (dwFirstChance && pRecord->ExceptionCode == STATUS_BREAKPOINT && pRecord->ExceptionAddress == m_runtimeOffsets.m_setThreadContextNeededAddr)
11540
+ {
11541
+ // this is a request to set the thread context out of process
11380
11542
11543
+ HandleSetThreadContextNeeded(dwThreadId);
11544
+ *pContinueStatus = DBG_CONTINUE;
11545
+ }
11546
+ #endif
11381
11547
}
11382
11548
PUBLIC_API_END(hr);
11383
11549
// we may not find the correct mscordacwks so fail gracefully
0 commit comments