Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port ComWrappers 5.0 diagnostic changes back to master and add stowed exception array to minidumps #43164

Merged
merged 2 commits into from
Oct 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/coreclr/src/debug/daccess/dacimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1482,6 +1482,7 @@ class ClrDataAccess
#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);
Expand Down Expand Up @@ -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__
32 changes: 30 additions & 2 deletions src/coreclr/src/debug/daccess/enummem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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),
Expand All @@ -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))
Expand Down Expand Up @@ -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
Expand Down
129 changes: 68 additions & 61 deletions src/coreclr/src/debug/daccess/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand All @@ -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)
{
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/src/inc/holder.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ struct AutoExpVisibleValue
template <typename TYPE>
class HolderBase
{
friend class ClrDataAccess;

protected:
TYPE m_value;

Expand Down Expand Up @@ -227,6 +229,7 @@ template
>
class BaseHolder : protected BASE
{
friend class ClrDataAccess;
protected:
BOOL m_acquired; // Have we acquired the resource?

Expand Down Expand Up @@ -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)
Expand Down
3 changes: 1 addition & 2 deletions src/coreclr/src/interop/comwrappers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,9 @@ class ManagedObjectWrapper
/* [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));
Expand Down
Loading