diff --git a/src/coreclr/debug/daccess/dacimpl.h b/src/coreclr/debug/daccess/dacimpl.h index 5b9f59575a692..29eb2610eba9c 100644 --- a/src/coreclr/debug/daccess/dacimpl.h +++ b/src/coreclr/debug/daccess/dacimpl.h @@ -1242,6 +1242,7 @@ class ClrDataAccess 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 GetObjectStringDataImpl(CLRDATA_ADDRESS obj, unsigned int count, _Inout_updates_z_(count) WCHAR *stringData, unsigned int *pNeeded); + HRESULT GetUsefulGlobalsImpl(struct DacpUsefulGlobalsData *globalsData); BOOL IsExceptionFromManagedCode(EXCEPTION_RECORD * pExceptionRecord); #ifndef TARGET_UNIX @@ -2005,7 +2006,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()); @@ -3478,8 +3512,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 f51ddd2745fb0..ad62d803c08d8 100644 --- a/src/coreclr/debug/runtimeinfo/datadescriptor.h +++ b/src/coreclr/debug/runtimeinfo/datadescriptor.h @@ -282,7 +282,10 @@ CDAC_GLOBAL(ObjectToMethodTableUnmask, uint8, 1 | 1 << 1 | 1 << 2) CDAC_GLOBAL(ObjectToMethodTableUnmask, uint8, 1 | 1 << 1) #endif //TARGET_64BIT 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) diff --git a/src/native/managed/cdacreader/src/Constants.cs b/src/native/managed/cdacreader/src/Constants.cs index d713a5e69598e..0acafb3160426 100644 --- a/src/native/managed/cdacreader/src/Constants.cs +++ b/src/native/managed/cdacreader/src/Constants.cs @@ -17,7 +17,10 @@ internal static class Globals internal const string ObjectToMethodTableUnmask = nameof(ObjectToMethodTableUnmask); 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); 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 9faba1459ad37..7195a3ff591cc 100644 --- a/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdacreader/src/Legacy/SOSDacImpl.cs @@ -403,7 +403,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;