Various SOS, dotnet-dump and documentation fixes (#1355)
authorMike McLaughlin <mikem@microsoft.com>
Fri, 17 Jul 2020 01:26:36 +0000 (18:26 -0700)
committerGitHub <noreply@github.com>
Fri, 17 Jul 2020 01:26:36 +0000 (18:26 -0700)
Remove some tabs

Fix a CurrentThread being nullable problem

Fix gallery manifest Linux trigger

Fix clrthreads OSID width for longer ids on xplat

Fix error messages and documentation

Add aks.ms link to diagnostics FAQ in SOS error messages
Issue: https://github.com/dotnet/diagnostics/issues/1339

Clarify x-plat dump debugging support
Issue: https://github.com/dotnet/diagnostics/issues/1247

16 files changed:
CMakeLists.txt
documentation/FAQ.md
documentation/dotnet-dump-instructions.md
src/SOS/SOS.Hosting/SOSHost.cs
src/SOS/SOS.Package/SOS.Package.csproj
src/SOS/Strike/exts.h
src/SOS/Strike/hostcoreclr.cpp
src/SOS/Strike/strike.cpp
src/SOS/debugshim/debugshim.h
src/SOS/gcdump/gcinfodecoder.cpp
src/SOS/lldbplugin.tests/test_libsosplugin.py
src/SOS/lldbplugin/swift-4.1/lldb/Core/Module.h
src/SOS/lldbplugin/swift-4.1/lldb/Host/Editline.h
src/Tools/dotnet-dump/Commands/RegistersCommand.cs
src/Tools/dotnet-dump/Commands/SetThreadCommand.cs
src/inc/gcdump.h

index 13ea079ef0b08d0eb7580859810fa9aaee7613bd..94b6c81324dcaa9b653d1d5df35b3ab4b63b32b2 100644 (file)
@@ -44,9 +44,9 @@ if (WIN32)
 
       # Confirm that Windows SDK is present
       if(NOT DEFINED CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION OR CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION STREQUAL "" )
-             message(FATAL_ERROR "Windows SDK is required for the Arm32 build.")
+          message(FATAL_ERROR "Windows SDK is required for the Arm32 build.")
       else()
-             message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
+          message("Using Windows SDK version ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
       endif()
 
       # Explicitly specify the assembler to be used for Arm32 compile
index c71b7af6c8c25638c53d1c1f98e8efb9f779cdcf..ec493dab7890b4ddd1afd7d4e2d7e07e7b896d75 100644 (file)
@@ -21,3 +21,14 @@ Frequently Asked Questions
     First try enabling the symbol downloading with `setsymbolserver -ms`. This is already enabled for `dotnet-dump analyze` and if SOS for lldb was installed with `dotnet-sos install`.
 
     If that doesn't work, try using the `setclrpath <directory>` command with a directory that contains the matching version of the DAC module. This is useful for private runtimes or debug builds that haven't been published to our symbol servers.
+
+* If you receive this error message executing a SOS command:
+    ```
+    Failed to find runtime module (libcoreclr.so), 0x80004005
+    Extension commands need it in order to have something to do.
+    ClrStack  failed
+    ```
+    The following could be the problem:
+    * The process or core dump hasn't loaded the .NET Core runtime yet.
+    * The coredump was loaded under lldb without specifying the host (i.e `dotnet`). `target modules list` doesn't display `libcoreclr.so` or `libcoreclr.dylib`. Start lldb with the host as the target program and the core file, for example `lldb --core coredump /usr/share/dotnet/dotnet`. In case you don't have the host available, `dotnet symbol` is will be able to download them.
+    * If a coredump was loaded under lldb, a host was specified, and `target modules list` displays the runtime module but you still get that message lldb needs the correct version of libcoreclr.so/dylib next to the coredump. You can use `dotnet-symbol --modules <coredump>` to download the needed binaries.
index 31d9a6b56f5e9d302516f06da618e47b0e40c6f9..fff4fa1f6907763772b4470516837cb71f51a305 100644 (file)
@@ -3,7 +3,7 @@ Dump collection and analysis utility (dotnet-dump)
 
 The dotnet-dump CLI global tool is way to collect and analyze Windows and Linux dumps all without any native debugger involved like lldb on Linux. This is important on platforms like Alpine Linux or Linux ARM32/ARM64 where a fully working lldb isn't available. The dotnet-dump tool will allow you to run SOS commands to analyze crashes and the GC, but it isn't a native debugger so things like displaying the native stack frames isn't supported.
 
-Currently not supported on macOS.
+The dotnet-dump tool is only supported on the same OS and architecture the dump was taken. Currently not supported on macOS.
 
 ## Installing dotnet-dump
 
@@ -19,7 +19,7 @@ If this is the first global tool installed or you get message `Could not execute
 
 ## Using dotnet-dump
 
-The next step is to collect a dump. This can be skipped if a core dump has already been generated by the operating system or [createdump](https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/xplat-minidump-generation.md#configurationpolicy) on Linux.
+The next step is to collect a dump. This can be skipped if a core dump has already been generated by the operating system or [createdump](https://github.com/dotnet/runtime/blob/master/docs/design/coreclr/botr/xplat-minidump-generation.md#configurationpolicy) on Linux. The default dump type (--type option) is currently "full".
 
 On Linux, the runtime version must be 3.0 or greater. On Windows, dotnet-dump collect will work with any version of the runtime.
      
index dfdf7b480525d83ddc74ddd63540b5f80997d320..0aceb67c82704c5432b97c83e8643c3750c29d5b 100644 (file)
@@ -984,7 +984,7 @@ namespace SOS
                 ThreadInfo threadInfo = _threadService.GetThreadInfoFromIndex(unchecked((int)id));
                 AnalyzeContext.CurrentThreadId = threadInfo.ThreadId;
             }
-            catch (InvalidOperationException)
+            catch (DiagnosticsException)
             {
                 return E_FAIL;
             }
@@ -1045,7 +1045,7 @@ namespace SOS
                     id = (uint)threadInfo.ThreadIndex;
                     return S_OK;
                 }
-                catch (InvalidOperationException)
+                catch (DiagnosticsException)
                 {
                 }
             }
@@ -1057,21 +1057,21 @@ namespace SOS
             IntPtr self,
             ulong* offset)
         {
-            if (!AnalyzeContext.CurrentThreadId.HasValue)
-            {
-                return E_FAIL;
-            }
-            uint threadId = AnalyzeContext.CurrentThreadId.Value;
-            try
+            if (AnalyzeContext.CurrentThreadId.HasValue)
             {
-                ulong teb = _threadService.GetThreadInfoFromId(threadId).ThreadTeb;
-                Write(offset, teb);
-                return S_OK;
-            }
-            catch (InvalidOperationException)
-            {
-                return E_FAIL;
+                uint threadId = AnalyzeContext.CurrentThreadId.Value;
+                try
+                {
+                    ulong teb = _threadService.GetThreadInfoFromId(threadId).ThreadTeb;
+                    Write(offset, teb);
+                    return S_OK;
+                }
+                catch (DiagnosticsException)
+                {
+                }
             }
+            Write(offset, 0);
+            return E_FAIL;
         }
 
         internal int GetInstructionOffset(
@@ -1100,7 +1100,7 @@ namespace SOS
             string name,
             out uint index)
         {
-            if (_threadService.GetRegisterIndexByName(name, out int value)) {
+            if (!_threadService.GetRegisterIndexByName(name, out int value)) {
                 index = 0;
                 return E_INVALIDARG;
             }
@@ -1145,8 +1145,8 @@ namespace SOS
             string register,
             out ulong value)
         {
-            value = 0;
             if (!_threadService.GetRegisterIndexByName(register, out int index)) {
+                value = 0;
                 return E_INVALIDARG;
             }
             return GetRegister(index, out value);
@@ -1156,16 +1156,15 @@ namespace SOS
             int index, 
             out ulong value)
         {
-            if (!AnalyzeContext.CurrentThreadId.HasValue)
+            if (AnalyzeContext.CurrentThreadId.HasValue)
             {
-                value = 0;
-                return E_FAIL;
-            }
-            uint threadId = AnalyzeContext.CurrentThreadId.Value;
-            if (!_threadService.GetRegisterValue(threadId, index, out value)) {
-                return E_FAIL;
+                uint threadId = AnalyzeContext.CurrentThreadId.Value;
+                if (_threadService.GetRegisterValue(threadId, index, out value)) {
+                    return S_OK;
+                }
             }
-            return S_OK;
+            value = 0;
+            return E_FAIL;
         }
 
         internal static bool IsCoreClrRuntimeModule(ModuleInfo module)
index ee9b0695ee2d40bdc82d991c3e61230b3b7beafc..111ab848837c5367805d53e826529c6b1e9453cf 100644 (file)
             <LoadTriggers>
                 <TriggerSet>
                     <ModuleTrigger Name="coreclr.dll" />
+                </TriggerSet>
+                <TriggerSet>
                     <ModuleTrigger Name="libcoreclr.so" />
+                    <OSTrigger Name="Linux" />
                 </TriggerSet>
             </LoadTriggers>
             <EngineCommands>
index 154aa289e13156d3c7c8af3e6e804f6f5774f8b5..36e55ab9ce7b18c231cdfa443ec63998cd8eb881 100644 (file)
@@ -158,6 +158,8 @@ extern ILLDBServices2*       g_ExtServices2;
 
 #endif // FEATURE_PAL
 
+extern bool g_dotnetDumpHost;
+
 HRESULT
 ExtQuery(PDEBUG_CLIENT client);
 
@@ -202,39 +204,51 @@ inline void EENotLoadedMessage(HRESULT Status)
     ExtOut("Failed to find runtime module (%s or %s or %s), 0x%08x\n", GetRuntimeDllName(IRuntime::Core), GetRuntimeDllName(IRuntime::WindowsDesktop), GetRuntimeDllName(IRuntime::UnixCore), Status);
 #endif
     ExtOut("Extension commands need it in order to have something to do.\n");
+    ExtOut("For more information see https://aka.ms/sos_faq\n");
 }
 
 inline void DACMessage(HRESULT Status)
 {
     ExtOut("Failed to load data access module, 0x%08x\n", Status);
-#ifndef FEATURE_PAL
-    ExtOut("Verify that 1) you have a recent build of the debugger (10.0.18317.1001 or newer)\n");
-    ExtOut("            2) the file %s that matches your version of %s is\n", GetDacDllName(), GetRuntimeDllName());
-    ExtOut("                in the version directory or on the symbol path\n");
-    ExtOut("            3) or, if you are debugging a dump file, verify that the file \n");
-    ExtOut("                %s_<arch>_<arch>_<version>.dll is on your symbol path.\n", GetDacModuleName());
-    ExtOut("            4) you are debugging on supported cross platform architecture as \n");
-    ExtOut("                the dump file. For example, an ARM dump file must be debugged\n");
-    ExtOut("                on an X86 or an ARM machine; an AMD64 dump file must be\n");
-    ExtOut("                debugged on an AMD64 machine.\n");
-    ExtOut("\n");
-    ExtOut("You can also run the debugger command .cordll to control the debugger's\n");
-    ExtOut("load of %s.dll. .cordll -ve -u -l will do a verbose reload.\n", GetDacDllName());
-    ExtOut("If that succeeds, the SOS command should work on retry.\n");
-    ExtOut("\n");
-    ExtOut("If you are debugging a minidump, you need to make sure that your executable\n");
-    ExtOut("path is pointing to %s as well.\n", GetRuntimeDllName());
-#else // FEATURE_PAL
-    if (Status == CORDBG_E_MISSING_DEBUGGER_EXPORTS)
+#ifdef FEATURE_PAL
+    if (true)
+#else 
+    if (g_dotnetDumpHost)
+#endif
     {
-        ExtOut("You can run the debugger command 'setclrpath' to control the load of %s.\n", GetDacDllName());
-        ExtOut("If that succeeds, the SOS command should work on retry.\n");
+        if (Status == CORDBG_E_MISSING_DEBUGGER_EXPORTS)
+        {
+            ExtOut("You can run the debugger command 'setclrpath <directory>' to control the load of %s.\n", GetDacDllName());
+            ExtOut("If that succeeds, the SOS command should work on retry.\n");
+        }
+        else
+        {
+            ExtOut("Can not load or initialize %s. The target runtime may not be initialized.\n", GetDacDllName());
+        }
     }
     else
     {
-        ExtOut("Can not load or initialize %s. The target runtime may not be initialized.\n", GetDacDllName());
+        ExtOut("Verify that 1) you have a recent build of the debugger (10.0.18317.1001 or newer)\n");
+        ExtOut("            2) the file %s that matches your version of %s is\n", GetDacDllName(), GetRuntimeDllName());
+        ExtOut("                in the version directory or on the symbol path\n");
+        ExtOut("            3) or, if you are debugging a dump file, verify that the file\n");
+        ExtOut("                %s_<arch>_<arch>_<version>.dll is on your symbol path.\n", GetDacModuleName());
+        ExtOut("            4) you are debugging on a platform and architecture that supports this\n");
+        ExtOut("                the dump file. For example, an ARM dump file must be debugged\n");
+        ExtOut("                on an X86 or an ARM machine; an AMD64 dump file must be\n");
+        ExtOut("                debugged on an AMD64 machine.\n");
+        ExtOut("\n");
+        ExtOut("You can run the command '!setclrpath <directory>' to control the load of %s.\n", GetDacDllName());
+        ExtOut("\n");
+        ExtOut("Or you can also run the debugger command .cordll to control the debugger's\n");
+        ExtOut("load of %s. .cordll -ve -u -l will do a verbose reload.\n", GetDacDllName());
+        ExtOut("If that succeeds, the SOS command should work on retry.\n");
+        ExtOut("\n");
+        ExtOut("If you are debugging a minidump, you need to make sure that your executable\n");
+        ExtOut("path is pointing to %s as well.\n", GetRuntimeDllName());
     }
-#endif // FEATURE_PAL
+    ExtOut("\n");
+    ExtOut("For more information see https://aka.ms/sos_faq\n");
 }
 
 HRESULT CheckEEDll();
index 1820a16d806ad9938c2b66bafad6d6a3eeae5a06..847493a1264e297350bf1a4ab80ad13a28da1245 100644 (file)
@@ -40,6 +40,7 @@
 #define IfFailRet(EXPR) do { Status = (EXPR); if(FAILED(Status)) { return (Status); } } while (0)
 #endif
 
+bool g_dotnetDumpHost = false;
 static bool g_hostingInitialized = false;
 bool g_symbolStoreInitialized = false;
 LPCSTR g_hostRuntimeDirectory = nullptr;
@@ -488,6 +489,7 @@ extern "C" HRESULT SOSInitializeByHost(
 #endif
     g_symbolStoreInitialized = symbolStoreEnabled;
     g_hostingInitialized = true;
+    g_dotnetDumpHost = true;
     return S_OK;
 }
 
index b6be37c473e87a700dd13643c9a00c4b875f35af..ca81752fa7f0c14b30d9e94a60290971ca4b78f7 100644 (file)
@@ -6580,9 +6580,7 @@ HRESULT PrintThreadsFromThreadStore(BOOL bMiniDump, BOOL bPrintLiveThreadsOnly)
 
     const bool hosted = (ThreadStore.fHostConfig & CLRTASKHOSTED) != 0;
     table.ReInit(hosted ? 12 : 11, POINTERSIZE_HEX);
-    table.SetWidths(10, 4, 4, 4, _max(9, POINTERSIZE_HEX),
-                      8, 11, 1+POINTERSIZE_HEX*2, POINTERSIZE_HEX,
-                      5, 3, POINTERSIZE_HEX);
+    table.SetWidths(10, 4, 4, 8, _max(9, POINTERSIZE_HEX), 8, 11, 1+POINTERSIZE_HEX*2, POINTERSIZE_HEX, 5, 3, POINTERSIZE_HEX);
 
     table.SetColAlignment(0, AlignRight);
     table.SetColAlignment(1, AlignRight);
index 7ba42bc37e459476ec0c8216de9fc2b378ed9147..d762e4a5817ad44721f92d8120c59fd39743b8a9 100644 (file)
@@ -48,16 +48,16 @@ public:
     
     STDMETHOD(CanUnloadNow(HMODULE hModule));
 
-       //IUnknown methods:
-       STDMETHOD(QueryInterface(
+    //IUnknown methods:
+    STDMETHOD(QueryInterface(
                 REFIID riid,
                 void **ppvObject));
 
-       // Standard AddRef implementation
-       STDMETHOD_(ULONG, AddRef());
+    // Standard AddRef implementation
+    STDMETHOD_(ULONG, AddRef());
 
-       // Standard Release implementation.
-       STDMETHOD_(ULONG, Release());
+    // Standard Release implementation.
+    STDMETHOD_(ULONG, Release());
 
 
 
@@ -82,7 +82,7 @@ private:
                                     DWORD targetImageFileMachine,
                                     VS_FIXEDFILEINFO * pVersion);
 
-       volatile LONG m_cRef;
+    volatile LONG m_cRef;
     GUID m_skuId;
     bool m_isWindowsTarget;
 
index 1a539b9e4fac5adad01557462548af1548987bf3..3703de086ac345b9c8f3e92ab43b5100477a186d 100644 (file)
@@ -1509,7 +1509,7 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot(
     }
 
     ppReg = &pRD->pCurrentContextPointers->R4;
-       
+
     return (OBJECTREF*)*(ppReg + regNum-4);
 
 }
@@ -1621,7 +1621,7 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot(
     }
 
     ppReg = &pRD->pCurrentContextPointers->X19;
-       
+
     return (OBJECTREF*)*(ppReg + regNum-19);
 }
 
index 1f7b8272dcabf6b1105667ff41836683fb388cbd..87b477af4fdc3567496fa56557d5d18ecf78ea10 100644 (file)
@@ -55,7 +55,7 @@ class TestSosCommands(unittest.TestCase):
         except:
             pass
 
-       logfile = os.path.join(logfiledir, command)
+        logfile = os.path.join(logfiledir, command)
 
         cmd = (('%s -b ' % lldb) +
                ("-k \"script open('%s', 'a').close()\" " % fail_flag_lldb) +
index def1131720418d166289fda80e3fb27b0a4a4cea..c7acc0851f83fb1bd914d170e23eb4de6f14aef3 100644 (file)
@@ -413,7 +413,7 @@ public:
   ///     Source line to locate.
   ///
   /// @param[in] function
-  ///      Optional filter function. Addresses within this function will be
+  ///     Optional filter function. Addresses within this function will be
   ///     added to the 'local' list. All others will be added to the 'extern'
   ///     list.
   ///
index 0b75e9c923cab77332e4dbca998574bdf7de1e4c..d563cf7fb2208f8d0604d992b5f7bf77ce26521e 100644 (file)
@@ -82,7 +82,7 @@ using EditLineStringStreamType = std::stringstream;
 using EditLineCharType = char;
 #endif
 
-#ifdef EL_CLIENTDATA   /* editline with wide support + wide char read function */
+#ifdef EL_CLIENTDATA    /* editline with wide support + wide char read function */
 using EditLineGetCharType = wchar_t;
 #else
 using EditLineGetCharType = char;
index fdcd2ecd7945be03a4be0bc756bcc7caaccb3a57..13d11187458824c794957fb99ab50426455890d4 100644 (file)
@@ -4,6 +4,7 @@
 
 using Microsoft.Diagnostics.DebugServices;
 using Microsoft.Diagnostics.Repl;
+using System;
 
 namespace Microsoft.Diagnostics.Tools.Dump
 {
@@ -27,7 +28,14 @@ namespace Microsoft.Diagnostics.Tools.Dump
             }
             else
             {
-                threadId = AnalyzeContext.CurrentThreadId.Value;
+                if (AnalyzeContext.CurrentThreadId.HasValue)
+                {
+                    threadId = AnalyzeContext.CurrentThreadId.Value;
+                }
+                else
+                {
+                    throw new InvalidOperationException($"No current thread");
+                }
             }
             foreach (RegisterInfo register in ThreadService.Registers)
             {
index 4411b5597fbbdbf31ea44baae79ef7f27443e0da..3b21662c7d29903af8445b4a075893a0da46e7ef 100644 (file)
@@ -39,9 +39,10 @@ namespace Microsoft.Diagnostics.Tools.Dump
             }
             else
             {
+                uint currentThreadId = AnalyzeContext.CurrentThreadId.GetValueOrDefault(uint.MaxValue);
                 foreach (ThreadInfo thread in ThreadService.EnumerateThreads())
                 {
-                    WriteLine("{0}{1} 0x{2:X4} ({2})", thread.ThreadId == AnalyzeContext.CurrentThreadId.Value ? "*" : " ", thread.ThreadIndex, thread.ThreadId);
+                    WriteLine("{0}{1} 0x{2:X4} ({2})", thread.ThreadId == currentThreadId ? "*" : " ", thread.ThreadIndex, thread.ThreadId);
                 }
             }
         }
index e4092a9c684325df2e6f4dadd2124bf8d563154a..2850e3231f505d3fd938ac79e493e41e90ebc3d4 100644 (file)
@@ -82,8 +82,8 @@ public:
 
 
 public:
-       typedef void (*printfFtn)(const char* fmt, ...);
-       printfFtn gcPrintf;     
+    typedef void (*printfFtn)(const char* fmt, ...);
+    printfFtn gcPrintf;        
     UINT32              gcInfoVersion;
     //-------------------------------------------------------------------------
 protected: