<rdar://problem/12491420>

Added a new setting that allows a python OS plug-in to detect threads and provide registers for memory threads. To enable this you set the setting:

settings set target.process.python-os-plugin-path lldb/examples/python/operating_system.py

Then run your program and see the extra threads. 



git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@166244 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp
index 4c41d31..5999f7c 100644
--- a/source/Commands/CommandObjectCommands.cpp
+++ b/source/Commands/CommandObjectCommands.cpp
@@ -1394,8 +1394,10 @@
         std::string path = command.GetArgumentAtIndex(0);
         Error error;
         
+        const bool init_session = true;
         if (m_interpreter.GetScriptInterpreter()->LoadScriptingModule(path.c_str(),
                                                                       m_options.m_allow_reload,
+                                                                      init_session,
                                                                       error))
         {
             result.SetStatus (eReturnStatusSuccessFinishNoResult);
diff --git a/source/Interpreter/ScriptInterpreterNone.cpp b/source/Interpreter/ScriptInterpreterNone.cpp
index 097133d..a23ce37 100644
--- a/source/Interpreter/ScriptInterpreterNone.cpp
+++ b/source/Interpreter/ScriptInterpreterNone.cpp
@@ -26,7 +26,7 @@
 }
 
 bool
-ScriptInterpreterNone::ExecuteOneLine (const char *command, CommandReturnObject *, bool enable_io)
+ScriptInterpreterNone::ExecuteOneLine (const char *command, CommandReturnObject *, bool enable_io, bool set_lldb_globals)
 {
     m_interpreter.GetDebugger().GetErrorStream().PutCString ("error: there is no embedded script interpreter in this mode.\n");
     return false;
diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp
index b069bf4..efb8841 100644
--- a/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/source/Interpreter/ScriptInterpreterPython.cpp
@@ -721,7 +721,7 @@
 }
 
 bool
-ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, bool enable_io)
+ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, bool enable_io, bool set_lldb_globals)
 {
     if (!m_valid_session)
         return false;
@@ -732,8 +732,8 @@
     // method to pass the command string directly down to Python.
 
     Locker locker(this,
-                  ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
-                  ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
+                  ScriptInterpreterPython::Locker::AcquireLock | (set_lldb_globals ? ScriptInterpreterPython::Locker::InitSession : 0),
+                  ScriptInterpreterPython::Locker::FreeAcquiredLock | (set_lldb_globals ? ScriptInterpreterPython::Locker::TearDownSession : 0));
 
     bool success = false;
 
@@ -1000,12 +1000,13 @@
 ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
                                                    ScriptInterpreter::ScriptReturnType return_type,
                                                    void *ret_value,
-                                                   bool enable_io)
+                                                   bool enable_io,
+                                                   bool set_lldb_globals)
 {
 
     Locker locker(this,
-                  ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
-                  ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
+                  ScriptInterpreterPython::Locker::AcquireLock | (set_lldb_globals ? ScriptInterpreterPython::Locker::InitSession : 0),
+                  ScriptInterpreterPython::Locker::FreeAcquiredLock | (set_lldb_globals ? ScriptInterpreterPython::Locker::TearDownSession : 0));
 
     PyObject *py_return = NULL;
     PyObject *mainmod = PyImport_AddModule ("__main__");
@@ -1165,13 +1166,13 @@
 }
 
 bool
-ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, bool enable_io)
+ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, bool enable_io, bool set_lldb_globals)
 {
     
     
     Locker locker(this,
-                  ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
-                  ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
+                  ScriptInterpreterPython::Locker::AcquireLock | (set_lldb_globals ? ScriptInterpreterPython::Locker::InitSession : 0),
+                  ScriptInterpreterPython::Locker::FreeAcquiredLock | (set_lldb_globals ? ScriptInterpreterPython::Locker::TearDownSession : 0));
 
     bool success = false;
     PyObject *py_return = NULL;
@@ -2373,6 +2374,7 @@
 bool
 ScriptInterpreterPython::LoadScriptingModule (const char* pathname,
                                               bool can_reload,
+                                              bool init_lldb_globals,
                                               lldb_private::Error& error)
 {
     if (!pathname || !pathname[0])
@@ -2404,14 +2406,16 @@
         std::string basename(target_file.GetFilename().GetCString());
 
         // Before executing Pyton code, lock the GIL.
-        Locker py_lock(this);
+        Locker py_lock (this,
+                        Locker::AcquireLock      | (init_lldb_globals ? Locker::InitSession     : 0),
+                        Locker::FreeAcquiredLock | (init_lldb_globals ? Locker::TearDownSession : 0));
         
         // now make sure that Python has "directory" in the search path
         StreamString command_stream;
         command_stream.Printf("if not (sys.path.__contains__('%s')):\n    sys.path.append('%s');\n\n",
                               directory,
                               directory);
-        bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), false);
+        bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), false, false);
         if (!syspath_retval)
         {
             error.SetErrorString("Python sys.path handling failed");
@@ -2432,7 +2436,10 @@
         // this call will fail if the module does not exist (because the parameter to it is not a string
         // but an actual Python module object, which is non-existant if the module was not imported before)
         bool was_imported = (ExecuteOneLineWithReturn(command_stream.GetData(),
-                                                      ScriptInterpreterPython::eScriptReturnTypeInt, &refcount, false) && refcount > 0);
+                                                      ScriptInterpreterPython::eScriptReturnTypeInt,
+                                                      &refcount,
+                                                      false,
+                                                      false) && refcount > 0);
         if (was_imported == true && can_reload == false)
         {
             error.SetErrorString("module already imported");
@@ -2442,7 +2449,7 @@
         // now actually do the import
         command_stream.Clear();
         command_stream.Printf("import %s",basename.c_str());
-        bool import_retval = ExecuteOneLine(command_stream.GetData(), NULL, false);
+        bool import_retval = ExecuteOneLine(command_stream.GetData(), NULL, false, false);
         if (!import_retval)
         {
             error.SetErrorString("Python import statement failed");
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index c5e3f8a..f139044 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -55,8 +55,13 @@
 OperatingSystemPython::CreateInstance (Process *process, bool force)
 {
     // Python OperatingSystem plug-ins must be requested by name, so force must be true
-    if (force)
-        return new OperatingSystemPython (process);
+    FileSpec python_os_plugin_spec (process->GetPythonOSPluginPath());
+    if (python_os_plugin_spec && python_os_plugin_spec.Exists())
+    {
+        std::auto_ptr<OperatingSystemPython> os_ap (new OperatingSystemPython (process, python_os_plugin_spec));
+        if (os_ap.get() && os_ap->IsValid())
+            return os_ap.release();
+    }
     return NULL;
 }
 
@@ -74,12 +79,12 @@
 }
 
 
-OperatingSystemPython::OperatingSystemPython (lldb_private::Process *process) :
+OperatingSystemPython::OperatingSystemPython (lldb_private::Process *process, const FileSpec &python_module_path) :
     OperatingSystem (process),
     m_thread_list_valobj_sp (),
     m_register_info_ap (),
-    m_interpreter(NULL),
-    m_python_object(NULL)
+    m_interpreter (NULL),
+    m_python_object (NULL)
 {
     if (!process)
         return;
@@ -89,13 +94,27 @@
     m_interpreter = target_sp->GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
     if (m_interpreter)
     {
-        // TODO: hardcoded is not good
-        auto object_sp = m_interpreter->CreateOSPlugin("operating_system.PlugIn",process->CalculateProcess());
-        if (object_sp)
+        
+        std::string os_plugin_class_name (python_module_path.GetFilename().AsCString(""));
+        if (!os_plugin_class_name.empty())
         {
-            m_python_object = object_sp->GetObject();
-            
-            //GetDynamicRegisterInfo (); // COMMENT THIS LINE OUT PRIOR TO CHECKIN!!!
+            const bool init_session = false;
+            const bool allow_reload = true;
+            char python_module_path_cstr[PATH_MAX];
+            python_module_path.GetPath(python_module_path_cstr, sizeof(python_module_path_cstr));
+            Error error;
+            if (m_interpreter->LoadScriptingModule (python_module_path_cstr, allow_reload, init_session, error))
+            {
+                // Strip the ".py" extension if there is one
+                size_t py_extension_pos = os_plugin_class_name.rfind(".py");
+                if (py_extension_pos != std::string::npos)
+                    os_plugin_class_name.erase (py_extension_pos);
+                // Add ".OperatingSystemPlugIn" to the module name to get a string like "modulename.OperatingSystemPlugIn"
+                os_plugin_class_name += ".OperatingSystemPlugIn";
+                auto object_sp = m_interpreter->CreateOSPlugin(os_plugin_class_name.c_str(), process->CalculateProcess());
+                if (object_sp)
+                    m_python_object = object_sp->GetObject();
+            }
         }
     }
 }
@@ -217,8 +236,8 @@
         return RegisterContextSP();
     auto object_sp = m_interpreter->OSPlugin_QueryForRegisterContextData (m_interpreter->MakeScriptObject(m_python_object),
                                                                           thread->GetID());
-
-           if (!object_sp)
+    
+    if (!object_sp)
         return RegisterContextSP();
     
     PythonDataString reg_context_data((PyObject*)object_sp->GetObject());
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
index 5711426..8dccf24 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
@@ -43,7 +43,8 @@
     //------------------------------------------------------------------
     // Class Methods
     //------------------------------------------------------------------
-    OperatingSystemPython (lldb_private::Process *process);
+    OperatingSystemPython (lldb_private::Process *process,
+                           const lldb_private::FileSpec &python_module_path);
     
     virtual
     ~OperatingSystemPython ();
@@ -78,6 +79,10 @@
 
 protected:
     
+    bool IsValid() const
+    {
+        return m_python_object != NULL;
+    }
     DynamicRegisterInfo *
     GetDynamicRegisterInfo ();
 
diff --git a/source/Target/Process.cpp b/source/Target/Process.cpp
index dd28cc1..65115b1 100644
--- a/source/Target/Process.cpp
+++ b/source/Target/Process.cpp
@@ -94,12 +94,14 @@
 {
     { "disable-memory-cache" , OptionValue::eTypeBoolean, false, DISABLE_MEM_CACHE_DEFAULT, NULL, NULL, "Disable reading and caching of memory in fixed-size units." },
     { "extra-startup-command", OptionValue::eTypeArray  , false, OptionValue::eTypeString, NULL, NULL, "A list containing extra commands understood by the particular process plugin used." },
+    { "python-os-plugin-path", OptionValue::eTypeFileSpec, false, 0, NULL, NULL, "A path to a python OS plug-in module file that contains a OperatingSystemPlugIn class." },
     {  NULL                  , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL  }
 };
 
 enum {
     ePropertyDisableMemCache,
-    ePropertyExtraStartCommand
+    ePropertyExtraStartCommand,
+    ePropertyPythonOSPluginPath
 };
 
 ProcessProperties::ProcessProperties (bool is_global) :
@@ -145,6 +147,20 @@
     m_collection_sp->SetPropertyAtIndexFromArgs(NULL, idx, args);
 }
 
+FileSpec
+ProcessProperties::GetPythonOSPluginPath () const
+{
+    const uint32_t idx = ePropertyPythonOSPluginPath;
+    return m_collection_sp->GetPropertyAtIndexAsFileSpec(NULL, idx);
+}
+
+void
+ProcessProperties::SetPythonOSPluginPath (const FileSpec &file)
+{
+    const uint32_t idx = ePropertyPythonOSPluginPath;
+    m_collection_sp->SetPropertyAtIndexAsFileSpec(NULL, idx, file);
+}
+
 void
 ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const
 {