include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CLR_DIR}/src/debug/ee)
include_directories(${CLR_DIR}/src/gcdump)
+include_directories(${CLR_DIR}/src/interop/inc)
if(CLR_CMAKE_HOST_UNIX)
include_directories(${GENERATED_INCLUDE_DIR})
PTR_IUnknown DACGetCOMIPFromCCW(PTR_ComCallWrapper pCCW, int vtableIndex);
#endif
+#ifdef FEATURE_COMWRAPPERS
+ HRESULT DACTryGetComWrappersObjectFromCCW(CLRDATA_ADDRESS ccwPtr, OBJECTREF* objRef);
+#endif
+
static LONG s_procInit;
public:
}
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// WinRT stowed exception holds the (CCW)pointer to a managed exception object.
if (ccwPtr == NULL)
return S_OK;
+ OBJECTREF managedExceptionObject = NULL;
+
+#ifdef FEATURE_COMINTEROP
// dump the managed exception object wrapped in CCW
// memory of the CCW object itself is dumped later by DacInstanceManager::DumpAllInstances
DacpCCWData ccwData;
GetCCWData(ccwPtr, &ccwData); // this call collects some memory implicitly
- DumpManagedExcepObject(flags, OBJECTREF(TO_TADDR(ccwData.managedObject)));
+ managedExceptionObject = OBJECTREF(CLRDATA_ADDRESS_TO_TADDR(ccwData.managedObject));
+#endif
+#ifdef FEATURE_COMWRAPPERS
+ if (managedExceptionObject == NULL)
+ {
+ OBJECTREF wrappedObjAddress;
+ if (DACTryGetComWrappersObjectFromCCW(ccwPtr, &wrappedObjAddress) == S_OK)
+ {
+ managedExceptionObject = wrappedObjAddress;
+ }
+ }
+#endif
+ DumpManagedExcepObject(flags, managedExceptionObject);
// dump memory of the 2nd slot in the CCW's vtable
// this is used in DACGetCCWFromAddress to identify if the passed in pointer is a valid CCW.
CATCH_ALL_EXCEPT_RETHROW_COR_E_OPERATIONCANCELLED
(
- ReportMem(vTableAddress + sizeof(PBYTE)* TEAR_OFF_SLOT, sizeof(TADDR));
+ ReportMem(vTableAddress, sizeof(TADDR)); // Report the QI slot on the vtable for ComWrappers
+ ReportMem(vTableAddress + sizeof(PBYTE) * TEAR_OFF_SLOT, sizeof(TADDR)); // Report the AddRef slot on the vtable for built-in CCWs
);
return S_OK;
#include <comcallablewrapper.h>
#endif // FEATURE_COMINTEROP
+#include <interoplibabi.h>
+
#ifndef TARGET_UNIX
// It is unfortunate having to include this header just to get the definition of GenericModeBlock
#include <msodw.h>
}
#endif
+#ifdef FEATURE_COMWRAPPERS
+HRESULT ClrDataAccess::DACTryGetComWrappersObjectFromCCW(CLRDATA_ADDRESS ccwPtr, OBJECTREF* objRef)
+{
+ if (ccwPtr == 0 || objRef == NULL)
+ return E_INVALIDARG;
+
+ SOSDacEnter();
+
+ // Read CCWs QI address and compare it to the managed object wrapper's implementation.
+ ULONG32 bytesRead = 0;
+ TADDR ccw = CLRDATA_ADDRESS_TO_TADDR(ccwPtr);
+ TADDR vTableAddress = NULL;
+ IfFailGo(m_pTarget->ReadVirtual(ccw, (PBYTE)&vTableAddress, sizeof(TADDR), &bytesRead));
+ if (bytesRead != sizeof(TADDR)
+ || vTableAddress == NULL)
+ {
+ hr = E_FAIL;
+ goto ErrExit;
+ }
+
+ TADDR qiAddress = NULL;
+ IfFailGo(m_pTarget->ReadVirtual(vTableAddress, (PBYTE)&qiAddress, sizeof(TADDR), &bytesRead));
+ if (bytesRead != sizeof(TADDR)
+ || qiAddress == NULL)
+ {
+ hr = E_FAIL;
+ goto ErrExit;
+ }
+
+
+#ifdef TARGET_ARM
+ // clear the THUMB bit on qiAddress before comparing with known vtable entry
+ qiAddress &= ~THUMB_CODE;
+#endif
+
+ if (qiAddress != GetEEFuncEntryPoint(ManagedObjectWrapper_QueryInterface))
+ {
+ hr = E_FAIL;
+ goto ErrExit;
+ }
+
+ // Mask the "dispatch pointer" to get a double pointer to the ManagedObjectWrapper
+ TADDR managedObjectWrapperPtrPtr = ccw & InteropLib::ABI::DispatchThisPtrMask;
+
+ // Return ManagedObjectWrapper as an OBJECTHANDLE. (The OBJECTHANDLE is guaranteed to live at offset 0).
+ TADDR managedObjectWrapperPtr;
+ IfFailGo(m_pTarget->ReadVirtual(managedObjectWrapperPtrPtr, (PBYTE)&managedObjectWrapperPtr, sizeof(TADDR), &bytesRead));
+ if (bytesRead != sizeof(TADDR))
+ {
+ hr = E_FAIL;
+ goto ErrExit;
+ }
+
+ OBJECTHANDLE handle;
+ IfFailGo(m_pTarget->ReadVirtual(managedObjectWrapperPtr, (PBYTE)&handle, sizeof(OBJECTHANDLE), &bytesRead));
+ if (bytesRead != sizeof(OBJECTHANDLE))
+ {
+ hr = E_FAIL;
+ goto ErrExit;
+ }
+
+ *objRef = ObjectFromHandle(handle);
+
+ SOSDacLeave();
+
+ return S_OK;
+
+ErrExit: return hr;
+}
+#endif
HRESULT ClrDataAccess::GetCCWData(CLRDATA_ADDRESS ccw, struct DacpCCWData *ccwData)
{
ULONG fn__Unknown_AddRefSpecial;
ULONG fn__Unknown_AddRefInner;
#endif
+#ifdef FEATURE_COMWRAPPERS
+ ULONG fn__ManagedObjectWrapper_QueryInterface;
+#endif
// Vtable pointer values for all classes that must
// be instanted using vtable pointers as the identity.
// See the LICENSE file in the project root for more information.
#include "comwrappers.hpp"
+#include <interoplibabi.h>
#include <interoplibimports.h>
#include <new> // placement new
};
ABI_ASSERT(sizeof(ComInterfaceDispatch) == sizeof(void*));
- const size_t DispatchAlignmentThisPtr = 16; // Should be a power of 2.
- const intptr_t DispatchThisPtrMask = ~(DispatchAlignmentThisPtr - 1);
+ using InteropLib::ABI::DispatchAlignmentThisPtr;
+ using InteropLib::ABI::DispatchThisPtrMask;
ABI_ASSERT(sizeof(void*) < DispatchAlignmentThisPtr);
const intptr_t AlignmentThisPtrMaxPadding = DispatchAlignmentThisPtr - sizeof(void*);
}
}
-namespace
+// ManagedObjectWrapper_QueryInterface needs to be visible outside of this compilation unit
+// to support the DAC. See code:ClrDataAccess::DACTryGetComWrappersObjectFromCCW for the
+// usage in the DAC (look for the GetEEFuncEntryPoint call).
+HRESULT STDMETHODCALLTYPE ManagedObjectWrapper_QueryInterface(
+ _In_ ABI::ComInterfaceDispatch* disp,
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject)
{
- HRESULT STDMETHODCALLTYPE ManagedObjectWrapper_QueryInterface(
- _In_ ABI::ComInterfaceDispatch* disp,
- /* [in] */ REFIID riid,
- /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject)
- {
- ManagedObjectWrapper* wrapper = ABI::ToManagedObjectWrapper(disp);
- return wrapper->QueryInterface(riid, ppvObject);
- }
+ ManagedObjectWrapper* wrapper = ABI::ToManagedObjectWrapper(disp);
+ return wrapper->QueryInterface(riid, ppvObject);
+}
+namespace
+{
ULONG STDMETHODCALLTYPE ManagedObjectWrapper_AddRef(_In_ ABI::ComInterfaceDispatch* disp)
{
ManagedObjectWrapper* wrapper = ABI::ToManagedObjectWrapper(disp);
*fpRelease = ManagedObjectWrapper_IUnknownImpl.Release;
}
+// The logic here should match code:ClrDataAccess::DACTryGetComWrappersObjectFromCCW in daccess/request.cpp
ManagedObjectWrapper* ManagedObjectWrapper::MapFromIUnknown(_In_ IUnknown* pUnk)
{
_ASSERTE(pUnk != nullptr);
--- /dev/null
+// 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.
+
+#include <stddef.h>
+
+namespace InteropLib
+{
+ namespace ABI
+ {
+ const size_t DispatchAlignmentThisPtr = 16; // Should be a power of 2.
+ const intptr_t DispatchThisPtrMask = ~(DispatchAlignmentThisPtr - 1);
+ }
+}