From 7bec01cb6b89c41675c19f2d9490688cb87e0968 Mon Sep 17 00:00:00 2001 From: Elinor Fung Date: Thu, 18 Jul 2024 11:08:35 -0700 Subject: [PATCH] [cdac] Implement ISOSDacInterface::GetUsefulGlobals --- src/coreclr/debug/daccess/dacimpl.h | 3 +- src/coreclr/debug/daccess/request.cpp | 39 +++++++++++++++++-- .../debug/runtimeinfo/datadescriptor.h | 4 ++ .../managed/cdacreader/src/Constants.cs | 4 ++ .../cdacreader/src/Legacy/ISOSDacInterface.cs | 11 +++++- .../cdacreader/src/Legacy/SOSDacImpl.cs | 25 +++++++++++- 6 files changed, 80 insertions(+), 6 deletions(-) diff --git a/src/coreclr/debug/daccess/dacimpl.h b/src/coreclr/debug/daccess/dacimpl.h index f3d12c3427263..70aed04d93470 100644 --- a/src/coreclr/debug/daccess/dacimpl.h +++ b/src/coreclr/debug/daccess/dacimpl.h @@ -1241,6 +1241,7 @@ class ClrDataAccess 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 GetObjectExceptionDataImpl(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data); + HRESULT GetUsefulGlobalsImpl(struct DacpUsefulGlobalsData *globalsData); BOOL IsExceptionFromManagedCode(EXCEPTION_RECORD * pExceptionRecord); #ifndef TARGET_UNIX @@ -2004,7 +2005,7 @@ class DacMethodTableSlotEnumerator : public DefaultCOMImplGetUsefulGlobals(globalsData); + if (FAILED(hr)) + { + hr = GetUsefulGlobals(globalsData); + } +#ifdef _DEBUG + else + { + // Assert that the data is the same as what we get from the DAC. + DacpUsefulGlobalsData globalsDataLocal; + HRESULT hrLocal = GetUsefulGlobalsImpl(&globalsDataLocal); + _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 = GetUsefulGlobals(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()); @@ -3449,8 +3483,7 @@ ClrDataAccess::GetUsefulGlobals(struct DacpUsefulGlobalsData *globalsData) globalsData->ExceptionMethodTable = HOST_CDADDR(g_pExceptionClass); globalsData->FreeMethodTable = HOST_CDADDR(g_pFreeObjectMethodTable); - SOSDacLeave(); - return hr; + return S_OK; } HRESULT diff --git a/src/coreclr/debug/runtimeinfo/datadescriptor.h b/src/coreclr/debug/runtimeinfo/datadescriptor.h index da83bebcfea39..85aad34502f99 100644 --- a/src/coreclr/debug/runtimeinfo/datadescriptor.h +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.h @@ -265,7 +265,11 @@ CDAC_GLOBAL(FeatureEHFunclets, uint8, 1) CDAC_GLOBAL(FeatureEHFunclets, uint8, 0) #endif CDAC_GLOBAL(SOSBreakingChangeVersion, uint8, SOS_BREAKING_CHANGE_VERSION) +CDAC_GLOBAL_POINTER(ExceptionMethodTable, &::g_pExceptionClass) CDAC_GLOBAL_POINTER(FreeObjectMethodTable, &::g_pFreeObjectMethodTable) +CDAC_GLOBAL_POINTER(ObjectMethodTable, &::g_pObjectClass) +CDAC_GLOBAL_POINTER(ObjectArrayMethodTable, &::g_pPredefinedArrayTypes[ELEMENT_TYPE_OBJECT]) +CDAC_GLOBAL_POINTER(StringMethodTable, &::g_pStringClass) CDAC_GLOBAL_POINTER(MiniMetaDataBuffAddress, &::g_MiniMetaDataBuffAddress) CDAC_GLOBAL_POINTER(MiniMetaDataBuffMaxSize, &::g_MiniMetaDataBuffMaxSize) CDAC_GLOBALS_END() diff --git a/src/native/managed/cdacreader/src/Constants.cs b/src/native/managed/cdacreader/src/Constants.cs index 6ca10e46a949b..2bceeff964272 100644 --- a/src/native/managed/cdacreader/src/Constants.cs +++ b/src/native/managed/cdacreader/src/Constants.cs @@ -16,7 +16,11 @@ internal static class Globals internal const string FeatureEHFunclets = nameof(FeatureEHFunclets); internal const string SOSBreakingChangeVersion = nameof(SOSBreakingChangeVersion); + internal const string ExceptionMethodTable = nameof(ExceptionMethodTable); internal const string FreeObjectMethodTable = nameof(FreeObjectMethodTable); + internal const string ObjectMethodTable = nameof(ObjectMethodTable); + internal const string ObjectArrayMethodTable = nameof(ObjectArrayMethodTable); + internal const string StringMethodTable = nameof(StringMethodTable); internal const string MiniMetaDataBuffAddress = nameof(MiniMetaDataBuffAddress); internal const string MiniMetaDataBuffMaxSize = nameof(MiniMetaDataBuffMaxSize); diff --git a/src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs b/src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs index ef4952f64f61c..25b7dd4fab2fb 100644 --- a/src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs +++ b/src/native/managed/cdacreader/src/Legacy/ISOSDacInterface.cs @@ -91,6 +91,15 @@ internal struct DacpMethodTableData public int bIsDynamic; public int bContainsGCPointers; } + +internal struct DacpUsefulGlobalsData +{ + public ulong ArrayMethodTable; + public ulong StringMethodTable; + public ulong ObjectMethodTable; + public ulong ExceptionMethodTable; + public ulong FreeMethodTable; +} #pragma warning restore CS0649 // Field is never assigned to, and will always have its default value [GeneratedComInterface] @@ -280,7 +289,7 @@ internal unsafe partial interface ISOSDacInterface // Other [PreserveSig] - int GetUsefulGlobals(/*struct DacpUsefulGlobalsData */ void* data); + int GetUsefulGlobals(DacpUsefulGlobalsData* data); [PreserveSig] int GetClrWatsonBuckets(ulong thread, void* pGenericModeBlock); [PreserveSig] diff --git a/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs index e4f2968f29f79..415b096619414 100644 --- a/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs @@ -389,7 +389,30 @@ public unsafe int GetThreadStoreData(DacpThreadStoreData* data) } public unsafe int GetTLSIndex(uint* pIndex) => HResults.E_NOTIMPL; - public unsafe int GetUsefulGlobals(void* data) => HResults.E_NOTIMPL; + + public unsafe int GetUsefulGlobals(DacpUsefulGlobalsData* data) + { + try + { + data->ArrayMethodTable = _target.ReadPointer( + _target.ReadGlobalPointer(Constants.Globals.ObjectArrayMethodTable)); + data->StringMethodTable = _target.ReadPointer( + _target.ReadGlobalPointer(Constants.Globals.StringMethodTable)); + data->ObjectMethodTable = _target.ReadPointer( + _target.ReadGlobalPointer(Constants.Globals.ObjectMethodTable)); + data->ExceptionMethodTable = _target.ReadPointer( + _target.ReadGlobalPointer(Constants.Globals.ExceptionMethodTable)); + data->FreeMethodTable = _target.ReadPointer( + _target.ReadGlobalPointer(Constants.Globals.FreeObjectMethodTable)); + } + 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;