Added a "setsostid" command to workaround a bug in lldb on a core dump where the...
authorMike McLaughlin <mikem@microsoft.com>
Fri, 31 Jul 2015 01:29:06 +0000 (18:29 -0700)
committerMike McLaughlin <mikem@microsoft.com>
Sat, 1 Aug 2015 19:29:19 +0000 (12:29 -0700)
First find the managed thread os id is:

(lldb) sos Threads
                                                                                                                                                           Lock
       ID OSID ThreadOBJ           State GC Mode     GC Alloc Context                  Domain           Count Apt Exception
   1    1 3787 00000000006547F8    20220 Preemptive  00007FFFCC0145D0:00007FFFCC015FD0 00000000006357F8 0     Ukn
   6    2 3790 0000000000678FB8    21220 Preemptive  0000000000000000:0000000000000000 00000000006357F8 0     Ukn (Finalizer)

(lldb) thread list
Process 0 stopped
* thread #1: tid = 0x0000, 0x00007f01fe64d267 libc.so.6`__GI_raise(sig=6) + 55 at raise.c:55, name = 'corerun', stop reason = signal SIGABRT
  thread #2: tid = 0x0001, 0x00007f01fe7138dd libc.so.6, stop reason = signal SIGABRT
  thread #3: tid = 0x0002, 0x00007f01fd27dda0 libpthread.so.0`__pthread_cond_wait + 192, stop reason = signal SIGABRT
  thread #4: tid = 0x0003, 0x00007f01fd27e149 libpthread.so.0`__pthread_cond_timedwait + 297, stop reason = signal SIGABRT
  thread #5: tid = 0x0004, 0x00007f01fe70f28d libc.so.6, stop reason = signal SIGABRT
  thread #6: tid = 0x0005, 0x00007f01fe70f49d libc.so.6, stop reason = signal SIGABRT

Then use the new command "setsostid" to set the current thread using the "OSID" from above:
(lldb) setsostid 3790 6
Set sos thread os id to 0x3790 which maps to lldb thread index 6

Now ClrStack should dump that managed thread:
(lldb) sos ClrStack

To undo the affect of this command:
(lldb) setsostid

Added setclrpath command that allows the path that sos/dac/dbi are loaded from to be changes instead of using
the coreclr path. This may be needed if loading a core dump and the debugger binaries are in a different directory
that what the dump has for coreclr's path.

src/ToolBox/SOS/Strike/strike.cpp
src/ToolBox/SOS/lldbplugin/CMakeLists.txt
src/ToolBox/SOS/lldbplugin/debugclient.cpp
src/ToolBox/SOS/lldbplugin/debugclient.h
src/ToolBox/SOS/lldbplugin/setclrpathcommand.cpp [new file with mode: 0644]
src/ToolBox/SOS/lldbplugin/setsostidcommand.cpp [new file with mode: 0644]
src/ToolBox/SOS/lldbplugin/soscommand.cpp
src/ToolBox/SOS/lldbplugin/sosplugin.cpp
src/ToolBox/SOS/lldbplugin/sosplugin.h

index 0c2f97f..a6b1834 100644 (file)
@@ -14019,4 +14019,4 @@ Help(PDEBUG_CLIENT Client, PCSTR Args)
     return S_OK;
 }
 
-#endif // !FEATURE_PAL
+#endif // FEATURE_PAL
index ce279e9..6eb3005 100644 (file)
@@ -28,7 +28,7 @@ if(NOT ENABLE_LLDBPLUGIN)
 endif()
 
 # Check for LLDB library
-find_library(LLDB NAMES lldb-3.6 lldb-3.5 LLDB lldb PATHS "${WITH_LLDB_LIBS}" PATH_SUFFIXES llvm)
+find_library(LLDB NAMES LLDB lldb lldb-3.6 lldb-3.5 PATHS "${WITH_LLDB_LIBS}" PATH_SUFFIXES llvm)
 if(LLDB STREQUAL LLDB-NOTFOUND)
     if(REQUIRE_LLDBPLUGIN)
         message(FATAL_ERROR "Cannot find lldb-3.5 or lldb-3.6. Try installing lldb-3.6-dev (or the appropriate package for your platform)")
@@ -70,6 +70,8 @@ include_directories(${CLR_DIR}/src/coreclr/hosts/unixcoreruncommon)
 set(SOURCES
     sosplugin.cpp
     soscommand.cpp
+    setclrpathcommand.cpp
+    setsostidcommand.cpp
     coreruncommand.cpp
     debugclient.cpp
     ${CLR_DIR}/src/coreclr/hosts/unixcorerun/corerun.cpp
index f2a690b..51d61ba 100644 (file)
 #include <dbgtargetcontext.h>
 #include <string>
 
-DebugClient::DebugClient(lldb::SBDebugger &debugger, lldb::SBCommandReturnObject &returnObject, char *coreclrDirectory) :
+ULONG g_currentThreadIndex = -1;
+ULONG g_currentThreadSystemId = -1;
+char *g_coreclrDirectory;
+
+DebugClient::DebugClient(lldb::SBDebugger &debugger, lldb::SBCommandReturnObject &returnObject) :
     m_debugger(debugger),
-    m_returnObject(returnObject),
-    m_coreclrDirectory(coreclrDirectory)
+    m_returnObject(returnObject)
 {
     returnObject.SetStatus(lldb::eReturnStatusSuccessFinishResult);
 }
@@ -741,6 +744,14 @@ DebugClient::GetCurrentThreadId(
         return E_FAIL;
     }
 
+    // This is allow the a valid current TID to be returned to 
+    // workaround a bug in lldb on core dumps.
+    if (g_currentThreadIndex != -1)
+    {
+        *id = g_currentThreadIndex;
+        return S_OK;
+    }
+
     *id = thread.GetIndexID();
     return S_OK;
 }
@@ -774,6 +785,14 @@ DebugClient::GetCurrentThreadSystemId(
         return E_FAIL;
     }
 
+    // This is allow the a valid current TID to be returned to 
+    // workaround a bug in lldb on core dumps.
+    if (g_currentThreadSystemId != -1)
+    {
+        *sysId = g_currentThreadSystemId;
+        return S_OK;
+    }
+
     *sysId = thread.GetThreadID();
     return S_OK;
 }
@@ -795,13 +814,22 @@ DebugClient::GetThreadIdBySystemId(
         goto exit;
     }
 
-    thread = process.GetThreadByID(sysId);
-    if (!thread.IsValid())
+    // If we have a "fake" thread OS (system) id and a fake thread index,
+    // we need to return fake thread index.
+    if (g_currentThreadSystemId == sysId && g_currentThreadIndex != -1)
     {
-        goto exit;
+        id = g_currentThreadIndex;
     }
+    else
+    {
+        thread = process.GetThreadByID(sysId);
+        if (!thread.IsValid())
+        {
+            goto exit;
+        }
 
-    id = thread.GetIndexID();
+        id = thread.GetIndexID();
+    }
     hr = S_OK;
 
 exit:
@@ -834,7 +862,17 @@ DebugClient::GetThreadContextById(
         goto exit;
     }
 
-    thread = process.GetThreadByID(threadID);
+    // If we have a "fake" thread OS (system) id and a fake thread index,
+    // use the fake thread index to get the context.
+    if (g_currentThreadSystemId == threadID && g_currentThreadIndex != -1)
+    {
+        thread = process.GetThreadByIndexID(g_currentThreadIndex);
+    }
+    else
+    {
+        thread = process.GetThreadByID(threadID);
+    }
+    
     if (!thread.IsValid())
     {
         goto exit;
@@ -1001,7 +1039,7 @@ DebugClient::GetFrameOffset(
 PCSTR
 DebugClient::GetCoreClrDirectory()
 {
-    return m_coreclrDirectory;
+    return g_coreclrDirectory;
 }
 
 DWORD_PTR
index 3081189..cb2d089 100644 (file)
@@ -8,7 +8,6 @@ class DebugClient : public IDebugClient
 private:
     lldb::SBDebugger &m_debugger;
     lldb::SBCommandReturnObject &m_returnObject;
-    char *m_coreclrDirectory;
 
     void OutputString(ULONG mask, PCSTR str);
     lldb::SBProcess GetCurrentProcess();
@@ -19,7 +18,7 @@ private:
     DWORD_PTR GetRegister(lldb::SBFrame frame, const char *name);
 
 public:
-    DebugClient(lldb::SBDebugger &debugger, lldb::SBCommandReturnObject &returnObject, char *coreclrDirectory);
+    DebugClient(lldb::SBDebugger &debugger, lldb::SBCommandReturnObject &returnObject);
     ~DebugClient();
 
     //----------------------------------------------------------------------------
@@ -139,6 +138,9 @@ public:
         ULONG loadedImageNameBufferSize,
         PULONG loadedImageNameSize);
 
+    PCSTR GetModuleDirectory(
+        PCSTR name);
+
     //----------------------------------------------------------------------------
     // IDebugSystemObjects
     //----------------------------------------------------------------------------
@@ -187,7 +189,4 @@ public:
 
     DWORD_PTR GetExpression(
         PCSTR exp);
-
-    PCSTR GetModuleDirectory(
-        PCSTR name);
 };
diff --git a/src/ToolBox/SOS/lldbplugin/setclrpathcommand.cpp b/src/ToolBox/SOS/lldbplugin/setclrpathcommand.cpp
new file mode 100644 (file)
index 0000000..2810ff4
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+
+#include "sosplugin.h"
+#include <dlfcn.h>
+#include <string.h>
+#include <string>
+
+class setclrpathCommand : public lldb::SBCommandPluginInterface
+{
+public:
+    setclrpathCommand()
+    {
+    }
+
+    virtual bool
+    DoExecute (lldb::SBDebugger debugger,
+               char** arguments,
+               lldb::SBCommandReturnObject &result)
+    {
+        if (arguments[0] == NULL)
+        {
+            result.Printf("setclrpath error - no path\n");
+            return false;
+        }
+
+        if (g_coreclrDirectory != NULL)
+        {
+            free(g_coreclrDirectory);
+        }
+
+        std::string path(arguments[0]);
+        if (path[path.length() - 1] != '/')
+        {
+            path.append("/");
+        }
+
+        g_coreclrDirectory = strdup(path.c_str());
+        result.Printf("Set load path for sos/dac/dbi to %s\n", g_coreclrDirectory);
+        return result.Succeeded();
+    }
+};
+
+bool
+setclrpathCommandInitialize(lldb::SBDebugger debugger)
+{
+    lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
+    lldb::SBCommand command = interpreter.AddCommand("setclrpath", new setclrpathCommand(), "Set the path to load coreclr sos/dac/dbi files. setclrpath <path>");
+    return true;
+}
diff --git a/src/ToolBox/SOS/lldbplugin/setsostidcommand.cpp b/src/ToolBox/SOS/lldbplugin/setsostidcommand.cpp
new file mode 100644 (file)
index 0000000..c1366e3
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information. 
+//
+
+#include "sosplugin.h"
+#include <dlfcn.h>
+#include <string.h>
+#include <string>
+
+class setsostidCommand : public lldb::SBCommandPluginInterface
+{
+public:
+    setsostidCommand()
+    {
+    }
+
+    virtual bool
+        DoExecute(lldb::SBDebugger debugger,
+        char** arguments,
+        lldb::SBCommandReturnObject &result)
+    {
+        if (arguments[0] == NULL)
+        {
+            result.Printf("Clearing sos thread os id/index\n");
+            g_currentThreadIndex = -1;
+            g_currentThreadSystemId = -1;
+        }
+        else if (arguments[1] == NULL)
+        {
+            result.Printf("Need thread index parameter that maps to the os id\n");
+        }
+        else
+        {
+            ULONG tid = strtoul(arguments[0], NULL, 16);
+            g_currentThreadSystemId = tid;
+
+            ULONG index = strtoul(arguments[1], NULL, 16);
+            g_currentThreadIndex = index;
+
+            result.Printf("Set sos thread os id to 0x%x which maps to lldb thread index %d\n", tid, index);
+        }
+        return result.Succeeded();
+    }
+};
+
+bool
+setsostidCommandInitialize(lldb::SBDebugger debugger)
+{
+    lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
+    lldb::SBCommand command = interpreter.AddCommand("setsostid", new setsostidCommand(), "Set the current os tid/thread index instead of using the one lldb provides. setsostid <tid> <index>");
+    return true;
+}
index be0ef9b..660295d 100644 (file)
@@ -11,7 +11,6 @@
 class sosCommand : public lldb::SBCommandPluginInterface
 {
     void *m_sosHandle;
-    char m_coreclrDirectory[MAX_PATH];
 
 public:
     sosCommand()
@@ -24,7 +23,7 @@ public:
                char** arguments,
                lldb::SBCommandReturnObject &result)
     {
-        DebugClient* client = new DebugClient(debugger, result, m_coreclrDirectory);
+        DebugClient* client = new DebugClient(debugger, result);
         if (arguments)
         {
             LoadSos(client);
@@ -65,16 +64,24 @@ public:
     {
         if (m_sosHandle == NULL)
         {
-            const char *coreclrModule = MAKEDLLNAME_A("coreclr");
-            const char *directory = client->GetModuleDirectory(coreclrModule);
-            if (directory == NULL)
+            if (g_coreclrDirectory == NULL)
             {
-                client->Output(DEBUG_OUTPUT_WARNING, "The %s module is not loaded yet in the target process\n", coreclrModule);
+                const char *coreclrModule = MAKEDLLNAME_A("coreclr");
+                const char *directory = client->GetModuleDirectory(coreclrModule);
+                if (directory != NULL)
+                {
+                    std::string path(directory);
+                    path.append("/");
+                    g_coreclrDirectory = strdup(path.c_str());
+                }
+                else
+                {
+                    client->Output(DEBUG_OUTPUT_WARNING, "The %s module is not loaded yet in the target process\n", coreclrModule);
+                }
             }
-            else 
+
+            if (g_coreclrDirectory != NULL)
             {
-                strcpy(m_coreclrDirectory, directory);
-                strcat(m_coreclrDirectory, "/");
 
                 // Load the DAC module first explicitly because SOS and DBI
                 // have implicit references to the DAC's PAL.
@@ -88,7 +95,7 @@ public:
     void *
     LoadModule(DebugClient *client, const char *moduleName)
     {
-        std::string modulePath(m_coreclrDirectory);
+        std::string modulePath(g_coreclrDirectory);
         modulePath.append(moduleName);
 
         void *moduleHandle = dlopen(modulePath.c_str(), RTLD_NOW);
index a6111b6..024e42c 100644 (file)
@@ -14,5 +14,7 @@ lldb::PluginInitialize (lldb::SBDebugger debugger)
 {
     corerunCommandInitialize(debugger);
     sosCommandInitialize(debugger);
+    setclrpathCommandInitialize(debugger);
+    setsostidCommandInitialize(debugger);
     return true;
 }
\ No newline at end of file
index 412955c..54a7aee 100644 (file)
 
 typedef HRESULT (*CommandFunc)(PDEBUG_CLIENT client, const char *args);
 
+extern char *g_coreclrDirectory;
+extern ULONG g_currentThreadIndex;
+extern ULONG g_currentThreadSystemId;
+
 bool 
 sosCommandInitialize(lldb::SBDebugger debugger);
 
 bool
-corerunCommandInitialize(lldb::SBDebugger debugger);
\ No newline at end of file
+setsostidCommandInitialize(lldb::SBDebugger debugger);
+
+bool
+setclrpathCommandInitialize(lldb::SBDebugger debugger);
+
+bool
+corerunCommandInitialize(lldb::SBDebugger debugger);