Display internal SOS status with sosstatus command (#519)
authorMike McLaughlin <mikem@microsoft.com>
Wed, 2 Oct 2019 17:25:39 +0000 (10:25 -0700)
committerGitHub <noreply@github.com>
Wed, 2 Oct 2019 17:25:39 +0000 (10:25 -0700)
Display internal SOS status with sosstatus command

Add dumpvc to dotnet-dump/lldb commands.

Remove reductant dotnet-dump error message when SOS command fails.

Fixes issues:

    https://github.com/dotnet/diagnostics/issues/511
    https://github.com/dotnet/diagnostics/issues/508
    https://github.com/dotnet/diagnostics/issues/509

Change SyncBlk test not to run on xplat.

src/SOS/SOS.Hosting/SOSHost.cs
src/SOS/SOS.UnitTests/Scripts/OtherCommands.script
src/SOS/Strike/hostcoreclr.cpp
src/SOS/Strike/hostcoreclr.h
src/SOS/Strike/sos.def
src/SOS/Strike/sos_unixexports.src
src/SOS/Strike/strike.cpp
src/SOS/Strike/util.cpp
src/SOS/Strike/util.h
src/SOS/lldbplugin/soscommand.cpp
src/Tools/dotnet-dump/Commands/SOSCommand.cs

index d3a7d827753d0667b6a1572d161299af24e69103..0f26ec1121ead1880e351eafdbe070d0789d71bf 100644 (file)
@@ -318,7 +318,7 @@ namespace SOS
             int result = commandFunc(_interface, arguments ?? "");
             if (result != 0)
             {
-                throw new InvalidOperationException($"SOS command FAILED 0x{result:X8}");
+                Trace.TraceError($"SOS command FAILED 0x{result:X8}");
             }
         }
 
index 85e37b577954a1d75fc871c28d08b008ae9ff026..87fa292f701b743b0b5c2cd5207cb6f53c5c33b0 100644 (file)
@@ -76,11 +76,10 @@ VERIFY:(\s*<HEXVAL>\s+<DECVAL>\s+<DECVAL>\s+.*)?
 VERIFY:\s*Total\s+<DECVAL>\s+objects\s+
 
 SOSCOMMAND:SyncBlk
-!IFDEF:LINUX
+# On Linux/MacOS we sometimes get "Error requesting SyncBlk data" error from the DAC.
+IFDEF:WINDOWS
 VERIFY:\s*Index\s+SyncBlock\s+MonitorHeld\s+Recursion\s+Owning\s+Thread\s+Info\s+SyncBlock\s+Owner\s+
 VERIFY:\s*Total\s+<DECVAL>
-IFDEF:WINDOWS
 VERIFY:\s*CCW\s+<DECVAL>
 VERIFY:\s*RCW\s+<DECVAL>
 ENDIF:WINDOWS
-ENDIF:LINUX
\ No newline at end of file
index 863a337c286e3d2d75ed41265b9ec287cf60f2fc..3f1318d3c5adb74a068a465403a3ac5ac25241ef 100644 (file)
@@ -30,7 +30,6 @@
 
 #include <coreclrhost.h>
 #include <set>
-#include <string>
 
 #if defined(__APPLE__)
 #include <mach-o/dyld.h>
@@ -231,7 +230,7 @@ static bool GetEntrypointExecutableAbsolutePath(std::string& entrypointExecutabl
 /**********************************************************************\
  * Returns the coreclr module/runtime directory of the target.
 \**********************************************************************/
-static HRESULT GetCoreClrDirectory(std::string& coreClrDirectory)
+HRESULT GetCoreClrDirectory(std::string& coreClrDirectory)
 {
 #ifdef FEATURE_PAL
     LPCSTR directory = g_ExtServices->GetCoreClrDirectory();
index ef260a399471d418d09cc6e4bffd1204b56150ef..075e4ed1fb2f5990c9319a595aacf08054a9e108 100644 (file)
@@ -60,9 +60,13 @@ static const char *MetadataHelperClassName = "SOS.MetadataHelper";
 
 extern HMODULE g_hInstance;
 extern LPCSTR g_hostRuntimeDirectory;
+extern LPCSTR g_dacFilePath;
+extern LPCSTR g_dbiFilePath;
+extern LPCSTR g_tmpPath;
 extern SOSNetCoreCallbacks g_SOSNetCoreCallbacks;
 
 extern HRESULT GetCoreClrDirectory(LPWSTR modulePath, int modulePathSize);
+extern HRESULT GetCoreClrDirectory(std::string& coreClrDirectory);
 extern LPCSTR GetDacFilePath();
 extern LPCSTR GetDbiFilePath();
 extern BOOL IsHostingInitialized();
index 8bbfcf17114ad9f458e98e17cb8986791a2165ea..2d983d59e1d47533b4376d32331aa22924a44fff 100644 (file)
@@ -211,6 +211,8 @@ EXPORTS
     pathto=PathTo
     ProcInfo
     procinfo=ProcInfo
+    SOSStatus
+    sosstatus=SOSStatus
     VerifyStackTrace
     WatsonBuckets
 
index b5c066d595627f33d5d10826c77b294d1579a642..a9afa599c519e64f2f19c42fa4f7f54954a5ca6f 100644 (file)
@@ -49,6 +49,7 @@ StopOnCatch
 SetHostRuntime
 SetSymbolServer
 SOSFlush
+SOSStatus
 SyncBlk
 Threads
 ThreadState
index 8c452f23494d7266a9b2a40f69e56f83ea528bd5..2942af788831a3340d1b16c5740f650eb9c486f2 100644 (file)
@@ -10240,10 +10240,10 @@ DECLARE_API(DumpGCData)
 * Routine Description:                                                 *
 *                                                                      *
 *    This function is called to dump the build number and type of the  *  
-*    mscoree.dll                                                       *
+*    runtime and SOS.                                                  *
 *                                                                      *
 \**********************************************************************/
-DECLARE_API (EEVersion)
+DECLARE_API(EEVersion)
 {
     INIT_API();
 
@@ -10257,23 +10257,27 @@ DECLARE_API (EEVersion)
     VS_FIXEDFILEINFO version;
 
     BOOL ret = GetEEVersion(&version, fileVersionBuffer.GetPtr(), fileVersionBufferSize);
-    if (ret) 
+    if (ret)
     {
         if (version.dwFileVersionMS != (DWORD)-1)
         {
             ExtOut("%u.%u.%u.%u",
-                   HIWORD(version.dwFileVersionMS),
-                   LOWORD(version.dwFileVersionMS),
-                   HIWORD(version.dwFileVersionLS),
-                   LOWORD(version.dwFileVersionLS));
+                HIWORD(version.dwFileVersionMS),
+                LOWORD(version.dwFileVersionMS),
+                HIWORD(version.dwFileVersionLS),
+                LOWORD(version.dwFileVersionLS));
+
+            if (IsRuntimeVersion(version, 3)) {
+                ExtOut(" (3.x runtime)");
+            }
+
 #ifndef FEATURE_PAL
-            if (version.dwFileFlags & VS_FF_DEBUG) 
-            {                    
+            if (version.dwFileFlags & VS_FF_DEBUG) {
                 ExtOut(" checked or debug build");
             }
             else
-            { 
-                BOOL fRet = IsRetailBuild ((size_t)g_moduleInfo[eef].baseAddr);
+            {
+                BOOL fRet = IsRetailBuild((size_t)g_moduleInfo[eef].baseAddr);
                 if (fRet)
                     ExtOut(" retail");
                 else
@@ -10282,22 +10286,20 @@ DECLARE_API (EEVersion)
 #endif
             ExtOut("\n");
 
-            if (fileVersionBuffer[0] != '\0')
-            {
+            if (fileVersionBuffer[0] != '\0') {
                 ExtOut("%s\n", fileVersionBuffer.GetPtr());
             }
         }
     }
-    
-    if (!InitializeHeapData ())
+
+    if (!InitializeHeapData())
         ExtOut("GC Heap not initialized, so GC mode is not determined yet.\n");
-    else if (IsServerBuild()) 
-        ExtOut("Server mode with %d gc heaps\n", GetGcHeapCount()); 
+    else if (IsServerBuild())
+        ExtOut("Server mode with %d gc heaps\n", GetGcHeapCount());
     else
         ExtOut("Workstation mode\n");
 
-    if (!GetGcStructuresValid())
-    {
+    if (!GetGcStructuresValid()) {
         ExtOut("In plan phase of garbage collection\n");
     }
 
@@ -10309,18 +10311,16 @@ DECLARE_API (EEVersion)
         if (sosVersion.dwFileVersionMS != (DWORD)-1)
         {
             ExtOut("SOS Version: %u.%u.%u.%u",
-                   HIWORD(sosVersion.dwFileVersionMS),
-                   LOWORD(sosVersion.dwFileVersionMS),
-                   HIWORD(sosVersion.dwFileVersionLS),
-                   LOWORD(sosVersion.dwFileVersionLS));
+                HIWORD(sosVersion.dwFileVersionMS),
+                LOWORD(sosVersion.dwFileVersionMS),
+                HIWORD(sosVersion.dwFileVersionLS),
+                LOWORD(sosVersion.dwFileVersionLS));
 
-            if (sosVersion.dwFileFlags & VS_FF_DEBUG) 
-            {                    
-                ExtOut(" debug build");                    
+            if (sosVersion.dwFileFlags & VS_FF_DEBUG) {
+                ExtOut(" debug build");
             }
-            else
-            { 
-                ExtOut(" retail build");                    
+            else {
+                ExtOut(" retail build");
             }
             ExtOut("\n");
         }
@@ -10329,6 +10329,40 @@ DECLARE_API (EEVersion)
     return Status;
 }
 
+/**********************************************************************\
+* Routine Description:                                                 *
+*                                                                      *
+*    This function the global SOS status                               *
+*                                                                      *
+\**********************************************************************/
+DECLARE_API(SOSStatus)
+{
+    INIT_API_NOEE();
+
+    if (g_targetMachine != nullptr) {
+        ExtOut("Target platform: %04x Context size %04x\n", g_targetMachine->GetPlatform(), g_targetMachine->GetContextSize());
+    }
+    if (g_tmpPath != nullptr) {
+        ExtOut("Temp path: %s\n", g_tmpPath);
+    }
+    if (g_dacFilePath != nullptr) {
+        ExtOut("DAC file path: %s\n", g_dacFilePath);
+    }
+    if (g_dbiFilePath != nullptr) {
+        ExtOut("DBI file path: %s\n", g_dbiFilePath);
+    }
+    if (g_hostRuntimeDirectory != nullptr) {
+        ExtOut("Host runtime path: %s\n", g_hostRuntimeDirectory);
+    }
+    std::string coreclrDirectory;
+    if (SUCCEEDED(GetCoreClrDirectory(coreclrDirectory))) {
+        ExtOut("Runtime path: %s\n", coreclrDirectory.c_str());
+    }
+    DisplaySymbolStore();
+
+    return Status;
+}
+
 #ifndef FEATURE_PAL
 /**********************************************************************\
 * Routine Description:                                                 *
index a550da79ac84d9c8bcc6171086b8b6e8079bf502..1d7a79bc5ff544e1add0c1cc8b8fafe19eb411fe 100644 (file)
@@ -63,6 +63,7 @@ const char * const CorElementTypeNamespace[ELEMENT_TYPE_MAX]=
 
 IXCLRDataProcess *g_clrData = NULL;
 ISOSDacInterface *g_sos = NULL;
+IXCLRDataProcess *g_clrDataProcess = NULL;
 ICorDebugProcess *g_pCorDebugProcess = NULL;
 
 #ifndef IfFailRet
@@ -3315,16 +3316,22 @@ bool IsRuntimeVersion(DWORD major)
     VS_FIXEDFILEINFO fileInfo;
     if (GetEEVersion(&fileInfo, nullptr, 0))
     {
-        switch (major)
-        {
-            case 5:
-                return HIWORD(fileInfo.dwFileVersionMS) == 5;
-            case 3:
-                return HIWORD(fileInfo.dwFileVersionMS) == 4 && LOWORD(fileInfo.dwFileVersionMS) == 700;
-            default:
-                _ASSERTE(FALSE);
-                break;
-        }
+        return IsRuntimeVersion(fileInfo, major);
+    }
+    return false;
+}
+
+bool IsRuntimeVersion(VS_FIXEDFILEINFO& fileInfo, DWORD major)
+{
+    switch (major)
+    {
+        case 5:
+            return HIWORD(fileInfo.dwFileVersionMS) == 5;
+        case 3:
+            return HIWORD(fileInfo.dwFileVersionMS) == 4 && LOWORD(fileInfo.dwFileVersionMS) == 700;
+        default:
+            _ASSERTE(FALSE);
+            break;
     }
     return false;
 }
@@ -3872,10 +3879,9 @@ void ResetGlobals(void)
 
 static HRESULT GetClrDataProcess()
 {
-    static IXCLRDataProcess* clrDataProcess = NULL;
     HRESULT hr = S_OK;
 
-    if (clrDataProcess == NULL)
+    if (g_clrDataProcess == NULL)
     {
         LPCSTR dacFilePath = GetDacFilePath();
         if (dacFilePath == nullptr)
@@ -3894,18 +3900,18 @@ static HRESULT GetClrDataProcess()
             return CORDBG_E_MISSING_DEBUGGER_EXPORTS;
         }
         ICLRDataTarget *target = new DataTarget();
-        hr = pfnCLRDataCreateInstance(__uuidof(IXCLRDataProcess), target, (void**)&clrDataProcess);
+        hr = pfnCLRDataCreateInstance(__uuidof(IXCLRDataProcess), target, (void**)&g_clrDataProcess);
         if (FAILED(hr))
         {
-            clrDataProcess = NULL;
+            g_clrDataProcess = NULL;
             return hr;
         }
         ULONG32 flags = 0;
-        clrDataProcess->GetOtherNotificationFlags(&flags);
+        g_clrDataProcess->GetOtherNotificationFlags(&flags);
         flags |= (CLRDATA_NOTIFY_ON_MODULE_LOAD | CLRDATA_NOTIFY_ON_MODULE_UNLOAD | CLRDATA_NOTIFY_ON_EXCEPTION);
-        clrDataProcess->SetOtherNotificationFlags(flags);
+        g_clrDataProcess->SetOtherNotificationFlags(flags);
     }
-    g_clrData = clrDataProcess;
+    g_clrData = g_clrDataProcess;
     g_clrData->AddRef();
     g_clrData->Flush();
 
@@ -3921,7 +3927,6 @@ static HRESULT GetClrDataProcess()
 //
 HRESULT LoadClrDebugDll(void)
 {
-    static IXCLRDataProcess* clrDataProcess = NULL;
     HRESULT hr = GetClrDataProcess();
     if (FAILED(hr)) 
     {
@@ -3929,23 +3934,20 @@ HRESULT LoadClrDebugDll(void)
         return hr;
 #else
         // Fail if ExtensionApis wasn't initialized because we are hosted under dotnet-dump
-        if (Ioctl == nullptr)
-        {
+        if (Ioctl == nullptr) {
             return hr;
         }
         // Try getting the DAC interface from dbgeng if the above fails on Windows
         WDBGEXTS_CLR_DATA_INTERFACE Query;
 
         Query.Iid = &__uuidof(IXCLRDataProcess);
-        if (!Ioctl(IG_GET_CLR_DATA_INTERFACE, &Query, sizeof(Query)))
-        {
+        if (!Ioctl(IG_GET_CLR_DATA_INTERFACE, &Query, sizeof(Query))) {
             return hr;
         }
         g_clrData = (IXCLRDataProcess*)Query.Iface;
         g_clrData->Flush();
 #endif
     }
-
     hr = g_clrData->QueryInterface(__uuidof(ISOSDacInterface), (void**)&g_sos);
     if (FAILED(hr))
     {
index 2ff025788c562e5eb58fb1a911183cdab1186472..d1a811572d266e81be14184d94696c9aabb2b0df 100644 (file)
@@ -37,6 +37,7 @@ inline void RestoreSOToleranceState() {}
 
 #include "cordebug.h"
 #include "static_assert.h"
+#include <string>
 #include "hostcoreclr.h"
 
 typedef LPCSTR  LPCUTF8;
@@ -1561,6 +1562,7 @@ HRESULT InitCorDebugInterface();
 VOID UninitCorDebugInterface();
 BOOL GetEEVersion(VS_FIXEDFILEINFO* pFileInfo, char* fileVersionBuffer, int fileVersionBufferSizeInBytes);
 bool IsRuntimeVersion(DWORD major);
+bool IsRuntimeVersion(VS_FIXEDFILEINFO& fileInfo, DWORD major);
 #ifndef FEATURE_PAL
 BOOL IsRetailBuild (size_t base);
 BOOL GetSOSVersion(VS_FIXEDFILEINFO *pFileInfo);
index f63befb647630ba6a0fc63349696568fca4eb522..487c62d561977a0f2c2688ebcd9e9c1b1649517a 100644 (file)
@@ -148,6 +148,7 @@ sosCommandInitialize(lldb::SBDebugger debugger)
     interpreter.AddCommand("dumpmodule", new sosCommand("DumpModule"), "Displays information about a EE module structure at the specified address.");
     interpreter.AddCommand("dumpmt", new sosCommand("DumpMT"), "Displays information about a method table at the specified address.");
     interpreter.AddCommand("dumpobj", new sosCommand("DumpObj"), "Displays info about an object at the specified address.");
+    interpreter.AddCommand("dumpvc", new sosCommand("DumpVC"), "Displays info about the fields of a value class.");
     interpreter.AddCommand("dumpstack", new sosCommand("DumpStack"), "Displays a native and managed stack trace.");
     interpreter.AddCommand("dso", new sosCommand("DumpStackObjects"), "Displays all managed objects found within the bounds of the current stack.");
     interpreter.AddCommand("eeheap", new sosCommand("EEHeap"), "Displays info about process memory consumed by internal runtime data structures.");
@@ -170,5 +171,6 @@ sosCommandInitialize(lldb::SBDebugger debugger)
     interpreter.AddCommand("setsymbolserver", new sosCommand("SetSymbolServer"), "Enables the symbol server support ");
     interpreter.AddCommand("sympath", new sosCommand("SetSymbolServer", "-sympath"), "Add server, cache and directory paths in the Windows symbol path format.");
     interpreter.AddCommand("soshelp", new sosCommand("Help"), "Displays all available commands when no parameter is specified, or displays detailed help information about the specified command. soshelp <command>");
+    interpreter.AddCommand("sosstatus", new sosCommand("SOSStatus"), "Displays the global SOS status.");
     return true;
 }
index e6d6311cae910d87e6715451285c209b8062a973..bc258de370b58b4ea432615a07599ee57af58fff 100644 (file)
@@ -28,6 +28,7 @@ namespace Microsoft.Diagnostics.Tools.Dump
     [Command(Name = "dumpmodule",       AliasExpansion = "DumpModule",          Help = "Displays information about a EE module structure at the specified address.")]
     [Command(Name = "dumpmt",           AliasExpansion = "DumpMT",              Help = "Displays information about a method table at the specified address.")]
     [Command(Name = "dumpobj",          AliasExpansion = "DumpObj",             Help = "Displays info about an object at the specified address.")]
+    [Command(Name = "dumpvc",           AliasExpansion = "DumpVC",              Help = "Displays info about the fields of a value class.")]
     [Command(Name = "dumpstackobjects", AliasExpansion = "DumpStackObjects",    Help = "Displays all managed objects found within the bounds of the current stack.")]
     [CommandAlias(Name = "dso")]
     [Command(Name = "eeheap",           AliasExpansion = "EEHeap",              Help = "Displays info about process memory consumed by internal runtime data structures.")]
@@ -39,6 +40,7 @@ namespace Microsoft.Diagnostics.Tools.Dump
     [Command(Name = "name2ee",          AliasExpansion = "Name2EE",             Help = "Displays the MethodTable structure and EEClass structure for the specified type or method in the specified module.")]
     [Command(Name = "printexception",   AliasExpansion = "PrintException",      Help = "Displays and formats fields of any object derived from the Exception class at the specified address.")]
     [CommandAlias(Name = "pe")]
+    [Command(Name = "sosstatus",        AliasExpansion = "SOSStatus",           Help = "Displays the global SOS status.")]
     [Command(Name = "syncblk",          AliasExpansion = "SyncBlk",             Help = "Displays the SyncBlock holder info.")]
     [Command(Name = "histclear",        AliasExpansion = "HistClear",           Help = "Releases any resources used by the family of Hist commands.")]
     [Command(Name = "histinit",         AliasExpansion = "HistInit",            Help = "Initializes the SOS structures from the stress log saved in the debuggee.")]