未验证 提交 789845fa 编写于 作者: D David Mason 提交者: GitHub

Port ComWrappers 5.0 diagnostic changes back to master and add stowed...

Port ComWrappers 5.0 diagnostic changes back to master and add stowed exception array to minidumps (#43164)
上级 5104f58e
......@@ -1482,6 +1482,7 @@ private:
#endif
#ifdef FEATURE_COMWRAPPERS
BOOL DACGetComWrappersCCWVTableQIAddress(CLRDATA_ADDRESS ccwPtr, TADDR *vTableAddress, TADDR *qiAddress);
BOOL DACIsComWrappersCCW(CLRDATA_ADDRESS ccwPtr);
TADDR DACGetManagedObjectWrapperFromCCW(CLRDATA_ADDRESS ccwPtr);
HRESULT DACTryGetComWrappersObjectFromCCW(CLRDATA_ADDRESS ccwPtr, OBJECTREF* objRef);
......@@ -4036,4 +4037,36 @@ extern unsigned __int64 g_nFindStackTotalTime;
#endif // #if defined(DAC_MEASURE_PERF)
#ifdef FEATURE_COMWRAPPERS
// Public contract for ExternalObjectContext, keep in sync with definition in
// interoplibinterface.cpp
struct ExternalObjectContextDACnterface
{
PTR_VOID identity;
INT_PTR _padding1;
DWORD SyncBlockIndex;
INT64 _padding3;
};
typedef DPTR(ExternalObjectContextDACnterface) PTR_ExternalObjectContext;
// Public contract for ManagedObjectWrapper, keep in sync with definition in
// comwrappers.hpp
struct ManagedObjectWrapperDACInterface
{
PTR_VOID managedObject;
INT32 _padding1;
INT32 _padding2;
INT_PTR _padding3;
INT_PTR _padding4;
INT_PTR _padding6;
LONGLONG _refCount;
INT32 _padding7;
};
typedef DPTR(ManagedObjectWrapperDACInterface) PTR_ManagedObjectWrapper;
#endif // FEATURE_COMWRAPPERS
#endif // #ifndef __DACIMPL_H__
......@@ -20,6 +20,11 @@
#include "binder.h"
#include "win32threadpool.h"
#ifdef FEATURE_COMWRAPPERS
#include <interoplibinterface.h>
#include <interoplibabi.h>
#endif // FEATURE_COMWRAPPERS
extern HRESULT GetDacTableAddress(ICorDebugDataTarget* dataTarget, ULONG64 baseAddress, PULONG64 dacTableAddress);
#if defined(DAC_MEASURE_PERF)
......@@ -1056,10 +1061,10 @@ HRESULT ClrDataAccess::EnumMemDumpAllThreadsStack(CLRDataEnumMemoryFlags flags)
{
SUPPORTS_DAC;
#ifdef FEATURE_COMINTEROP
#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
// Dump the exception object stored in the WinRT stowed exception
EnumMemStowedException(flags);
#endif
#endif // defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
HRESULT status = S_OK;
TSIZE_T cbMemoryReported = m_cbMemoryReported;
......@@ -1377,6 +1382,10 @@ HRESULT ClrDataAccess::EnumMemStowedException(CLRDataEnumMemoryFlags flags)
return S_OK;
}
// Make sure we include the whole stowed exception array so we can debug a stowed exception
// in a minidump
ReportMem(remoteStowedExceptionArray, stowedExceptionCount * sizeof(TADDR));
for (ULONG i = 0; i < stowedExceptionCount; ++i)
{
// Read the i-th stowed exception
......@@ -1389,6 +1398,8 @@ HRESULT ClrDataAccess::EnumMemStowedException(CLRDataEnumMemoryFlags flags)
continue;
}
ReportMem(remoteStowedException, sizeof(STOWED_EXCEPTION_INFORMATION_HEADER));
// check if this is a v2 stowed exception
STOWED_EXCEPTION_INFORMATION_V2 stowedException = { 0 };
if (FAILED(m_pTarget->ReadVirtual(TO_CDADDR(remoteStowedException),
......@@ -1399,6 +1410,8 @@ HRESULT ClrDataAccess::EnumMemStowedException(CLRDataEnumMemoryFlags flags)
continue;
}
ReportMem(remoteStowedException, sizeof(STOWED_EXCEPTION_INFORMATION_V2));
// Read the full v2 stowed exception and get the CCW pointer out of it
if (FAILED(m_pTarget->ReadVirtual(TO_CDADDR(remoteStowedException),
(PBYTE)&stowedException, sizeof(STOWED_EXCEPTION_INFORMATION_V2), &bytesRead))
......@@ -1429,6 +1442,21 @@ HRESULT ClrDataAccess::DumpStowedExceptionObject(CLRDataEnumMemoryFlags flags, C
if (DACTryGetComWrappersObjectFromCCW(ccwPtr, &wrappedObjAddress) == S_OK)
{
managedExceptionObject = wrappedObjAddress;
// Now report the CCW itself
ReportMem(TO_TADDR(ccwPtr), sizeof(TADDR));
TADDR managedObjectWrapperPtrPtr = ccwPtr & InteropLib::ABI::DispatchThisPtrMask;
ReportMem(managedObjectWrapperPtrPtr, sizeof(TADDR));
// Plus its QI and VTable that we query to determine if it is a ComWrappers CCW
TADDR vTableAddress = NULL;
TADDR qiAddress = NULL;
DACGetComWrappersCCWVTableQIAddress(ccwPtr, &vTableAddress, &qiAddress);
ReportMem(vTableAddress, sizeof(TADDR));
ReportMem(qiAddress, sizeof(TADDR));
// And the MOW it points to
TADDR mow = DACGetManagedObjectWrapperFromCCW(ccwPtr);
ReportMem(mow, sizeof(ManagedObjectWrapperDACInterface));
}
#endif
#ifdef FEATURE_COMINTEROP
......
......@@ -23,36 +23,6 @@
#ifdef FEATURE_COMWRAPPERS
#include <interoplibinterface.h>
#include <interoplibabi.h>
// Public contract for ExternalObjectContext, keep in sync with definition in
// interoplibinterface.cpp
struct ExternalObjectContextDACnterface
{
INT_PTR sentinel;
PTR_VOID identity;
INT_PTR _padding1;
DWORD _padding2;
INT64 _padding3;
};
typedef DPTR(ExternalObjectContextDACnterface) PTR_ExternalObjectContext;
// Public contract for ManagedObjectWrapper, keep in sync with definition in
// comwrappers.hpp
struct ManagedObjectWrapperDACInterface
{
PTR_VOID managedObject;
INT32 _padding1;
INT32 _padding2;
INT_PTR _padding3;
INT_PTR _padding4;
INT_PTR _padding6;
LONGLONG _refCount;
INT32 _padding7;
};
typedef DPTR(ManagedObjectWrapperDACInterface) PTR_ManagedObjectWrapper;
#endif // FEATURE_COMWRAPPERS
#ifndef TARGET_UNIX
......@@ -4105,22 +4075,23 @@ PTR_IUnknown ClrDataAccess::DACGetCOMIPFromCCW(PTR_ComCallWrapper pCCW, int vtab
#endif
#ifdef FEATURE_COMWRAPPERS
BOOL ClrDataAccess::DACIsComWrappersCCW(CLRDATA_ADDRESS ccwPtr)
BOOL ClrDataAccess::DACGetComWrappersCCWVTableQIAddress(CLRDATA_ADDRESS ccwPtr, TADDR *vTableAddress, TADDR *qiAddress)
{
// Read CCWs QI address and compare it to the managed object wrapper's implementation.
_ASSERTE(vTableAddress != NULL && qiAddress != NULL);
HRESULT hr = S_OK;
ULONG32 bytesRead = 0;
TADDR ccw = CLRDATA_ADDRESS_TO_TADDR(ccwPtr);
TADDR vTableAddress = NULL;
if (FAILED(m_pTarget->ReadVirtual(ccw, (PBYTE)&vTableAddress, sizeof(TADDR), &bytesRead))
*vTableAddress = NULL;
if (FAILED(m_pTarget->ReadVirtual(ccw, (PBYTE)vTableAddress, sizeof(TADDR), &bytesRead))
|| bytesRead != sizeof(TADDR)
|| vTableAddress == NULL)
{
return FALSE;
}
TADDR qiAddress = NULL;
if (FAILED(m_pTarget->ReadVirtual(vTableAddress, (PBYTE)&qiAddress, sizeof(TADDR), &bytesRead))
*qiAddress = NULL;
if (FAILED(m_pTarget->ReadVirtual(*vTableAddress, (PBYTE)qiAddress, sizeof(TADDR), &bytesRead))
|| bytesRead != sizeof(TADDR)
|| qiAddress == NULL)
{
......@@ -4130,15 +4101,22 @@ BOOL ClrDataAccess::DACIsComWrappersCCW(CLRDATA_ADDRESS ccwPtr)
#ifdef TARGET_ARM
// clear the THUMB bit on qiAddress before comparing with known vtable entry
qiAddress &= ~THUMB_CODE;
*qiAddress &= ~THUMB_CODE;
#endif
if (qiAddress != GetEEFuncEntryPoint(ManagedObjectWrapper_QueryInterface))
return TRUE;
}
BOOL ClrDataAccess::DACIsComWrappersCCW(CLRDATA_ADDRESS ccwPtr)
{
TADDR vTableAddress = NULL;
TADDR qiAddress = NULL;
if (!DACGetComWrappersCCWVTableQIAddress(ccwPtr, &vTableAddress, &qiAddress))
{
return FALSE;
}
return TRUE;
return qiAddress == GetEEFuncEntryPoint(ManagedObjectWrapper_QueryInterface);
}
TADDR ClrDataAccess::DACGetManagedObjectWrapperFromCCW(CLRDATA_ADDRESS ccwPtr)
......@@ -4174,8 +4152,6 @@ HRESULT ClrDataAccess::DACTryGetComWrappersObjectFromCCW(CLRDATA_ADDRESS ccwPtr,
}
TADDR ccw = CLRDATA_ADDRESS_TO_TADDR(ccwPtr);
// 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 = DACGetManagedObjectWrapperFromCCW(ccwPtr);
......@@ -4819,14 +4795,6 @@ HRESULT ClrDataAccess::GetObjectComWrappersData(CLRDATA_ADDRESS objAddr, CLRDATA
}
SOSDacEnter();
auto ComWrapperCallback = [](void *mocw, void *additionalData)
{
CQuickArrayList<CLRDATA_ADDRESS> *comWrappers = (CQuickArrayList<CLRDATA_ADDRESS>*)additionalData;
comWrappers->Push(TO_CDADDR(mocw));
};
if (pNeeded != NULL)
{
*pNeeded = 0;
......@@ -4845,11 +4813,24 @@ HRESULT ClrDataAccess::GetObjectComWrappersData(CLRDATA_ADDRESS objAddr, CLRDATA
{
if (rcw != NULL)
{
*rcw = PTR_CDADDR(pInfo->m_externalComObjectContext);
*rcw = TO_TADDR(pInfo->m_externalComObjectContext);
}
DPTR(NewHolder<ManagedObjectComWrapperByIdMap>) mapHolder(PTR_TO_MEMBER_TADDR(InteropSyncBlockInfo, pInfo, m_managedObjectComWrapperMap));
DPTR(ManagedObjectComWrapperByIdMap *)ppMap(PTR_TO_MEMBER_TADDR(NewHolder<ManagedObjectComWrapperByIdMap>, mapHolder, m_value));
DPTR(ManagedObjectComWrapperByIdMap) pMap(TO_TADDR(*ppMap));
CQuickArrayList<CLRDATA_ADDRESS> comWrappers;
pInfo->IterateComWrappers(ComWrapperCallback, (void *)&comWrappers);
if (pMap != NULL)
{
ManagedObjectComWrapperByIdMap::Iterator iter = pMap->Begin();
while (iter != pMap->End())
{
comWrappers.Push(TO_CDADDR(iter->Value()));
++iter;
}
}
if (pNeeded != NULL)
{
......@@ -4963,16 +4944,48 @@ HRESULT ClrDataAccess::IsComWrappersRCW(CLRDATA_ADDRESS rcw, BOOL *isComWrappers
}
SOSDacEnter();
PTR_ExternalObjectContext pEOC(TO_TADDR(rcw));
if (isComWrappersRCW != NULL)
{
*isComWrappersRCW = pEOC->sentinel == ExternalObjectContextSentinelValue;
PTR_ExternalObjectContext pRCW(TO_TADDR(rcw));
BOOL stillValid = TRUE;
if(pRCW->SyncBlockIndex >= SyncBlockCache::s_pSyncBlockCache->m_SyncTableSize)
{
stillValid = FALSE;
}
PTR_SyncBlock pSyncBlk = NULL;
if (stillValid)
{
PTR_SyncTableEntry ste = PTR_SyncTableEntry(dac_cast<TADDR>(g_pSyncTable) + (sizeof(SyncTableEntry) * pRCW->SyncBlockIndex));
pSyncBlk = ste->m_SyncBlock;
if(pSyncBlk == NULL)
{
stillValid = FALSE;
}
}
PTR_InteropSyncBlockInfo pInfo = NULL;
if (stillValid)
{
pInfo = pSyncBlk->GetInteropInfoNoCreate();
if(pInfo == NULL)
{
stillValid = FALSE;
}
}
if (stillValid)
{
stillValid = TO_TADDR(pInfo->m_externalComObjectContext) == PTR_HOST_TO_TADDR(pRCW);
}
*isComWrappersRCW = stillValid;
hr = *isComWrappersRCW ? S_OK : S_FALSE;
}
SOSDacLeave();
return hr;
return hr;
#else // FEATURE_COMWRAPPERS
return E_NOTIMPL;
#endif // FEATURE_COMWRAPPERS
......@@ -4989,12 +5002,6 @@ HRESULT ClrDataAccess::GetComWrappersRCWData(CLRDATA_ADDRESS rcw, CLRDATA_ADDRES
SOSDacEnter();
PTR_ExternalObjectContext pEOC(TO_TADDR(rcw));
if (pEOC->sentinel != ExternalObjectContextSentinelValue)
{
// Not a ComWrappers RCW
hr = E_INVALIDARG;
}
if (identity != NULL)
{
*identity = PTR_CDADDR(pEOC->identity);
......
......@@ -115,6 +115,8 @@ struct AutoExpVisibleValue
template <typename TYPE>
class HolderBase
{
friend class ClrDataAccess;
protected:
TYPE m_value;
......@@ -227,6 +229,7 @@ template
>
class BaseHolder : protected BASE
{
friend class ClrDataAccess;
protected:
BOOL m_acquired; // Have we acquired the resource?
......@@ -695,6 +698,7 @@ FORCEINLINE void SafeArrayDoNothing(SAFEARRAY* p)
template <typename TYPE, void (*ACQUIREF)(TYPE), void (*RELEASEF)(TYPE)>
class FunctionBase : protected HolderBase<TYPE>
{
friend class ClrDataAccess;
protected:
FORCEINLINE FunctionBase(TYPE value)
......
......@@ -117,10 +117,9 @@ public: // Lifetime
/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR * __RPC_FAR * ppvObject);
ULONG AddRef(void);
ULONG Release(void);
};
// These Sentinel and Identity are used by the DAC, any changes to the layout must be updated on the DAC side (request.cpp)
// The Target and _refCount fields are used by the DAC, any changes to the layout must be updated on the DAC side (request.cpp)
static constexpr size_t DACTargetOffset = 0;
static_assert(offsetof(ManagedObjectWrapper, Target) == DACTargetOffset, "Keep in sync with DAC interfaces");
static constexpr size_t DACRefCountOffset = (4 * sizeof(intptr_t)) + (2 * sizeof(int32_t));
......
......@@ -12,7 +12,6 @@
#include "interoplibinterface.h"
using CreateObjectFlags = InteropLib::Com::CreateObjectFlags;
using CreateComInterfaceFlags = InteropLib::Com::CreateComInterfaceFlags;
......@@ -23,7 +22,6 @@ namespace
{
static const DWORD InvalidSyncBlockIndex;
INT_PTR Sentinel;
void* Identity;
void* ThreadContext;
DWORD SyncBlockIndex;
......@@ -57,7 +55,6 @@ namespace
}
CONTRACTL_END;
cxt->Sentinel = ExternalObjectContextSentinelValue;
cxt->Identity = (void*)identity;
cxt->ThreadContext = threadContext;
cxt->SyncBlockIndex = syncBlockIndex;
......@@ -132,10 +129,8 @@ namespace
}
};
// These Sentinel and Identity are used by the DAC, any changes to the layout must be updated on the DAC side (request.cpp)
static constexpr size_t DACSentinelOffset = 0;
static constexpr size_t DACIdentityOffset = sizeof(INT_PTR);
static_assert(offsetof(ExternalObjectContext, Sentinel) == DACSentinelOffset, "Keep in sync with DAC interfaces");
// Identity is used by the DAC, any changes to the layout must be updated on the DAC side (request.cpp)
static constexpr size_t DACIdentityOffset = 0;
static_assert(offsetof(ExternalObjectContext, Identity) == DACIdentityOffset, "Keep in sync with DAC interfaces");
const DWORD ExternalObjectContext::InvalidSyncBlockIndex = 0; // See syncblk.h
......@@ -1368,7 +1363,7 @@ void QCALLTYPE ComWrappersNative::GetIUnknownImpl(
END_QCALL;
}
void ComWrappersNative::DestroyManagedObjectComWrapper(_In_ void* wrapper, void *unused)
void ComWrappersNative::DestroyManagedObjectComWrapper(_In_ void* wrapper)
{
CONTRACTL
{
......@@ -1378,8 +1373,6 @@ void ComWrappersNative::DestroyManagedObjectComWrapper(_In_ void* wrapper, void
}
CONTRACTL_END;
_ASSERTE(unused == NULL && "Someone is passing data to this function but it is ignoring it.");
STRESS_LOG1(LF_INTEROP, LL_INFO100, "Destroying MOW: 0x%p\n", wrapper);
InteropLib::Com::DestroyWrapperForObject(wrapper);
}
......
......@@ -35,7 +35,7 @@ public: // Native QCalls for the abstract ComWrappers managed type.
_Inout_ QCall::ObjectHandleOnStack retValue);
public: // Lifetime management for COM Wrappers
static void DestroyManagedObjectComWrapper(_In_ void* wrapper, _Out_opt_ void *unused);
static void DestroyManagedObjectComWrapper(_In_ void* wrapper);
static void DestroyExternalComObjectContext(_In_ void* context);
static void MarkExternalComObjectContextCollected(_In_ void* context);
......@@ -99,5 +99,3 @@ public:
// Notify when GC finished
static void OnGCFinished(_In_ int nCondemnedGeneration);
};
constexpr INT_PTR ExternalObjectContextSentinelValue = (INT_PTR)0xE0E0E0E0E0E0E0E0;
......@@ -606,14 +606,10 @@ typedef DPTR(class ComCallWrapper) PTR_ComCallWrapper;
#endif // FEATURE_COMINTEROP
using ManagedObjectComWrapperByIdMap = MapSHash<INT64, void*>;
typedef DPTR(ManagedObjectComWrapperByIdMap) PTR_ManagedObjectComWrapperByIdMap;
class InteropSyncBlockInfo
{
friend class RCWHolder;
#ifdef DACCESS_COMPILE
friend class ClrDataAccess;
#endif
public:
#ifndef TARGET_UNIX
......@@ -798,7 +794,6 @@ public:
#endif
public:
bool TryGetManagedObjectComWrapper(_In_ INT64 wrapperId, _Out_ void** mocw)
{
LIMITED_METHOD_DAC_CONTRACT;
......@@ -811,15 +806,6 @@ public:
return m_managedObjectComWrapperMap->Lookup(wrapperId, mocw);
}
using EnumWrappersCallback = void(void* mocw, void *additionalData);
void IterateComWrappers(EnumWrappersCallback* callback, void *additionalData = NULL)
{
LIMITED_METHOD_DAC_CONTRACT;
CrstHolder lock(&m_managedObjectComWrapperLock);
IterateComWrappersDontTakeLock(callback, additionalData);
}
#ifndef DACCESS_COMPILE
bool TrySetManagedObjectComWrapper(_In_ INT64 wrapperId, _In_ void* mocw, _In_ void* curr = NULL)
{
......@@ -846,6 +832,7 @@ public:
return true;
}
using EnumWrappersCallback = void(void* mocw);
void ClearManagedObjectComWrappers(EnumWrappersCallback* callback)
{
LIMITED_METHOD_CONTRACT;
......@@ -854,9 +841,20 @@ public:
return;
CrstHolder lock(&m_managedObjectComWrapperLock);
IterateComWrappersDontTakeLock(callback);
if (callback != NULL)
{
ManagedObjectComWrapperByIdMap::Iterator iter = m_managedObjectComWrapperMap->Begin();
while (iter != m_managedObjectComWrapperMap->End())
{
callback(iter->Value());
++iter;
}
}
m_managedObjectComWrapperMap->RemoveAll();
}
#endif // !DACCESS_COMPILE
bool TryGetExternalComObjectContext(_Out_ void** eoc)
{
......@@ -865,6 +863,7 @@ public:
return (*eoc != NULL);
}
#ifndef DACCESS_COMPILE
bool TrySetExternalComObjectContext(_In_ void* eoc, _In_ void* curr = NULL)
{
LIMITED_METHOD_CONTRACT;
......@@ -878,26 +877,10 @@ public:
private:
// See InteropLib API for usage.
PTR_VOID m_externalComObjectContext;
void* m_externalComObjectContext;
CrstExplicitInit m_managedObjectComWrapperLock;
PTR_ManagedObjectComWrapperByIdMap m_managedObjectComWrapperMap;
void IterateComWrappersDontTakeLock(EnumWrappersCallback* callback, void *additionalData = NULL)
{
LIMITED_METHOD_DAC_CONTRACT;
if (m_managedObjectComWrapperMap != NULL && callback != NULL)
{
ManagedObjectComWrapperByIdMap::Iterator iter = m_managedObjectComWrapperMap->Begin();
while (iter != m_managedObjectComWrapperMap->End())
{
callback(iter->Value(), additionalData);
++iter;
}
}
}
NewHolder<ManagedObjectComWrapperByIdMap> m_managedObjectComWrapperMap;
#endif // FEATURE_COMINTEROP
};
......@@ -907,7 +890,6 @@ typedef DPTR(InteropSyncBlockInfo) PTR_InteropSyncBlockInfo;
// this is a lazily created additional block for an object which contains
// synchronzation information and other "kitchen sink" data
typedef DPTR(SyncBlock) PTR_SyncBlock;
// See code:#SyncBlockOverview for more
class SyncBlock
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册