From 981aa2cb6708f465a4f564debe9da8dd8303e5f8 Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Mon, 29 Aug 2022 18:39:27 -0700 Subject: [PATCH] Misc SOS fixes Use new EnumMemoryRegion flags. Update the clrdata.idl/clrdata.h/clrdata_i.cpp to the new DAC log message interface name. Change the name of the "enummemory" command to "enummem". Add memory region verify on the callback. Fix dumpobj/dumpruntimetypes with TypeDescs Add memory usage to sosstatus Fix https://github.com/dotnet/diagnostics/issues/3187 --- .../Host/StatusCommand.cs | 3 + .../ConsoleService.cs | 5 +- src/SOS/SOS.Hosting/Commands/SOSCommand.cs | 1 + src/SOS/Strike/sos.def | 2 +- src/SOS/Strike/sos_unixexports.src | 2 +- src/SOS/Strike/strike.cpp | 91 ++++++++++++++----- src/SOS/Strike/util.cpp | 2 +- src/Tools/dotnet-dump/Commands/SOSCommand.cs | 2 +- src/shared/inc/clrdata.idl | 2 +- src/shared/pal/prebuilt/idl/clrdata_i.cpp | 5 +- src/shared/pal/prebuilt/inc/clrdata.h | 52 ++++++----- 11 files changed, 109 insertions(+), 58 deletions(-) diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/Host/StatusCommand.cs b/src/Microsoft.Diagnostics.ExtensionCommands/Host/StatusCommand.cs index 5edce2a823..6f11b8b035 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/Host/StatusCommand.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/Host/StatusCommand.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using Microsoft.Diagnostics.DebugServices; +using System; namespace Microsoft.Diagnostics.ExtensionCommands { @@ -27,6 +28,8 @@ public override void Invoke() { Write(Target.ToString()); Write(SymbolService.ToString()); + long memoryUsage = GC.GetTotalMemory(forceFullCollection: true); + WriteLine($"GC memory usage: {memoryUsage:##,#} bytes"); } } } diff --git a/src/Microsoft.Diagnostics.Repl/ConsoleService.cs b/src/Microsoft.Diagnostics.Repl/ConsoleService.cs index fa4687baea..27bd1b4223 100644 --- a/src/Microsoft.Diagnostics.Repl/ConsoleService.cs +++ b/src/Microsoft.Diagnostics.Repl/ConsoleService.cs @@ -268,8 +268,9 @@ private void ClearLine() return; } - if (m_clearLine == null || m_clearLine.Length != Console.WindowWidth) { - m_clearLine = "\r" + new string(' ', Console.WindowWidth - 1); + int width = Console.WindowWidth; + if (m_clearLine == null || width != m_clearLine.Length) { + m_clearLine = "\r" + (width > 0 ? new string(' ', width - 1) : ""); } Console.Write(m_clearLine); diff --git a/src/SOS/SOS.Hosting/Commands/SOSCommand.cs b/src/SOS/SOS.Hosting/Commands/SOSCommand.cs index d4e5f38570..2d011c4804 100644 --- a/src/SOS/SOS.Hosting/Commands/SOSCommand.cs +++ b/src/SOS/SOS.Hosting/Commands/SOSCommand.cs @@ -36,6 +36,7 @@ namespace SOS.Hosting [Command(Name = "eeheap", DefaultOptions = "EEHeap", Help = "Displays info about process memory consumed by internal runtime data structures.")] [Command(Name = "eeversion", DefaultOptions = "EEVersion", Help = "Displays information about the runtime version.")] [Command(Name = "ehinfo", DefaultOptions = "EHInfo", Help = "Displays the exception handling blocks in a jitted method.")] + [Command(Name = "enummem", DefaultOptions = "enummem", Help = "ICLRDataEnumMemoryRegions.EnumMemoryRegions test command.")] [Command(Name = "finalizequeue", DefaultOptions = "FinalizeQueue", Help = "Displays all objects registered for finalization.")] [Command(Name = "findappdomain", DefaultOptions = "FindAppDomain", Help = "Attempts to resolve the AppDomain of a GC object.")] [Command(Name = "gchandles", DefaultOptions = "GCHandles", Help = "Provides statistics about GCHandles in the process.")] diff --git a/src/SOS/Strike/sos.def b/src/SOS/Strike/sos.def index 6dec87fd17..0e9876503f 100644 --- a/src/SOS/Strike/sos.def +++ b/src/SOS/Strike/sos.def @@ -74,7 +74,7 @@ EXPORTS EHInfo ehinfo=EHInfo Ehinfo=EHInfo - enummemory + enummem ext sos=ext FinalizeQueue diff --git a/src/SOS/Strike/sos_unixexports.src b/src/SOS/Strike/sos_unixexports.src index 9ac9f71d9a..95b267029e 100644 --- a/src/SOS/Strike/sos_unixexports.src +++ b/src/SOS/Strike/sos_unixexports.src @@ -30,7 +30,7 @@ EEHeap EEVersion EEStack EHInfo -enummemory +enummem FinalizeQueue FindAppDomain FindRoots diff --git a/src/SOS/Strike/strike.cpp b/src/SOS/Strike/strike.cpp index efd0124967..03d0ef1a9a 100644 --- a/src/SOS/Strike/strike.cpp +++ b/src/SOS/Strike/strike.cpp @@ -1455,11 +1455,19 @@ void PrintRuntimeTypeInfo(TADDR p_rtObject, const DacpObjectData & rtObjectData) if (iOffset > 0) { TADDR mtPtr; - if (SUCCEEDED(GetMTOfObject(p_rtObject + iOffset, &mtPtr))) + if (MOVE(mtPtr, p_rtObject + iOffset) == S_OK) { - sos::MethodTable mt = mtPtr; - ExtOut("Type Name: %S\n", mt.GetName()); - DMLOut("Type MT: %s\n", DMLMethodTable(mtPtr)); + // Check if TypeDesc + if ((mtPtr & 2) != 0) + { + ExtOut("TypeDesc: %p\n", mtPtr & ~2); + } + else + { + sos::MethodTable mt = mtPtr; + ExtOut("Type Name: %S\n", mt.GetName()); + DMLOut("Type MT: %s\n", DMLMethodTable(mtPtr)); + } } } } @@ -3912,24 +3920,34 @@ void PrintRuntimeTypes(DWORD_PTR objAddr,size_t Size,DWORD_PTR methodTable,LPVOI { DMLOut(DMLObject(objAddr)); - CLRDATA_ADDRESS appDomain = GetAppDomainForMT(mtPtr); - if (appDomain != NULL) + // Check if TypeDesc + if ((mtPtr & 2) != 0) { - if (appDomain == pArgs->adstore.sharedDomain) - ExtOut(" %" POINTERSIZE "s", "Shared"); - - else if (appDomain == pArgs->adstore.systemDomain) - ExtOut(" %" POINTERSIZE "s", "System"); - else - DMLOut(" %s", DMLDomain(appDomain)); + ExtOut(" %p\n", mtPtr & ~2); } else { - ExtOut(" %" POINTERSIZE "s", "?"); - } + CLRDATA_ADDRESS appDomain = GetAppDomainForMT(mtPtr); + if (appDomain != NULL) + { + if (appDomain == pArgs->adstore.sharedDomain) + ExtOut(" %" POINTERSIZE "s", "Shared"); + + else if (appDomain == pArgs->adstore.systemDomain) + ExtOut(" %" POINTERSIZE "s", "System"); + else + DMLOut(" %s", DMLDomain(appDomain)); + } + else + { + ExtOut(" %" POINTERSIZE "s", "?"); + } - NameForMT_s(mtPtr, g_mdName, mdNameLen); - DMLOut(" %s %S\n", DMLMethodTable(mtPtr), g_mdName); + if (NameForMT_s(mtPtr, g_mdName, mdNameLen)) + { + DMLOut(" %s %S\n", DMLMethodTable(mtPtr), g_mdName); + } + } } } } @@ -15711,16 +15729,18 @@ DECLARE_API(StopOnCatch) return S_OK; } -class EnumMemoryCallback : public ICLRDataEnumMemoryRegionsCallback, ICLRDataEnumMemoryRegionsLoggingCallback +class EnumMemoryCallback : public ICLRDataEnumMemoryRegionsCallback, ICLRDataLoggingCallback { private: LONG m_ref; bool m_log; + bool m_valid; public: - EnumMemoryCallback(bool log) : + EnumMemoryCallback(bool log, bool valid) : m_ref(1), - m_log(log) + m_log(log), + m_valid(valid) { } @@ -15739,9 +15759,9 @@ class EnumMemoryCallback : public ICLRDataEnumMemoryRegionsCallback, ICLRDataEnu AddRef(); return S_OK; } - else if (InterfaceId == IID_ICLRDataEnumMemoryRegionsLoggingCallback) + else if (InterfaceId == IID_ICLRDataLoggingCallback) { - *Interface = (ICLRDataEnumMemoryRegionsLoggingCallback*)this; + *Interface = (ICLRDataLoggingCallback*)this; AddRef(); return S_OK; } @@ -15776,6 +15796,25 @@ class EnumMemoryCallback : public ICLRDataEnumMemoryRegionsCallback, ICLRDataEnu { ExtOut("%016llx %08x\n", address, size); } + if (m_valid) + { + uint64_t start = address; + uint64_t numberPages = (size + DT_OS_PAGE_SIZE - 1) / DT_OS_PAGE_SIZE; + for (size_t p = 0; p < numberPages; p++, start += DT_OS_PAGE_SIZE) + { + BYTE buffer[1]; + ULONG read; + if (FAILED(g_ExtData->ReadVirtual(start, buffer, 1, &read))) + { + ExtOut("Invalid: %016llx %08x start %016llx\n", address, size, start); + break; + } + } + } + if (IsInterrupt()) + { + return COR_E_OPERATIONCANCELED; + } return S_OK; } @@ -15783,11 +15822,15 @@ class EnumMemoryCallback : public ICLRDataEnumMemoryRegionsCallback, ICLRDataEnu /* [in] */ LPCSTR message) { ExtOut("%s", message); + if (IsInterrupt()) + { + return COR_E_OPERATIONCANCELED; + } return S_OK; } }; -DECLARE_API(enummemory) +DECLARE_API(enummem) { INIT_API(); @@ -15795,7 +15838,7 @@ DECLARE_API(enummemory) Status = g_clrData->QueryInterface(__uuidof(ICLRDataEnumMemoryRegions), (void**)&enumMemoryRegions); if (SUCCEEDED(Status)) { - ToRelease callback = new EnumMemoryCallback(false); + ToRelease callback = new EnumMemoryCallback(false, true); ULONG32 minidumpType = (MiniDumpWithPrivateReadWriteMemory | MiniDumpWithDataSegs | diff --git a/src/SOS/Strike/util.cpp b/src/SOS/Strike/util.cpp index 37b3f73ab4..3c55c64420 100644 --- a/src/SOS/Strike/util.cpp +++ b/src/SOS/Strike/util.cpp @@ -4406,7 +4406,7 @@ HRESULT GetMTOfObject(TADDR obj, TADDR *mt) // Read the MethodTable and if we succeed, get rid of the mark bits. HRESULT hr = rvCache->Read(obj, mt, sizeof(TADDR), NULL); if (SUCCEEDED(hr)) - *mt &= ~3; + *mt &= ~sos::Object::METHODTABLE_PTR_LOW_BITMASK; return hr; } diff --git a/src/Tools/dotnet-dump/Commands/SOSCommand.cs b/src/Tools/dotnet-dump/Commands/SOSCommand.cs index 4d3a2f4a8f..31e86ce941 100644 --- a/src/Tools/dotnet-dump/Commands/SOSCommand.cs +++ b/src/Tools/dotnet-dump/Commands/SOSCommand.cs @@ -10,7 +10,7 @@ namespace Microsoft.Diagnostics.Tools.Dump { - [Command(Name = "sos", Aliases = new string[] { "ext" }, Help = "Run SOS command", Flags = CommandFlags.Global | CommandFlags.Manual)] + [Command(Name = "sos", Aliases = new string[] { "ext" }, Help = "Run a SOS command.", Flags = CommandFlags.Global | CommandFlags.Manual)] public class SOSCommand : CommandBase { private readonly CommandService _commandService; diff --git a/src/shared/inc/clrdata.idl b/src/shared/inc/clrdata.idl index 4252dc6409..2663a7b057 100644 --- a/src/shared/inc/clrdata.idl +++ b/src/shared/inc/clrdata.idl @@ -296,7 +296,7 @@ interface ICLRDataEnumMemoryRegionsCallback2 : ICLRDataEnumMemoryRegionsCallback local, uuid(F315248D-8B79-49DB-B184-37426559F703) ] -interface ICLRDataEnumMemoryRegionsLoggingCallback : IUnknown +interface ICLRDataLoggingCallback : IUnknown { HRESULT LogMessage( [in] LPCSTR message); diff --git a/src/shared/pal/prebuilt/idl/clrdata_i.cpp b/src/shared/pal/prebuilt/idl/clrdata_i.cpp index 872841a0d9..26d36c133b 100644 --- a/src/shared/pal/prebuilt/idl/clrdata_i.cpp +++ b/src/shared/pal/prebuilt/idl/clrdata_i.cpp @@ -1,4 +1,5 @@ - +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. /* this ALWAYS GENERATED file contains the IIDs and CLSIDs */ @@ -86,7 +87,7 @@ MIDL_DEFINE_GUID(IID, IID_ICLRDataEnumMemoryRegionsCallback,0xBCDD6908,0xBA2D,0x MIDL_DEFINE_GUID(IID, IID_ICLRDataEnumMemoryRegionsCallback2,0x3721A26F,0x8B91,0x4D98,0xA3,0x88,0xDB,0x17,0xB3,0x56,0xFA,0xDB); -MIDL_DEFINE_GUID(IID, IID_ICLRDataEnumMemoryRegionsLoggingCallback,0xF315248D,0x8B79,0x49DB,0xB1,0x84,0x37,0x42,0x65,0x59,0xF7,0x03); +MIDL_DEFINE_GUID(IID, IID_ICLRDataLoggingCallback,0xF315248D,0x8B79,0x49DB,0xB1,0x84,0x37,0x42,0x65,0x59,0xF7,0x03); MIDL_DEFINE_GUID(IID, IID_ICLRDataEnumMemoryRegions,0x471c35b4,0x7c2f,0x4ef0,0xa9,0x45,0x00,0xf8,0xc3,0x80,0x56,0xf1); diff --git a/src/shared/pal/prebuilt/inc/clrdata.h b/src/shared/pal/prebuilt/inc/clrdata.h index 3999908b26..802c34a87b 100644 --- a/src/shared/pal/prebuilt/inc/clrdata.h +++ b/src/shared/pal/prebuilt/inc/clrdata.h @@ -1,4 +1,5 @@ - +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. /* this ALWAYS GENERATED file contains the definitions for the interfaces */ @@ -100,11 +101,11 @@ typedef interface ICLRDataEnumMemoryRegionsCallback2 ICLRDataEnumMemoryRegionsCa #endif /* __ICLRDataEnumMemoryRegionsCallback2_FWD_DEFINED__ */ -#ifndef __ICLRDataEnumMemoryRegionsLoggingCallback_FWD_DEFINED__ -#define __ICLRDataEnumMemoryRegionsLoggingCallback_FWD_DEFINED__ -typedef interface ICLRDataEnumMemoryRegionsLoggingCallback ICLRDataEnumMemoryRegionsLoggingCallback; +#ifndef __ICLRDataLoggingCallback_FWD_DEFINED__ +#define __ICLRDataLoggingCallback_FWD_DEFINED__ +typedef interface ICLRDataLoggingCallback ICLRDataLoggingCallback; -#endif /* __ICLRDataEnumMemoryRegionsLoggingCallback_FWD_DEFINED__ */ +#endif /* __ICLRDataLoggingCallback_FWD_DEFINED__ */ #ifndef __ICLRDataEnumMemoryRegions_FWD_DEFINED__ @@ -1205,19 +1206,19 @@ EXTERN_C const IID IID_ICLRDataEnumMemoryRegionsCallback2; #endif /* __ICLRDataEnumMemoryRegionsCallback2_INTERFACE_DEFINED__ */ -#ifndef __ICLRDataEnumMemoryRegionsLoggingCallback_INTERFACE_DEFINED__ -#define __ICLRDataEnumMemoryRegionsLoggingCallback_INTERFACE_DEFINED__ +#ifndef __ICLRDataLoggingCallback_INTERFACE_DEFINED__ +#define __ICLRDataLoggingCallback_INTERFACE_DEFINED__ -/* interface ICLRDataEnumMemoryRegionsLoggingCallback */ +/* interface ICLRDataLoggingCallback */ /* [uuid][local][object] */ -EXTERN_C const IID IID_ICLRDataEnumMemoryRegionsLoggingCallback; +EXTERN_C const IID IID_ICLRDataLoggingCallback; #if defined(__cplusplus) && !defined(CINTERFACE) MIDL_INTERFACE("F315248D-8B79-49DB-B184-37426559F703") - ICLRDataEnumMemoryRegionsLoggingCallback : public IUnknown + ICLRDataLoggingCallback : public IUnknown { public: virtual HRESULT STDMETHODCALLTYPE LogMessage( @@ -1228,36 +1229,36 @@ EXTERN_C const IID IID_ICLRDataEnumMemoryRegionsLoggingCallback; #else /* C style interface */ - typedef struct ICLRDataEnumMemoryRegionsLoggingCallbackVtbl + typedef struct ICLRDataLoggingCallbackVtbl { BEGIN_INTERFACE DECLSPEC_XFGVIRT(IUnknown, QueryInterface) HRESULT ( STDMETHODCALLTYPE *QueryInterface )( - ICLRDataEnumMemoryRegionsLoggingCallback * This, + ICLRDataLoggingCallback * This, /* [in] */ REFIID riid, /* [annotation][iid_is][out] */ _COM_Outptr_ void **ppvObject); DECLSPEC_XFGVIRT(IUnknown, AddRef) ULONG ( STDMETHODCALLTYPE *AddRef )( - ICLRDataEnumMemoryRegionsLoggingCallback * This); + ICLRDataLoggingCallback * This); DECLSPEC_XFGVIRT(IUnknown, Release) ULONG ( STDMETHODCALLTYPE *Release )( - ICLRDataEnumMemoryRegionsLoggingCallback * This); + ICLRDataLoggingCallback * This); - DECLSPEC_XFGVIRT(ICLRDataEnumMemoryRegionsLoggingCallback, LogMessage) + DECLSPEC_XFGVIRT(ICLRDataLoggingCallback, LogMessage) HRESULT ( STDMETHODCALLTYPE *LogMessage )( - ICLRDataEnumMemoryRegionsLoggingCallback * This, + ICLRDataLoggingCallback * This, /* [in] */ LPCSTR message); END_INTERFACE - } ICLRDataEnumMemoryRegionsLoggingCallbackVtbl; + } ICLRDataLoggingCallbackVtbl; - interface ICLRDataEnumMemoryRegionsLoggingCallback + interface ICLRDataLoggingCallback { - CONST_VTBL struct ICLRDataEnumMemoryRegionsLoggingCallbackVtbl *lpVtbl; + CONST_VTBL struct ICLRDataLoggingCallbackVtbl *lpVtbl; }; @@ -1265,17 +1266,17 @@ EXTERN_C const IID IID_ICLRDataEnumMemoryRegionsLoggingCallback; #ifdef COBJMACROS -#define ICLRDataEnumMemoryRegionsLoggingCallback_QueryInterface(This,riid,ppvObject) \ +#define ICLRDataLoggingCallback_QueryInterface(This,riid,ppvObject) \ ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) -#define ICLRDataEnumMemoryRegionsLoggingCallback_AddRef(This) \ +#define ICLRDataLoggingCallback_AddRef(This) \ ( (This)->lpVtbl -> AddRef(This) ) -#define ICLRDataEnumMemoryRegionsLoggingCallback_Release(This) \ +#define ICLRDataLoggingCallback_Release(This) \ ( (This)->lpVtbl -> Release(This) ) -#define ICLRDataEnumMemoryRegionsLoggingCallback_LogMessage(This,message) \ +#define ICLRDataLoggingCallback_LogMessage(This,message) \ ( (This)->lpVtbl -> LogMessage(This,message) ) #endif /* COBJMACROS */ @@ -1286,7 +1287,7 @@ EXTERN_C const IID IID_ICLRDataEnumMemoryRegionsLoggingCallback; -#endif /* __ICLRDataEnumMemoryRegionsLoggingCallback_INTERFACE_DEFINED__ */ +#endif /* __ICLRDataLoggingCallback_INTERFACE_DEFINED__ */ /* interface __MIDL_itf_clrdata_0000_0008 */ @@ -1298,7 +1299,8 @@ enum CLRDataEnumMemoryFlags CLRDATA_ENUM_MEM_DEFAULT = 0, CLRDATA_ENUM_MEM_MINI = CLRDATA_ENUM_MEM_DEFAULT, CLRDATA_ENUM_MEM_HEAP = 0x1, - CLRDATA_ENUM_MEM_TRIAGE = 0x2 + CLRDATA_ENUM_MEM_TRIAGE = 0x2, + CLRDATA_ENUM_MEM_HEAP2 = 0x3 } CLRDataEnumMemoryFlags;