Skip to content

Commit 789845f

Browse files
authored
Port ComWrappers 5.0 diagnostic changes back to master and add stowed exception array to minidumps (#43164)
1 parent 5104f58 commit 789845f

File tree

9 files changed

+960
-919
lines changed

9 files changed

+960
-919
lines changed

src/coreclr/src/debug/daccess/dacimpl.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,6 +1482,7 @@ class ClrDataAccess
14821482
#endif
14831483

14841484
#ifdef FEATURE_COMWRAPPERS
1485+
BOOL DACGetComWrappersCCWVTableQIAddress(CLRDATA_ADDRESS ccwPtr, TADDR *vTableAddress, TADDR *qiAddress);
14851486
BOOL DACIsComWrappersCCW(CLRDATA_ADDRESS ccwPtr);
14861487
TADDR DACGetManagedObjectWrapperFromCCW(CLRDATA_ADDRESS ccwPtr);
14871488
HRESULT DACTryGetComWrappersObjectFromCCW(CLRDATA_ADDRESS ccwPtr, OBJECTREF* objRef);
@@ -4036,4 +4037,36 @@ extern unsigned __int64 g_nFindStackTotalTime;
40364037

40374038
#endif // #if defined(DAC_MEASURE_PERF)
40384039

4040+
#ifdef FEATURE_COMWRAPPERS
4041+
4042+
// Public contract for ExternalObjectContext, keep in sync with definition in
4043+
// interoplibinterface.cpp
4044+
struct ExternalObjectContextDACnterface
4045+
{
4046+
PTR_VOID identity;
4047+
INT_PTR _padding1;
4048+
DWORD SyncBlockIndex;
4049+
INT64 _padding3;
4050+
};
4051+
4052+
typedef DPTR(ExternalObjectContextDACnterface) PTR_ExternalObjectContext;
4053+
4054+
// Public contract for ManagedObjectWrapper, keep in sync with definition in
4055+
// comwrappers.hpp
4056+
struct ManagedObjectWrapperDACInterface
4057+
{
4058+
PTR_VOID managedObject;
4059+
INT32 _padding1;
4060+
INT32 _padding2;
4061+
INT_PTR _padding3;
4062+
INT_PTR _padding4;
4063+
INT_PTR _padding6;
4064+
LONGLONG _refCount;
4065+
INT32 _padding7;
4066+
};
4067+
4068+
typedef DPTR(ManagedObjectWrapperDACInterface) PTR_ManagedObjectWrapper;
4069+
4070+
#endif // FEATURE_COMWRAPPERS
4071+
40394072
#endif // #ifndef __DACIMPL_H__

src/coreclr/src/debug/daccess/enummem.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
#include "binder.h"
2121
#include "win32threadpool.h"
2222

23+
#ifdef FEATURE_COMWRAPPERS
24+
#include <interoplibinterface.h>
25+
#include <interoplibabi.h>
26+
#endif // FEATURE_COMWRAPPERS
27+
2328
extern HRESULT GetDacTableAddress(ICorDebugDataTarget* dataTarget, ULONG64 baseAddress, PULONG64 dacTableAddress);
2429

2530
#if defined(DAC_MEASURE_PERF)
@@ -1056,10 +1061,10 @@ HRESULT ClrDataAccess::EnumMemDumpAllThreadsStack(CLRDataEnumMemoryFlags flags)
10561061
{
10571062
SUPPORTS_DAC;
10581063

1059-
#ifdef FEATURE_COMINTEROP
1064+
#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
10601065
// Dump the exception object stored in the WinRT stowed exception
10611066
EnumMemStowedException(flags);
1062-
#endif
1067+
#endif // defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
10631068

10641069
HRESULT status = S_OK;
10651070
TSIZE_T cbMemoryReported = m_cbMemoryReported;
@@ -1377,6 +1382,10 @@ HRESULT ClrDataAccess::EnumMemStowedException(CLRDataEnumMemoryFlags flags)
13771382
return S_OK;
13781383
}
13791384

1385+
// Make sure we include the whole stowed exception array so we can debug a stowed exception
1386+
// in a minidump
1387+
ReportMem(remoteStowedExceptionArray, stowedExceptionCount * sizeof(TADDR));
1388+
13801389
for (ULONG i = 0; i < stowedExceptionCount; ++i)
13811390
{
13821391
// Read the i-th stowed exception
@@ -1389,6 +1398,8 @@ HRESULT ClrDataAccess::EnumMemStowedException(CLRDataEnumMemoryFlags flags)
13891398
continue;
13901399
}
13911400

1401+
ReportMem(remoteStowedException, sizeof(STOWED_EXCEPTION_INFORMATION_HEADER));
1402+
13921403
// check if this is a v2 stowed exception
13931404
STOWED_EXCEPTION_INFORMATION_V2 stowedException = { 0 };
13941405
if (FAILED(m_pTarget->ReadVirtual(TO_CDADDR(remoteStowedException),
@@ -1399,6 +1410,8 @@ HRESULT ClrDataAccess::EnumMemStowedException(CLRDataEnumMemoryFlags flags)
13991410
continue;
14001411
}
14011412

1413+
ReportMem(remoteStowedException, sizeof(STOWED_EXCEPTION_INFORMATION_V2));
1414+
14021415
// Read the full v2 stowed exception and get the CCW pointer out of it
14031416
if (FAILED(m_pTarget->ReadVirtual(TO_CDADDR(remoteStowedException),
14041417
(PBYTE)&stowedException, sizeof(STOWED_EXCEPTION_INFORMATION_V2), &bytesRead))
@@ -1429,6 +1442,21 @@ HRESULT ClrDataAccess::DumpStowedExceptionObject(CLRDataEnumMemoryFlags flags, C
14291442
if (DACTryGetComWrappersObjectFromCCW(ccwPtr, &wrappedObjAddress) == S_OK)
14301443
{
14311444
managedExceptionObject = wrappedObjAddress;
1445+
// Now report the CCW itself
1446+
ReportMem(TO_TADDR(ccwPtr), sizeof(TADDR));
1447+
TADDR managedObjectWrapperPtrPtr = ccwPtr & InteropLib::ABI::DispatchThisPtrMask;
1448+
ReportMem(managedObjectWrapperPtrPtr, sizeof(TADDR));
1449+
1450+
// Plus its QI and VTable that we query to determine if it is a ComWrappers CCW
1451+
TADDR vTableAddress = NULL;
1452+
TADDR qiAddress = NULL;
1453+
DACGetComWrappersCCWVTableQIAddress(ccwPtr, &vTableAddress, &qiAddress);
1454+
ReportMem(vTableAddress, sizeof(TADDR));
1455+
ReportMem(qiAddress, sizeof(TADDR));
1456+
1457+
// And the MOW it points to
1458+
TADDR mow = DACGetManagedObjectWrapperFromCCW(ccwPtr);
1459+
ReportMem(mow, sizeof(ManagedObjectWrapperDACInterface));
14321460
}
14331461
#endif
14341462
#ifdef FEATURE_COMINTEROP

src/coreclr/src/debug/daccess/request.cpp

Lines changed: 68 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -23,36 +23,6 @@
2323
#ifdef FEATURE_COMWRAPPERS
2424
#include <interoplibinterface.h>
2525
#include <interoplibabi.h>
26-
27-
// Public contract for ExternalObjectContext, keep in sync with definition in
28-
// interoplibinterface.cpp
29-
struct ExternalObjectContextDACnterface
30-
{
31-
INT_PTR sentinel;
32-
PTR_VOID identity;
33-
INT_PTR _padding1;
34-
DWORD _padding2;
35-
INT64 _padding3;
36-
};
37-
38-
typedef DPTR(ExternalObjectContextDACnterface) PTR_ExternalObjectContext;
39-
40-
// Public contract for ManagedObjectWrapper, keep in sync with definition in
41-
// comwrappers.hpp
42-
struct ManagedObjectWrapperDACInterface
43-
{
44-
PTR_VOID managedObject;
45-
INT32 _padding1;
46-
INT32 _padding2;
47-
INT_PTR _padding3;
48-
INT_PTR _padding4;
49-
INT_PTR _padding6;
50-
LONGLONG _refCount;
51-
INT32 _padding7;
52-
};
53-
54-
typedef DPTR(ManagedObjectWrapperDACInterface) PTR_ManagedObjectWrapper;
55-
5626
#endif // FEATURE_COMWRAPPERS
5727

5828
#ifndef TARGET_UNIX
@@ -4105,22 +4075,23 @@ PTR_IUnknown ClrDataAccess::DACGetCOMIPFromCCW(PTR_ComCallWrapper pCCW, int vtab
41054075
#endif
41064076

41074077
#ifdef FEATURE_COMWRAPPERS
4108-
BOOL ClrDataAccess::DACIsComWrappersCCW(CLRDATA_ADDRESS ccwPtr)
4078+
BOOL ClrDataAccess::DACGetComWrappersCCWVTableQIAddress(CLRDATA_ADDRESS ccwPtr, TADDR *vTableAddress, TADDR *qiAddress)
41094079
{
4110-
// Read CCWs QI address and compare it to the managed object wrapper's implementation.
4080+
_ASSERTE(vTableAddress != NULL && qiAddress != NULL);
4081+
41114082
HRESULT hr = S_OK;
41124083
ULONG32 bytesRead = 0;
41134084
TADDR ccw = CLRDATA_ADDRESS_TO_TADDR(ccwPtr);
4114-
TADDR vTableAddress = NULL;
4115-
if (FAILED(m_pTarget->ReadVirtual(ccw, (PBYTE)&vTableAddress, sizeof(TADDR), &bytesRead))
4085+
*vTableAddress = NULL;
4086+
if (FAILED(m_pTarget->ReadVirtual(ccw, (PBYTE)vTableAddress, sizeof(TADDR), &bytesRead))
41164087
|| bytesRead != sizeof(TADDR)
41174088
|| vTableAddress == NULL)
41184089
{
41194090
return FALSE;
41204091
}
41214092

4122-
TADDR qiAddress = NULL;
4123-
if (FAILED(m_pTarget->ReadVirtual(vTableAddress, (PBYTE)&qiAddress, sizeof(TADDR), &bytesRead))
4093+
*qiAddress = NULL;
4094+
if (FAILED(m_pTarget->ReadVirtual(*vTableAddress, (PBYTE)qiAddress, sizeof(TADDR), &bytesRead))
41244095
|| bytesRead != sizeof(TADDR)
41254096
|| qiAddress == NULL)
41264097
{
@@ -4130,15 +4101,22 @@ BOOL ClrDataAccess::DACIsComWrappersCCW(CLRDATA_ADDRESS ccwPtr)
41304101

41314102
#ifdef TARGET_ARM
41324103
// clear the THUMB bit on qiAddress before comparing with known vtable entry
4133-
qiAddress &= ~THUMB_CODE;
4104+
*qiAddress &= ~THUMB_CODE;
41344105
#endif
41354106

4136-
if (qiAddress != GetEEFuncEntryPoint(ManagedObjectWrapper_QueryInterface))
4107+
return TRUE;
4108+
}
4109+
4110+
BOOL ClrDataAccess::DACIsComWrappersCCW(CLRDATA_ADDRESS ccwPtr)
4111+
{
4112+
TADDR vTableAddress = NULL;
4113+
TADDR qiAddress = NULL;
4114+
if (!DACGetComWrappersCCWVTableQIAddress(ccwPtr, &vTableAddress, &qiAddress))
41374115
{
41384116
return FALSE;
41394117
}
41404118

4141-
return TRUE;
4119+
return qiAddress == GetEEFuncEntryPoint(ManagedObjectWrapper_QueryInterface);
41424120
}
41434121

41444122
TADDR ClrDataAccess::DACGetManagedObjectWrapperFromCCW(CLRDATA_ADDRESS ccwPtr)
@@ -4174,8 +4152,6 @@ HRESULT ClrDataAccess::DACTryGetComWrappersObjectFromCCW(CLRDATA_ADDRESS ccwPtr,
41744152
}
41754153

41764154
TADDR ccw = CLRDATA_ADDRESS_TO_TADDR(ccwPtr);
4177-
// Mask the "dispatch pointer" to get a double pointer to the ManagedObjectWrapper
4178-
TADDR managedObjectWrapperPtrPtr = ccw & InteropLib::ABI::DispatchThisPtrMask;
41794155

41804156
// Return ManagedObjectWrapper as an OBJECTHANDLE. (The OBJECTHANDLE is guaranteed to live at offset 0).
41814157
TADDR managedObjectWrapperPtr = DACGetManagedObjectWrapperFromCCW(ccwPtr);
@@ -4819,14 +4795,6 @@ HRESULT ClrDataAccess::GetObjectComWrappersData(CLRDATA_ADDRESS objAddr, CLRDATA
48194795
}
48204796

48214797
SOSDacEnter();
4822-
auto ComWrapperCallback = [](void *mocw, void *additionalData)
4823-
{
4824-
CQuickArrayList<CLRDATA_ADDRESS> *comWrappers = (CQuickArrayList<CLRDATA_ADDRESS>*)additionalData;
4825-
4826-
comWrappers->Push(TO_CDADDR(mocw));
4827-
4828-
};
4829-
48304798
if (pNeeded != NULL)
48314799
{
48324800
*pNeeded = 0;
@@ -4845,11 +4813,24 @@ HRESULT ClrDataAccess::GetObjectComWrappersData(CLRDATA_ADDRESS objAddr, CLRDATA
48454813
{
48464814
if (rcw != NULL)
48474815
{
4848-
*rcw = PTR_CDADDR(pInfo->m_externalComObjectContext);
4816+
*rcw = TO_TADDR(pInfo->m_externalComObjectContext);
48494817
}
48504818

4819+
DPTR(NewHolder<ManagedObjectComWrapperByIdMap>) mapHolder(PTR_TO_MEMBER_TADDR(InteropSyncBlockInfo, pInfo, m_managedObjectComWrapperMap));
4820+
DPTR(ManagedObjectComWrapperByIdMap *)ppMap(PTR_TO_MEMBER_TADDR(NewHolder<ManagedObjectComWrapperByIdMap>, mapHolder, m_value));
4821+
DPTR(ManagedObjectComWrapperByIdMap) pMap(TO_TADDR(*ppMap));
4822+
48514823
CQuickArrayList<CLRDATA_ADDRESS> comWrappers;
4852-
pInfo->IterateComWrappers(ComWrapperCallback, (void *)&comWrappers);
4824+
if (pMap != NULL)
4825+
{
4826+
ManagedObjectComWrapperByIdMap::Iterator iter = pMap->Begin();
4827+
while (iter != pMap->End())
4828+
{
4829+
comWrappers.Push(TO_CDADDR(iter->Value()));
4830+
++iter;
4831+
4832+
}
4833+
}
48534834

48544835
if (pNeeded != NULL)
48554836
{
@@ -4963,16 +4944,48 @@ HRESULT ClrDataAccess::IsComWrappersRCW(CLRDATA_ADDRESS rcw, BOOL *isComWrappers
49634944
}
49644945

49654946
SOSDacEnter();
4966-
4967-
PTR_ExternalObjectContext pEOC(TO_TADDR(rcw));
4947+
49684948
if (isComWrappersRCW != NULL)
49694949
{
4970-
*isComWrappersRCW = pEOC->sentinel == ExternalObjectContextSentinelValue;
4950+
PTR_ExternalObjectContext pRCW(TO_TADDR(rcw));
4951+
BOOL stillValid = TRUE;
4952+
if(pRCW->SyncBlockIndex >= SyncBlockCache::s_pSyncBlockCache->m_SyncTableSize)
4953+
{
4954+
stillValid = FALSE;
4955+
}
4956+
4957+
PTR_SyncBlock pSyncBlk = NULL;
4958+
if (stillValid)
4959+
{
4960+
PTR_SyncTableEntry ste = PTR_SyncTableEntry(dac_cast<TADDR>(g_pSyncTable) + (sizeof(SyncTableEntry) * pRCW->SyncBlockIndex));
4961+
pSyncBlk = ste->m_SyncBlock;
4962+
if(pSyncBlk == NULL)
4963+
{
4964+
stillValid = FALSE;
4965+
}
4966+
}
4967+
4968+
PTR_InteropSyncBlockInfo pInfo = NULL;
4969+
if (stillValid)
4970+
{
4971+
pInfo = pSyncBlk->GetInteropInfoNoCreate();
4972+
if(pInfo == NULL)
4973+
{
4974+
stillValid = FALSE;
4975+
}
4976+
}
4977+
4978+
if (stillValid)
4979+
{
4980+
stillValid = TO_TADDR(pInfo->m_externalComObjectContext) == PTR_HOST_TO_TADDR(pRCW);
4981+
}
4982+
4983+
*isComWrappersRCW = stillValid;
49714984
hr = *isComWrappersRCW ? S_OK : S_FALSE;
49724985
}
49734986

49744987
SOSDacLeave();
4975-
return hr;
4988+
return hr;
49764989
#else // FEATURE_COMWRAPPERS
49774990
return E_NOTIMPL;
49784991
#endif // FEATURE_COMWRAPPERS
@@ -4989,12 +5002,6 @@ HRESULT ClrDataAccess::GetComWrappersRCWData(CLRDATA_ADDRESS rcw, CLRDATA_ADDRES
49895002
SOSDacEnter();
49905003

49915004
PTR_ExternalObjectContext pEOC(TO_TADDR(rcw));
4992-
if (pEOC->sentinel != ExternalObjectContextSentinelValue)
4993-
{
4994-
// Not a ComWrappers RCW
4995-
hr = E_INVALIDARG;
4996-
}
4997-
49985005
if (identity != NULL)
49995006
{
50005007
*identity = PTR_CDADDR(pEOC->identity);

src/coreclr/src/inc/holder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ struct AutoExpVisibleValue
115115
template <typename TYPE>
116116
class HolderBase
117117
{
118+
friend class ClrDataAccess;
119+
118120
protected:
119121
TYPE m_value;
120122

@@ -227,6 +229,7 @@ template
227229
>
228230
class BaseHolder : protected BASE
229231
{
232+
friend class ClrDataAccess;
230233
protected:
231234
BOOL m_acquired; // Have we acquired the resource?
232235

@@ -695,6 +698,7 @@ FORCEINLINE void SafeArrayDoNothing(SAFEARRAY* p)
695698
template <typename TYPE, void (*ACQUIREF)(TYPE), void (*RELEASEF)(TYPE)>
696699
class FunctionBase : protected HolderBase<TYPE>
697700
{
701+
friend class ClrDataAccess;
698702
protected:
699703

700704
FORCEINLINE FunctionBase(TYPE value)

src/coreclr/src/interop/comwrappers.hpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,9 @@ class ManagedObjectWrapper
117117
/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR * __RPC_FAR * ppvObject);
118118
ULONG AddRef(void);
119119
ULONG Release(void);
120-
121120
};
122121

123-
// These Sentinel and Identity are used by the DAC, any changes to the layout must be updated on the DAC side (request.cpp)
122+
// The Target and _refCount fields are used by the DAC, any changes to the layout must be updated on the DAC side (request.cpp)
124123
static constexpr size_t DACTargetOffset = 0;
125124
static_assert(offsetof(ManagedObjectWrapper, Target) == DACTargetOffset, "Keep in sync with DAC interfaces");
126125
static constexpr size_t DACRefCountOffset = (4 * sizeof(intptr_t)) + (2 * sizeof(int32_t));

0 commit comments

Comments
 (0)