diff --git a/src/coreclr/debug/daccess/cdac.cpp b/src/coreclr/debug/daccess/cdac.cpp index 47631fab1785f..cf129318ae961 100644 --- a/src/coreclr/debug/daccess/cdac.cpp +++ b/src/coreclr/debug/daccess/cdac.cpp @@ -43,7 +43,7 @@ namespace } } -CDAC CDAC::Create(uint64_t descriptorAddr, ICorDebugDataTarget* target) +CDAC CDAC::Create(uint64_t descriptorAddr, ICorDebugDataTarget* target, IUnknown* legacyImpl) { HMODULE cdacLib; if (!TryLoadCDACLibrary(&cdacLib)) @@ -59,20 +59,18 @@ CDAC CDAC::Create(uint64_t descriptorAddr, ICorDebugDataTarget* target) return {}; } - return CDAC{cdacLib, handle, target}; + return CDAC{cdacLib, handle, target, legacyImpl}; } -CDAC::CDAC(HMODULE module, intptr_t handle, ICorDebugDataTarget* target) +CDAC::CDAC(HMODULE module, intptr_t handle, ICorDebugDataTarget* target, IUnknown* legacyImpl) : m_module{module} , m_cdac_handle{handle} , m_target{target} + , m_legacyImpl{legacyImpl} { _ASSERTE(m_module != NULL && m_cdac_handle != 0 && m_target != NULL); m_target->AddRef(); - decltype(&cdac_reader_get_sos_interface) getSosInterface = reinterpret_cast(::GetProcAddress(m_module, "cdac_reader_get_sos_interface")); - _ASSERTE(getSosInterface != nullptr); - getSosInterface(m_cdac_handle, &m_sos); } CDAC::~CDAC() @@ -88,7 +86,10 @@ CDAC::~CDAC() ::FreeLibrary(m_module); } -IUnknown* CDAC::SosInterface() +void CDAC::CreateSosInterface(IUnknown** sos) { - return m_sos; + decltype(&cdac_reader_create_sos_interface) createSosInterface = reinterpret_cast(::GetProcAddress(m_module, "cdac_reader_create_sos_interface")); + _ASSERTE(createSosInterface != nullptr); + int ret = createSosInterface(m_cdac_handle, m_legacyImpl, sos); + _ASSERTE(ret == 0); } diff --git a/src/coreclr/debug/daccess/cdac.h b/src/coreclr/debug/daccess/cdac.h index 51078ffcf2e46..f6d1cdcbe5035 100644 --- a/src/coreclr/debug/daccess/cdac.h +++ b/src/coreclr/debug/daccess/cdac.h @@ -7,7 +7,7 @@ class CDAC final { public: // static - static CDAC Create(uint64_t descriptorAddr, ICorDebugDataTarget *pDataTarget); + static CDAC Create(uint64_t descriptorAddr, ICorDebugDataTarget *pDataTarget, IUnknown* legacyImpl); public: CDAC() = default; @@ -19,12 +19,12 @@ class CDAC final : m_module{ other.m_module } , m_cdac_handle{ other.m_cdac_handle } , m_target{ other.m_target.Extract() } - , m_sos{ other.m_sos.Extract() } + , m_legacyImpl{ other.m_legacyImpl } { other.m_module = NULL; other.m_cdac_handle = 0; other.m_target = NULL; - other.m_sos = NULL; + other.m_legacyImpl = NULL; } CDAC& operator=(CDAC&& other) @@ -32,12 +32,12 @@ class CDAC final m_module = other.m_module; m_cdac_handle = other.m_cdac_handle; m_target = other.m_target.Extract(); - m_sos = other.m_sos.Extract(); + m_legacyImpl = other.m_legacyImpl; other.m_module = NULL; other.m_cdac_handle = 0; other.m_target = NULL; - other.m_sos = NULL; + other.m_legacyImpl = NULL; return *this; } @@ -49,17 +49,18 @@ class CDAC final return m_module != NULL && m_cdac_handle != 0; } - // This does not AddRef the returned interface - IUnknown* SosInterface(); + void CreateSosInterface(IUnknown** sos); private: - CDAC(HMODULE module, intptr_t handle, ICorDebugDataTarget* target); + CDAC(HMODULE module, intptr_t handle, ICorDebugDataTarget* target, IUnknown* legacyImpl); private: HMODULE m_module; intptr_t m_cdac_handle; NonVMComHolder m_target; - NonVMComHolder m_sos; + + // Assumes the legacy impl lives for the lifetime of this class - currently ClrDataAccess, which contains this class + IUnknown* m_legacyImpl; }; #endif // CDAC_H diff --git a/src/coreclr/debug/daccess/daccess.cpp b/src/coreclr/debug/daccess/daccess.cpp index 466041074a1ed..dbcd5f5dded3b 100644 --- a/src/coreclr/debug/daccess/daccess.cpp +++ b/src/coreclr/debug/daccess/daccess.cpp @@ -5501,31 +5501,6 @@ ClrDataAccess::Initialize(void) IfFailRet(GetDacGlobalValues()); IfFailRet(DacGetHostVtPtrs()); -// TODO: [cdac] TryGetSymbol is only implemented for Linux, OSX, and Windows. -#ifdef CAN_USE_CDAC - CLRConfigNoCache enable = CLRConfigNoCache::Get("ENABLE_CDAC"); - if (enable.IsSet()) - { - DWORD val; - if (enable.TryAsInteger(10, val) && val == 1) - { - uint64_t contractDescriptorAddr = 0; - if (TryGetSymbol(m_pTarget, m_globalBase, "DotNetRuntimeContractDescriptor", &contractDescriptorAddr)) - { - m_cdac = CDAC::Create(contractDescriptorAddr, m_pTarget); - if (m_cdac.IsValid()) - { - // Get SOS interfaces from the cDAC if available. - IUnknown* unk = m_cdac.SosInterface(); - (void)unk->QueryInterface(__uuidof(ISOSDacInterface), (void**)&m_cdacSos); - (void)unk->QueryInterface(__uuidof(ISOSDacInterface2), (void**)&m_cdacSos2); - (void)unk->QueryInterface(__uuidof(ISOSDacInterface9), (void**)&m_cdacSos9); - } - } - } - } -#endif - // // DAC is now setup and ready to use // @@ -7146,9 +7121,53 @@ CLRDataCreateInstance(REFIID iid, #ifdef LOGGING InitializeLogging(); #endif - hr = pClrDataAccess->QueryInterface(iid, iface); - pClrDataAccess->Release(); + // TODO: [cdac] Remove when cDAC deploys with SOS - https://github.com/dotnet/runtime/issues/108720 + NonVMComHolder cdacInterface = nullptr; +#ifdef CAN_USE_CDAC + CLRConfigNoCache enable = CLRConfigNoCache::Get("ENABLE_CDAC"); + if (enable.IsSet()) + { + DWORD val; + if (enable.TryAsInteger(10, val) && val == 1) + { + // TODO: [cdac] TryGetSymbol is only implemented for Linux, OSX, and Windows. + uint64_t contractDescriptorAddr = 0; + if (TryGetSymbol(pClrDataAccess->m_pTarget, pClrDataAccess->m_globalBase, "DotNetRuntimeContractDescriptor", &contractDescriptorAddr)) + { + IUnknown* thisImpl; + HRESULT qiRes = pClrDataAccess->QueryInterface(IID_IUnknown, (void**)&thisImpl); + _ASSERTE(SUCCEEDED(qiRes)); + CDAC& cdac = pClrDataAccess->m_cdac; + cdac = CDAC::Create(contractDescriptorAddr, pClrDataAccess->m_pTarget, thisImpl); + if (cdac.IsValid()) + { + // Get SOS interfaces from the cDAC if available. + cdac.CreateSosInterface(&cdacInterface); + _ASSERTE(cdacInterface != nullptr); + + // Lifetime is now managed by cDAC implementation of SOS interfaces + pClrDataAccess->Release(); + } + + // Release the AddRef from the QI. + pClrDataAccess->Release(); + } + } + } +#endif + if (cdacInterface != nullptr) + { + hr = cdacInterface->QueryInterface(iid, iface); + } + else + { + hr = pClrDataAccess->QueryInterface(iid, iface); + + // Lifetime is now managed by caller + pClrDataAccess->Release(); + } + return hr; } diff --git a/src/coreclr/debug/daccess/dacimpl.h b/src/coreclr/debug/daccess/dacimpl.h index 2d3123a575870..4fe548cc50358 100644 --- a/src/coreclr/debug/daccess/dacimpl.h +++ b/src/coreclr/debug/daccess/dacimpl.h @@ -1231,22 +1231,6 @@ class ClrDataAccess HRESULT Initialize(void); - HRESULT GetThreadDataImpl(CLRDATA_ADDRESS threadAddr, struct DacpThreadData *threadData); - HRESULT GetThreadStoreDataImpl(struct DacpThreadStoreData *data); - HRESULT GetModuleDataImpl(CLRDATA_ADDRESS addr, struct DacpModuleData *moduleData); - HRESULT GetNestedExceptionDataImpl(CLRDATA_ADDRESS exception, CLRDATA_ADDRESS *exceptionObject, CLRDATA_ADDRESS *nextNestedException); - HRESULT GetMethodTableDataImpl(CLRDATA_ADDRESS mt, struct DacpMethodTableData *data); - HRESULT GetMethodTableForEEClassImpl (CLRDATA_ADDRESS eeClassReallyMT, CLRDATA_ADDRESS *value); - HRESULT GetMethodTableNameImpl(CLRDATA_ADDRESS mt, unsigned int count, _Inout_updates_z_(count) WCHAR *mtName, unsigned int *pNeeded); - HRESULT GetObjectDataImpl(CLRDATA_ADDRESS addr, struct DacpObjectData *objectData); - HRESULT GetObjectExceptionDataImpl(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data); - HRESULT GetObjectStringDataImpl(CLRDATA_ADDRESS obj, unsigned int count, _Inout_updates_z_(count) WCHAR *stringData, unsigned int *pNeeded); - HRESULT GetPEFileBaseImpl(CLRDATA_ADDRESS moduleAddr, CLRDATA_ADDRESS *base); - HRESULT GetPEFileNameImpl(CLRDATA_ADDRESS moduleAddr, unsigned int count, _Inout_updates_z_(count) WCHAR *fileName, unsigned int *pNeeded); - HRESULT GetUsefulGlobalsImpl(struct DacpUsefulGlobalsData *globalsData); - HRESULT GetMethodDescDataImpl(CLRDATA_ADDRESS methodDesc, CLRDATA_ADDRESS ip, struct DacpMethodDescData *data, ULONG cRevertedRejitVersions, DacpReJitData * rgRevertedRejitData, ULONG * pcNeededRevertedRejitData); - HRESULT GetMethodDescNameImpl(CLRDATA_ADDRESS methodDesc, unsigned int count, _Inout_updates_z_(count) WCHAR *name, unsigned int *pNeeded); - BOOL IsExceptionFromManagedCode(EXCEPTION_RECORD * pExceptionRecord); #ifndef TARGET_UNIX HRESULT GetWatsonBuckets(DWORD dwThreadId, GenericModeBlock * pGM); @@ -1433,10 +1417,9 @@ class ClrDataAccess ULONG32 m_instanceAge; bool m_debugMode; + // This currently exists on the DAC as a way of managing lifetime of loading/freeing the cdacreader + // TODO: [cdac] Remove when cDAC deploys with SOS - https://github.com/dotnet/runtime/issues/108720 CDAC m_cdac; - NonVMComHolder m_cdacSos; - NonVMComHolder m_cdacSos2; - NonVMComHolder m_cdacSos9; #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS diff --git a/src/coreclr/debug/daccess/request.cpp b/src/coreclr/debug/daccess/request.cpp index 252d68a71cf6a..485503e025c4a 100644 --- a/src/coreclr/debug/daccess/request.cpp +++ b/src/coreclr/debug/daccess/request.cpp @@ -303,65 +303,31 @@ HRESULT ClrDataAccess::GetThreadStoreData(struct DacpThreadStoreData *threadStor { SOSDacEnter(); - if (m_cdacSos != NULL) + ThreadStore* threadStore = ThreadStore::s_pThreadStore; + if (!threadStore) { - // Try the cDAC first - it will return E_NOTIMPL if it doesn't support this method yet. Fall back to the DAC. - hr = m_cdacSos->GetThreadStoreData(threadStoreData); - if (FAILED(hr)) - { - hr = GetThreadStoreDataImpl(threadStoreData); - } -#ifdef _DEBUG - else - { - // Assert that the data is the same as what we get from the DAC. - DacpThreadStoreData threadStoreDataLocal; - HRESULT hrLocal = GetThreadStoreDataImpl(&threadStoreDataLocal); - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(threadStoreData->threadCount == threadStoreDataLocal.threadCount); - _ASSERTE(threadStoreData->unstartedThreadCount == threadStoreDataLocal.unstartedThreadCount); - _ASSERTE(threadStoreData->backgroundThreadCount == threadStoreDataLocal.backgroundThreadCount); - _ASSERTE(threadStoreData->pendingThreadCount == threadStoreDataLocal.pendingThreadCount); - _ASSERTE(threadStoreData->deadThreadCount == threadStoreDataLocal.deadThreadCount); - _ASSERTE(threadStoreData->fHostConfig == threadStoreDataLocal.fHostConfig); - _ASSERTE(threadStoreData->firstThread == threadStoreDataLocal.firstThread); - _ASSERTE(threadStoreData->finalizerThread == threadStoreDataLocal.finalizerThread); - _ASSERTE(threadStoreData->gcThread == threadStoreDataLocal.gcThread); - } -#endif + hr = E_UNEXPECTED; } else { - hr = GetThreadStoreDataImpl(threadStoreData); + // initialize the fields of our local structure + threadStoreData->threadCount = threadStore->m_ThreadCount; + threadStoreData->unstartedThreadCount = threadStore->m_UnstartedThreadCount; + threadStoreData->backgroundThreadCount = threadStore->m_BackgroundThreadCount; + threadStoreData->pendingThreadCount = threadStore->m_PendingThreadCount; + threadStoreData->deadThreadCount = threadStore->m_DeadThreadCount; + threadStoreData->fHostConfig = FALSE; + + // identify the "important" threads + threadStoreData->firstThread = HOST_CDADDR(threadStore->m_ThreadList.GetHead()); + threadStoreData->finalizerThread = HOST_CDADDR(g_pFinalizerThread); + threadStoreData->gcThread = HOST_CDADDR(g_pSuspensionThread); } SOSDacLeave(); return hr; } -HRESULT ClrDataAccess::GetThreadStoreDataImpl(struct DacpThreadStoreData *threadStoreData) -{ - ThreadStore* threadStore = ThreadStore::s_pThreadStore; - if (!threadStore) - return E_UNEXPECTED; - - // initialize the fields of our local structure - threadStoreData->threadCount = threadStore->m_ThreadCount; - threadStoreData->unstartedThreadCount = threadStore->m_UnstartedThreadCount; - threadStoreData->backgroundThreadCount = threadStore->m_BackgroundThreadCount; - threadStoreData->pendingThreadCount = threadStore->m_PendingThreadCount; - threadStoreData->deadThreadCount = threadStore->m_DeadThreadCount; - threadStoreData->fHostConfig = FALSE; - - // identify the "important" threads - threadStoreData->firstThread = HOST_CDADDR(threadStore->m_ThreadList.GetHead()); - threadStoreData->finalizerThread = HOST_CDADDR(g_pFinalizerThread); - threadStoreData->gcThread = HOST_CDADDR(g_pSuspensionThread); - - return S_OK; -} - HRESULT ClrDataAccess::GetStressLogAddress(CLRDATA_ADDRESS *stressLog) { @@ -880,53 +846,10 @@ ClrDataAccess::GetHeapAllocData(unsigned int count, struct DacpGenerationAllocDa return hr; } -HRESULT ClrDataAccess::GetThreadData(CLRDATA_ADDRESS threadAddr, struct DacpThreadData* threadData) +HRESULT ClrDataAccess::GetThreadData(CLRDATA_ADDRESS threadAddr, struct DacpThreadData *threadData) { SOSDacEnter(); - if (m_cdacSos != NULL) - { - hr = m_cdacSos->GetThreadData(threadAddr, threadData); - if (FAILED(hr)) - { - hr = GetThreadDataImpl(threadAddr, threadData); - } -#ifdef _DEBUG - else - { - DacpThreadData threadDataLocal; - HRESULT hrLocal = GetThreadDataImpl(threadAddr, &threadDataLocal); - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(threadData->corThreadId == threadDataLocal.corThreadId); - _ASSERTE(threadData->osThreadId == threadDataLocal.osThreadId); - _ASSERTE(threadData->state == threadDataLocal.state); - _ASSERTE(threadData->preemptiveGCDisabled == threadDataLocal.preemptiveGCDisabled); - _ASSERTE(threadData->allocContextPtr == threadDataLocal.allocContextPtr); - _ASSERTE(threadData->allocContextLimit == threadDataLocal.allocContextLimit); - _ASSERTE(threadData->context == threadDataLocal.context); - _ASSERTE(threadData->domain == threadDataLocal.domain); - _ASSERTE(threadData->pFrame == threadDataLocal.pFrame); - _ASSERTE(threadData->lockCount == threadDataLocal.lockCount); - _ASSERTE(threadData->firstNestedException == threadDataLocal.firstNestedException); - _ASSERTE(threadData->teb == threadDataLocal.teb); - _ASSERTE(threadData->fiberData == threadDataLocal.fiberData); - _ASSERTE(threadData->lastThrownObjectHandle == threadDataLocal.lastThrownObjectHandle); - _ASSERTE(threadData->nextThread == threadDataLocal.nextThread);; - } -#endif - } - else - { - hr = GetThreadDataImpl(threadAddr, threadData); - } - - SOSDacLeave(); - return hr; -} - -HRESULT ClrDataAccess::GetThreadDataImpl(CLRDATA_ADDRESS threadAddr, struct DacpThreadData *threadData) -{ // marshal the Thread object from the target Thread* thread = PTR_Thread(TO_TADDR(threadAddr)); @@ -975,7 +898,8 @@ HRESULT ClrDataAccess::GetThreadDataImpl(CLRDATA_ADDRESS threadAddr, struct Dacp thread->m_ExceptionState.m_currentExInfo.m_pPrevNestedInfo); #endif // FEATURE_EH_FUNCLETS - return S_OK; + SOSDacLeave(); + return hr; } #ifdef FEATURE_REJIT @@ -1032,7 +956,6 @@ void CopyNativeCodeVersionToReJitData(NativeCodeVersion nativeCodeVersion, Nativ // Return Value: // HRESULT indicating success or failure. // - HRESULT ClrDataAccess::GetMethodDescData( CLRDATA_ADDRESS methodDesc, CLRDATA_ADDRESS ip, @@ -1057,71 +980,6 @@ HRESULT ClrDataAccess::GetMethodDescData( } SOSDacEnter(); - if (m_cdacSos != NULL) - { - // Try the cDAC first - it will return E_NOTIMPL if it doesn't support this method yet. Fall back to the DAC. - hr = m_cdacSos->GetMethodDescData(methodDesc, ip, methodDescData, cRevertedRejitVersions, rgRevertedRejitData, pcNeededRevertedRejitData); - if (FAILED(hr)) - { - hr = GetMethodDescDataImpl(methodDesc, ip, methodDescData, cRevertedRejitVersions, rgRevertedRejitData, pcNeededRevertedRejitData); - } -#ifdef _DEBUG - else - { - // Assert that the data is the same as what we get from the DAC. - DacpMethodDescData mdDataLocal; - NewArrayHolder rgRevertedRejitDataLocal{}; - if (rgRevertedRejitData != nullptr) - { - rgRevertedRejitDataLocal = new DacpReJitData[cRevertedRejitVersions]; - } - ULONG cNeededRevertedRejitDataLocal = 0; - ULONG *pcNeededRevertedRejitDataLocal = NULL; - if (pcNeededRevertedRejitData != NULL) - { - pcNeededRevertedRejitDataLocal = &cNeededRevertedRejitDataLocal; - } - HRESULT hrLocal = GetMethodDescDataImpl(methodDesc, ip,&mdDataLocal, cRevertedRejitVersions, rgRevertedRejitDataLocal, pcNeededRevertedRejitDataLocal); - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(methodDescData->bHasNativeCode == mdDataLocal.bHasNativeCode); - _ASSERTE(methodDescData->bIsDynamic == mdDataLocal.bIsDynamic); - _ASSERTE(methodDescData->wSlotNumber == mdDataLocal.wSlotNumber); - _ASSERTE(methodDescData->NativeCodeAddr == mdDataLocal.NativeCodeAddr); - _ASSERTE(methodDescData->AddressOfNativeCodeSlot == mdDataLocal.AddressOfNativeCodeSlot); - //TODO[cdac]: assert the rest of mdDataLocal contains the same info as methodDescData - if (rgRevertedRejitData != NULL) - { - _ASSERTE (cNeededRevertedRejitDataLocal == *pcNeededRevertedRejitData); - for (ULONG i = 0; i < cNeededRevertedRejitDataLocal; i++) - { - _ASSERTE(rgRevertedRejitData[i].rejitID == rgRevertedRejitDataLocal[i].rejitID); - _ASSERTE(rgRevertedRejitData[i].NativeCodeAddr == rgRevertedRejitDataLocal[i].NativeCodeAddr); - _ASSERTE(rgRevertedRejitData[i].flags == rgRevertedRejitDataLocal[i].flags); - } - } - } -#endif - } - else - { - hr = GetMethodDescDataImpl(methodDesc, ip, methodDescData, cRevertedRejitVersions, rgRevertedRejitData, pcNeededRevertedRejitData); - } - - SOSDacLeave(); - return hr; -} - -HRESULT ClrDataAccess::GetMethodDescDataImpl( - CLRDATA_ADDRESS methodDesc, - CLRDATA_ADDRESS ip, - struct DacpMethodDescData *methodDescData, - ULONG cRevertedRejitVersions, - DacpReJitData * rgRevertedRejitData, - ULONG * pcNeededRevertedRejitData) -{ - - HRESULT hr = S_OK; PTR_MethodDesc pMD = PTR_MethodDesc(TO_TADDR(methodDesc)); @@ -1317,6 +1175,7 @@ HRESULT ClrDataAccess::GetMethodDescDataImpl( } } + SOSDacLeave(); return hr; } @@ -1584,51 +1443,6 @@ ClrDataAccess::GetMethodDescName(CLRDATA_ADDRESS methodDesc, unsigned int count, SOSDacEnter(); - if (m_cdacSos != NULL) - { - hr = m_cdacSos->GetMethodDescName(methodDesc, count, name, pNeeded); - if (FAILED(hr)) - { - hr = GetMethodDescNameImpl(methodDesc, count, name, pNeeded); - } -#ifdef _DEBUG - else - { - NewArrayHolder nameLocal = new WCHAR[count]; - unsigned int neededLocal = 0; - HRESULT hrLocal = GetMethodDescNameImpl(methodDesc, count, nameLocal, &neededLocal); - - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - - if (name != NULL) - { - _ASSERTE(0 == u16_strncmp(name, (WCHAR *)nameLocal, count)); - } - if (pNeeded != NULL) - { - _ASSERTE(*pNeeded == neededLocal); - } - } -#endif - } - else - { - hr = GetMethodDescNameImpl(methodDesc, count, name, pNeeded); - } - - SOSDacLeave(); - return hr; -} - -HRESULT -ClrDataAccess::GetMethodDescNameImpl(CLRDATA_ADDRESS methodDesc, unsigned int count, _Inout_updates_z_(count) WCHAR *name, unsigned int *pNeeded) -{ - if (methodDesc == 0) - return E_INVALIDARG; - - SOSDacEnter(); - MethodDesc* pMD = PTR_MethodDesc(TO_TADDR(methodDesc)); StackSString str; @@ -1724,9 +1538,8 @@ ClrDataAccess::GetDomainFromContext(CLRDATA_ADDRESS contextAddr, CLRDATA_ADDRESS return hr; } - HRESULT -ClrDataAccess::GetObjectStringData(CLRDATA_ADDRESS obj, unsigned int count, _Inout_updates_z_(count) WCHAR* stringData, unsigned int* pNeeded) +ClrDataAccess::GetObjectStringData(CLRDATA_ADDRESS obj, unsigned int count, _Inout_updates_z_(count) WCHAR *stringData, unsigned int *pNeeded) { if (obj == 0) return E_INVALIDARG; @@ -1736,74 +1549,45 @@ ClrDataAccess::GetObjectStringData(CLRDATA_ADDRESS obj, unsigned int count, _Ino SOSDacEnter(); - if (m_cdacSos != NULL) - { - hr = m_cdacSos->GetObjectStringData(obj, count, stringData, pNeeded); - if (FAILED(hr)) - { - hr = GetObjectStringDataImpl(obj, count, stringData, pNeeded); - } -#ifdef _DEBUG - else - { - unsigned int neededLocal; - SString stringDataLocal; - HRESULT hrLocal = GetObjectStringDataImpl(obj, count, stringDataLocal.OpenUnicodeBuffer(count), &neededLocal); - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(pNeeded == NULL || *pNeeded == neededLocal); - _ASSERTE(u16_strncmp(stringData, stringDataLocal, count) == 0); - } -#endif - } - else - { - hr = GetObjectStringDataImpl(obj, count, stringData, pNeeded); - } - - SOSDacLeave(); - return hr; -} - -HRESULT -ClrDataAccess::GetObjectStringDataImpl(CLRDATA_ADDRESS obj, unsigned int count, _Inout_updates_z_(count) WCHAR *stringData, unsigned int *pNeeded) -{ TADDR mtTADDR = DACGetMethodTableFromObjectPointer(TO_TADDR(obj), m_pTarget); PTR_MethodTable mt = PTR_MethodTable(mtTADDR); // Object must be a string BOOL bFree = FALSE; - if (!DacValidateMethodTable(mt, bFree)) - return E_INVALIDARG; - - if (HOST_CDADDR(mt) != HOST_CDADDR(g_pStringClass)) - return E_INVALIDARG; - - PTR_StringObject str(TO_TADDR(obj)); - ULONG32 needed = (ULONG32)str->GetStringLength() + 1; - - HRESULT hr; - if (stringData && count > 0) + if (!DacValidateMethodTable(mt, bFree) + || HOST_CDADDR(mt) != HOST_CDADDR(g_pStringClass)) { - if (count > needed) - count = needed; - - TADDR pszStr = TO_TADDR(obj)+offsetof(StringObject, m_FirstChar); - hr = m_pTarget->ReadVirtual(pszStr, (PBYTE)stringData, count * sizeof(WCHAR), &needed); - - if (SUCCEEDED(hr)) - stringData[count - 1] = W('\0'); - else - stringData[0] = W('\0'); + hr = E_INVALIDARG; } else { - hr = E_INVALIDARG; - } + PTR_StringObject str(TO_TADDR(obj)); + ULONG32 needed = (ULONG32)str->GetStringLength() + 1; - if (pNeeded) - *pNeeded = needed; + HRESULT hr; + if (stringData && count > 0) + { + if (count > needed) + count = needed; + + TADDR pszStr = TO_TADDR(obj)+offsetof(StringObject, m_FirstChar); + hr = m_pTarget->ReadVirtual(pszStr, (PBYTE)stringData, count * sizeof(WCHAR), &needed); + + if (SUCCEEDED(hr)) + stringData[count - 1] = W('\0'); + else + stringData[0] = W('\0'); + } + else + { + hr = E_INVALIDARG; + } + + if (pNeeded) + *pNeeded = needed; + } + SOSDacLeave(); return hr; } @@ -1960,63 +1744,13 @@ ClrDataAccess::GetModule(CLRDATA_ADDRESS addr, IXCLRDataModule **mod) } HRESULT -ClrDataAccess::GetModuleData(CLRDATA_ADDRESS addr, struct DacpModuleData* moduleData) +ClrDataAccess::GetModuleData(CLRDATA_ADDRESS addr, struct DacpModuleData *ModuleData) { - if (addr == 0 || moduleData == NULL) + if (addr == 0 || ModuleData == NULL) return E_INVALIDARG; SOSDacEnter(); - if (m_cdacSos != NULL) - { - hr = m_cdacSos->GetModuleData(addr, moduleData); - if (FAILED(hr)) - { - hr = GetModuleDataImpl(addr, moduleData); - } -#ifdef _DEBUG - else - { - DacpModuleData moduleDataLocal; - HRESULT hrLocal = GetModuleDataImpl(addr, &moduleDataLocal); - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(moduleData->Address == moduleDataLocal.Address); - _ASSERTE(moduleData->PEAssembly == moduleDataLocal.PEAssembly); - _ASSERTE(moduleData->ilBase == moduleDataLocal.ilBase); - _ASSERTE(moduleData->metadataStart == moduleDataLocal.metadataStart); - _ASSERTE(moduleData->metadataSize == moduleDataLocal.metadataSize); - _ASSERTE(moduleData->Assembly == moduleDataLocal.Assembly); - _ASSERTE(moduleData->bIsReflection == moduleDataLocal.bIsReflection); - _ASSERTE(moduleData->bIsPEFile == moduleDataLocal.bIsPEFile); - _ASSERTE(moduleData->dwBaseClassIndex == moduleDataLocal.dwBaseClassIndex); - _ASSERTE(moduleData->dwModuleID == moduleDataLocal.dwModuleID); - _ASSERTE(moduleData->dwTransientFlags == moduleDataLocal.dwTransientFlags); - _ASSERTE(moduleData->TypeDefToMethodTableMap == moduleDataLocal.TypeDefToMethodTableMap); - _ASSERTE(moduleData->TypeRefToMethodTableMap == moduleDataLocal.TypeRefToMethodTableMap); - _ASSERTE(moduleData->MethodDefToDescMap == moduleDataLocal.MethodDefToDescMap); - _ASSERTE(moduleData->FieldDefToDescMap == moduleDataLocal.FieldDefToDescMap); - _ASSERTE(moduleData->MemberRefToDescMap == moduleDataLocal.MemberRefToDescMap); - _ASSERTE(moduleData->FileReferencesMap == moduleDataLocal.FileReferencesMap); - _ASSERTE(moduleData->ManifestModuleReferencesMap == moduleDataLocal.ManifestModuleReferencesMap); - _ASSERTE(moduleData->LoaderAllocator == moduleDataLocal.LoaderAllocator); - _ASSERTE(moduleData->ThunkHeap == moduleDataLocal.ThunkHeap); - _ASSERTE(moduleData->dwModuleIndex == moduleDataLocal.dwModuleIndex); - } -#endif - } - else - { - hr = GetModuleDataImpl(addr, moduleData); - } - - SOSDacLeave(); - return hr; -} - -HRESULT -ClrDataAccess::GetModuleDataImpl(CLRDATA_ADDRESS addr, struct DacpModuleData *ModuleData) -{ Module* pModule = PTR_Module(TO_TADDR(addr)); ZeroMemory(ModuleData,sizeof(DacpModuleData)); @@ -2058,7 +1792,8 @@ ClrDataAccess::GetModuleDataImpl(CLRDATA_ADDRESS addr, struct DacpModuleData *Mo } EX_END_CATCH(SwallowAllExceptions) - return S_OK; + SOSDacLeave(); + return hr; } HRESULT @@ -2083,86 +1818,46 @@ ClrDataAccess::GetMethodTableData(CLRDATA_ADDRESS mt, struct DacpMethodTableData return E_INVALIDARG; SOSDacEnter(); - if (m_cdacSos != NULL) - { - // Try the cDAC first - it will return E_NOTIMPL if it doesn't support this method yet. Fall back to the DAC. - hr = m_cdacSos->GetMethodTableData(mt, MTData); - if (FAILED(hr)) - { - hr = GetMethodTableDataImpl(mt, MTData); - } -#ifdef _DEBUG - else - { - // Assert that the data is the same as what we get from the DAC. - DacpMethodTableData mtDataLocal; - HRESULT hrLocal = GetMethodTableDataImpl(mt, &mtDataLocal); - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(MTData->BaseSize == mtDataLocal.BaseSize); - _ASSERTE(MTData->ComponentSize == mtDataLocal.ComponentSize); - _ASSERTE(MTData->bIsFree == mtDataLocal.bIsFree); - _ASSERTE(MTData->Module == mtDataLocal.Module); - _ASSERTE(MTData->Class == mtDataLocal.Class); - _ASSERTE(MTData->ParentMethodTable == mtDataLocal.ParentMethodTable); - _ASSERTE(MTData->wNumInterfaces == mtDataLocal.wNumInterfaces); - _ASSERTE(MTData->wNumMethods == mtDataLocal.wNumMethods); - _ASSERTE(MTData->wNumVtableSlots == mtDataLocal.wNumVtableSlots); - _ASSERTE(MTData->wNumVirtuals == mtDataLocal.wNumVirtuals); - _ASSERTE(MTData->cl == mtDataLocal.cl); - _ASSERTE(MTData->dwAttrClass == mtDataLocal.dwAttrClass); - _ASSERTE(MTData->bContainsPointers == mtDataLocal.bContainsPointers); - _ASSERTE(MTData->bIsShared == mtDataLocal.bIsShared); - _ASSERTE(MTData->bIsDynamic == mtDataLocal.bIsDynamic); - } -#endif - } - else - { - hr = GetMethodTableDataImpl (mt, MTData); - } - SOSDacLeave(); - return hr; -} -HRESULT -ClrDataAccess::GetMethodTableDataImpl(CLRDATA_ADDRESS mt, struct DacpMethodTableData *MTData) -{ PTR_MethodTable pMT = PTR_MethodTable(TO_TADDR(mt)); BOOL bIsFree = FALSE; if (!DacValidateMethodTable(pMT, bIsFree)) { - return E_INVALIDARG; + hr = E_INVALIDARG; } - - ZeroMemory(MTData,sizeof(DacpMethodTableData)); - MTData->BaseSize = pMT->GetBaseSize(); - // [compat] SOS DAC APIs added this base size adjustment for strings - // due to: "2008/09/25 Title: New implementation of StringBuilder and improvements in String class" - // which changed StringBuilder not to use a String as an internal buffer and in the process - // changed the String internals so that StringObject::GetBaseSize() now includes the nul terminator character, - // which is apparently not expected by SOS. - if(pMT->IsString()) - MTData->BaseSize -= sizeof(WCHAR); - MTData->ComponentSize = (DWORD)pMT->GetComponentSize(); - MTData->bIsFree = bIsFree; - if(!bIsFree) - { - MTData->Module = HOST_CDADDR(pMT->GetModule()); - // Note: DacpMethodTableData::Class is really a pointer to the canonical method table - MTData->Class = HOST_CDADDR(pMT->GetClass()->GetMethodTable()); - MTData->ParentMethodTable = HOST_CDADDR(pMT->GetParentMethodTable());; - MTData->wNumInterfaces = (WORD)pMT->GetNumInterfaces(); - MTData->wNumMethods = pMT->GetNumMethods(); // printed as "number of vtable slots" and used to iterate over method slots - MTData->wNumVtableSlots = 0; // always return 0 since .NET 9 - MTData->wNumVirtuals = 0; // always return 0 since .NET 9 - MTData->cl = pMT->GetCl(); - MTData->dwAttrClass = pMT->GetAttrClass(); - MTData->bContainsPointers = pMT->ContainsGCPointers(); - MTData->bIsShared = FALSE; - MTData->bIsDynamic = pMT->IsDynamicStatics() ? TRUE : FALSE; + else + { + ZeroMemory(MTData,sizeof(DacpMethodTableData)); + MTData->BaseSize = pMT->GetBaseSize(); + // [compat] SOS DAC APIs added this base size adjustment for strings + // due to: "2008/09/25 Title: New implementation of StringBuilder and improvements in String class" + // which changed StringBuilder not to use a String as an internal buffer and in the process + // changed the String internals so that StringObject::GetBaseSize() now includes the nul terminator character, + // which is apparently not expected by SOS. + if(pMT->IsString()) + MTData->BaseSize -= sizeof(WCHAR); + MTData->ComponentSize = (DWORD)pMT->GetComponentSize(); + MTData->bIsFree = bIsFree; + if(!bIsFree) + { + MTData->Module = HOST_CDADDR(pMT->GetModule()); + // Note: DacpMethodTableData::Class is really a pointer to the canonical method table + MTData->Class = HOST_CDADDR(pMT->GetClass()->GetMethodTable()); + MTData->ParentMethodTable = HOST_CDADDR(pMT->GetParentMethodTable());; + MTData->wNumInterfaces = (WORD)pMT->GetNumInterfaces(); + MTData->wNumMethods = pMT->GetNumMethods(); // printed as "number of vtable slots" and used to iterate over method slots + MTData->wNumVtableSlots = 0; // always return 0 since .NET 9 + MTData->wNumVirtuals = 0; // always return 0 since .NET 9 + MTData->cl = pMT->GetCl(); + MTData->dwAttrClass = pMT->GetAttrClass(); + MTData->bContainsPointers = pMT->ContainsGCPointers(); + MTData->bIsShared = FALSE; + MTData->bIsDynamic = pMT->IsDynamicStatics() ? TRUE : FALSE; + } } - return S_OK; + + SOSDacLeave(); + return hr; } HRESULT @@ -2172,48 +1867,7 @@ ClrDataAccess::GetMethodTableName(CLRDATA_ADDRESS mt, unsigned int count, _Inout return E_INVALIDARG; SOSDacEnter(); - if (m_cdacSos != NULL) - { - // Try the cDAC first - it will return E_NOTIMPL if it doesn't support this method yet. Fall back to the DAC. - hr = m_cdacSos->GetMethodTableName(mt, count, mtName, pNeeded); - if (FAILED(hr)) - { - hr = GetMethodTableNameImpl(mt, count, mtName, pNeeded); - } -#ifdef _DEBUG - else - { - // Assert that the data is the same as what we get from the DAC. - NewArrayHolder pwszNameLocal(new WCHAR[count]); - unsigned int neededLocal = 0; - HRESULT hrLocal = GetMethodTableNameImpl(mt, count, mtName != NULL ? (WCHAR *)pwszNameLocal : NULL, pNeeded != NULL ? &neededLocal : NULL); - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - - if (mtName != NULL) - { - _ASSERTE(0 == u16_strncmp(mtName, (WCHAR *)pwszNameLocal, count)); - } - if (pNeeded != NULL) - { - _ASSERTE(*pNeeded == neededLocal); - } - } -#endif - } - else - { - hr = GetMethodTableNameImpl(mt, count, mtName, pNeeded); - } - SOSDacLeave(); - return hr; -} - -HRESULT -ClrDataAccess::GetMethodTableNameImpl(CLRDATA_ADDRESS mt, unsigned int count, _Inout_updates_z_(count) WCHAR *mtName, unsigned int *pNeeded) -{ - HRESULT hr = S_OK; PTR_MethodTable pMT = PTR_MethodTable(TO_TADDR(mt)); BOOL free = FALSE; @@ -2284,6 +1938,7 @@ ClrDataAccess::GetMethodTableNameImpl(CLRDATA_ADDRESS mt, unsigned int count, _I } } + SOSDacLeave(); return hr; } @@ -2453,46 +2108,20 @@ ClrDataAccess::GetMethodTableForEEClass(CLRDATA_ADDRESS eeClassReallyCanonMT, CL return E_INVALIDARG; SOSDacEnter(); - if (m_cdacSos != NULL) - { - // Try the cDAC first - it will return E_NOTIMPL if it doesn't support this method yet. Fall back to the DAC. - hr = m_cdacSos->GetMethodTableForEEClass(eeClassReallyCanonMT, value); - if (FAILED(hr)) - { - hr = GetMethodTableForEEClassImpl(eeClassReallyCanonMT, value); - } -#ifdef _DEBUG - else - { - // Assert that the data is the same as what we get from the DAC. - CLRDATA_ADDRESS valueLocal; - HRESULT hrLocal = GetMethodTableForEEClassImpl(eeClassReallyCanonMT, &valueLocal); - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(*value == valueLocal); - } -#endif - } - else - { - hr = GetMethodTableForEEClassImpl(eeClassReallyCanonMT, value); - } - SOSDacLeave(); - return hr; -} -HRESULT -ClrDataAccess::GetMethodTableForEEClassImpl(CLRDATA_ADDRESS eeClassReallyCanonMT, CLRDATA_ADDRESS *value) -{ PTR_MethodTable pCanonMT = PTR_MethodTable(TO_TADDR(eeClassReallyCanonMT)); BOOL bIsFree; if (!DacValidateMethodTable(pCanonMT, bIsFree)) { - return E_INVALIDARG; + hr = E_INVALIDARG; + } + else + { + *value = HOST_CDADDR(pCanonMT); } - *value = HOST_CDADDR(pCanonMT); - return S_OK; + SOSDacLeave(); + return hr; } HRESULT @@ -2543,40 +2172,6 @@ ClrDataAccess::GetPEFileName(CLRDATA_ADDRESS moduleAddr, unsigned int count, _In SOSDacEnter(); - if (m_cdacSos != NULL) - { - hr = m_cdacSos->GetPEFileName(moduleAddr, count, fileName, pNeeded); - if (FAILED(hr)) - { - hr = GetPEFileNameImpl(moduleAddr, count, fileName, pNeeded); - } -#ifdef _DEBUG - else - { - NewArrayHolder fileNameLocal(new WCHAR[count]); - unsigned int neededLocal = 0; - HRESULT hrLocal = GetPEFileNameImpl(moduleAddr, count, fileNameLocal, &neededLocal); - - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(pNeeded == NULL || *pNeeded == neededLocal); - _ASSERTE(fileName == NULL || u16_strncmp(fileName, fileNameLocal, count) == 0); - } -#endif - } - else - { - hr = GetPEFileNameImpl(moduleAddr, count, fileName, pNeeded);; - } - - - SOSDacLeave(); - return hr; -} - -HRESULT -ClrDataAccess::GetPEFileNameImpl(CLRDATA_ADDRESS moduleAddr, unsigned int count, _Inout_updates_z_(count) WCHAR *fileName, unsigned int *pNeeded) -{ PTR_Module pModule = PTR_Module(TO_TADDR(moduleAddr)); PEAssembly* pPEAssembly = pModule->GetPEAssembly(); @@ -2584,11 +2179,11 @@ ClrDataAccess::GetPEFileNameImpl(CLRDATA_ADDRESS moduleAddr, unsigned int count, if (!pPEAssembly->GetPath().IsEmpty()) { if (!pPEAssembly->GetPath().DacGetUnicode(count, fileName, pNeeded)) - return E_FAIL; + hr = E_FAIL; } else if (!pPEAssembly->IsReflectionEmit()) { - return E_NOTIMPL; + hr = E_NOTIMPL; } else { @@ -2599,7 +2194,8 @@ ClrDataAccess::GetPEFileNameImpl(CLRDATA_ADDRESS moduleAddr, unsigned int count, *pNeeded = 1; } - return S_OK; + SOSDacLeave(); + return hr; } HRESULT @@ -2610,37 +2206,6 @@ ClrDataAccess::GetPEFileBase(CLRDATA_ADDRESS moduleAddr, CLRDATA_ADDRESS *base) SOSDacEnter(); - if (m_cdacSos != NULL) - { - hr = m_cdacSos->GetPEFileBase(moduleAddr, base); - if (FAILED(hr)) - { - hr = GetPEFileBaseImpl(moduleAddr, base); - } -#ifdef _DEBUG - else - { - CLRDATA_ADDRESS baseLocal = 0; - HRESULT hrLocal = GetPEFileBaseImpl(moduleAddr, &baseLocal); - - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(*base == baseLocal); - } -#endif - } - else - { - hr = GetPEFileBaseImpl(moduleAddr, base); - } - - SOSDacLeave(); - return hr; -} - -HRESULT -ClrDataAccess::GetPEFileBaseImpl(CLRDATA_ADDRESS moduleAddr, CLRDATA_ADDRESS *base) -{ PTR_Module pModule = PTR_Module(TO_TADDR(moduleAddr)); // More fields later? @@ -2653,7 +2218,8 @@ ClrDataAccess::GetPEFileBaseImpl(CLRDATA_ADDRESS moduleAddr, CLRDATA_ADDRESS *ba *base = (CLRDATA_ADDRESS)NULL; } - return S_OK; + SOSDacLeave(); + return hr; } DWORD DACGetNumComponents(TADDR addr, ICorDebugDataTarget* target) @@ -2676,143 +2242,111 @@ DWORD DACGetNumComponents(TADDR addr, ICorDebugDataTarget* target) } HRESULT -ClrDataAccess::GetObjectData(CLRDATA_ADDRESS addr, struct DacpObjectData* objectData) +ClrDataAccess::GetObjectData(CLRDATA_ADDRESS addr, struct DacpObjectData *objectData) { if (addr == 0 || objectData == NULL) return E_INVALIDARG; SOSDacEnter(); - ZeroMemory (objectData, sizeof(DacpObjectData)); - if (m_cdacSos != NULL) - { - hr = m_cdacSos->GetObjectData(addr, objectData); - if (FAILED(hr)) - { - hr = GetObjectDataImpl(addr, objectData); - } -#ifdef _DEBUG - else - { - DacpObjectData objectDataLocal; - HRESULT hrLocal = GetObjectDataImpl(addr, &objectDataLocal); - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(objectData->MethodTable == objectDataLocal.MethodTable); - _ASSERTE(objectData->ObjectType == objectDataLocal.ObjectType); - _ASSERTE(objectData->Size == objectDataLocal.Size); - _ASSERTE(objectData->ElementTypeHandle == objectDataLocal.ElementTypeHandle); - _ASSERTE(objectData->ElementType == objectDataLocal.ElementType); - _ASSERTE(objectData->dwRank == objectDataLocal.dwRank); - _ASSERTE(objectData->dwNumComponents == objectDataLocal.dwNumComponents); - _ASSERTE(objectData->dwComponentSize == objectDataLocal.dwComponentSize); - _ASSERTE(objectData->ArrayDataPtr == objectDataLocal.ArrayDataPtr); - _ASSERTE(objectData->ArrayBoundsPtr == objectDataLocal.ArrayBoundsPtr); - _ASSERTE(objectData->ArrayLowerBoundsPtr == objectDataLocal.ArrayLowerBoundsPtr); - _ASSERTE(objectData->RCW == objectDataLocal.RCW); - _ASSERTE(objectData->CCW == objectDataLocal.CCW); - } -#endif - } - else - { - hr = GetObjectDataImpl(addr, objectData); - } - - SOSDacLeave(); - return hr; -} - -HRESULT -ClrDataAccess::GetObjectDataImpl(CLRDATA_ADDRESS addr, struct DacpObjectData *objectData) -{ TADDR mtTADDR = DACGetMethodTableFromObjectPointer(CLRDATA_ADDRESS_TO_TADDR(addr),m_pTarget); if (mtTADDR==(TADDR)NULL) - return E_INVALIDARG; + hr = E_INVALIDARG; BOOL bFree = FALSE; - PTR_MethodTable mt = PTR_MethodTable(mtTADDR); - if (!DacValidateMethodTable(mt, bFree)) - return E_INVALIDARG; - - objectData->MethodTable = HOST_CDADDR(mt); - objectData->Size = mt->GetBaseSize(); - if (mt->GetComponentSize()) + PTR_MethodTable mt = NULL; + if (SUCCEEDED(hr)) { - objectData->Size += (DACGetNumComponents(CLRDATA_ADDRESS_TO_TADDR(addr),m_pTarget) * mt->GetComponentSize()); - objectData->dwComponentSize = mt->GetComponentSize(); + mt = PTR_MethodTable(mtTADDR); + if (!DacValidateMethodTable(mt, bFree)) + hr = E_INVALIDARG; } - if (bFree) - { - objectData->ObjectType = OBJ_FREE; - } - else + if (SUCCEEDED(hr)) { - if (objectData->MethodTable == HOST_CDADDR(g_pStringClass)) + objectData->MethodTable = HOST_CDADDR(mt); + objectData->Size = mt->GetBaseSize(); + if (mt->GetComponentSize()) { - objectData->ObjectType = OBJ_STRING; + objectData->Size += (DACGetNumComponents(CLRDATA_ADDRESS_TO_TADDR(addr),m_pTarget) * mt->GetComponentSize()); + objectData->dwComponentSize = mt->GetComponentSize(); } - else if (objectData->MethodTable == HOST_CDADDR(g_pObjectClass)) + + if (bFree) { - objectData->ObjectType = OBJ_OBJECT; + objectData->ObjectType = OBJ_FREE; } - else if (mt->IsArray()) + else { - objectData->ObjectType = OBJ_ARRAY; + if (objectData->MethodTable == HOST_CDADDR(g_pStringClass)) + { + objectData->ObjectType = OBJ_STRING; + } + else if (objectData->MethodTable == HOST_CDADDR(g_pObjectClass)) + { + objectData->ObjectType = OBJ_OBJECT; + } + else if (mt->IsArray()) + { + objectData->ObjectType = OBJ_ARRAY; + + // For now, go ahead and instantiate array classes. + // TODO: avoid instantiating even object Arrays in the host. + // NOTE: This code is carefully written to deal with MethodTable fields + // in the array object having the mark bit set (because we may + // be in mark phase when this function is called). + ArrayBase *pArrayObj = PTR_ArrayBase(TO_TADDR(addr)); + objectData->ElementType = mt->GetArrayElementType(); - // For now, go ahead and instantiate array classes. - // TODO: avoid instantiating even object Arrays in the host. - // NOTE: This code is carefully written to deal with MethodTable fields - // in the array object having the mark bit set (because we may - // be in mark phase when this function is called). - ArrayBase *pArrayObj = PTR_ArrayBase(TO_TADDR(addr)); - objectData->ElementType = mt->GetArrayElementType(); + TypeHandle thElem = mt->GetArrayElementTypeHandle(); - TypeHandle thElem = mt->GetArrayElementTypeHandle(); + TypeHandle thCur = thElem; + while (thCur.IsArray()) + thCur = thCur.GetArrayElementTypeHandle(); - TypeHandle thCur = thElem; - while (thCur.IsArray()) - thCur = thCur.GetArrayElementTypeHandle(); + TADDR mtCurTADDR = thCur.AsTAddr(); + if (!DacValidateMethodTable(PTR_MethodTable(mtCurTADDR), bFree)) + { + hr = E_INVALIDARG; + } - TADDR mtCurTADDR = thCur.AsTAddr(); - if (!DacValidateMethodTable(PTR_MethodTable(mtCurTADDR), bFree)) + objectData->ElementTypeHandle = (CLRDATA_ADDRESS)(thElem.AsTAddr()); + objectData->dwRank = mt->GetRank(); + objectData->dwNumComponents = pArrayObj->GetNumComponents (); + objectData->ArrayDataPtr = PTR_CDADDR(pArrayObj->GetDataPtr (TRUE)); + objectData->ArrayBoundsPtr = HOST_CDADDR(pArrayObj->GetBoundsPtr()); + objectData->ArrayLowerBoundsPtr = HOST_CDADDR(pArrayObj->GetLowerBoundsPtr()); + } + else { - return E_INVALIDARG; + objectData->ObjectType = OBJ_OTHER; } - - objectData->ElementTypeHandle = (CLRDATA_ADDRESS)(thElem.AsTAddr()); - objectData->dwRank = mt->GetRank(); - objectData->dwNumComponents = pArrayObj->GetNumComponents (); - objectData->ArrayDataPtr = PTR_CDADDR(pArrayObj->GetDataPtr (TRUE)); - objectData->ArrayBoundsPtr = HOST_CDADDR(pArrayObj->GetBoundsPtr()); - objectData->ArrayLowerBoundsPtr = HOST_CDADDR(pArrayObj->GetLowerBoundsPtr()); - } - else - { - objectData->ObjectType = OBJ_OTHER; } } #ifdef FEATURE_COMINTEROP - EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY + if (SUCCEEDED(hr)) { - PTR_SyncBlock pSyncBlk = DACGetSyncBlockFromObjectPointer(CLRDATA_ADDRESS_TO_TADDR(addr), m_pTarget); - if (pSyncBlk != NULL) + EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY { - // see if we have an RCW and/or CCW associated with this object - PTR_InteropSyncBlockInfo pInfo = pSyncBlk->GetInteropInfoNoCreate(); - if (pInfo != NULL) + PTR_SyncBlock pSyncBlk = DACGetSyncBlockFromObjectPointer(CLRDATA_ADDRESS_TO_TADDR(addr), m_pTarget); + if (pSyncBlk != NULL) { - objectData->RCW = TO_CDADDR(pInfo->DacGetRawRCW()); - objectData->CCW = HOST_CDADDR(pInfo->GetCCW()); + // see if we have an RCW and/or CCW associated with this object + PTR_InteropSyncBlockInfo pInfo = pSyncBlk->GetInteropInfoNoCreate(); + if (pInfo != NULL) + { + objectData->RCW = TO_CDADDR(pInfo->DacGetRawRCW()); + objectData->CCW = HOST_CDADDR(pInfo->GetCCW()); + } } } + EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY; } - EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY; #endif // FEATURE_COMINTEROP - return S_OK; + SOSDacLeave(); + return hr; } HRESULT ClrDataAccess::GetAppDomainList(unsigned int count, CLRDATA_ADDRESS values[], unsigned int *fetched) @@ -3687,48 +3221,13 @@ ClrDataAccess::GetHeapAnalyzeStaticData(struct DacpGcHeapAnalyzeData *analyzeDat } HRESULT -ClrDataAccess::GetUsefulGlobals(struct DacpUsefulGlobalsData* globalsData) +ClrDataAccess::GetUsefulGlobals(struct DacpUsefulGlobalsData *globalsData) { if (globalsData == NULL) return E_INVALIDARG; SOSDacEnter(); - if (m_cdacSos != NULL) - { - hr = m_cdacSos->GetUsefulGlobals(globalsData); - if (FAILED(hr)) - { - hr = GetUsefulGlobalsImpl(globalsData); - } -#ifdef _DEBUG - else - { - // Assert that the data is the same as what we get from the DAC. - DacpUsefulGlobalsData globalsDataLocal; - HRESULT hrLocal = GetUsefulGlobalsImpl(&globalsDataLocal); - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(globalsData->ArrayMethodTable == globalsDataLocal.ArrayMethodTable); - _ASSERTE(globalsData->StringMethodTable == globalsDataLocal.StringMethodTable); - _ASSERTE(globalsData->ObjectMethodTable == globalsDataLocal.ObjectMethodTable); - _ASSERTE(globalsData->ExceptionMethodTable == globalsDataLocal.ExceptionMethodTable); - _ASSERTE(globalsData->FreeMethodTable == globalsDataLocal.FreeMethodTable); - } -#endif - } - else - { - hr = GetUsefulGlobalsImpl(globalsData);; - } - - SOSDacLeave(); - return hr; -} - -HRESULT -ClrDataAccess::GetUsefulGlobalsImpl(struct DacpUsefulGlobalsData *globalsData) -{ TypeHandle objArray = g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT]; if (objArray != NULL) globalsData->ArrayMethodTable = HOST_CDADDR(objArray.AsMethodTable()); @@ -3740,7 +3239,8 @@ ClrDataAccess::GetUsefulGlobalsImpl(struct DacpUsefulGlobalsData *globalsData) globalsData->ExceptionMethodTable = HOST_CDADDR(g_pExceptionClass); globalsData->FreeMethodTable = HOST_CDADDR(g_pFreeObjectMethodTable); - return S_OK; + SOSDacLeave(); + return hr; } HRESULT @@ -3751,40 +3251,6 @@ ClrDataAccess::GetNestedExceptionData(CLRDATA_ADDRESS exception, CLRDATA_ADDRESS SOSDacEnter(); - if (m_cdacSos != NULL) - { - // Try the cDAC first - it will return E_NOTIMPL if it doesn't support this method yet. Fall back to the DAC. - hr = m_cdacSos->GetNestedExceptionData(exception, exceptionObject, nextNestedException); - if (FAILED(hr)) - { - hr = GetNestedExceptionDataImpl(exception, exceptionObject, nextNestedException); - } -#ifdef _DEBUG - else - { - // Assert that the data is the same as what we get from the DAC. - CLRDATA_ADDRESS exceptionObjectLocal; - CLRDATA_ADDRESS nextNestedExceptionLocal; - HRESULT hrLocal = GetNestedExceptionDataImpl(exception, &exceptionObjectLocal, &nextNestedExceptionLocal); - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(*exceptionObject == exceptionObjectLocal); - _ASSERTE(*nextNestedException == nextNestedExceptionLocal); - } -#endif - } - else - { - hr = GetNestedExceptionDataImpl(exception, exceptionObject, nextNestedException); - } - - SOSDacLeave(); - return hr; -} - -HRESULT -ClrDataAccess::GetNestedExceptionDataImpl(CLRDATA_ADDRESS exception, CLRDATA_ADDRESS *exceptionObject, CLRDATA_ADDRESS *nextNestedException) -{ #ifdef FEATURE_EH_FUNCLETS ExceptionTrackerBase *pExData = PTR_ExceptionTrackerBase(TO_TADDR(exception)); #else @@ -3792,11 +3258,17 @@ ClrDataAccess::GetNestedExceptionDataImpl(CLRDATA_ADDRESS exception, CLRDATA_ADD #endif // FEATURE_EH_FUNCLETS if (!pExData) - return E_INVALIDARG; + { + hr = E_INVALIDARG; + } + else + { + *exceptionObject = TO_CDADDR(*PTR_TADDR(pExData->m_hThrowable)); + *nextNestedException = PTR_HOST_TO_TADDR(pExData->m_pPrevNestedInfo); + } - *exceptionObject = TO_CDADDR(*PTR_TADDR(pExData->m_hThrowable)); - *nextNestedException = PTR_HOST_TO_TADDR(pExData->m_pPrevNestedInfo); - return S_OK; + SOSDacLeave(); + return hr; } HRESULT @@ -5074,42 +4546,6 @@ HRESULT ClrDataAccess::GetObjectExceptionData(CLRDATA_ADDRESS objAddr, struct Da SOSDacEnter(); - if (m_cdacSos2 != NULL) - { - hr = m_cdacSos2->GetObjectExceptionData(objAddr, data); - if (FAILED(hr)) - { - hr = GetObjectExceptionDataImpl(objAddr, data); - } -#ifdef _DEBUG - else - { - DacpExceptionObjectData dataLocal; - HRESULT hrLocal = GetObjectExceptionDataImpl(objAddr, &dataLocal); - DacAssertsEnabledHolder assertsEnabled; - _ASSERTE(hr == hrLocal); - _ASSERTE(data->Message == dataLocal.Message); - _ASSERTE(data->InnerException == dataLocal.InnerException); - _ASSERTE(data->StackTrace == dataLocal.StackTrace); - _ASSERTE(data->WatsonBuckets == dataLocal.WatsonBuckets); - _ASSERTE(data->StackTraceString == dataLocal.StackTraceString); - _ASSERTE(data->RemoteStackTraceString == dataLocal.RemoteStackTraceString); - _ASSERTE(data->HResult == dataLocal.HResult); - _ASSERTE(data->XCode == dataLocal.XCode); - } -#endif - } - else - { - hr = GetObjectExceptionDataImpl(objAddr, data); - } - - SOSDacLeave(); - return hr; -} - -HRESULT ClrDataAccess::GetObjectExceptionDataImpl(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data) -{ PTR_ExceptionObject pObj = dac_cast(TO_TADDR(objAddr)); data->Message = TO_CDADDR(dac_cast(pObj->GetMessage())); data->InnerException = TO_CDADDR(dac_cast(pObj->GetInnerException())); @@ -5119,7 +4555,9 @@ HRESULT ClrDataAccess::GetObjectExceptionDataImpl(CLRDATA_ADDRESS objAddr, struc data->RemoteStackTraceString = TO_CDADDR(dac_cast(pObj->GetRemoteStackTraceString())); data->HResult = pObj->GetHResult(); data->XCode = pObj->GetXCode(); - return S_OK; + + SOSDacLeave(); + return hr; } HRESULT ClrDataAccess::IsRCWDCOMProxy(CLRDATA_ADDRESS rcwAddr, BOOL* isDCOMProxy) @@ -5560,15 +4998,7 @@ HRESULT ClrDataAccess::GetBreakingChangeVersion(int* pVersion) if (pVersion == nullptr) return E_INVALIDARG; - if (m_cdacSos9 != nullptr && SUCCEEDED(m_cdacSos9->GetBreakingChangeVersion(pVersion))) - { - _ASSERTE(*pVersion == SOS_BREAKING_CHANGE_VERSION); - } - else - { - *pVersion = SOS_BREAKING_CHANGE_VERSION; - } - + *pVersion = SOS_BREAKING_CHANGE_VERSION; return S_OK; } diff --git a/src/native/managed/cdacreader/inc/cdac_reader.h b/src/native/managed/cdacreader/inc/cdac_reader.h index 505dab92815db..8fe07b4d013e4 100644 --- a/src/native/managed/cdacreader/inc/cdac_reader.h +++ b/src/native/managed/cdacreader/inc/cdac_reader.h @@ -22,8 +22,9 @@ int cdac_reader_free(intptr_t handle); // Get the SOS interface from the cDAC reader // handle: handle to the reader +// legacyImpl: optional legacy implementation of the interface tha will be used as a fallback // obj: returned SOS interface that can be QI'd to ISOSDacInterface* -int cdac_reader_get_sos_interface(intptr_t handle, IUnknown** obj); +int cdac_reader_create_sos_interface(intptr_t handle, IUnknown* legacyImpl, IUnknown** obj); #ifdef __cplusplus } diff --git a/src/native/managed/cdacreader/src/Entrypoints.cs b/src/native/managed/cdacreader/src/Entrypoints.cs index 17983bb68ed20..cc24447ef3f13 100644 --- a/src/native/managed/cdacreader/src/Entrypoints.cs +++ b/src/native/managed/cdacreader/src/Entrypoints.cs @@ -38,20 +38,24 @@ private static unsafe int Free(IntPtr handle) } /// - /// Get the SOS-DAC interface implementation. + /// Create the SOS-DAC interface implementation. /// /// Handle crated via cdac initialization + /// Optional. Pointer to legacy implementation of ISOSDacInterface* /// IUnknown pointer that can be queried for ISOSDacInterface* /// - [UnmanagedCallersOnly(EntryPoint = $"{CDAC}get_sos_interface")] - private static unsafe int GetSOSInterface(IntPtr handle, nint* obj) + [UnmanagedCallersOnly(EntryPoint = $"{CDAC}create_sos_interface")] + private static unsafe int CreateSosInterface(IntPtr handle, IntPtr legacyImplPtr, nint* obj) { ComWrappers cw = new StrategyBasedComWrappers(); Target? target = GCHandle.FromIntPtr(handle).Target as Target; if (target == null) return -1; - Legacy.SOSDacImpl impl = new(target); + object? legacyImpl = legacyImplPtr != IntPtr.Zero + ? cw.GetOrCreateObjectForComInstance(legacyImplPtr, CreateObjectFlags.None) + : null; + Legacy.SOSDacImpl impl = new(target, legacyImpl); nint ptr = cw.GetOrCreateComInterfaceForObject(impl, CreateComInterfaceFlags.None); *obj = ptr; return 0; diff --git a/src/native/managed/cdacreader/src/Legacy/ICLRData.cs b/src/native/managed/cdacreader/src/Legacy/ICLRData.cs new file mode 100644 index 0000000000000..5b33d833beb51 --- /dev/null +++ b/src/native/managed/cdacreader/src/Legacy/ICLRData.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace Microsoft.Diagnostics.DataContractReader.Legacy; + +// This file contains managed declarations for the IXCLRData interfaces. +// See src/coreclr/inc/clrdata.idl + +[GeneratedComInterface] +[Guid("471c35b4-7c2f-4ef0-a945-00f8c38056f1")] +internal unsafe partial interface ICLRDataEnumMemoryRegions +{ + [PreserveSig] + int EnumMemoryRegions(/*ICLRDataEnumMemoryRegionsCallback*/ void* callback, uint miniDumpFlags, /*CLRDataEnumMemoryFlags*/ int clrFlags); +} diff --git a/src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs b/src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs index 8bc3d91f1a5cb..e1d42466b5bcb 100644 --- a/src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs +++ b/src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs @@ -442,9 +442,165 @@ internal unsafe partial interface ISOSDacInterface2 int IsRCWDCOMProxy(ulong rcwAddress, int* inDCOMProxy); } +[GeneratedComInterface] +[Guid("B08C5CDC-FD8A-49C5-AB38-5FEEF35235B4")] +internal unsafe partial interface ISOSDacInterface3 +{ + [PreserveSig] + int GetGCInterestingInfoData(ulong interestingInfoAddr, /*struct DacpGCInterestingInfoData*/ void* data); + [PreserveSig] + int GetGCInterestingInfoStaticData(/*struct DacpGCInterestingInfoData*/ void* data); + [PreserveSig] + int GetGCGlobalMechanisms(nuint* globalMechanisms); +}; + +[GeneratedComInterface] +[Guid("74B9D34C-A612-4B07-93DD-5462178FCE11")] +internal unsafe partial interface ISOSDacInterface4 +{ + [PreserveSig] + int GetClrNotification([In, Out, MarshalUsing(CountElementName = nameof(count))] ulong[] arguments, int count, int* pNeeded); +}; + +[GeneratedComInterface] +[Guid("127d6abe-6c86-4e48-8e7b-220781c58101")] +internal unsafe partial interface ISOSDacInterface5 +{ + [PreserveSig] + int GetTieredVersions(ulong methodDesc, int rejitId, /*struct DacpTieredVersionData*/void* nativeCodeAddrs, int cNativeCodeAddrs, int* pcNativeCodeAddrs); +}; + +[GeneratedComInterface] +[Guid("11206399-4B66-4EDB-98EA-85654E59AD45")] +internal unsafe partial interface ISOSDacInterface6 +{ + [PreserveSig] + int GetMethodTableCollectibleData(ulong mt, /*struct DacpMethodTableCollectibleData*/ void* data); +}; + +[GeneratedComInterface] +[Guid("c1020dde-fe98-4536-a53b-f35a74c327eb")] +internal unsafe partial interface ISOSDacInterface7 +{ + [PreserveSig] + int GetPendingReJITID(ulong methodDesc, int* pRejitId); + [PreserveSig] + int GetReJITInformation(ulong methodDesc, int rejitId, /*struct DacpReJitData2*/ void* pRejitData); + [PreserveSig] + int GetProfilerModifiedILInformation(ulong methodDesc, /*struct DacpProfilerILData*/ void* pILData); + [PreserveSig] + int GetMethodsWithProfilerModifiedIL(ulong mod, ulong* methodDescs, int cMethodDescs, int* pcMethodDescs); +}; + +[GeneratedComInterface] +[Guid("c12f35a9-e55c-4520-a894-b3dc5165dfce")] +internal unsafe partial interface ISOSDacInterface8 +{ + [PreserveSig] + int GetNumberGenerations(uint* pGenerations); + + // WKS + [PreserveSig] + int GetGenerationTable(uint cGenerations, /*struct DacpGenerationData*/ void* pGenerationData, uint* pNeeded); + [PreserveSig] + int GetFinalizationFillPointers(uint cFillPointers, ulong* pFinalizationFillPointers, uint* pNeeded); + + // SVR + [PreserveSig] + int GetGenerationTableSvr(ulong heapAddr, uint cGenerations, /*struct DacpGenerationData*/ void* pGenerationData, uint* pNeeded); + [PreserveSig] + int GetFinalizationFillPointersSvr(ulong heapAddr, uint cFillPointers, ulong* pFinalizationFillPointers, uint* pNeeded); + + [PreserveSig] + int GetAssemblyLoadContext(ulong methodTable, ulong* assemblyLoadContext); +} + [GeneratedComInterface] [Guid("4eca42d8-7e7b-4c8a-a116-7bfbf6929267")] internal partial interface ISOSDacInterface9 { int GetBreakingChangeVersion(); } + +[GeneratedComInterface] +[Guid("90B8FCC3-7251-4B0A-AE3D-5C13A67EC9AA")] +internal unsafe partial interface ISOSDacInterface10 +{ + [PreserveSig] + int GetObjectComWrappersData(ulong objAddr, ulong* rcw, uint count, ulong* mowList, uint* pNeeded); + [PreserveSig] + int IsComWrappersCCW(ulong ccw, Interop.BOOL* isComWrappersCCW); + [PreserveSig] + int GetComWrappersCCWData(ulong ccw, ulong* managedObject, int* refCount); + [PreserveSig] + int IsComWrappersRCW(ulong rcw, Interop.BOOL* isComWrappersRCW); + [PreserveSig] + int GetComWrappersRCWData(ulong rcw, ulong* identity); +} + +[GeneratedComInterface] +[Guid("96BA1DB9-14CD-4492-8065-1CAAECF6E5CF")] +internal unsafe partial interface ISOSDacInterface11 +{ + [PreserveSig] + int IsTrackedType(ulong objAddr, Interop.BOOL* isTrackedType, Interop.BOOL* hasTaggedMemory); + [PreserveSig] + int GetTaggedMemory(ulong objAddr, ulong* taggedMemory, nuint* taggedMemorySizeInBytes); +} + +[GeneratedComInterface] +[Guid("1b93bacc-8ca4-432d-943a-3e6e7ec0b0a3")] +internal unsafe partial interface ISOSDacInterface12 +{ + [PreserveSig] + int GetGlobalAllocationContext(ulong* allocPtr, ulong* allocLimit); +} + +internal struct VISITHEAP +{ + public ulong blockData; + public nuint blockSize; + public Interop.BOOL blockIsCurrentBlock; +} + +[GeneratedComInterface] +[Guid("3176a8ed-597b-4f54-a71f-83695c6a8c5e")] +internal unsafe partial interface ISOSDacInterface13 +{ + [PreserveSig] + int TraverseLoaderHeap(ulong loaderHeapAddr, /*LoaderHeapKind*/ int kind, VISITHEAP pCallback); + [PreserveSig] + int GetDomainLoaderAllocator(ulong domainAddress, ulong* pLoaderAllocator); + [PreserveSig] + int GetLoaderAllocatorHeapNames(int count, char** ppNames, int* pNeeded); + [PreserveSig] + int GetLoaderAllocatorHeaps(ulong loaderAllocator, int count, ulong* pLoaderHeaps, /*LoaderHeapKind*/ int* pKinds, int* pNeeded); + [PreserveSig] + int GetHandleTableMemoryRegions(/*ISOSMemoryEnum*/ void** ppEnum); + [PreserveSig] + int GetGCBookkeepingMemoryRegions(/*ISOSMemoryEnum*/ void** ppEnum); + [PreserveSig] + int GetGCFreeRegions(/*ISOSMemoryEnum*/ void** ppEnum); + [PreserveSig] + int LockedFlush(); +} + +[GeneratedComInterface] +[Guid("9aa22aca-6dc6-4a0c-b4e0-70d2416b9837")] +internal unsafe partial interface ISOSDacInterface14 +{ + [PreserveSig] + int GetStaticBaseAddress(ulong methodTable, ulong* nonGCStaticsAddress, ulong* GCStaticsAddress); + [PreserveSig] + int GetThreadStaticBaseAddress(ulong methodTable, ulong thread, ulong* nonGCStaticsAddress, ulong* GCStaticsAddress); + [PreserveSig] + int GetMethodTableInitializationFlags(ulong methodTable, /*MethodTableInitializationFlags*/ int* initializationStatus); +} + +[GeneratedComInterface] +[Guid("7ed81261-52a9-4a23-a358-c3313dea30a8")] +internal unsafe partial interface ISOSDacInterface15 +{ + [PreserveSig] + int GetMethodTableSlotEnumerator(ulong mt, /*ISOSMethodEnum*/void** enumerator); +} diff --git a/src/native/managed/cdacreader/src/Legacy/IXCLRData.cs b/src/native/managed/cdacreader/src/Legacy/IXCLRData.cs new file mode 100644 index 0000000000000..fb2aff16dc7ac --- /dev/null +++ b/src/native/managed/cdacreader/src/Legacy/IXCLRData.cs @@ -0,0 +1,205 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace Microsoft.Diagnostics.DataContractReader.Legacy; + +// This file contains managed declarations for the IXCLRData interfaces. +// See src/coreclr/inc/xclrdata.idl + +[GeneratedComInterface] +[Guid("5c552ab6-fc09-4cb3-8e36-22fa03c798b7")] +internal unsafe partial interface IXCLRDataProcess +{ + [PreserveSig] + int Flush(); + + [PreserveSig] + int StartEnumTasks(ulong* handle); + [PreserveSig] + int EnumTask(ulong* handle, /*IXCLRDataTask*/ void** task); + [PreserveSig] + int EndEnumTasks(ulong handle); + + [PreserveSig] + int GetTaskByOSThreadID(uint osThreadID, /*IXCLRDataTask*/ void** task); + [PreserveSig] + int GetTaskByUniqueID(ulong taskID, /*IXCLRDataTask*/ void** task); + + [PreserveSig] + int GetFlags(uint* flags); + + [PreserveSig] + int IsSameObject(IXCLRDataProcess* process); + + [PreserveSig] + int GetManagedObject(/*IXCLRDataValue*/ void** value); + + [PreserveSig] + int GetDesiredExecutionState(uint* state); + [PreserveSig] + int SetDesiredExecutionState(uint state); + + [PreserveSig] + int GetAddressType(ulong address, /*CLRDataAddressType*/ uint* type); + + [PreserveSig] + int GetRuntimeNameByAddress( + ulong address, + uint flags, + uint bufLen, + uint* nameLen, + char* nameBuf, + ulong* displacement); + + [PreserveSig] + int StartEnumAppDomains(ulong* handle); + [PreserveSig] + int EnumAppDomain(ulong* handle, /*IXCLRDataAppDomain*/ void** appDomain); + [PreserveSig] + int EndEnumAppDomains(ulong handle); + [PreserveSig] + int GetAppDomainByUniqueID(ulong id, /*IXCLRDataAppDomain*/ void** appDomain); + + [PreserveSig] + int StartEnumAssemblies(ulong* handle); + [PreserveSig] + int EnumAssembly(ulong* handle, /*IXCLRDataAssembly*/ void** assembly); + [PreserveSig] + int EndEnumAssemblies(ulong handle); + + [PreserveSig] + int StartEnumModules(ulong* handle); + [PreserveSig] + int EnumModule(ulong* handle, /*IXCLRDataModule*/ void** mod); + [PreserveSig] + int EndEnumModules(ulong handle); + [PreserveSig] + int GetModuleByAddress(ulong address, /*IXCLRDataModule*/ void** mod); + + [PreserveSig] + int StartEnumMethodInstancesByAddress(ulong address, /*IXCLRDataAppDomain*/ void* appDomain, ulong* handle); + [PreserveSig] + int EnumMethodInstanceByAddress(ulong* handle, /*IXCLRDataMethodInstance*/ void** method); + [PreserveSig] + int EndEnumMethodInstancesByAddress(ulong handle); + + [PreserveSig] + int GetDataByAddress( + ulong address, + uint flags, + /*IXCLRDataAppDomain*/ void* appDomain, + /*IXCLRDataTask*/ void* tlsTask, + uint bufLen, + uint* nameLen, + char* nameBuf, + /*IXCLRDataValue*/ void** value, + ulong* displacement); + + [PreserveSig] + int GetExceptionStateByExceptionRecord(/*struct EXCEPTION_RECORD64*/ void* record, /*IXCLRDataExceptionState*/ void** exState); + [PreserveSig] + int TranslateExceptionRecordToNotification(/*struct EXCEPTION_RECORD64*/ void* record, /*IXCLRDataExceptionNotification*/ void* notify); + + [PreserveSig] + int Request(uint reqCode, uint inBufferSize, byte* inBuffer, uint outBufferSize, byte* outBuffer); + + [PreserveSig] + int CreateMemoryValue( + /*IXCLRDataAppDomain*/ void* appDomain, + /*IXCLRDataTask*/ void* tlsTask, + /*IXCLRDataTypeInstance*/ void* type, + ulong addr, + /*IXCLRDataValue*/ void** value); + + [PreserveSig] + int SetAllTypeNotifications(/*IXCLRDataModule*/ void* mod, uint flags); + [PreserveSig] + int SetAllCodeNotifications(/*IXCLRDataModule*/ void* mod, uint flags); + [PreserveSig] + int GetTypeNotifications( + uint numTokens, + /*IXCLRDataModule*/ void** mods, + /*IXCLRDataModule*/ void* singleMod, + [In, MarshalUsing(CountElementName = nameof(numTokens))] /*mdTypeDef*/ uint[] tokens, + [In, Out, MarshalUsing(CountElementName = nameof(numTokens))] uint[] flags); + [PreserveSig] + int SetTypeNotifications( + uint numTokens, + /*IXCLRDataModule*/ void** mods, + /*IXCLRDataModule*/ void* singleMod, + [In, MarshalUsing(CountElementName = nameof(numTokens))] /*mdTypeDef*/ uint[] tokens, + [In, MarshalUsing(CountElementName = nameof(numTokens))] uint[] flags, + uint singleFlags); + [PreserveSig] + int GetCodeNotifications( + uint numTokens, + /*IXCLRDataModule*/ void** mods, + /*IXCLRDataModule*/ void* singleMod, + [In, MarshalUsing(CountElementName = nameof(numTokens))] /*mdMethodDef*/ uint[] tokens, + [In, Out, MarshalUsing(CountElementName = nameof(numTokens))] uint[] flags); + [PreserveSig] + int SetCodeNotifications( + uint numTokens, + /*IXCLRDataModule*/ void** mods, + /*IXCLRDataModule*/ void* singleMod, + [In, MarshalUsing(CountElementName = nameof(numTokens))] /*mdMethodDef */ uint[] tokens, + [In, MarshalUsing(CountElementName = nameof(numTokens))] uint[] flags, + uint singleFlags); + [PreserveSig] + int GetOtherNotificationFlags(uint* flags); + [PreserveSig] + int SetOtherNotificationFlags(uint flags); + + [PreserveSig] + int StartEnumMethodDefinitionsByAddress(ulong address, ulong* handle); + [PreserveSig] + int EnumMethodDefinitionByAddress(ulong* handle, /*IXCLRDataMethodDefinition*/ void** method); + [PreserveSig] + int EndEnumMethodDefinitionsByAddress(ulong handle); + + [PreserveSig] + int FollowStub( + uint inFlags, + ulong inAddr, + /*struct CLRDATA_FOLLOW_STUB_BUFFER*/ void* inBuffer, + ulong* outAddr, + /*struct CLRDATA_FOLLOW_STUB_BUFFER*/ void* outBuffer, + uint* outFlags); + [PreserveSig] + int FollowStub2( + /*IXCLRDataTask*/ void* task, + uint inFlags, + ulong inAddr, + /*struct CLRDATA_FOLLOW_STUB_BUFFER*/ void* inBuffer, + ulong* outAddr, + /*struct CLRDATA_FOLLOW_STUB_BUFFER*/ void* outBuffer, + uint* outFlags); + + [PreserveSig] + int DumpNativeImage( + ulong loadedBase, + char* name, + /*IXCLRDataDisplay*/ void* display, + /*IXCLRLibrarySupport*/ void* libSupport, + /*IXCLRDisassemblySupport*/ void* dis); +} + +internal struct GcEvtArgs +{ + public /*GcEvt_t*/ uint type; + public int condemnedGeneration; +} + +[GeneratedComInterface] +[Guid("5c552ab6-fc09-4cb3-8e36-22fa03c798b8")] +internal unsafe partial interface IXCLRDataProcess2 : IXCLRDataProcess +{ + [PreserveSig] + int GetGcNotification(GcEvtArgs* gcEvtArgs); + [PreserveSig] + int SetGcNotification(GcEvtArgs gcEvtArgs); +} diff --git a/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.ICLRDataEnumMemoryRegions.cs b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.ICLRDataEnumMemoryRegions.cs new file mode 100644 index 0000000000000..c0a327e21f969 --- /dev/null +++ b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.ICLRDataEnumMemoryRegions.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace Microsoft.Diagnostics.DataContractReader.Legacy; + +/// +/// Implementation of ICLRDataEnumMemoryRegions interface intended to be passed out to consumers +/// interacting with the DAC via those COM interfaces. +/// +internal sealed unsafe partial class SOSDacImpl : ICLRDataEnumMemoryRegions +{ + int ICLRDataEnumMemoryRegions.EnumMemoryRegions(void* callback, uint miniDumpFlags, int clrFlags) + => _legacyEnumMemory is not null ? _legacyEnumMemory.EnumMemoryRegions(callback, miniDumpFlags, clrFlags) : HResults.E_NOTIMPL; +} diff --git a/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.IXCLRDataProcess.cs b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.IXCLRDataProcess.cs new file mode 100644 index 0000000000000..f2529c109dff3 --- /dev/null +++ b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.IXCLRDataProcess.cs @@ -0,0 +1,219 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; + +namespace Microsoft.Diagnostics.DataContractReader.Legacy; + +/// +/// Implementation of IXCLRDataProcess* interfaces intended to be passed out to consumers +/// interacting with the DAC via those COM interfaces. +/// +internal sealed unsafe partial class SOSDacImpl : IXCLRDataProcess, IXCLRDataProcess2 +{ + int IXCLRDataProcess.Flush() + => _legacyProcess is not null ? _legacyProcess.Flush() : HResults.E_NOTIMPL; + + int IXCLRDataProcess.StartEnumTasks(ulong* handle) + => _legacyProcess is not null ? _legacyProcess.StartEnumTasks(handle) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.EnumTask(ulong* handle, /*IXCLRDataTask*/ void** task) + => _legacyProcess is not null ? _legacyProcess.EnumTask(handle, task) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.EndEnumTasks(ulong handle) + => _legacyProcess is not null ? _legacyProcess.EndEnumTasks(handle) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetTaskByOSThreadID(uint osThreadID, /*IXCLRDataTask*/ void** task) + => _legacyProcess is not null ? _legacyProcess.GetTaskByOSThreadID(osThreadID, task) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetTaskByUniqueID(ulong taskID, /*IXCLRDataTask*/ void** task) + => _legacyProcess is not null ? _legacyProcess.GetTaskByUniqueID(taskID, task) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetFlags(uint* flags) + => _legacyProcess is not null ? _legacyProcess.GetFlags(flags) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.IsSameObject(IXCLRDataProcess* process) + => _legacyProcess is not null ? _legacyProcess.IsSameObject(process) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetManagedObject(/*IXCLRDataValue*/ void** value) + => _legacyProcess is not null ? _legacyProcess.GetManagedObject(value) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetDesiredExecutionState(uint* state) + => _legacyProcess is not null ? _legacyProcess.GetDesiredExecutionState(state) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.SetDesiredExecutionState(uint state) + => _legacyProcess is not null ? _legacyProcess.SetDesiredExecutionState(state) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetAddressType(ulong address, /*CLRDataAddressType*/ uint* type) + => _legacyProcess is not null ? _legacyProcess.GetAddressType(address, type) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetRuntimeNameByAddress( + ulong address, + uint flags, + uint bufLen, + uint* nameLen, + char* nameBuf, + ulong* displacement) + => _legacyProcess is not null ? _legacyProcess.GetRuntimeNameByAddress(address, flags, bufLen, nameLen, nameBuf, displacement) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.StartEnumAppDomains(ulong* handle) + => _legacyProcess is not null ? _legacyProcess.StartEnumAppDomains(handle) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.EnumAppDomain(ulong* handle, /*IXCLRDataAppDomain*/ void** appDomain) + => _legacyProcess is not null ? _legacyProcess.EnumAppDomain(handle, appDomain) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.EndEnumAppDomains(ulong handle) + => _legacyProcess is not null ? _legacyProcess.EndEnumAppDomains(handle) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetAppDomainByUniqueID(ulong id, /*IXCLRDataAppDomain*/ void** appDomain) + => _legacyProcess is not null ? _legacyProcess.GetAppDomainByUniqueID(id, appDomain) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.StartEnumAssemblies(ulong* handle) + => _legacyProcess is not null ? _legacyProcess.StartEnumAssemblies(handle) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.EnumAssembly(ulong* handle, /*IXCLRDataAssembly*/ void** assembly) + => _legacyProcess is not null ? _legacyProcess.EnumAssembly(handle, assembly) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.EndEnumAssemblies(ulong handle) + => _legacyProcess is not null ? _legacyProcess.EndEnumAssemblies(handle) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.StartEnumModules(ulong* handle) + => _legacyProcess is not null ? _legacyProcess.StartEnumModules(handle) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.EnumModule(ulong* handle, /*IXCLRDataModule*/ void** mod) + => _legacyProcess is not null ? _legacyProcess.EnumModule(handle, mod) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.EndEnumModules(ulong handle) + => _legacyProcess is not null ? _legacyProcess.EndEnumModules(handle) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetModuleByAddress(ulong address, /*IXCLRDataModule*/ void** mod) + => _legacyProcess is not null ? _legacyProcess.GetModuleByAddress(address, mod) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.StartEnumMethodInstancesByAddress(ulong address, /*IXCLRDataAppDomain*/ void* appDomain, ulong* handle) + => _legacyProcess is not null ? _legacyProcess.StartEnumMethodInstancesByAddress(address, appDomain, handle) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.EnumMethodInstanceByAddress(ulong* handle, /*IXCLRDataMethodInstance*/ void** method) + => _legacyProcess is not null ? _legacyProcess.EnumMethodInstanceByAddress(handle, method) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.EndEnumMethodInstancesByAddress(ulong handle) + => _legacyProcess is not null ? _legacyProcess.EndEnumMethodInstancesByAddress(handle) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetDataByAddress( + ulong address, + uint flags, + /*IXCLRDataAppDomain*/ void* appDomain, + /*IXCLRDataTask*/ void* tlsTask, + uint bufLen, + uint* nameLen, + char* nameBuf, + /*IXCLRDataValue*/ void** value, + ulong* displacement) + => _legacyProcess is not null ? _legacyProcess.GetDataByAddress(address, flags, appDomain, tlsTask, bufLen, nameLen, nameBuf, value, displacement) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetExceptionStateByExceptionRecord(/*struct EXCEPTION_RECORD64*/ void* record, /*IXCLRDataExceptionState*/ void** exState) + => _legacyProcess is not null ? _legacyProcess.GetExceptionStateByExceptionRecord(record, exState) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.TranslateExceptionRecordToNotification(/*struct EXCEPTION_RECORD64*/ void* record, /*IXCLRDataExceptionNotification*/ void* notify) + => _legacyProcess is not null ? _legacyProcess.TranslateExceptionRecordToNotification(record, notify) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.Request(uint reqCode, uint inBufferSize, byte* inBuffer, uint outBufferSize, byte* outBuffer) + => _legacyProcess is not null ? _legacyProcess.Request(reqCode, inBufferSize, inBuffer, outBufferSize, outBuffer) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.CreateMemoryValue( + /*IXCLRDataAppDomain*/ void* appDomain, + /*IXCLRDataTask*/ void* tlsTask, + /*IXCLRDataTypeInstance*/ void* type, + ulong addr, + /*IXCLRDataValue*/ void** value) + => _legacyProcess is not null ? _legacyProcess.CreateMemoryValue(appDomain, tlsTask, type, addr, value) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.SetAllTypeNotifications(/*IXCLRDataModule*/ void* mod, uint flags) + => _legacyProcess is not null ? _legacyProcess.SetAllTypeNotifications(mod, flags) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.SetAllCodeNotifications(/*IXCLRDataModule*/ void* mod, uint flags) + => _legacyProcess is not null ? _legacyProcess.SetAllCodeNotifications(mod, flags) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetTypeNotifications( + uint numTokens, + /*IXCLRDataModule*/ void** mods, + /*IXCLRDataModule*/ void* singleMod, + [In, MarshalUsing(CountElementName = nameof(numTokens))] /*mdTypeDef*/ uint[] tokens, + [In, Out, MarshalUsing(CountElementName = nameof(numTokens))] uint[] flags) + => _legacyProcess is not null ? _legacyProcess.GetTypeNotifications(numTokens, mods, singleMod, tokens, flags) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.SetTypeNotifications( + uint numTokens, + /*IXCLRDataModule*/ void** mods, + /*IXCLRDataModule*/ void* singleMod, + [In, MarshalUsing(CountElementName = nameof(numTokens))] /*mdTypeDef*/ uint[] tokens, + [In, MarshalUsing(CountElementName = nameof(numTokens))] uint[] flags, + uint singleFlags) + => _legacyProcess is not null ? _legacyProcess.SetTypeNotifications(numTokens, mods, singleMod, tokens, flags, singleFlags) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetCodeNotifications( + uint numTokens, + /*IXCLRDataModule*/ void** mods, + /*IXCLRDataModule*/ void* singleMod, + [In, MarshalUsing(CountElementName = nameof(numTokens))] /*mdMethodDef*/ uint[] tokens, + [In, Out, MarshalUsing(CountElementName = nameof(numTokens))] uint[] flags) + => _legacyProcess is not null ? _legacyProcess.GetCodeNotifications(numTokens, mods, singleMod, tokens, flags) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.SetCodeNotifications( + uint numTokens, + /*IXCLRDataModule*/ void** mods, + /*IXCLRDataModule*/ void* singleMod, + [In, MarshalUsing(CountElementName = nameof(numTokens))] /*mdMethodDef */ uint[] tokens, + [In, MarshalUsing(CountElementName = nameof(numTokens))] uint[] flags, + uint singleFlags) + => _legacyProcess is not null ? _legacyProcess.SetCodeNotifications(numTokens, mods, singleMod, tokens, flags, singleFlags) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.GetOtherNotificationFlags(uint* flags) + => _legacyProcess is not null ? _legacyProcess.GetOtherNotificationFlags(flags) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.SetOtherNotificationFlags(uint flags) + => _legacyProcess is not null ? _legacyProcess.SetOtherNotificationFlags(flags) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.StartEnumMethodDefinitionsByAddress(ulong address, ulong* handle) + => _legacyProcess is not null ? _legacyProcess.StartEnumMethodDefinitionsByAddress(address, handle) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.EnumMethodDefinitionByAddress(ulong* handle, /*IXCLRDataMethodDefinition*/ void** method) + => _legacyProcess is not null ? _legacyProcess.EnumMethodDefinitionByAddress(handle, method) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.EndEnumMethodDefinitionsByAddress(ulong handle) + => _legacyProcess is not null ? _legacyProcess.EndEnumMethodDefinitionsByAddress(handle) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.FollowStub( + uint inFlags, + ulong inAddr, + /*struct CLRDATA_FOLLOW_STUB_BUFFER*/ void* inBuffer, + ulong* outAddr, + /*struct CLRDATA_FOLLOW_STUB_BUFFER*/ void* outBuffer, + uint* outFlags) + => _legacyProcess is not null ? _legacyProcess.FollowStub(inFlags, inAddr, inBuffer, outAddr, outBuffer, outFlags) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.FollowStub2( + /*IXCLRDataTask*/ void* task, + uint inFlags, + ulong inAddr, + /*struct CLRDATA_FOLLOW_STUB_BUFFER*/ void* inBuffer, + ulong* outAddr, + /*struct CLRDATA_FOLLOW_STUB_BUFFER*/ void* outBuffer, + uint* outFlags) + => _legacyProcess is not null ? _legacyProcess.FollowStub2(task, inFlags, inAddr, inBuffer, outAddr, outBuffer, outFlags) : HResults.E_NOTIMPL; + + int IXCLRDataProcess.DumpNativeImage( + ulong loadedBase, + char* name, + /*IXCLRDataDisplay*/ void* display, + /*IXCLRLibrarySupport*/ void* libSupport, + /*IXCLRDisassemblySupport*/ void* dis) + => _legacyProcess is not null ? _legacyProcess.DumpNativeImage(loadedBase, name, display, libSupport, dis) : HResults.E_NOTIMPL; + + int IXCLRDataProcess2.GetGcNotification(GcEvtArgs* gcEvtArgs) + => _legacyProcess2 is not null ? _legacyProcess2.GetGcNotification(gcEvtArgs) : HResults.E_NOTIMPL; + + int IXCLRDataProcess2.SetGcNotification(GcEvtArgs gcEvtArgs) + => _legacyProcess2 is not null ? _legacyProcess2.SetGcNotification(gcEvtArgs) : HResults.E_NOTIMPL; +} diff --git a/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs index e56bbc04dd49c..58b129b4bbf91 100644 --- a/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs @@ -1,12 +1,14 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using Microsoft.Diagnostics.DataContractReader.Contracts; using System; +using System.Diagnostics; using System.Runtime.InteropServices; using System.Runtime.InteropServices.Marshalling; using System.Text; +using Microsoft.Diagnostics.DataContractReader.Contracts; + namespace Microsoft.Diagnostics.DataContractReader.Legacy; /// @@ -19,69 +21,154 @@ namespace Microsoft.Diagnostics.DataContractReader.Legacy; /// corresponding error code. /// [GeneratedComClass] -internal sealed partial class SOSDacImpl : ISOSDacInterface, ISOSDacInterface2, ISOSDacInterface9 +internal sealed unsafe partial class SOSDacImpl + : ISOSDacInterface, ISOSDacInterface2, ISOSDacInterface3, ISOSDacInterface4, ISOSDacInterface5, + ISOSDacInterface6, ISOSDacInterface7, ISOSDacInterface8, ISOSDacInterface9, ISOSDacInterface10, + ISOSDacInterface11, ISOSDacInterface12, ISOSDacInterface13, ISOSDacInterface14, ISOSDacInterface15 { private readonly Target _target; private readonly TargetPointer _stringMethodTable; private readonly TargetPointer _objectMethodTable; - public SOSDacImpl(Target target) + private readonly ISOSDacInterface? _legacyImpl; + private readonly ISOSDacInterface2? _legacyImpl2; + private readonly ISOSDacInterface3? _legacyImpl3; + private readonly ISOSDacInterface4? _legacyImpl4; + private readonly ISOSDacInterface5? _legacyImpl5; + private readonly ISOSDacInterface6? _legacyImpl6; + private readonly ISOSDacInterface7? _legacyImpl7; + private readonly ISOSDacInterface8? _legacyImpl8; + private readonly ISOSDacInterface9? _legacyImpl9; + private readonly ISOSDacInterface10? _legacyImpl10; + private readonly ISOSDacInterface11? _legacyImpl11; + private readonly ISOSDacInterface12? _legacyImpl12; + private readonly ISOSDacInterface13? _legacyImpl13; + private readonly ISOSDacInterface14? _legacyImpl14; + private readonly ISOSDacInterface15? _legacyImpl15; + private readonly IXCLRDataProcess? _legacyProcess; + private readonly IXCLRDataProcess2? _legacyProcess2; + private readonly ICLRDataEnumMemoryRegions? _legacyEnumMemory; + + public SOSDacImpl(Target target, object? legacyObj) { _target = target; _stringMethodTable = _target.ReadPointer(_target.ReadGlobalPointer(Constants.Globals.StringMethodTable)); _objectMethodTable = _target.ReadPointer(_target.ReadGlobalPointer(Constants.Globals.ObjectMethodTable)); - } - public unsafe int GetAppDomainConfigFile(ulong appDomain, int count, char* configFile, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetAppDomainData(ulong addr, void* data) => HResults.E_NOTIMPL; - public unsafe int GetAppDomainList(uint count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] values, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetAppDomainName(ulong addr, uint count, char* name, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetAppDomainStoreData(void* data) => HResults.E_NOTIMPL; - public unsafe int GetApplicationBase(ulong appDomain, int count, char* appBase, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetAssemblyData(ulong baseDomainPtr, ulong assembly, void* data) => HResults.E_NOTIMPL; - public unsafe int GetAssemblyList(ulong appDomain, int count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] values, int* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetAssemblyLocation(ulong assembly, int count, char* location, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetAssemblyModuleList(ulong assembly, uint count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] modules, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetAssemblyName(ulong assembly, uint count, char* name, uint* pNeeded) => HResults.E_NOTIMPL; - - public int GetBreakingChangeVersion() - { - return _target.ReadGlobal(Constants.Globals.SOSBreakingChangeVersion); + // Get all the interfaces for delegating to the legacy DAC + if (legacyObj is not null) + { + _legacyImpl = legacyObj as ISOSDacInterface; + _legacyImpl2 = legacyObj as ISOSDacInterface2; + _legacyImpl3 = legacyObj as ISOSDacInterface3; + _legacyImpl4 = legacyObj as ISOSDacInterface4; + _legacyImpl5 = legacyObj as ISOSDacInterface5; + _legacyImpl6 = legacyObj as ISOSDacInterface6; + _legacyImpl7 = legacyObj as ISOSDacInterface7; + _legacyImpl8 = legacyObj as ISOSDacInterface8; + _legacyImpl9 = legacyObj as ISOSDacInterface9; + _legacyImpl10 = legacyObj as ISOSDacInterface10; + _legacyImpl11 = legacyObj as ISOSDacInterface11; + _legacyImpl12 = legacyObj as ISOSDacInterface12; + _legacyImpl13 = legacyObj as ISOSDacInterface13; + _legacyImpl14 = legacyObj as ISOSDacInterface14; + _legacyImpl15 = legacyObj as ISOSDacInterface15; + + _legacyProcess = legacyObj as IXCLRDataProcess; + _legacyProcess2 = legacyObj as IXCLRDataProcess2; + + _legacyEnumMemory = legacyObj as ICLRDataEnumMemoryRegions; + } } - public unsafe int GetCCWData(ulong ccw, void* data) => HResults.E_NOTIMPL; - public unsafe int GetCCWInterfaces(ulong ccw, uint count, void* interfaces, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetClrWatsonBuckets(ulong thread, void* pGenericModeBlock) => HResults.E_NOTIMPL; - public unsafe int GetCodeHeaderData(ulong ip, void* data) => HResults.E_NOTIMPL; - public unsafe int GetCodeHeapList(ulong jitManager, uint count, void* codeHeaps, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetDacModuleHandle(void* phModule) => HResults.E_NOTIMPL; - public unsafe int GetDomainFromContext(ulong context, ulong* domain) => HResults.E_NOTIMPL; - public unsafe int GetDomainLocalModuleData(ulong addr, void* data) => HResults.E_NOTIMPL; - public unsafe int GetDomainLocalModuleDataFromAppDomain(ulong appDomainAddr, int moduleID, void* data) => HResults.E_NOTIMPL; - public unsafe int GetDomainLocalModuleDataFromModule(ulong moduleAddr, void* data) => HResults.E_NOTIMPL; - public unsafe int GetFailedAssemblyData(ulong assembly, uint* pContext, int* pResult) => HResults.E_NOTIMPL; - public unsafe int GetFailedAssemblyDisplayName(ulong assembly, uint count, char* name, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetFailedAssemblyList(ulong appDomain, int count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] values, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetFailedAssemblyLocation(ulong assesmbly, uint count, char* location, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetFieldDescData(ulong fieldDesc, void* data) => HResults.E_NOTIMPL; - public unsafe int GetFrameName(ulong vtable, uint count, char* frameName, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetGCHeapData(void* data) => HResults.E_NOTIMPL; - public unsafe int GetGCHeapDetails(ulong heap, void* details) => HResults.E_NOTIMPL; - public unsafe int GetGCHeapList(uint count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] heaps, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetGCHeapStaticData(void* data) => HResults.E_NOTIMPL; - public unsafe int GetHandleEnum(void** ppHandleEnum) => HResults.E_NOTIMPL; - public unsafe int GetHandleEnumForGC(uint gen, void** ppHandleEnum) => HResults.E_NOTIMPL; - public unsafe int GetHandleEnumForTypes([In, MarshalUsing(CountElementName = "count")] uint[] types, uint count, void** ppHandleEnum) => HResults.E_NOTIMPL; - public unsafe int GetHeapAllocData(uint count, void* data, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetHeapAnalyzeData(ulong addr, void* data) => HResults.E_NOTIMPL; - public unsafe int GetHeapAnalyzeStaticData(void* data) => HResults.E_NOTIMPL; - public unsafe int GetHeapSegmentData(ulong seg, void* data) => HResults.E_NOTIMPL; - public unsafe int GetHillClimbingLogEntry(ulong addr, void* data) => HResults.E_NOTIMPL; - public unsafe int GetILForModule(ulong moduleAddr, int rva, ulong* il) => HResults.E_NOTIMPL; - public unsafe int GetJitHelperFunctionName(ulong ip, uint count, byte* name, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetJitManagerList(uint count, void* managers, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetJumpThunkTarget(void* ctx, ulong* targetIP, ulong* targetMD) => HResults.E_NOTIMPL; - public unsafe int GetMethodDescData(ulong methodDesc, ulong ip, DacpMethodDescData* data, uint cRevertedRejitVersions, DacpReJitData* rgRevertedRejitData, uint* pcNeededRevertedRejitData) + #region ISOSDacInterface + int ISOSDacInterface.GetAppDomainConfigFile(ulong appDomain, int count, char* configFile, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetAppDomainConfigFile(appDomain, count, configFile, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetAppDomainData(ulong addr, void* data) + => _legacyImpl is not null ? _legacyImpl.GetAppDomainData(addr, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetAppDomainList(uint count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] values, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetAppDomainList(count, values, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetAppDomainName(ulong addr, uint count, char* name, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetAppDomainName(addr, count, name, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetAppDomainStoreData(void* data) + => _legacyImpl is not null ? _legacyImpl.GetAppDomainStoreData(data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetApplicationBase(ulong appDomain, int count, char* appBase, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetApplicationBase(appDomain, count, appBase, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetAssemblyData(ulong baseDomainPtr, ulong assembly, void* data) + => _legacyImpl is not null ? _legacyImpl.GetAssemblyData(baseDomainPtr, assembly, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetAssemblyList(ulong appDomain, int count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] values, int* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetAssemblyList(appDomain, count, values, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetAssemblyLocation(ulong assembly, int count, char* location, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetAssemblyLocation(assembly, count, location, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetAssemblyModuleList(ulong assembly, uint count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] modules, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetAssemblyModuleList(assembly, count, modules, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetAssemblyName(ulong assembly, uint count, char* name, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetAssemblyName(assembly, count, name, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetCCWData(ulong ccw, void* data) + => _legacyImpl is not null ? _legacyImpl.GetCCWData(ccw, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetCCWInterfaces(ulong ccw, uint count, void* interfaces, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetCCWInterfaces(ccw, count, interfaces, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetClrWatsonBuckets(ulong thread, void* pGenericModeBlock) + => _legacyImpl is not null ? _legacyImpl.GetClrWatsonBuckets(thread, pGenericModeBlock) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetCodeHeaderData(ulong ip, void* data) + => _legacyImpl is not null ? _legacyImpl.GetCodeHeaderData(ip, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetCodeHeapList(ulong jitManager, uint count, void* codeHeaps, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetCodeHeapList(jitManager, count, codeHeaps, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetDacModuleHandle(void* phModule) + => _legacyImpl is not null ? _legacyImpl.GetDacModuleHandle(phModule) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetDomainFromContext(ulong context, ulong* domain) + => _legacyImpl is not null ? _legacyImpl.GetDomainFromContext(context, domain) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetDomainLocalModuleData(ulong addr, void* data) + => _legacyImpl is not null ? _legacyImpl.GetDomainLocalModuleData(addr, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetDomainLocalModuleDataFromAppDomain(ulong appDomainAddr, int moduleID, void* data) + => _legacyImpl is not null ? _legacyImpl.GetDomainLocalModuleDataFromAppDomain(appDomainAddr, moduleID, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetDomainLocalModuleDataFromModule(ulong moduleAddr, void* data) + => _legacyImpl is not null ? _legacyImpl.GetDomainLocalModuleDataFromModule(moduleAddr, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetFailedAssemblyData(ulong assembly, uint* pContext, int* pResult) + => _legacyImpl is not null ? _legacyImpl.GetFailedAssemblyData(assembly, pContext, pResult) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetFailedAssemblyDisplayName(ulong assembly, uint count, char* name, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetFailedAssemblyDisplayName(assembly, count, name, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetFailedAssemblyList(ulong appDomain, int count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] values, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetFailedAssemblyList(appDomain, count, values, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetFailedAssemblyLocation(ulong assesmbly, uint count, char* location, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetFailedAssemblyLocation(assesmbly, count, location, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetFieldDescData(ulong fieldDesc, void* data) + => _legacyImpl is not null ? _legacyImpl.GetFieldDescData(fieldDesc, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetFrameName(ulong vtable, uint count, char* frameName, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetFrameName(vtable, count, frameName, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetGCHeapData(void* data) + => _legacyImpl is not null ? _legacyImpl.GetGCHeapData(data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetGCHeapDetails(ulong heap, void* details) + => _legacyImpl is not null ? _legacyImpl.GetGCHeapDetails(heap, details) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetGCHeapList(uint count, [In, MarshalUsing(CountElementName = "count"), Out] ulong[] heaps, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetGCHeapList(count, heaps, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetGCHeapStaticData(void* data) + => _legacyImpl is not null ? _legacyImpl.GetGCHeapStaticData(data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetHandleEnum(void** ppHandleEnum) + => _legacyImpl is not null ? _legacyImpl.GetHandleEnum(ppHandleEnum) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetHandleEnumForGC(uint gen, void** ppHandleEnum) + => _legacyImpl is not null ? _legacyImpl.GetHandleEnumForGC(gen, ppHandleEnum) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetHandleEnumForTypes([In, MarshalUsing(CountElementName = "count")] uint[] types, uint count, void** ppHandleEnum) + => _legacyImpl is not null ? _legacyImpl.GetHandleEnumForTypes(types, count, ppHandleEnum) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetHeapAllocData(uint count, void* data, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetHeapAllocData(count, data, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetHeapAnalyzeData(ulong addr, void* data) + => _legacyImpl is not null ? _legacyImpl.GetHeapAnalyzeData(addr, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetHeapAnalyzeStaticData(void* data) + => _legacyImpl is not null ? _legacyImpl.GetHeapAnalyzeStaticData(data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetHeapSegmentData(ulong seg, void* data) + => _legacyImpl is not null ? _legacyImpl.GetHeapSegmentData(seg, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetHillClimbingLogEntry(ulong addr, void* data) + => _legacyImpl is not null ? _legacyImpl.GetHillClimbingLogEntry(addr, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetILForModule(ulong moduleAddr, int rva, ulong* il) + => _legacyImpl is not null ? _legacyImpl.GetILForModule(moduleAddr, rva, il) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetJitHelperFunctionName(ulong ip, uint count, byte* name, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetJitHelperFunctionName(ip, count, name, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetJitManagerList(uint count, void* managers, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetJitManagerList(count, managers, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetJumpThunkTarget(void* ctx, ulong* targetIP, ulong* targetMD) + => _legacyImpl is not null ? _legacyImpl.GetJumpThunkTarget(ctx, targetIP, targetMD) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetMethodDescData(ulong methodDesc, ulong ip, DacpMethodDescData* data, uint cRevertedRejitVersions, DacpReJitData* rgRevertedRejitData, uint* pcNeededRevertedRejitData) { if (methodDesc == 0) { @@ -103,17 +190,20 @@ public unsafe int GetMethodDescData(ulong methodDesc, ulong ip, DacpMethodDescDa Contracts.MethodDescHandle methodDescHandle = rtsContract.GetMethodDescHandle(methodDesc); data->MethodTablePtr = rtsContract.GetMethodTable(methodDescHandle); - - return HResults.E_NOTIMPL; } catch (global::System.Exception ex) { return ex.HResult; } + + return _legacyImpl is not null + ? _legacyImpl.GetMethodDescData(methodDesc, ip, data, cRevertedRejitVersions, rgRevertedRejitData, pcNeededRevertedRejitData) + : HResults.E_NOTIMPL; } - public unsafe int GetMethodDescFromToken(ulong moduleAddr, uint token, ulong* methodDesc) => HResults.E_NOTIMPL; - public unsafe int GetMethodDescName(ulong methodDesc, uint count, char* name, uint* pNeeded) + int ISOSDacInterface.GetMethodDescFromToken(ulong moduleAddr, uint token, ulong* methodDesc) + => _legacyImpl is not null ? _legacyImpl.GetMethodDescFromToken(moduleAddr, token, methodDesc) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetMethodDescName(ulong methodDesc, uint count, char* name, uint* pNeeded) { if (methodDesc == 0) return HResults.E_INVALIDARG; @@ -181,13 +271,31 @@ public unsafe int GetMethodDescName(ulong methodDesc, uint count, char* name, ui return ex.HResult; } +#if DEBUG + if (_legacyImpl is not null) + { + char[] nameLocal = new char[count]; + uint neededLocal; + int hrLocal; + fixed (char* ptr = nameLocal) + { + hrLocal = _legacyImpl.GetMethodDescName(methodDesc, count, ptr, &neededLocal); + } + Debug.Assert(hrLocal == HResults.S_OK); + Debug.Assert(pNeeded == null || *pNeeded == neededLocal); + Debug.Assert(name == null || new ReadOnlySpan(nameLocal, 0, (int)neededLocal - 1).SequenceEqual(new string(name))); + } +#endif return hr; } - public unsafe int GetMethodDescPtrFromFrame(ulong frameAddr, ulong* ppMD) => HResults.E_NOTIMPL; - public unsafe int GetMethodDescPtrFromIP(ulong ip, ulong* ppMD) => HResults.E_NOTIMPL; - public unsafe int GetMethodDescTransparencyData(ulong methodDesc, void* data) => HResults.E_NOTIMPL; - public unsafe int GetMethodTableData(ulong mt, DacpMethodTableData* data) + int ISOSDacInterface.GetMethodDescPtrFromFrame(ulong frameAddr, ulong* ppMD) + => _legacyImpl is not null ? _legacyImpl.GetMethodDescPtrFromFrame(frameAddr, ppMD) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetMethodDescPtrFromIP(ulong ip, ulong* ppMD) + => _legacyImpl is not null ? _legacyImpl.GetMethodDescPtrFromIP(ip, ppMD) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetMethodDescTransparencyData(ulong methodDesc, void* data) + => _legacyImpl is not null ? _legacyImpl.GetMethodDescTransparencyData(methodDesc, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetMethodTableData(ulong mt, DacpMethodTableData* data) { if (mt == 0 || data == null) return HResults.E_INVALIDARG; @@ -227,15 +335,37 @@ public unsafe int GetMethodTableData(ulong mt, DacpMethodTableData* data) result.bIsDynamic = contract.IsDynamicStatics(methodTable) ? 1 : 0; } *data = result; - return HResults.S_OK; } catch (System.Exception ex) { return ex.HResult; } + +#if DEBUG + if (_legacyImpl is not null) + { + DacpMethodTableData dataLocal; + int hrLocal = _legacyImpl.GetMethodTableData(mt, &dataLocal); + Debug.Assert(hrLocal == HResults.S_OK); + Debug.Assert(data->module == dataLocal.module); + Debug.Assert(data->klass == dataLocal.klass); + Debug.Assert(data->parentMethodTable == dataLocal.parentMethodTable); + Debug.Assert(data->wNumInterfaces == dataLocal.wNumInterfaces); + Debug.Assert(data->wNumMethods == dataLocal.wNumMethods); + Debug.Assert(data->wNumVtableSlots == dataLocal.wNumVtableSlots); + Debug.Assert(data->wNumVirtuals == dataLocal.wNumVirtuals); + Debug.Assert(data->cl == dataLocal.cl); + Debug.Assert(data->dwAttrClass == dataLocal.dwAttrClass); + Debug.Assert(data->bContainsGCPointers == dataLocal.bContainsGCPointers); + Debug.Assert(data->bIsShared == dataLocal.bIsShared); + Debug.Assert(data->bIsDynamic == dataLocal.bIsDynamic); + } +#endif + return HResults.S_OK; } - public unsafe int GetMethodTableFieldData(ulong mt, void* data) => HResults.E_NOTIMPL; - public unsafe int GetMethodTableForEEClass(ulong eeClassReallyCanonMT, ulong* value) + int ISOSDacInterface.GetMethodTableFieldData(ulong mt, void* data) + => _legacyImpl is not null ? _legacyImpl.GetMethodTableFieldData(mt, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetMethodTableForEEClass(ulong eeClassReallyCanonMT, ulong* value) { if (eeClassReallyCanonMT == 0 || value == null) return HResults.E_INVALIDARG; @@ -245,12 +375,22 @@ public unsafe int GetMethodTableForEEClass(ulong eeClassReallyCanonMT, ulong* va Contracts.IRuntimeTypeSystem contract = _target.Contracts.RuntimeTypeSystem; Contracts.TypeHandle methodTableHandle = contract.GetTypeHandle(eeClassReallyCanonMT); *value = methodTableHandle.Address; - return HResults.S_OK; } catch (global::System.Exception ex) { return ex.HResult; } + +#if DEBUG + if (_legacyImpl is not null) + { + ulong valueLocal; + int hrLocal = _legacyImpl.GetMethodTableForEEClass(eeClassReallyCanonMT, &valueLocal); + Debug.Assert(hrLocal == HResults.S_OK); + Debug.Assert(*value == valueLocal); + } +#endif + return HResults.S_OK; } private unsafe void CopyStringToTargetBuffer(char* stringBuf, uint bufferSize, uint* neededBufferSize, string str) @@ -269,7 +409,7 @@ private unsafe void CopyStringToTargetBuffer(char* stringBuf, uint bufferSize, u } } - public unsafe int GetMethodTableName(ulong mt, uint count, char* mtName, uint* pNeeded) + int ISOSDacInterface.GetMethodTableName(ulong mt, uint count, char* mtName, uint* pNeeded) { if (mt == 0) return HResults.E_INVALIDARG; @@ -307,19 +447,38 @@ public unsafe int GetMethodTableName(ulong mt, uint count, char* mtName, uint* p { } } CopyStringToTargetBuffer(mtName, count, pNeeded, methodTableName.ToString()); - return HResults.S_OK; } catch (global::System.Exception ex) { return ex.HResult; } + +#if DEBUG + if (_legacyImpl is not null) + { + char[] mtNameLocal = new char[count]; + uint neededLocal; + int hrLocal; + fixed (char* ptr = mtNameLocal) + { + hrLocal = _legacyImpl.GetMethodTableName(mt, count, ptr, &neededLocal); + } + Debug.Assert(hrLocal == HResults.S_OK); + Debug.Assert(pNeeded == null || *pNeeded == neededLocal); + Debug.Assert(mtName == null || new ReadOnlySpan(mtNameLocal, 0, (int)neededLocal - 1).SequenceEqual(new string(mtName))); + } +#endif + return HResults.S_OK; } - public unsafe int GetMethodTableSlot(ulong mt, uint slot, ulong* value) => HResults.E_NOTIMPL; - public unsafe int GetMethodTableTransparencyData(ulong mt, void* data) => HResults.E_NOTIMPL; - public unsafe int GetModule(ulong addr, void** mod) => HResults.E_NOTIMPL; + int ISOSDacInterface.GetMethodTableSlot(ulong mt, uint slot, ulong* value) + => _legacyImpl is not null ? _legacyImpl.GetMethodTableSlot(mt, slot, value) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetMethodTableTransparencyData(ulong mt, void* data) + => _legacyImpl is not null ? _legacyImpl.GetMethodTableTransparencyData(mt, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetModule(ulong addr, /*IXCLRDataModule*/ void** mod) + => _legacyImpl is not null ? _legacyImpl.GetModule(addr, mod) : HResults.E_NOTIMPL; - public unsafe int GetModuleData(ulong moduleAddr, DacpModuleData* data) + int ISOSDacInterface.GetModuleData(ulong moduleAddr, DacpModuleData* data) { if (moduleAddr == 0 || data == null) return HResults.E_INVALIDARG; @@ -368,11 +527,42 @@ public unsafe int GetModuleData(ulong moduleAddr, DacpModuleData* data) return e.HResult; } +#if DEBUG + if (_legacyImpl is not null) + { + DacpModuleData dataLocal; + int hrLocal = _legacyImpl.GetModuleData(moduleAddr, &dataLocal); + Debug.Assert(hrLocal == HResults.S_OK); + Debug.Assert(data->Address == dataLocal.Address); + Debug.Assert(data->PEAssembly == dataLocal.PEAssembly); + Debug.Assert(data->Assembly == dataLocal.Assembly); + Debug.Assert(data->isReflection == dataLocal.isReflection); + Debug.Assert(data->isPEFile == dataLocal.isPEFile); + Debug.Assert(data->dwTransientFlags == dataLocal.dwTransientFlags); + Debug.Assert(data->ilBase == dataLocal.ilBase); + Debug.Assert(data->metadataStart == dataLocal.metadataStart); + Debug.Assert(data->metadataSize == dataLocal.metadataSize); + Debug.Assert(data->LoaderAllocator == dataLocal.LoaderAllocator); + Debug.Assert(data->ThunkHeap == dataLocal.ThunkHeap); + Debug.Assert(data->FieldDefToDescMap == dataLocal.FieldDefToDescMap); + Debug.Assert(data->ManifestModuleReferencesMap == dataLocal.ManifestModuleReferencesMap); + Debug.Assert(data->MemberRefToDescMap == dataLocal.MemberRefToDescMap); + Debug.Assert(data->MethodDefToDescMap == dataLocal.MethodDefToDescMap); + Debug.Assert(data->TypeDefToMethodTableMap == dataLocal.TypeDefToMethodTableMap); + Debug.Assert(data->TypeRefToMethodTableMap == dataLocal.TypeRefToMethodTableMap); + Debug.Assert(data->dwModuleID == dataLocal.dwModuleID); + Debug.Assert(data->dwBaseClassIndex == dataLocal.dwBaseClassIndex); + Debug.Assert(data->dwModuleIndex == dataLocal.dwModuleIndex); + } +#endif return HResults.S_OK; } - public unsafe int GetNestedExceptionData(ulong exception, ulong* exceptionObject, ulong* nextNestedException) + int ISOSDacInterface.GetNestedExceptionData(ulong exception, ulong* exceptionObject, ulong* nextNestedException) { + if (exception == 0 || exceptionObject == null || nextNestedException == null) + return HResults.E_INVALIDARG; + try { Contracts.IException contract = _target.Contracts.Exception; @@ -385,13 +575,28 @@ public unsafe int GetNestedExceptionData(ulong exception, ulong* exceptionObject return ex.HResult; } +#if DEBUG + if (_legacyImpl is not null) + { + ulong exceptionObjectLocal; + ulong nextNestedExceptionLocal; + int hrLocal = _legacyImpl.GetNestedExceptionData(exception, &exceptionObjectLocal, &nextNestedExceptionLocal); + Debug.Assert(hrLocal == HResults.S_OK); + Debug.Assert(*exceptionObject == exceptionObjectLocal); + Debug.Assert(*nextNestedException == nextNestedExceptionLocal); + } +#endif return HResults.S_OK; } - public unsafe int GetObjectClassName(ulong obj, uint count, char* className, uint* pNeeded) => HResults.E_NOTIMPL; + int ISOSDacInterface.GetObjectClassName(ulong obj, uint count, char* className, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetObjectClassName(obj, count, className, pNeeded) : HResults.E_NOTIMPL; - public unsafe int GetObjectData(ulong objAddr, DacpObjectData* data) + int ISOSDacInterface.GetObjectData(ulong objAddr, DacpObjectData* data) { + if (objAddr == 0 || data == null) + return HResults.E_INVALIDARG; + try { Contracts.IObject objectContract = _target.Contracts.Object; @@ -469,34 +674,35 @@ public unsafe int GetObjectData(ulong objAddr, DacpObjectData* data) return ex.HResult; } - return HResults.S_OK; - } - - public unsafe int GetObjectExceptionData(ulong objectAddress, DacpExceptionObjectData* data) - { - try - { - Contracts.IException contract = _target.Contracts.Exception; - Contracts.ExceptionData exceptionData = contract.GetExceptionData(objectAddress); - data->Message = exceptionData.Message; - data->InnerException = exceptionData.InnerException; - data->StackTrace = exceptionData.StackTrace; - data->WatsonBuckets = exceptionData.WatsonBuckets; - data->StackTraceString = exceptionData.StackTraceString; - data->RemoteStackTraceString = exceptionData.RemoteStackTraceString; - data->HResult = exceptionData.HResult; - data->XCode = exceptionData.XCode; - } - catch (System.Exception ex) +#if DEBUG + if (_legacyImpl is not null) { - return ex.HResult; + DacpObjectData dataLocal; + int hrLocal = _legacyImpl.GetObjectData(objAddr, &dataLocal); + Debug.Assert(hrLocal == HResults.S_OK); + Debug.Assert(data->MethodTable == dataLocal.MethodTable); + Debug.Assert(data->ObjectType == dataLocal.ObjectType); + Debug.Assert(data->Size == dataLocal.Size); + Debug.Assert(data->ElementTypeHandle == dataLocal.ElementTypeHandle); + Debug.Assert(data->ElementType == dataLocal.ElementType); + Debug.Assert(data->dwRank == dataLocal.dwRank); + Debug.Assert(data->dwNumComponents == dataLocal.dwNumComponents); + Debug.Assert(data->dwComponentSize == dataLocal.dwComponentSize); + Debug.Assert(data->ArrayDataPtr == dataLocal.ArrayDataPtr); + Debug.Assert(data->ArrayBoundsPtr == dataLocal.ArrayBoundsPtr); + Debug.Assert(data->ArrayLowerBoundsPtr == dataLocal.ArrayLowerBoundsPtr); + Debug.Assert(data->RCW == dataLocal.RCW); + Debug.Assert(data->CCW == dataLocal.CCW); } - +#endif return HResults.S_OK; } - public unsafe int GetObjectStringData(ulong obj, uint count, char* stringData, uint* pNeeded) + int ISOSDacInterface.GetObjectStringData(ulong obj, uint count, char* stringData, uint* pNeeded) { + if (obj == 0 || (stringData == null && pNeeded == null) || (stringData is not null && count <= 0)) + return HResults.E_INVALIDARG; + try { Contracts.IObject contract = _target.Contracts.Object; @@ -508,13 +714,35 @@ public unsafe int GetObjectStringData(ulong obj, uint count, char* stringData, u return ex.HResult; } +#if DEBUG + if (_legacyImpl is not null) + { + char[] stringDataLocal = new char[count]; + uint neededLocal; + int hrLocal; + fixed (char* ptr = stringDataLocal) + { + hrLocal = _legacyImpl.GetObjectStringData(obj, count, ptr, &neededLocal); + } + Debug.Assert(hrLocal == HResults.S_OK); + Debug.Assert(pNeeded == null || *pNeeded == neededLocal); + Debug.Assert(stringData == null || new ReadOnlySpan(stringDataLocal, 0, (int)neededLocal - 1).SequenceEqual(new string(stringData))); + } +#endif + return HResults.S_OK; } - public unsafe int GetOOMData(ulong oomAddr, void* data) => HResults.E_NOTIMPL; - public unsafe int GetOOMStaticData(void* data) => HResults.E_NOTIMPL; - public unsafe int GetPEFileBase(ulong addr, ulong* peBase) + int ISOSDacInterface.GetOOMData(ulong oomAddr, void* data) + => _legacyImpl is not null ? _legacyImpl.GetOOMData(oomAddr, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetOOMStaticData(void* data) + => _legacyImpl is not null ? _legacyImpl.GetOOMStaticData(data) : HResults.E_NOTIMPL; + + int ISOSDacInterface.GetPEFileBase(ulong addr, ulong* peBase) { + if (addr == 0 || peBase == null) + return HResults.E_INVALIDARG; + try { Contracts.ILoader contract = _target.Contracts.Loader; @@ -535,11 +763,23 @@ public unsafe int GetPEFileBase(ulong addr, ulong* peBase) return ex.HResult; } +#if DEBUG + if (_legacyImpl is not null) + { + ulong peBaseLocal; + int hrLocal = _legacyImpl.GetPEFileBase(addr, &peBaseLocal); + Debug.Assert(hrLocal == HResults.S_OK); + Debug.Assert(*peBase == peBaseLocal); + } +#endif return HResults.S_OK; } - public unsafe int GetPEFileName(ulong addr, uint count, char* fileName, uint* pNeeded) + int ISOSDacInterface.GetPEFileName(ulong addr, uint count, char* fileName, uint* pNeeded) { + if (addr == 0 || (fileName == null && pNeeded == null) || (fileName is not null && count <= 0)) + return HResults.E_INVALIDARG; + try { Contracts.ILoader contract = _target.Contracts.Loader; @@ -563,22 +803,50 @@ public unsafe int GetPEFileName(ulong addr, uint count, char* fileName, uint* pN return ex.HResult; } +#if DEBUG + if (_legacyImpl is not null) + { + char[] fileNameLocal = new char[count]; + uint neededLocal; + int hrLocal; + fixed (char* ptr = fileNameLocal) + { + hrLocal = _legacyImpl.GetPEFileName(addr, count, ptr, &neededLocal); + } + Debug.Assert(hrLocal == HResults.S_OK); + Debug.Assert(pNeeded == null || *pNeeded == neededLocal); + Debug.Assert(fileName == null || new Span(fileName, (int)*pNeeded).SequenceEqual(fileNameLocal.AsSpan(0, (int)neededLocal))); + } +#endif return HResults.S_OK; } - public unsafe int GetPrivateBinPaths(ulong appDomain, int count, char* paths, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetRCWData(ulong addr, void* data) => HResults.E_NOTIMPL; - public unsafe int GetRCWInterfaces(ulong rcw, uint count, void* interfaces, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetRegisterName(int regName, uint count, char* buffer, uint* pNeeded) => HResults.E_NOTIMPL; - public unsafe int GetStackLimits(ulong threadPtr, ulong* lower, ulong* upper, ulong* fp) => HResults.E_NOTIMPL; - public unsafe int GetStackReferences(int osThreadID, void** ppEnum) => HResults.E_NOTIMPL; - public unsafe int GetStressLogAddress(ulong* stressLog) => HResults.E_NOTIMPL; - public unsafe int GetSyncBlockCleanupData(ulong addr, void* data) => HResults.E_NOTIMPL; - public unsafe int GetSyncBlockData(uint number, void* data) => HResults.E_NOTIMPL; - public unsafe int GetThreadAllocData(ulong thread, void* data) => HResults.E_NOTIMPL; - - public unsafe int GetThreadData(ulong thread, DacpThreadData* data) + int ISOSDacInterface.GetPrivateBinPaths(ulong appDomain, int count, char* paths, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetPrivateBinPaths(appDomain, count, paths, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetRCWData(ulong addr, void* data) + => _legacyImpl is not null ? _legacyImpl.GetRCWData(addr, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetRCWInterfaces(ulong rcw, uint count, void* interfaces, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetRCWInterfaces(rcw, count, interfaces, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetRegisterName(int regName, uint count, char* buffer, uint* pNeeded) + => _legacyImpl is not null ? _legacyImpl.GetRegisterName(regName, count, buffer, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetStackLimits(ulong threadPtr, ulong* lower, ulong* upper, ulong* fp) + => _legacyImpl is not null ? _legacyImpl.GetStackLimits(threadPtr, lower, upper, fp) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetStackReferences(int osThreadID, void** ppEnum) + => _legacyImpl is not null ? _legacyImpl.GetStackReferences(osThreadID, ppEnum) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetStressLogAddress(ulong* stressLog) + => _legacyImpl is not null ? _legacyImpl.GetStressLogAddress(stressLog) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetSyncBlockCleanupData(ulong addr, void* data) + => _legacyImpl is not null ? _legacyImpl.GetSyncBlockCleanupData(addr, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetSyncBlockData(uint number, void* data) + => _legacyImpl is not null ? _legacyImpl.GetSyncBlockData(number, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetThreadAllocData(ulong thread, void* data) + => _legacyImpl is not null ? _legacyImpl.GetThreadAllocData(thread, data) : HResults.E_NOTIMPL; + + int ISOSDacInterface.GetThreadData(ulong thread, DacpThreadData* data) { + if (thread == 0 || data == null) + return HResults.E_INVALIDARG; + try { Contracts.IThread contract = _target.Contracts.Thread; @@ -608,14 +876,43 @@ public unsafe int GetThreadData(ulong thread, DacpThreadData* data) return ex.HResult; } +#if DEBUG + if (_legacyImpl is not null) + { + DacpThreadData dataLocal; + int hrLocal = _legacyImpl.GetThreadData(thread, &dataLocal); + Debug.Assert(hrLocal >= 0); + Debug.Assert(data->corThreadId == dataLocal.corThreadId); + Debug.Assert(data->osThreadId == dataLocal.osThreadId); + Debug.Assert(data->state == dataLocal.state); + Debug.Assert(data->preemptiveGCDisabled == dataLocal.preemptiveGCDisabled); + Debug.Assert(data->allocContextPtr == dataLocal.allocContextPtr); + Debug.Assert(data->allocContextLimit == dataLocal.allocContextLimit); + Debug.Assert(data->fiberData == dataLocal.fiberData); + Debug.Assert(data->context == dataLocal.context); + Debug.Assert(data->domain == dataLocal.domain); + Debug.Assert(data->lockCount == dataLocal.lockCount); + Debug.Assert(data->pFrame == dataLocal.pFrame); + Debug.Assert(data->firstNestedException == dataLocal.firstNestedException); + Debug.Assert(data->teb == dataLocal.teb); + Debug.Assert(data->lastThrownObjectHandle == dataLocal.lastThrownObjectHandle); + Debug.Assert(data->nextThread == dataLocal.nextThread); + } +#endif return HResults.S_OK; } - public unsafe int GetThreadFromThinlockID(uint thinLockId, ulong* pThread) => HResults.E_NOTIMPL; - public unsafe int GetThreadLocalModuleData(ulong thread, uint index, void* data) => HResults.E_NOTIMPL; - public unsafe int GetThreadpoolData(void* data) => HResults.E_NOTIMPL; - - public unsafe int GetThreadStoreData(DacpThreadStoreData* data) + int ISOSDacInterface.GetThreadFromThinlockID(uint thinLockId, ulong* pThread) + => _legacyImpl is not null ? _legacyImpl.GetThreadFromThinlockID(thinLockId, pThread) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetThreadLocalModuleData(ulong thread, uint index, void* data) + => _legacyImpl is not null ? _legacyImpl.GetThreadLocalModuleData(thread, index, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.GetThreadpoolData(void* data) + => _legacyImpl is not null ? _legacyImpl.GetThreadpoolData(data) : HResults.E_NOTIMPL; + + int ISOSDacInterface.GetThreadStoreData(DacpThreadStoreData* data) { + if (data == null) + return HResults.E_INVALIDARG; + try { Contracts.IThread thread = _target.Contracts.Thread; @@ -638,13 +935,34 @@ public unsafe int GetThreadStoreData(DacpThreadStoreData* data) return ex.HResult; } +#if DEBUG + if (_legacyImpl is not null) + { + DacpThreadStoreData dataLocal; + int hrLocal = _legacyImpl.GetThreadStoreData(&dataLocal); + Debug.Assert(hrLocal >= 0); + Debug.Assert(data->threadCount == dataLocal.threadCount); + Debug.Assert(data->firstThread == dataLocal.firstThread); + Debug.Assert(data->finalizerThread == dataLocal.finalizerThread); + Debug.Assert(data->gcThread == dataLocal.gcThread); + Debug.Assert(data->unstartedThreadCount == dataLocal.unstartedThreadCount); + Debug.Assert(data->backgroundThreadCount == dataLocal.backgroundThreadCount); + Debug.Assert(data->pendingThreadCount == dataLocal.pendingThreadCount); + Debug.Assert(data->deadThreadCount == dataLocal.deadThreadCount); + Debug.Assert(data->fHostConfig == dataLocal.fHostConfig); + } +#endif return HResults.S_OK; } - public unsafe int GetTLSIndex(uint* pIndex) => HResults.E_NOTIMPL; + int ISOSDacInterface.GetTLSIndex(uint* pIndex) + => _legacyImpl is not null ? _legacyImpl.GetTLSIndex(pIndex) : HResults.E_NOTIMPL; - public unsafe int GetUsefulGlobals(DacpUsefulGlobalsData* data) + int ISOSDacInterface.GetUsefulGlobals(DacpUsefulGlobalsData* data) { + if (data == null) + return HResults.E_INVALIDARG; + try { data->ArrayMethodTable = _target.ReadPointer( @@ -661,14 +979,189 @@ public unsafe int GetUsefulGlobals(DacpUsefulGlobalsData* data) return ex.HResult; } +#if DEBUG + if (_legacyImpl is not null) + { + DacpUsefulGlobalsData dataLocal; + int hrLocal = _legacyImpl.GetUsefulGlobals(&dataLocal); + Debug.Assert(hrLocal >= 0); + Debug.Assert(data->ArrayMethodTable == dataLocal.ArrayMethodTable); + Debug.Assert(data->StringMethodTable == dataLocal.StringMethodTable); + Debug.Assert(data->ObjectMethodTable == dataLocal.ObjectMethodTable); + Debug.Assert(data->ExceptionMethodTable == dataLocal.ExceptionMethodTable); + Debug.Assert(data->FreeMethodTable == dataLocal.FreeMethodTable); + } +#endif + return HResults.S_OK; + } + + int ISOSDacInterface.GetWorkRequestData(ulong addrWorkRequest, void* data) + => _legacyImpl is not null ? _legacyImpl.GetWorkRequestData(addrWorkRequest, data) : HResults.E_NOTIMPL; + int ISOSDacInterface.TraverseEHInfo(ulong ip, void* pCallback, void* token) + => _legacyImpl is not null ? _legacyImpl.TraverseEHInfo(ip, pCallback, token) : HResults.E_NOTIMPL; + int ISOSDacInterface.TraverseLoaderHeap(ulong loaderHeapAddr, void* pCallback) + => _legacyImpl is not null ? _legacyImpl.TraverseLoaderHeap(loaderHeapAddr, pCallback) : HResults.E_NOTIMPL; + int ISOSDacInterface.TraverseModuleMap(int mmt, ulong moduleAddr, void* pCallback, void* token) + => _legacyImpl is not null ? _legacyImpl.TraverseModuleMap(mmt, moduleAddr, pCallback, token) : HResults.E_NOTIMPL; + int ISOSDacInterface.TraverseRCWCleanupList(ulong cleanupListPtr, void* pCallback, void* token) + => _legacyImpl is not null ? _legacyImpl.TraverseRCWCleanupList(cleanupListPtr, pCallback, token) : HResults.E_NOTIMPL; + int ISOSDacInterface.TraverseVirtCallStubHeap(ulong pAppDomain, int heaptype, void* pCallback) + => _legacyImpl is not null ? _legacyImpl.TraverseVirtCallStubHeap(pAppDomain, heaptype, pCallback) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface + + #region ISOSDacInterface2 + int ISOSDacInterface2.GetObjectExceptionData(ulong objectAddress, DacpExceptionObjectData* data) + { + try + { + Contracts.IException contract = _target.Contracts.Exception; + Contracts.ExceptionData exceptionData = contract.GetExceptionData(objectAddress); + data->Message = exceptionData.Message; + data->InnerException = exceptionData.InnerException; + data->StackTrace = exceptionData.StackTrace; + data->WatsonBuckets = exceptionData.WatsonBuckets; + data->StackTraceString = exceptionData.StackTraceString; + data->RemoteStackTraceString = exceptionData.RemoteStackTraceString; + data->HResult = exceptionData.HResult; + data->XCode = exceptionData.XCode; + } + catch (System.Exception ex) + { + return ex.HResult; + } + return HResults.S_OK; } - public unsafe int GetWorkRequestData(ulong addrWorkRequest, void* data) => HResults.E_NOTIMPL; - public unsafe int IsRCWDCOMProxy(ulong rcwAddress, int* inDCOMProxy) => HResults.E_NOTIMPL; - public unsafe int TraverseEHInfo(ulong ip, void* pCallback, void* token) => HResults.E_NOTIMPL; - public unsafe int TraverseLoaderHeap(ulong loaderHeapAddr, void* pCallback) => HResults.E_NOTIMPL; - public unsafe int TraverseModuleMap(int mmt, ulong moduleAddr, void* pCallback, void* token) => HResults.E_NOTIMPL; - public unsafe int TraverseRCWCleanupList(ulong cleanupListPtr, void* pCallback, void* token) => HResults.E_NOTIMPL; - public unsafe int TraverseVirtCallStubHeap(ulong pAppDomain, int heaptype, void* pCallback) => HResults.E_NOTIMPL; + int ISOSDacInterface2.IsRCWDCOMProxy(ulong rcwAddress, int* inDCOMProxy) + => _legacyImpl2 is not null ? _legacyImpl2.IsRCWDCOMProxy(rcwAddress, inDCOMProxy) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface2 + + #region ISOSDacInterface3 + int ISOSDacInterface3.GetGCInterestingInfoData(ulong interestingInfoAddr, /*struct DacpGCInterestingInfoData*/ void* data) + => _legacyImpl3 is not null ? _legacyImpl3.GetGCInterestingInfoData(interestingInfoAddr, data) : HResults.E_NOTIMPL; + int ISOSDacInterface3.GetGCInterestingInfoStaticData(/*struct DacpGCInterestingInfoData*/ void* data) + => _legacyImpl3 is not null ? _legacyImpl3.GetGCInterestingInfoStaticData(data) : HResults.E_NOTIMPL; + int ISOSDacInterface3.GetGCGlobalMechanisms(nuint* globalMechanisms) + => _legacyImpl3 is not null ? _legacyImpl3.GetGCGlobalMechanisms(globalMechanisms) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface3 + + #region ISOSDacInterface4 + int ISOSDacInterface4.GetClrNotification(ulong[] arguments, int count, int* pNeeded) + => _legacyImpl4 is not null ? _legacyImpl4.GetClrNotification(arguments, count, pNeeded) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface4 + + #region ISOSDacInterface5 + int ISOSDacInterface5.GetTieredVersions(ulong methodDesc, int rejitId, /*struct DacpTieredVersionData*/ void* nativeCodeAddrs, int cNativeCodeAddrs, int* pcNativeCodeAddrs) + => _legacyImpl5 is not null ? _legacyImpl5.GetTieredVersions(methodDesc, rejitId, nativeCodeAddrs, cNativeCodeAddrs, pcNativeCodeAddrs) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface5 + + #region ISOSDacInterface6 + int ISOSDacInterface6.GetMethodTableCollectibleData(ulong mt, /*struct DacpMethodTableCollectibleData*/ void* data) + => _legacyImpl6 is not null ? _legacyImpl6.GetMethodTableCollectibleData(mt, data) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface6 + + #region ISOSDacInterface7 + int ISOSDacInterface7.GetPendingReJITID(ulong methodDesc, int* pRejitId) + => _legacyImpl7 is not null ? _legacyImpl7.GetPendingReJITID(methodDesc, pRejitId) : HResults.E_NOTIMPL; + int ISOSDacInterface7.GetReJITInformation(ulong methodDesc, int rejitId, /*struct DacpReJitData2*/ void* pRejitData) + => _legacyImpl7 is not null ? _legacyImpl7.GetReJITInformation(methodDesc, rejitId, pRejitData) : HResults.E_NOTIMPL; + int ISOSDacInterface7.GetProfilerModifiedILInformation(ulong methodDesc, /*struct DacpProfilerILData*/ void* pILData) + => _legacyImpl7 is not null ? _legacyImpl7.GetProfilerModifiedILInformation(methodDesc, pILData) : HResults.E_NOTIMPL; + int ISOSDacInterface7.GetMethodsWithProfilerModifiedIL(ulong mod, ulong* methodDescs, int cMethodDescs, int* pcMethodDescs) + => _legacyImpl7 is not null ? _legacyImpl7.GetMethodsWithProfilerModifiedIL(mod, methodDescs, cMethodDescs, pcMethodDescs) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface7 + + #region ISOSDacInterface8 + int ISOSDacInterface8.GetNumberGenerations(uint* pGenerations) + => _legacyImpl8 is not null ? _legacyImpl8.GetNumberGenerations(pGenerations) : HResults.E_NOTIMPL; + + // WKS + int ISOSDacInterface8.GetGenerationTable(uint cGenerations, /*struct DacpGenerationData*/ void* pGenerationData, uint* pNeeded) + => _legacyImpl8 is not null ? _legacyImpl8.GetGenerationTable(cGenerations, pGenerationData, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface8.GetFinalizationFillPointers(uint cFillPointers, ulong* pFinalizationFillPointers, uint* pNeeded) + => _legacyImpl8 is not null ? _legacyImpl8.GetFinalizationFillPointers(cFillPointers, pFinalizationFillPointers, pNeeded) : HResults.E_NOTIMPL; + + // SVR + int ISOSDacInterface8.GetGenerationTableSvr(ulong heapAddr, uint cGenerations, /*struct DacpGenerationData*/ void* pGenerationData, uint* pNeeded) + => _legacyImpl8 is not null ? _legacyImpl8.GetGenerationTableSvr(heapAddr, cGenerations, pGenerationData, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface8.GetFinalizationFillPointersSvr(ulong heapAddr, uint cFillPointers, ulong* pFinalizationFillPointers, uint* pNeeded) + => _legacyImpl8 is not null ? _legacyImpl8.GetFinalizationFillPointersSvr(heapAddr, cFillPointers, pFinalizationFillPointers, pNeeded) : HResults.E_NOTIMPL; + + int ISOSDacInterface8.GetAssemblyLoadContext(ulong methodTable, ulong* assemblyLoadContext) + => _legacyImpl8 is not null ? _legacyImpl8.GetAssemblyLoadContext(methodTable, assemblyLoadContext) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface8 + + #region ISOSDacInterface9 + int ISOSDacInterface9.GetBreakingChangeVersion() + { + int version = _target.ReadGlobal(Constants.Globals.SOSBreakingChangeVersion); + +#if DEBUG + if (_legacyImpl9 is not null) + { + Debug.Assert(version == _legacyImpl9.GetBreakingChangeVersion()); + } +#endif + return version; + } + #endregion ISOSDacInterface9 + + #region ISOSDacInterface10 + int ISOSDacInterface10.GetObjectComWrappersData(ulong objAddr, ulong* rcw, uint count, ulong* mowList, uint* pNeeded) + => _legacyImpl10 is not null ? _legacyImpl10.GetObjectComWrappersData(objAddr, rcw, count, mowList, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface10.IsComWrappersCCW(ulong ccw, Interop.BOOL* isComWrappersCCW) + => _legacyImpl10 is not null ? _legacyImpl10.IsComWrappersCCW(ccw, isComWrappersCCW) : HResults.E_NOTIMPL; + int ISOSDacInterface10.GetComWrappersCCWData(ulong ccw, ulong* managedObject, int* refCount) + => _legacyImpl10 is not null ? _legacyImpl10.GetComWrappersCCWData(ccw, managedObject, refCount) : HResults.E_NOTIMPL; + int ISOSDacInterface10.IsComWrappersRCW(ulong rcw, Interop.BOOL* isComWrappersRCW) + => _legacyImpl10 is not null ? _legacyImpl10.IsComWrappersRCW(rcw, isComWrappersRCW) : HResults.E_NOTIMPL; + int ISOSDacInterface10.GetComWrappersRCWData(ulong rcw, ulong* identity) + => _legacyImpl10 is not null ? _legacyImpl10.GetComWrappersRCWData(rcw, identity) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface10 + + #region ISOSDacInterface11 + int ISOSDacInterface11.IsTrackedType(ulong objAddr, Interop.BOOL* isTrackedType, Interop.BOOL* hasTaggedMemory) + => _legacyImpl11 is not null ? _legacyImpl11.IsTrackedType(objAddr, isTrackedType, hasTaggedMemory) : HResults.E_NOTIMPL; + int ISOSDacInterface11.GetTaggedMemory(ulong objAddr, ulong* taggedMemory, nuint* taggedMemorySizeInBytes) + => _legacyImpl11 is not null ? _legacyImpl11.GetTaggedMemory(objAddr, taggedMemory, taggedMemorySizeInBytes) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface11 + + #region ISOSDacInterface12 + int ISOSDacInterface12.GetGlobalAllocationContext(ulong* allocPtr, ulong* allocLimit) + => _legacyImpl12 is not null ? _legacyImpl12.GetGlobalAllocationContext(allocPtr, allocLimit) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface12 + + #region ISOSDacInterface13 + int ISOSDacInterface13.TraverseLoaderHeap(ulong loaderHeapAddr, /*LoaderHeapKind*/ int kind, VISITHEAP pCallback) + => _legacyImpl13 is not null ? _legacyImpl13.TraverseLoaderHeap(loaderHeapAddr, kind, pCallback) : HResults.E_NOTIMPL; + int ISOSDacInterface13.GetDomainLoaderAllocator(ulong domainAddress, ulong* pLoaderAllocator) + => _legacyImpl13 is not null ? _legacyImpl13.GetDomainLoaderAllocator(domainAddress, pLoaderAllocator) : HResults.E_NOTIMPL; + int ISOSDacInterface13.GetLoaderAllocatorHeapNames(int count, char** ppNames, int* pNeeded) + => _legacyImpl13 is not null ? _legacyImpl13.GetLoaderAllocatorHeapNames(count, ppNames, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface13.GetLoaderAllocatorHeaps(ulong loaderAllocator, int count, ulong* pLoaderHeaps, /*LoaderHeapKind*/ int* pKinds, int* pNeeded) + => _legacyImpl13 is not null ? _legacyImpl13.GetLoaderAllocatorHeaps(loaderAllocator, count, pLoaderHeaps, pKinds, pNeeded) : HResults.E_NOTIMPL; + int ISOSDacInterface13.GetHandleTableMemoryRegions(/*ISOSMemoryEnum*/ void** ppEnum) + => _legacyImpl13 is not null ? _legacyImpl13.GetHandleTableMemoryRegions(ppEnum) : HResults.E_NOTIMPL; + int ISOSDacInterface13.GetGCBookkeepingMemoryRegions(/*ISOSMemoryEnum*/ void** ppEnum) + => _legacyImpl13 is not null ? _legacyImpl13.GetGCBookkeepingMemoryRegions(ppEnum) : HResults.E_NOTIMPL; + int ISOSDacInterface13.GetGCFreeRegions(/*ISOSMemoryEnum*/ void** ppEnum) + => _legacyImpl13 is not null ? _legacyImpl13.GetGCFreeRegions(ppEnum) : HResults.E_NOTIMPL; + int ISOSDacInterface13.LockedFlush() + => _legacyImpl13 is not null ? _legacyImpl13.LockedFlush() : HResults.E_NOTIMPL; + #endregion ISOSDacInterface13 + + #region ISOSDacInterface14 + int ISOSDacInterface14.GetStaticBaseAddress(ulong methodTable, ulong* nonGCStaticsAddress, ulong* GCStaticsAddress) + => _legacyImpl14 is not null ? _legacyImpl14.GetStaticBaseAddress(methodTable, nonGCStaticsAddress, GCStaticsAddress) : HResults.E_NOTIMPL; + int ISOSDacInterface14.GetThreadStaticBaseAddress(ulong methodTable, ulong thread, ulong* nonGCStaticsAddress, ulong* GCStaticsAddress) + => _legacyImpl14 is not null ? _legacyImpl14.GetThreadStaticBaseAddress(methodTable, thread, nonGCStaticsAddress, GCStaticsAddress) : HResults.E_NOTIMPL; + int ISOSDacInterface14.GetMethodTableInitializationFlags(ulong methodTable, /*MethodTableInitializationFlags*/ int* initializationStatus) + => _legacyImpl14 is not null ? _legacyImpl14.GetMethodTableInitializationFlags(methodTable, initializationStatus) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface14 + + #region ISOSDacInterface15 + int ISOSDacInterface15.GetMethodTableSlotEnumerator(ulong mt, /*ISOSMethodEnum*/void** enumerator) + => _legacyImpl15 is not null ? _legacyImpl15.GetMethodTableSlotEnumerator(mt, enumerator) : HResults.E_NOTIMPL; + #endregion ISOSDacInterface15 } diff --git a/src/native/managed/cdacreader/src/cdacreader.csproj b/src/native/managed/cdacreader/src/cdacreader.csproj index a8fd13e499234..2af9e9281927c 100644 --- a/src/native/managed/cdacreader/src/cdacreader.csproj +++ b/src/native/managed/cdacreader/src/cdacreader.csproj @@ -12,6 +12,15 @@ false + + $([MSBuild]::NormalizeDirectory('$(LibrariesProjectRoot)', 'Common', 'src')) + + + + + Common\Interop\Windows\Interop.BOOL.cs + +