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);
133 m_hr = CORDBG_E_OBJECT_NEUTERED;
136 //---------------------------------------------------------------------------------------
138 // Construction method for data-target
141 // machineInfo - (input) the IP address of the remote machine and the port number of the debugger proxy
142 // processId - (input) live OS process ID to build a data-target for.
143 // ppDataTarget - (output) new data-target instance. This gets addreffed.
149 // pid is for a process on the remote machine specified by the IP address in machineInfo
150 // Caller must release *ppDataTarget.
153 HRESULT BuildPlatformSpecificDataTarget(MachineInfo machineInfo,
155 ShimDataTarget ** ppDataTarget)
160 ShimRemoteDataTarget * pRemoteDataTarget = NULL;
161 DbgTransportTarget * pProxy = g_pDbgTransportTarget;
162 DbgTransportSession * pTransport = NULL;
164 hr = pProxy->GetTransportForProcess(processId, &pTransport, &hDummy);
170 if (!pTransport->WaitForSessionToOpen(10000))
172 hr = CORDBG_E_TIMEOUT;
176 pRemoteDataTarget = new (nothrow) ShimRemoteDataTarget(processId, pProxy, pTransport);
177 if (pRemoteDataTarget == NULL)
183 _ASSERTE(SUCCEEDED(hr));
184 *ppDataTarget = pRemoteDataTarget;
185 pRemoteDataTarget->AddRef(); // must addref out-parameters
190 if (pRemoteDataTarget != NULL)
192 // The ShimRemoteDataTarget has ownership of the proxy and the transport,
193 // so we don't need to clean them up here.
194 delete pRemoteDataTarget;
198 if (pTransport != NULL)
200 pProxy->ReleaseTransport(pTransport);
208 // impl of interface method ICorDebugDataTarget::GetPlatform
209 HRESULT STDMETHODCALLTYPE
210 ShimRemoteDataTarget::GetPlatform(
211 CorDebugPlatform *pPlatform)
214 #if defined(DBG_TARGET_X86)
215 *pPlatform = CORDB_PLATFORM_POSIX_X86;
216 #elif defined(DBG_TARGET_AMD64)
217 *pPlatform = CORDB_PLATFORM_POSIX_AMD64;
218 #elif defined(DBG_TARGET_ARM)
219 *pPlatform = CORDB_PLATFORM_POSIX_ARM;
220 #elif defined(DBG_TARGET_ARM64)
221 *pPlatform = CORDB_PLATFORM_POSIX_ARM64;
223 #error Unknown Processor.
226 #if defined(DBG_TARGET_X86)
227 *pPlatform = CORDB_PLATFORM_WINDOWS_X86;
228 #elif defined(DBG_TARGET_AMD64)
229 *pPlatform = CORDB_PLATFORM_WINDOWS_AMD64;
230 #elif defined(DBG_TARGET_ARM)
231 *pPlatform = CORDB_PLATFORM_WINDOWS_ARM;
232 #elif defined(DBG_TARGET_ARM64)
233 *pPlatform = CORDB_PLATFORM_WINDOWS_ARM64;
235 #error Unknown Processor.
242 // impl of interface method ICorDebugDataTarget::ReadVirtual
243 HRESULT STDMETHODCALLTYPE
244 ShimRemoteDataTarget::ReadVirtual(
245 CORDB_ADDRESS address,
247 ULONG32 cbRequestSize,
250 ReturnFailureIfStateNotOk();
253 hr = m_pTransport->ReadMemory(reinterpret_cast<BYTE *>(CORDB_ADDRESS_TO_PTR(address)),
258 *pcbRead = (SUCCEEDED(hr) ? cbRequestSize : 0);
263 // impl of interface method ICorDebugMutableDataTarget::WriteVirtual
264 HRESULT STDMETHODCALLTYPE
265 ShimRemoteDataTarget::WriteVirtual(
266 CORDB_ADDRESS pAddress,
267 const BYTE * pBuffer,
268 ULONG32 cbRequestSize)
270 ReturnFailureIfStateNotOk();
273 hr = m_pTransport->WriteMemory(reinterpret_cast<BYTE *>(CORDB_ADDRESS_TO_PTR(pAddress)),
274 const_cast<BYTE *>(pBuffer),
279 // impl of interface method ICorDebugMutableDataTarget::GetThreadContext
280 HRESULT STDMETHODCALLTYPE
281 ShimRemoteDataTarget::GetThreadContext(
283 ULONG32 contextFlags,
287 ReturnFailureIfStateNotOk();
289 // GetThreadContext() is currently not implemented in ShimRemoteDataTarget, which is used with our pipe transport
290 // (FEATURE_DBGIPC_TRANSPORT_DI). Pipe transport is used on POSIX system, but occasionally we can turn it on for Windows for testing,
291 // and then we'd like to have same behavior as on POSIX system (zero context).
293 // 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
294 // thread handle. The function to do the conversion is OpenThread(), which is not implemented in PAL. Even if we had a handle, PAL implementation
295 // of GetThreadContext() is very limited and doesn't work when we're not attached with ptrace.
296 // Instead, we just zero out the seed CONTEXT for the stackwalk. This tells the stackwalker to
297 // start the stackwalk with the first explicit frame. This won't work when we do native debugging,
298 // but that won't happen on the POSIX systems since they don't support native debugging.
299 ZeroMemory(pContext, contextSize);
303 // impl of interface method ICorDebugMutableDataTarget::SetThreadContext
304 HRESULT STDMETHODCALLTYPE
305 ShimRemoteDataTarget::SetThreadContext(
308 const BYTE * pContext)
310 ReturnFailureIfStateNotOk();
312 // ICorDebugDataTarget::GetThreadContext() and ICorDebugDataTarget::SetThreadContext() are currently only
313 // required for interop-debugging and inspection of floating point registers, both of which are not
314 // implemented on Mac.
315 _ASSERTE(!"The remote data target doesn't know how to set a thread's CONTEXT.");
319 // Public implementation of ICorDebugMutableDataTarget::ContinueStatusChanged
320 HRESULT STDMETHODCALLTYPE
321 ShimRemoteDataTarget::ContinueStatusChanged(
323 CORDB_CONTINUE_STATUS dwContinueStatus)
325 ReturnFailureIfStateNotOk();
327 _ASSERTE(!"ShimRemoteDataTarget::ContinueStatusChanged() is called unexpectedly");
328 if (m_fpContinueStatusChanged != NULL)
330 return m_fpContinueStatusChanged(m_pContinueStatusChangedUserData, dwThreadId, dwContinueStatus);