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 //*****************************************************************************
7 // File: ShimRemoteDataTarget.cpp
9 //*****************************************************************************
18 #include "shimdatatarget.h"
20 #include "dbgtransportsession.h"
21 #include "dbgtransportmanager.h"
24 class ShimRemoteDataTarget : public ShimDataTarget
27 ShimRemoteDataTarget(DWORD processId, DbgTransportTarget * pProxy, DbgTransportSession * pTransport);
29 virtual ~ShimRemoteDataTarget();
31 virtual void Dispose();
34 // ICorDebugMutableDataTarget.
37 virtual HRESULT STDMETHODCALLTYPE GetPlatform(
38 CorDebugPlatform *pPlatform);
40 virtual HRESULT STDMETHODCALLTYPE ReadVirtual(
41 CORDB_ADDRESS address,
46 virtual HRESULT STDMETHODCALLTYPE WriteVirtual(
47 CORDB_ADDRESS address,
51 virtual HRESULT STDMETHODCALLTYPE GetThreadContext(
57 virtual HRESULT STDMETHODCALLTYPE SetThreadContext(
60 const BYTE * context);
62 virtual HRESULT STDMETHODCALLTYPE ContinueStatusChanged(
64 CORDB_CONTINUE_STATUS dwContinueStatus);
66 virtual HRESULT STDMETHODCALLTYPE VirtualUnwind(
67 DWORD threadId, ULONG32 contextSize, PBYTE context);
70 DbgTransportTarget * m_pProxy;
71 DbgTransportSession * m_pTransport;
75 // Helper macro to check for failure conditions at the start of data-target methods.
76 #define ReturnFailureIfStateNotOk() \
82 //---------------------------------------------------------------------------------------
84 // This is the ctor for ShimRemoteDataTarget.
87 // processId - pid of live process on the remote machine
88 // pProxy - connection to the debugger proxy
89 // pTransport - connection to the debuggee process
92 ShimRemoteDataTarget::ShimRemoteDataTarget(DWORD processId,
93 DbgTransportTarget * pProxy,
94 DbgTransportSession * pTransport)
98 m_processId = processId;
100 m_pTransport = pTransport;
104 m_fpContinueStatusChanged = NULL;
105 m_pContinueStatusChangedUserData = NULL;
108 //---------------------------------------------------------------------------------------
110 // dtor for ShimRemoteDataTarget
113 ShimRemoteDataTarget::~ShimRemoteDataTarget()
118 //---------------------------------------------------------------------------------------
120 // Dispose all resources and neuter the object.
123 // Release all resources (such as the connections to the debugger proxy and the debuggee process).
124 // May be called multiple times.
125 // All other non-trivial APIs (eg, not IUnknown) will fail after this.
128 void ShimRemoteDataTarget::Dispose()
130 if (m_pTransport != NULL)
132 m_pProxy->ReleaseTransport(m_pTransport);
136 m_hr = CORDBG_E_OBJECT_NEUTERED;
139 //---------------------------------------------------------------------------------------
141 // Construction method for data-target
144 // machineInfo - (input) the IP address of the remote machine and the port number of the debugger proxy
145 // processId - (input) live OS process ID to build a data-target for.
146 // ppDataTarget - (output) new data-target instance. This gets addreffed.
152 // pid is for a process on the remote machine specified by the IP address in machineInfo
153 // Caller must release *ppDataTarget.
156 HRESULT BuildPlatformSpecificDataTarget(MachineInfo machineInfo,
158 ShimDataTarget ** ppDataTarget)
163 ShimRemoteDataTarget * pRemoteDataTarget = NULL;
164 DbgTransportTarget * pProxy = g_pDbgTransportTarget;
165 DbgTransportSession * pTransport = NULL;
167 hr = pProxy->GetTransportForProcess(processId, &pTransport, &hDummy);
173 if (!pTransport->WaitForSessionToOpen(10000))
175 hr = CORDBG_E_TIMEOUT;
179 pRemoteDataTarget = new (nothrow) ShimRemoteDataTarget(processId, pProxy, pTransport);
180 if (pRemoteDataTarget == NULL)
186 _ASSERTE(SUCCEEDED(hr));
187 *ppDataTarget = pRemoteDataTarget;
188 pRemoteDataTarget->AddRef(); // must addref out-parameters
193 if (pRemoteDataTarget != NULL)
195 // The ShimRemoteDataTarget has ownership of the proxy and the transport,
196 // so we don't need to clean them up here.
197 delete pRemoteDataTarget;
201 if (pTransport != NULL)
203 pProxy->ReleaseTransport(pTransport);
211 // impl of interface method ICorDebugDataTarget::GetPlatform
212 HRESULT STDMETHODCALLTYPE
213 ShimRemoteDataTarget::GetPlatform(
214 CorDebugPlatform *pPlatform)
217 #if defined(DBG_TARGET_X86)
218 *pPlatform = CORDB_PLATFORM_POSIX_X86;
219 #elif defined(DBG_TARGET_AMD64)
220 *pPlatform = CORDB_PLATFORM_POSIX_AMD64;
221 #elif defined(DBG_TARGET_ARM)
222 *pPlatform = CORDB_PLATFORM_POSIX_ARM;
223 #elif defined(DBG_TARGET_ARM64)
224 *pPlatform = CORDB_PLATFORM_POSIX_ARM64;
226 #error Unknown Processor.
229 #if defined(DBG_TARGET_X86)
230 *pPlatform = CORDB_PLATFORM_WINDOWS_X86;
231 #elif defined(DBG_TARGET_AMD64)
232 *pPlatform = CORDB_PLATFORM_WINDOWS_AMD64;
233 #elif defined(DBG_TARGET_ARM)
234 *pPlatform = CORDB_PLATFORM_WINDOWS_ARM;
235 #elif defined(DBG_TARGET_ARM64)
236 *pPlatform = CORDB_PLATFORM_WINDOWS_ARM64;
238 #error Unknown Processor.
245 // impl of interface method ICorDebugDataTarget::ReadVirtual
246 HRESULT STDMETHODCALLTYPE
247 ShimRemoteDataTarget::ReadVirtual(
248 CORDB_ADDRESS address,
250 ULONG32 cbRequestSize,
253 ReturnFailureIfStateNotOk();
256 hr = m_pTransport->ReadMemory(reinterpret_cast<BYTE *>(CORDB_ADDRESS_TO_PTR(address)),
261 *pcbRead = (SUCCEEDED(hr) ? cbRequestSize : 0);
266 // impl of interface method ICorDebugMutableDataTarget::WriteVirtual
267 HRESULT STDMETHODCALLTYPE
268 ShimRemoteDataTarget::WriteVirtual(
269 CORDB_ADDRESS pAddress,
270 const BYTE * pBuffer,
271 ULONG32 cbRequestSize)
273 ReturnFailureIfStateNotOk();
276 hr = m_pTransport->WriteMemory(reinterpret_cast<BYTE *>(CORDB_ADDRESS_TO_PTR(pAddress)),
277 const_cast<BYTE *>(pBuffer),
282 // impl of interface method ICorDebugMutableDataTarget::GetThreadContext
283 HRESULT STDMETHODCALLTYPE
284 ShimRemoteDataTarget::GetThreadContext(
286 ULONG32 contextFlags,
290 ReturnFailureIfStateNotOk();
292 // GetThreadContext() is currently not implemented in ShimRemoteDataTarget, which is used with our pipe transport
293 // (FEATURE_DBGIPC_TRANSPORT_DI). Pipe transport is used on POSIX system, but occasionally we can turn it on for Windows for testing,
294 // and then we'd like to have same behavior as on POSIX system (zero context).
296 // We don't have a good way to implement GetThreadContext() in ShimRemoteDataTarget yet, because we have no way to convert a thread ID to a
297 // thread handle. The function to do the conversion is OpenThread(), which is not implemented in PAL. Even if we had a handle, PAL implementation
298 // of GetThreadContext() is very limited and doesn't work when we're not attached with ptrace.
299 // Instead, we just zero out the seed CONTEXT for the stackwalk. This tells the stackwalker to
300 // start the stackwalk with the first explicit frame. This won't work when we do native debugging,
301 // but that won't happen on the POSIX systems since they don't support native debugging.
302 ZeroMemory(pContext, contextSize);
306 // impl of interface method ICorDebugMutableDataTarget::SetThreadContext
307 HRESULT STDMETHODCALLTYPE
308 ShimRemoteDataTarget::SetThreadContext(
311 const BYTE * pContext)
313 ReturnFailureIfStateNotOk();
315 // ICorDebugDataTarget::GetThreadContext() and ICorDebugDataTarget::SetThreadContext() are currently only
316 // required for interop-debugging and inspection of floating point registers, both of which are not
317 // implemented on Mac.
318 _ASSERTE(!"The remote data target doesn't know how to set a thread's CONTEXT.");
322 // Public implementation of ICorDebugMutableDataTarget::ContinueStatusChanged
323 HRESULT STDMETHODCALLTYPE
324 ShimRemoteDataTarget::ContinueStatusChanged(
326 CORDB_CONTINUE_STATUS dwContinueStatus)
328 ReturnFailureIfStateNotOk();
330 _ASSERTE(!"ShimRemoteDataTarget::ContinueStatusChanged() is called unexpectedly");
331 if (m_fpContinueStatusChanged != NULL)
333 return m_fpContinueStatusChanged(m_pContinueStatusChangedUserData, dwThreadId, dwContinueStatus);
338 //---------------------------------------------------------------------------------------
340 // Unwind the stack to the next frame.
343 // context filled in with the next frame
345 HRESULT STDMETHODCALLTYPE
346 ShimRemoteDataTarget::VirtualUnwind(DWORD threadId, ULONG32 contextSize, PBYTE context)
348 return m_pTransport->VirtualUnwind(threadId, contextSize, context);