diff options
Diffstat (limited to 'src/debug/daccess/datatargetadapter.cpp')
-rw-r--r-- | src/debug/daccess/datatargetadapter.cpp | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/src/debug/daccess/datatargetadapter.cpp b/src/debug/daccess/datatargetadapter.cpp new file mode 100644 index 0000000000..f2a1cc652a --- /dev/null +++ b/src/debug/daccess/datatargetadapter.cpp @@ -0,0 +1,255 @@ +// 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. +//***************************************************************************** +// DataTargetAdapter.cpp +// + +// +// implementation of compatibility adapter for ICLRDataTarget +//***************************************************************************** + +#include "stdafx.h" +#include "datatargetadapter.h" +#include <clrdata.h> +#include "dacimpl.h" + +#ifndef IMAGE_FILE_MACHINE_ARM64 +#define IMAGE_FILE_MACHINE_ARM64 0xAA64 // ARM64 Little-Endian +#endif + +// +// DataTargetAdaptor ctor +// +// Instantiate a DataTargetAdapter over the supplied legacy DataTarget interface. +// Takes a ref on the supplied interface and releases it in our dtor. +// +DataTargetAdapter::DataTargetAdapter(ICLRDataTarget * pLegacyTarget) : + m_ref(0), + m_pLegacyTarget(pLegacyTarget) +{ + m_pLegacyTarget->AddRef(); +} + +// +// DataTargetAdapter dtor +// +// Releases the underlying DataTarget interface +// +DataTargetAdapter::~DataTargetAdapter() +{ + m_pLegacyTarget->Release(); +} + +// Standard impl of IUnknown::QueryInterface +HRESULT STDMETHODCALLTYPE +DataTargetAdapter::QueryInterface( + REFIID interfaceId, + PVOID* pInterface) +{ + if (interfaceId == IID_IUnknown) + { + *pInterface = static_cast<IUnknown *>(static_cast<ICorDebugDataTarget *>(this)); + } + else if (interfaceId == IID_ICorDebugDataTarget) + { + *pInterface = static_cast<ICorDebugDataTarget *>(this); + } + else if (interfaceId == IID_ICorDebugMutableDataTarget) + { + // Note that we always implement the mutable interface, even though our underlying target + // may return E_NOTIMPL for all the functions on this interface. There is no reliable way + // to tell apriori whether an ICLRDataTarget instance supports writing or not. + *pInterface = static_cast<ICorDebugMutableDataTarget *>(this); + } + else + { + // For ICorDebugDataTarget4 and other interfaces directly implemented by the legacy data target. + return m_pLegacyTarget->QueryInterface(interfaceId, pInterface); + } + + AddRef(); + return S_OK; +} + +// Standard impl of IUnknown::AddRef +ULONG STDMETHODCALLTYPE +DataTargetAdapter::AddRef() +{ + LONG ref = InterlockedIncrement(&m_ref); + return ref; +} + +// Standard impl of IUnknown::Release +ULONG STDMETHODCALLTYPE +DataTargetAdapter::Release() +{ + SUPPORTS_DAC_HOST_ONLY; + LONG ref = InterlockedDecrement(&m_ref); + if (ref == 0) + { + delete this; + } + return ref; +} + +// impl of interface method ICorDebugDataTarget::GetPlatform +HRESULT STDMETHODCALLTYPE +DataTargetAdapter::GetPlatform( + CorDebugPlatform * pPlatform) +{ + SUPPORTS_DAC_HOST_ONLY; + + // Get the target machine type, and assume it's Windows + HRESULT hr; + + ULONG32 ulMachineType; + IfFailRet(m_pLegacyTarget->GetMachineType(&ulMachineType)); + + ULONG32 ulExpectedPointerSize; + CorDebugPlatform platform; + + switch(ulMachineType) + { +#ifdef FEATURE_PAL + case IMAGE_FILE_MACHINE_I386: + ulExpectedPointerSize = 4; + platform = CORDB_PLATFORM_POSIX_X86; + break; + + case IMAGE_FILE_MACHINE_AMD64: + ulExpectedPointerSize = 8; + platform = CORDB_PLATFORM_POSIX_AMD64; + break; + + case IMAGE_FILE_MACHINE_ARMNT: + ulExpectedPointerSize = 4; + platform = CORDB_PLATFORM_POSIX_ARM; + break; + + case IMAGE_FILE_MACHINE_IA64: + case IMAGE_FILE_MACHINE_ARM64: + _ASSERTE_MSG(false, "Not supported platform."); + return E_NOTIMPL; + +#else // FEATURE_PAL + case IMAGE_FILE_MACHINE_I386: + ulExpectedPointerSize = 4; + platform = CORDB_PLATFORM_WINDOWS_X86; + break; + + case IMAGE_FILE_MACHINE_AMD64: + ulExpectedPointerSize = 8; + platform = CORDB_PLATFORM_WINDOWS_AMD64; + break; + + case IMAGE_FILE_MACHINE_IA64: + ulExpectedPointerSize = 8; + platform = CORDB_PLATFORM_WINDOWS_IA64; + break; + + case IMAGE_FILE_MACHINE_ARMNT: + ulExpectedPointerSize = 4; + platform = CORDB_PLATFORM_WINDOWS_ARM; + break; + + case IMAGE_FILE_MACHINE_ARM64: + ulExpectedPointerSize = 8; + platform = CORDB_PLATFORM_WINDOWS_ARM64; + break; +#endif // FEATURE_PAL + + default: + // No other platforms are current supported + return E_NOTIMPL; + } + + // Validate that the target pointer size matches + ULONG32 ulPointerSize; + IfFailRet(m_pLegacyTarget->GetPointerSize(&ulPointerSize)); + + if (ulPointerSize != ulExpectedPointerSize) + { + return E_UNEXPECTED; + } + + // Found a match + *pPlatform = platform; + return S_OK; +} + +// impl of interface method ICorDebugDataTarget::ReadVirtual +HRESULT STDMETHODCALLTYPE +DataTargetAdapter::ReadVirtual( + CORDB_ADDRESS address, + PBYTE pBuffer, + ULONG32 cbRequestSize, + ULONG32 * pcbRead) +{ + SUPPORTS_DAC_HOST_ONLY; + CLRDATA_ADDRESS cdAddr = TO_CDADDR(address); + return m_pLegacyTarget->ReadVirtual(cdAddr, pBuffer, cbRequestSize, pcbRead); +} + +// impl of interface method ICorDebugMutableDataTarget::WriteVirtual +HRESULT STDMETHODCALLTYPE +DataTargetAdapter::WriteVirtual( + CORDB_ADDRESS address, + const BYTE * pBuffer, + ULONG32 cbRequestSize) +{ + SUPPORTS_DAC_HOST_ONLY; + CLRDATA_ADDRESS cdAddr = TO_CDADDR(address); + ULONG32 cbWritten = 0; + HRESULT hr = S_OK; + + hr = m_pLegacyTarget->WriteVirtual(cdAddr, const_cast<BYTE *>(pBuffer), cbRequestSize, &cbWritten); + + if (SUCCEEDED(hr) && cbWritten != cbRequestSize) + { + // This shouldn't happen - existing data target implementations make writes atomic (eg. + // WriteProcessMemory), even though that isn't strictly required by the old interface. + // If this does happen, we technically leave the process in an inconsistent state, and we make no + // attempt to recover from that here. + _ASSERTE_MSG(false, "Legacy data target WriteVirtual partial write - target left in inconsistent state"); + return HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY); + } + return hr; +} + + +// impl of interface method ICorDebugDataTarget::GetThreadContext +HRESULT STDMETHODCALLTYPE +DataTargetAdapter::GetThreadContext( + DWORD dwThreadID, + ULONG32 contextFlags, + ULONG32 contextSize, + PBYTE pContext) +{ + SUPPORTS_DAC_HOST_ONLY; + return m_pLegacyTarget->GetThreadContext(dwThreadID, contextFlags, contextSize, pContext); +} + +// impl of interface method ICorDebugMutableDataTarget::SetThreadContext +HRESULT STDMETHODCALLTYPE +DataTargetAdapter::SetThreadContext( + DWORD dwThreadID, + ULONG32 contextSize, + const BYTE * pContext) +{ + SUPPORTS_DAC_HOST_ONLY; + return m_pLegacyTarget->SetThreadContext(dwThreadID, contextSize, const_cast<BYTE *>(pContext)); +} + +// implementation of ICorDebugMutableDataTarget::ContinueStatusChanged +HRESULT STDMETHODCALLTYPE +DataTargetAdapter::ContinueStatusChanged( + DWORD dwThreadId, + CORDB_CONTINUE_STATUS continueStatus) +{ + SUPPORTS_DAC_HOST_ONLY; + // No corresponding API in pre-arrowhead ICLRDataTarget* interfaces. + // Note that we briefly had a ICLRDataTarget4 with this API, but this was never released outside the CLR so + // all existing implementations should now be gone. + return E_NOTIMPL; +} |