summaryrefslogtreecommitdiff
path: root/src/debug/di/shimremotedatatarget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug/di/shimremotedatatarget.cpp')
-rw-r--r--src/debug/di/shimremotedatatarget.cpp349
1 files changed, 349 insertions, 0 deletions
diff --git a/src/debug/di/shimremotedatatarget.cpp b/src/debug/di/shimremotedatatarget.cpp
new file mode 100644
index 0000000000..f971b0d65a
--- /dev/null
+++ b/src/debug/di/shimremotedatatarget.cpp
@@ -0,0 +1,349 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//*****************************************************************************
+
+//
+// File: ShimRemoteDataTarget.cpp
+//
+//*****************************************************************************
+#include "stdafx.h"
+#include "safewrap.h"
+
+#include "check.h"
+
+#include <limits.h>
+
+#include "shimpriv.h"
+#include "shimdatatarget.h"
+
+#include "dbgtransportsession.h"
+#include "dbgtransportmanager.h"
+
+
+class ShimRemoteDataTarget : public ShimDataTarget
+{
+public:
+ ShimRemoteDataTarget(DWORD processId, DbgTransportTarget * pProxy, DbgTransportSession * pTransport);
+
+ virtual ~ShimRemoteDataTarget();
+
+ virtual void Dispose();
+
+ //
+ // ICorDebugMutableDataTarget.
+ //
+
+ virtual HRESULT STDMETHODCALLTYPE GetPlatform(
+ CorDebugPlatform *pPlatform);
+
+ virtual HRESULT STDMETHODCALLTYPE ReadVirtual(
+ CORDB_ADDRESS address,
+ BYTE * pBuffer,
+ ULONG32 request,
+ ULONG32 *pcbRead);
+
+ virtual HRESULT STDMETHODCALLTYPE WriteVirtual(
+ CORDB_ADDRESS address,
+ const BYTE * pBuffer,
+ ULONG32 request);
+
+ virtual HRESULT STDMETHODCALLTYPE GetThreadContext(
+ DWORD dwThreadID,
+ ULONG32 contextFlags,
+ ULONG32 contextSize,
+ BYTE * context);
+
+ virtual HRESULT STDMETHODCALLTYPE SetThreadContext(
+ DWORD dwThreadID,
+ ULONG32 contextSize,
+ const BYTE * context);
+
+ virtual HRESULT STDMETHODCALLTYPE ContinueStatusChanged(
+ DWORD dwThreadId,
+ CORDB_CONTINUE_STATUS dwContinueStatus);
+
+ virtual HRESULT STDMETHODCALLTYPE VirtualUnwind(
+ DWORD threadId, ULONG32 contextSize, PBYTE context);
+
+private:
+ DbgTransportTarget * m_pProxy;
+ DbgTransportSession * m_pTransport;
+};
+
+
+// Helper macro to check for failure conditions at the start of data-target methods.
+#define ReturnFailureIfStateNotOk() \
+ if (m_hr != S_OK) \
+ { \
+ return m_hr; \
+ }
+
+//---------------------------------------------------------------------------------------
+//
+// This is the ctor for ShimRemoteDataTarget.
+//
+// Arguments:
+// processId - pid of live process on the remote machine
+// pProxy - connection to the debugger proxy
+// pTransport - connection to the debuggee process
+//
+
+ShimRemoteDataTarget::ShimRemoteDataTarget(DWORD processId,
+ DbgTransportTarget * pProxy,
+ DbgTransportSession * pTransport)
+{
+ m_ref = 0;
+
+ m_processId = processId;
+ m_pProxy = pProxy;
+ m_pTransport = pTransport;
+
+ m_hr = S_OK;
+
+ m_fpContinueStatusChanged = NULL;
+ m_pContinueStatusChangedUserData = NULL;
+}
+
+//---------------------------------------------------------------------------------------
+//
+// dtor for ShimRemoteDataTarget
+//
+
+ShimRemoteDataTarget::~ShimRemoteDataTarget()
+{
+ Dispose();
+}
+
+//---------------------------------------------------------------------------------------
+//
+// Dispose all resources and neuter the object.
+//
+// Notes:
+// Release all resources (such as the connections to the debugger proxy and the debuggee process).
+// May be called multiple times.
+// All other non-trivial APIs (eg, not IUnknown) will fail after this.
+//
+
+void ShimRemoteDataTarget::Dispose()
+{
+ if (m_pTransport != NULL)
+ {
+ m_pProxy->ReleaseTransport(m_pTransport);
+ }
+
+ m_pTransport = NULL;
+ m_hr = CORDBG_E_OBJECT_NEUTERED;
+}
+
+//---------------------------------------------------------------------------------------
+//
+// Construction method for data-target
+//
+// Arguments:
+// machineInfo - (input) the IP address of the remote machine and the port number of the debugger proxy
+// processId - (input) live OS process ID to build a data-target for.
+// ppDataTarget - (output) new data-target instance. This gets addreffed.
+//
+// Return Value:
+// S_OK on success.
+//
+// Assumptions:
+// pid is for a process on the remote machine specified by the IP address in machineInfo
+// Caller must release *ppDataTarget.
+//
+
+HRESULT BuildPlatformSpecificDataTarget(MachineInfo machineInfo,
+ DWORD processId,
+ ShimDataTarget ** ppDataTarget)
+{
+ HandleHolder hDummy;
+ HRESULT hr = E_FAIL;
+
+ ShimRemoteDataTarget * pRemoteDataTarget = NULL;
+ DbgTransportTarget * pProxy = g_pDbgTransportTarget;
+ DbgTransportSession * pTransport = NULL;
+
+ hr = pProxy->GetTransportForProcess(processId, &pTransport, &hDummy);
+ if (FAILED(hr))
+ {
+ goto Label_Exit;
+ }
+
+ if (!pTransport->WaitForSessionToOpen(10000))
+ {
+ hr = CORDBG_E_TIMEOUT;
+ goto Label_Exit;
+ }
+
+ pRemoteDataTarget = new (nothrow) ShimRemoteDataTarget(processId, pProxy, pTransport);
+ if (pRemoteDataTarget == NULL)
+ {
+ hr = E_OUTOFMEMORY;
+ goto Label_Exit;
+ }
+
+ _ASSERTE(SUCCEEDED(hr));
+ *ppDataTarget = pRemoteDataTarget;
+ pRemoteDataTarget->AddRef(); // must addref out-parameters
+
+Label_Exit:
+ if (FAILED(hr))
+ {
+ if (pRemoteDataTarget != NULL)
+ {
+ // The ShimRemoteDataTarget has ownership of the proxy and the transport,
+ // so we don't need to clean them up here.
+ delete pRemoteDataTarget;
+ }
+ else
+ {
+ if (pTransport != NULL)
+ {
+ pProxy->ReleaseTransport(pTransport);
+ }
+ }
+ }
+
+ return hr;
+}
+
+// impl of interface method ICorDebugDataTarget::GetPlatform
+HRESULT STDMETHODCALLTYPE
+ShimRemoteDataTarget::GetPlatform(
+ CorDebugPlatform *pPlatform)
+{
+#ifdef FEATURE_PAL
+ #if defined(DBG_TARGET_X86)
+ *pPlatform = CORDB_PLATFORM_POSIX_X86;
+ #elif defined(DBG_TARGET_AMD64)
+ *pPlatform = CORDB_PLATFORM_POSIX_AMD64;
+ #elif defined(DBG_TARGET_ARM)
+ *pPlatform = CORDB_PLATFORM_POSIX_ARM;
+ #elif defined(DBG_TARGET_ARM64)
+ *pPlatform = CORDB_PLATFORM_POSIX_ARM64;
+ #else
+ #error Unknown Processor.
+ #endif
+#else
+ #if defined(DBG_TARGET_X86)
+ *pPlatform = CORDB_PLATFORM_WINDOWS_X86;
+ #elif defined(DBG_TARGET_AMD64)
+ *pPlatform = CORDB_PLATFORM_WINDOWS_AMD64;
+ #elif defined(DBG_TARGET_ARM)
+ *pPlatform = CORDB_PLATFORM_WINDOWS_ARM;
+ #elif defined(DBG_TARGET_ARM64)
+ *pPlatform = CORDB_PLATFORM_WINDOWS_ARM64;
+ #else
+ #error Unknown Processor.
+ #endif
+#endif
+
+ return S_OK;
+}
+
+// impl of interface method ICorDebugDataTarget::ReadVirtual
+HRESULT STDMETHODCALLTYPE
+ShimRemoteDataTarget::ReadVirtual(
+ CORDB_ADDRESS address,
+ PBYTE pBuffer,
+ ULONG32 cbRequestSize,
+ ULONG32 *pcbRead)
+{
+ ReturnFailureIfStateNotOk();
+
+ HRESULT hr = E_FAIL;
+ hr = m_pTransport->ReadMemory(reinterpret_cast<BYTE *>(CORDB_ADDRESS_TO_PTR(address)),
+ pBuffer,
+ cbRequestSize);
+ if (pcbRead != NULL)
+ {
+ *pcbRead = (SUCCEEDED(hr) ? cbRequestSize : 0);
+ }
+ return hr;
+}
+
+// impl of interface method ICorDebugMutableDataTarget::WriteVirtual
+HRESULT STDMETHODCALLTYPE
+ShimRemoteDataTarget::WriteVirtual(
+ CORDB_ADDRESS pAddress,
+ const BYTE * pBuffer,
+ ULONG32 cbRequestSize)
+{
+ ReturnFailureIfStateNotOk();
+
+ HRESULT hr = E_FAIL;
+ hr = m_pTransport->WriteMemory(reinterpret_cast<BYTE *>(CORDB_ADDRESS_TO_PTR(pAddress)),
+ const_cast<BYTE *>(pBuffer),
+ cbRequestSize);
+ return hr;
+}
+
+// impl of interface method ICorDebugMutableDataTarget::GetThreadContext
+HRESULT STDMETHODCALLTYPE
+ShimRemoteDataTarget::GetThreadContext(
+ DWORD dwThreadID,
+ ULONG32 contextFlags,
+ ULONG32 contextSize,
+ BYTE * pContext)
+{
+ ReturnFailureIfStateNotOk();
+
+ // GetThreadContext() is currently not implemented in ShimRemoteDataTarget, which is used with our pipe transport
+ // (FEATURE_DBGIPC_TRANSPORT_DI). Pipe transport is used on POSIX system, but occasionally we can turn it on for Windows for testing,
+ // and then we'd like to have same behavior as on POSIX system (zero context).
+ //
+ // 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
+ // thread handle. The function to do the conversion is OpenThread(), which is not implemented in PAL. Even if we had a handle, PAL implementation
+ // of GetThreadContext() is very limited and doesn't work when we're not attached with ptrace.
+ // Instead, we just zero out the seed CONTEXT for the stackwalk. This tells the stackwalker to
+ // start the stackwalk with the first explicit frame. This won't work when we do native debugging,
+ // but that won't happen on the POSIX systems since they don't support native debugging.
+ ZeroMemory(pContext, contextSize);
+ return E_NOTIMPL;
+}
+
+// impl of interface method ICorDebugMutableDataTarget::SetThreadContext
+HRESULT STDMETHODCALLTYPE
+ShimRemoteDataTarget::SetThreadContext(
+ DWORD dwThreadID,
+ ULONG32 contextSize,
+ const BYTE * pContext)
+{
+ ReturnFailureIfStateNotOk();
+
+ // ICorDebugDataTarget::GetThreadContext() and ICorDebugDataTarget::SetThreadContext() are currently only
+ // required for interop-debugging and inspection of floating point registers, both of which are not
+ // implemented on Mac.
+ _ASSERTE(!"The remote data target doesn't know how to set a thread's CONTEXT.");
+ return E_NOTIMPL;
+}
+
+// Public implementation of ICorDebugMutableDataTarget::ContinueStatusChanged
+HRESULT STDMETHODCALLTYPE
+ShimRemoteDataTarget::ContinueStatusChanged(
+ DWORD dwThreadId,
+ CORDB_CONTINUE_STATUS dwContinueStatus)
+{
+ ReturnFailureIfStateNotOk();
+
+ _ASSERTE(!"ShimRemoteDataTarget::ContinueStatusChanged() is called unexpectedly");
+ if (m_fpContinueStatusChanged != NULL)
+ {
+ return m_fpContinueStatusChanged(m_pContinueStatusChangedUserData, dwThreadId, dwContinueStatus);
+ }
+ return E_NOTIMPL;
+}
+
+//---------------------------------------------------------------------------------------
+//
+// Unwind the stack to the next frame.
+//
+// Return Value:
+// context filled in with the next frame
+//
+HRESULT STDMETHODCALLTYPE
+ShimRemoteDataTarget::VirtualUnwind(DWORD threadId, ULONG32 contextSize, PBYTE context)
+{
+ return m_pTransport->VirtualUnwind(threadId, contextSize, context);
+}