SOS: Automatically find a managed thread with an exception on Linux/OSX core dumps...
authorMike McLaughlin <mikem@microsoft.com>
Thu, 10 Nov 2016 23:44:11 +0000 (15:44 -0800)
committerGitHub <noreply@github.com>
Thu, 10 Nov 2016 23:44:11 +0000 (15:44 -0800)
SOS: Automatically find a managed thread with an exception on Linux/OSX core dumps

To be used in the debugger tests repo for SOS dump testing on Linux/OSX.

Added the "clrthreads -managedexception" option to switch to the first managed thread
that has thrown an exception.

Issue #6518

src/ToolBox/SOS/NETCore/project.json
src/ToolBox/SOS/Strike/sosdocsunix.txt
src/ToolBox/SOS/Strike/strike.cpp

index e9e4f09..7a3cf4f 100644 (file)
@@ -3,7 +3,7 @@
     "Microsoft.NETCore.Platforms": "1.0.1",
     "System.IO.FileSystem": "4.0.1",
     "System.Runtime.InteropServices": "4.1.0",
-    "System.Reflection.Metadata": "1.4.1-beta-24417-02"
+    "System.Reflection.Metadata": "1.4.1"
   },
   "frameworks": {
     "netcoreapp1.0": {}
index 52ec86d..5ab2b31 100644 (file)
@@ -844,6 +844,7 @@ corruption bug caused by invalid GCEncoding for a particular method.
 
 COMMAND: bpmd.
 bpmd [-nofuturemodule] <module name> <method name> [<il offset>]
+bpmd <source file name>:<line number>
 bpmd -md <MethodDesc>
 bpmd -list
 bpmd -clear <pending breakpoint number>
index e03e518..71db902 100644 (file)
@@ -5888,6 +5888,56 @@ HRESULT PrintSpecialThreads()
 }
 #endif //FEATURE_PAL
 
+HRESULT SwitchToExceptionThread()
+{
+    HRESULT Status;
+    
+    DacpThreadStoreData ThreadStore;
+    if ((Status = ThreadStore.Request(g_sos)) != S_OK)
+    {
+        Print("Failed to request ThreadStore\n");
+        return Status;
+    }
+
+    DacpThreadData Thread;
+    CLRDATA_ADDRESS CurThread = ThreadStore.firstThread;
+    while (CurThread)
+    {
+        if (IsInterrupt())
+            break;
+
+        if ((Status = Thread.Request(g_sos, CurThread)) != S_OK)
+        {
+            PrintLn("Failed to request Thread at ", Pointer(CurThread));
+            return Status;
+        }
+        
+        TADDR taLTOH;
+        if (Thread.lastThrownObjectHandle != NULL)
+        {
+            if (SafeReadMemory(TO_TADDR(Thread.lastThrownObjectHandle), &taLTOH, sizeof(taLTOH), NULL))
+            {
+                if (taLTOH != NULL)
+                {
+                    ULONG id;
+                    if (g_ExtSystem->GetThreadIdBySystemId(Thread.osThreadId, &id) == S_OK)
+                    {
+                        if (g_ExtSystem->SetCurrentThreadId(id) == S_OK)
+                        {
+                            PrintLn("Found managed exception on thread ", ThreadID(Thread.osThreadId));
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        CurThread = Thread.nextThread;
+    }
+
+    return Status;
+}
+
 struct ThreadStateTable
 {
     unsigned int State;
@@ -5961,12 +6011,14 @@ DECLARE_API(Threads)
 
     BOOL bPrintSpecialThreads = FALSE;
     BOOL bPrintLiveThreadsOnly = FALSE;
+    BOOL bSwitchToManagedExceptionThread = FALSE;
     BOOL dml = FALSE;
 
     CMDOption option[] = 
     {   // name, vptr, type, hasValue
         {"-special", &bPrintSpecialThreads, COBOOL, FALSE},
         {"-live", &bPrintLiveThreadsOnly, COBOOL, FALSE},
+        {"-managedexception", &bSwitchToManagedExceptionThread, COBOOL, FALSE},
 #ifndef FEATURE_PAL
         {"/d", &dml, COBOOL, FALSE},
 #endif
@@ -5975,6 +6027,11 @@ DECLARE_API(Threads)
     {
         return Status;
     }
+
+    if (bSwitchToManagedExceptionThread)
+    {
+        return SwitchToExceptionThread();
+    }
     
     // We need to support minidumps for this command.
     BOOL bMiniDump = IsMiniDumpFile();