2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
5 //*****************************************************************************
8 // File: ShimRemoteDataTarget.cpp
10 //*****************************************************************************
19 #include "shimdatatarget.h"
21 #include "dbgtransportsession.h"
22 #include "dbgtransportmanager.h"
25 class ShimRemoteDataTarget : public ShimDataTarget
28 ShimRemoteDataTarget(DWORD processId, DbgTransportTarget * pProxy, DbgTransportSession * pTransport);
30 virtual ~ShimRemoteDataTarget();
32 virtual void Dispose();
35 // ICorDebugMutableDataTarget.
38 virtual HRESULT STDMETHODCALLTYPE GetPlatform(
39 CorDebugPlatform *pPlatform);
41 virtual HRESULT STDMETHODCALLTYPE ReadVirtual(
42 CORDB_ADDRESS address,
47 virtual HRESULT STDMETHODCALLTYPE WriteVirtual(
48 CORDB_ADDRESS address,
52 virtual HRESULT STDMETHODCALLTYPE GetThreadContext(
58 virtual HRESULT STDMETHODCALLTYPE SetThreadContext(
61 const BYTE * context);
63 virtual HRESULT STDMETHODCALLTYPE ContinueStatusChanged(
65 CORDB_CONTINUE_STATUS dwContinueStatus);
68 DbgTransportTarget * m_pProxy;
69 DbgTransportSession * m_pTransport;
73 // Helper macro to check for failure conditions at the start of data-target methods.
74 #define ReturnFailureIfStateNotOk() \
80 //---------------------------------------------------------------------------------------
82 // This is the ctor for ShimRemoteDataTarget.
85 // processId - pid of live process on the remote machine
86 // pProxy - connection to the debugger proxy
87 // pTransport - connection to the debuggee process
90 ShimRemoteDataTarget::ShimRemoteDataTarget(DWORD processId,
91 DbgTransportTarget * pProxy,
92 DbgTransportSession * pTransport)
96 m_processId = processId;
98 m_pTransport = pTransport;
102 m_fpContinueStatusChanged = NULL;
103 m_pContinueStatusChangedUserData = NULL;
106 //---------------------------------------------------------------------------------------
108 // dtor for ShimRemoteDataTarget
111 ShimRemoteDataTarget::~ShimRemoteDataTarget()
116 //---------------------------------------------------------------------------------------
118 // Dispose all resources and neuter the object.
121 // Release all resources (such as the connections to the debugger proxy and the debuggee process).
122 // May be called multiple times.
123 // All other non-trivial APIs (eg, not IUnknown) will fail after this.
126 void ShimRemoteDataTarget::Dispose()
128 if (m_pTransport != NULL)
130 m_pProxy->ReleaseTransport(m_pTransport);
134 m_hr = CORDBG_E_OBJECT_NEUTERED;
137 //---------------------------------------------------------------------------------------
139 // Construction method for data-target
142 // machineInfo - (input) the IP address of the remote machine and the port number of the debugger proxy
143 // processId - (input) live OS process ID to build a data-target for.
144 // ppDataTarget - (output) new data-target instance. This gets addreffed.
150 // pid is for a process on the remote machine specified by the IP address in machineInfo
151 // Caller must release *ppDataTarget.
154 HRESULT BuildPlatformSpecificDataTarget(MachineInfo machineInfo,
156 ShimDataTarget ** ppDataTarget)
161 ShimRemoteDataTarget * pRemoteDataTarget = NULL;
162 DbgTransportTarget * pProxy = g_pDbgTransportTarget;
163 DbgTransportSession * pTransport = NULL;
165 hr = pProxy->GetTransportForProcess(processId, &pTransport, &hDummy);
171 if (!pTransport->WaitForSessionToOpen(10000))
173 hr = CORDBG_E_TIMEOUT;
177 pRemoteDataTarget = new (nothrow) ShimRemoteDataTarget(processId, pProxy, pTransport);
178 if (pRemoteDataTarget == NULL)
184 _ASSERTE(SUCCEEDED(hr));
185 *ppDataTarget = pRemoteDataTarget;
186 pRemoteDataTarget->AddRef(); // must addref out-parameters
191 if (pRemoteDataTarget != NULL)
193 // The ShimRemoteDataTarget has ownership of the proxy and the transport,
194 // so we don't need to clean them up here.
195 delete pRemoteDataTarget;
199 if (pTransport != NULL)
201 pProxy->ReleaseTransport(pTransport);
209 // impl of interface method ICorDebugDataTarget::GetPlatform
210 HRESULT STDMETHODCALLTYPE
211 ShimRemoteDataTarget::GetPlatform(
212 CorDebugPlatform *pPlatform)
215 #if defined(DBG_TARGET_X86)
216 *pPlatform = CORDB_PLATFORM_POSIX_X86;
217 #elif defined(DBG_TARGET_AMD64)
218 *pPlatform = CORDB_PLATFORM_POSIX_AMD64;
219 #elif defined(DBG_TARGET_ARM)
220 *pPlatform = CORDB_PLATFORM_POSIX_ARM;
221 #elif defined(DBG_TARGET_ARM64)
222 *pPlatform = CORDB_PLATFORM_POSIX_ARM64;
224 #error Unknown Processor.
227 #if defined(DBG_TARGET_X86)
228 *pPlatform = CORDB_PLATFORM_WINDOWS_X86;
229 #elif defined(DBG_TARGET_AMD64)
230 *pPlatform = CORDB_PLATFORM_WINDOWS_AMD64;
231 #elif defined(DBG_TARGET_ARM)
232 *pPlatform = CORDB_PLATFORM_WINDOWS_ARM;
233 #elif defined(DBG_TARGET_ARM64)
234 *pPlatform = CORDB_PLATFORM_WINDOWS_ARM64;
236 #error Unknown Processor.
243 // impl of interface method ICorDebugDataTarget::ReadVirtual
244 HRESULT STDMETHODCALLTYPE
245 ShimRemoteDataTarget::ReadVirtual(
246 CORDB_ADDRESS address,
248 ULONG32 cbRequestSize,
251 ReturnFailureIfStateNotOk();
254 hr = m_pTransport->ReadMemory(reinterpret_cast<BYTE *>(CORDB_ADDRESS_TO_PTR(address)),
259 *pcbRead = (SUCCEEDED(hr) ? cbRequestSize : 0);
264 // impl of interface method ICorDebugMutableDataTarget::WriteVirtual
265 HRESULT STDMETHODCALLTYPE
266 ShimRemoteDataTarget::WriteVirtual(
267 CORDB_ADDRESS pAddress,
268 const BYTE * pBuffer,
269 ULONG32 cbRequestSize)
271 ReturnFailureIfStateNotOk();
274 hr = m_pTransport->WriteMemory(reinterpret_cast<BYTE *>(CORDB_ADDRESS_TO_PTR(pAddress)),
275 const_cast<BYTE *>(pBuffer),
280 // impl of interface method ICorDebugMutableDataTarget::GetThreadContext
281 HRESULT STDMETHODCALLTYPE
282 ShimRemoteDataTarget::GetThreadContext(
284 ULONG32 contextFlags,
288 ReturnFailureIfStateNotOk();
290 // GetThreadContext() is currently not implemented in ShimRemoteDataTarget, which is used with our pipe transport
291 // (FEATURE_DBGIPC_TRANSPORT_DI). Pipe transport is used on POSIX system, but occasionally we can turn it on for Windows for testing,
292 // and then we'd like to have same behavior as on POSIX system (zero context).
294 // 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
295 // thread handle. The function to do the conversion is OpenThread(), which is not implemented in PAL. Even if we had a handle, PAL implementation
296 // of GetThreadContext() is very limited and doesn't work when we're not attached with ptrace.
297 // Instead, we just zero out the seed CONTEXT for the stackwalk. This tells the stackwalker to
298 // start the stackwalk with the first explicit frame. This won't work when we do native debugging,
299 // but that won't happen on the POSIX systems since they don't support native debugging.
300 ZeroMemory(pContext, contextSize);
304 // impl of interface method ICorDebugMutableDataTarget::SetThreadContext
305 HRESULT STDMETHODCALLTYPE
306 ShimRemoteDataTarget::SetThreadContext(
309 const BYTE * pContext)
311 ReturnFailureIfStateNotOk();
313 // ICorDebugDataTarget::GetThreadContext() and ICorDebugDataTarget::SetThreadContext() are currently only
314 // required for interop-debugging and inspection of floating point registers, both of which are not
315 // implemented on Mac.
316 _ASSERTE(!"The remote data target doesn't know how to set a thread's CONTEXT.");
320 // Public implementation of ICorDebugMutableDataTarget::ContinueStatusChanged
321 HRESULT STDMETHODCALLTYPE
322 ShimRemoteDataTarget::ContinueStatusChanged(
324 CORDB_CONTINUE_STATUS dwContinueStatus)
326 ReturnFailureIfStateNotOk();
328 _ASSERTE(!"ShimRemoteDataTarget::ContinueStatusChanged() is called unexpectedly");
329 if (m_fpContinueStatusChanged != NULL)
331 return m_fpContinueStatusChanged(m_pContinueStatusChangedUserData, dwThreadId, dwContinueStatus);