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);
67 virtual HRESULT STDMETHODCALLTYPE VirtualUnwind(
68 DWORD threadId, ULONG32 contextSize, PBYTE context);
71 DbgTransportTarget * m_pProxy;
72 DbgTransportSession * m_pTransport;
76 // Helper macro to check for failure conditions at the start of data-target methods.
77 #define ReturnFailureIfStateNotOk() \
83 //---------------------------------------------------------------------------------------
85 // This is the ctor for ShimRemoteDataTarget.
88 // processId - pid of live process on the remote machine
89 // pProxy - connection to the debugger proxy
90 // pTransport - connection to the debuggee process
93 ShimRemoteDataTarget::ShimRemoteDataTarget(DWORD processId,
94 DbgTransportTarget * pProxy,
95 DbgTransportSession * pTransport)
99 m_processId = processId;
101 m_pTransport = pTransport;
105 m_fpContinueStatusChanged = NULL;
106 m_pContinueStatusChangedUserData = NULL;
109 //---------------------------------------------------------------------------------------
111 // dtor for ShimRemoteDataTarget
114 ShimRemoteDataTarget::~ShimRemoteDataTarget()
119 //---------------------------------------------------------------------------------------
121 // Dispose all resources and neuter the object.
124 // Release all resources (such as the connections to the debugger proxy and the debuggee process).
125 // May be called multiple times.
126 // All other non-trivial APIs (eg, not IUnknown) will fail after this.
129 void ShimRemoteDataTarget::Dispose()
131 if (m_pTransport != NULL)
133 m_pProxy->ReleaseTransport(m_pTransport);
137 m_hr = CORDBG_E_OBJECT_NEUTERED;
140 //---------------------------------------------------------------------------------------
142 // Construction method for data-target
145 // machineInfo - (input) the IP address of the remote machine and the port number of the debugger proxy
146 // processId - (input) live OS process ID to build a data-target for.
147 // ppDataTarget - (output) new data-target instance. This gets addreffed.
153 // pid is for a process on the remote machine specified by the IP address in machineInfo
154 // Caller must release *ppDataTarget.
157 HRESULT BuildPlatformSpecificDataTarget(MachineInfo machineInfo,
159 ShimDataTarget ** ppDataTarget)
164 ShimRemoteDataTarget * pRemoteDataTarget = NULL;
165 DbgTransportTarget * pProxy = g_pDbgTransportTarget;
166 DbgTransportSession * pTransport = NULL;
168 hr = pProxy->GetTransportForProcess(processId, &pTransport, &hDummy);
174 if (!pTransport->WaitForSessionToOpen(10000))
176 hr = CORDBG_E_TIMEOUT;
180 pRemoteDataTarget = new (nothrow) ShimRemoteDataTarget(processId, pProxy, pTransport);
181 if (pRemoteDataTarget == NULL)
187 _ASSERTE(SUCCEEDED(hr));
188 *ppDataTarget = pRemoteDataTarget;
189 pRemoteDataTarget->AddRef(); // must addref out-parameters
194 if (pRemoteDataTarget != NULL)
196 // The ShimRemoteDataTarget has ownership of the proxy and the transport,
197 // so we don't need to clean them up here.
198 delete pRemoteDataTarget;
202 if (pTransport != NULL)
204 pProxy->ReleaseTransport(pTransport);
212 // impl of interface method ICorDebugDataTarget::GetPlatform
213 HRESULT STDMETHODCALLTYPE
214 ShimRemoteDataTarget::GetPlatform(
215 CorDebugPlatform *pPlatform)
218 #if defined(DBG_TARGET_X86)
219 *pPlatform = CORDB_PLATFORM_POSIX_X86;
220 #elif defined(DBG_TARGET_AMD64)
221 *pPlatform = CORDB_PLATFORM_POSIX_AMD64;
222 #elif defined(DBG_TARGET_ARM)
223 *pPlatform = CORDB_PLATFORM_POSIX_ARM;
224 #elif defined(DBG_TARGET_ARM64)
225 *pPlatform = CORDB_PLATFORM_POSIX_ARM64;
227 #error Unknown Processor.
230 #if defined(DBG_TARGET_X86)
231 *pPlatform = CORDB_PLATFORM_WINDOWS_X86;
232 #elif defined(DBG_TARGET_AMD64)
233 *pPlatform = CORDB_PLATFORM_WINDOWS_AMD64;
234 #elif defined(DBG_TARGET_ARM)
235 *pPlatform = CORDB_PLATFORM_WINDOWS_ARM;
236 #elif defined(DBG_TARGET_ARM64)
237 *pPlatform = CORDB_PLATFORM_WINDOWS_ARM64;
239 #error Unknown Processor.
246 // impl of interface method ICorDebugDataTarget::ReadVirtual
247 HRESULT STDMETHODCALLTYPE
248 ShimRemoteDataTarget::ReadVirtual(
249 CORDB_ADDRESS address,
251 ULONG32 cbRequestSize,
254 ReturnFailureIfStateNotOk();
257 hr = m_pTransport->ReadMemory(reinterpret_cast<BYTE *>(CORDB_ADDRESS_TO_PTR(address)),
262 *pcbRead = (SUCCEEDED(hr) ? cbRequestSize : 0);
267 // impl of interface method ICorDebugMutableDataTarget::WriteVirtual
268 HRESULT STDMETHODCALLTYPE
269 ShimRemoteDataTarget::WriteVirtual(
270 CORDB_ADDRESS pAddress,
271 const BYTE * pBuffer,
272 ULONG32 cbRequestSize)
274 ReturnFailureIfStateNotOk();
277 hr = m_pTransport->WriteMemory(reinterpret_cast<BYTE *>(CORDB_ADDRESS_TO_PTR(pAddress)),
278 const_cast<BYTE *>(pBuffer),
283 // impl of interface method ICorDebugMutableDataTarget::GetThreadContext
284 HRESULT STDMETHODCALLTYPE
285 ShimRemoteDataTarget::GetThreadContext(
287 ULONG32 contextFlags,
291 ReturnFailureIfStateNotOk();
293 // GetThreadContext() is currently not implemented in ShimRemoteDataTarget, which is used with our pipe transport
294 // (FEATURE_DBGIPC_TRANSPORT_DI). Pipe transport is used on POSIX system, but occasionally we can turn it on for Windows for testing,
295 // and then we'd like to have same behavior as on POSIX system (zero context).
297 // 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
298 // thread handle. The function to do the conversion is OpenThread(), which is not implemented in PAL. Even if we had a handle, PAL implementation
299 // of GetThreadContext() is very limited and doesn't work when we're not attached with ptrace.
300 // Instead, we just zero out the seed CONTEXT for the stackwalk. This tells the stackwalker to
301 // start the stackwalk with the first explicit frame. This won't work when we do native debugging,
302 // but that won't happen on the POSIX systems since they don't support native debugging.
303 ZeroMemory(pContext, contextSize);
307 // impl of interface method ICorDebugMutableDataTarget::SetThreadContext
308 HRESULT STDMETHODCALLTYPE
309 ShimRemoteDataTarget::SetThreadContext(
312 const BYTE * pContext)
314 ReturnFailureIfStateNotOk();
316 // ICorDebugDataTarget::GetThreadContext() and ICorDebugDataTarget::SetThreadContext() are currently only
317 // required for interop-debugging and inspection of floating point registers, both of which are not
318 // implemented on Mac.
319 _ASSERTE(!"The remote data target doesn't know how to set a thread's CONTEXT.");
323 // Public implementation of ICorDebugMutableDataTarget::ContinueStatusChanged
324 HRESULT STDMETHODCALLTYPE
325 ShimRemoteDataTarget::ContinueStatusChanged(
327 CORDB_CONTINUE_STATUS dwContinueStatus)
329 ReturnFailureIfStateNotOk();
331 _ASSERTE(!"ShimRemoteDataTarget::ContinueStatusChanged() is called unexpectedly");
332 if (m_fpContinueStatusChanged != NULL)
334 return m_fpContinueStatusChanged(m_pContinueStatusChangedUserData, dwThreadId, dwContinueStatus);
339 //---------------------------------------------------------------------------------------
341 // Unwind the stack to the next frame.
344 // context filled in with the next frame
346 HRESULT STDMETHODCALLTYPE
347 ShimRemoteDataTarget::VirtualUnwind(DWORD threadId, ULONG32 contextSize, PBYTE context)
349 return m_pTransport->VirtualUnwind(threadId, contextSize, context);