From adba54da2298de9c715922b506bfe17a974a3650 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Mon, 14 Oct 2024 08:06:12 -0700 Subject: [PATCH] [cdac] Make cDAC delegate to the DAC instead of the other way around (#108772) - `SOSDacImpl` in cDAC implements all the interfaces implemented by `ClrDataAccess` - `CLRDataCreateInstance` returns cDAC if it is enabled - `cdac_reader_get_sos_interface` takes the legacy DAC implementation - Legacy DAC no longer calls into cDAC for its `ISOSDac*` implementations - cDAC delegates to legacy DAC (if it has one) for APIs it has not implemented and asserts that the results are the same for APIs it has implemented Behavioural differences of note: - Since asserts comparing results are in the cDAC instead of DAC now, they will come through as a fail fast with or without a debugger attached - as opposed to before, when they were silently ignored when a debugger was attached. The assert message will print to the debugger output (if attached) or OutputDebugString/syslog. - If the cDAC implementation of an API errors, it does not fall back to calling the legacy DAC. I think this is reasonable given that we plan to put the ability to choose cDAC vs legacy DAC at a higher level. If cDAC implementation fails, it should fail and not try to hide it. - `ClrDataAccess` lifetime is handled by cDAC (when enabled), so actual release is dependent on finalization of the COM object. I ran the SOS tests in diagnostics repo against this change locally both with and without the cDAC enabled. --- src/coreclr/debug/daccess/cdac.cpp | 17 +- src/coreclr/debug/daccess/cdac.h | 19 +- src/coreclr/debug/daccess/daccess.cpp | 73 +- src/coreclr/debug/daccess/dacimpl.h | 21 +- src/coreclr/debug/daccess/request.cpp | 938 ++++-------------- .../managed/cdacreader/inc/cdac_reader.h | 3 +- .../managed/cdacreader/src/Entrypoints.cs | 12 +- .../managed/cdacreader/src/Legacy/ICLRData.cs | 19 + .../cdacreader/src/Legacy/ISOSDacInterface.cs | 156 +++ .../cdacreader/src/Legacy/IXCLRData.cs | 205 ++++ .../SOSDacImpl.ICLRDataEnumMemoryRegions.cs | 16 + .../src/Legacy/SOSDacImpl.IXCLRDataProcess.cs | 219 ++++ .../cdacreader/src/Legacy/SOSDacImpl.cs | 743 +++++++++++--- .../managed/cdacreader/src/cdacreader.csproj | 9 + 14 files changed, 1503 insertions(+), 947 deletions(-) create mode 100644 src/native/managed/cdacreader/src/Legacy/ICLRData.cs create mode 100644 src/native/managed/cdacreader/src/Legacy/IXCLRData.cs create mode 100644 src/native/managed/cdacreader/src/Legacy/SOSDacImpl.ICLRDataEnumMemoryRegions.cs create mode 100644 src/native/managed/cdacreader/src/Legacy/SOSDacImpl.IXCLRDataProcess.cs 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 + +