Adding bindings to the Script Interpreter for some basic Python OS plugin functionality (still WIP)

git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@162513 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Interpreter/ScriptInterpreterPython.cpp b/source/Interpreter/ScriptInterpreterPython.cpp
index 79089c5..94b27bb 100644
--- a/source/Interpreter/ScriptInterpreterPython.cpp
+++ b/source/Interpreter/ScriptInterpreterPython.cpp
@@ -55,6 +55,7 @@
 static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = NULL;
 static ScriptInterpreter::SWIGPythonCallCommand g_swig_call_command = NULL;
 static ScriptInterpreter::SWIGPythonCallModuleInit g_swig_call_module_init = NULL;
+static ScriptInterpreter::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = NULL;
 
 // these are the Pythonic implementations of the required callbacks
 // these are scripting-language specific, which is why they belong here
@@ -121,6 +122,13 @@
  lldb::DebuggerSP& debugger
  );
 
+extern "C" void*        LLDBSWIGPythonCreateOSPlugin
+(
+ const std::string python_class_name,
+ const char *session_dictionary_name,
+ const lldb::ProcessSP& process_sp
+);
+
 static int
 _check_and_flush (FILE *stream)
 {
@@ -1697,6 +1705,85 @@
 }
 
 lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::CreateOSPlugin (std::string class_name,
+                lldb::ProcessSP process_sp)
+{
+    if (class_name.empty())
+        return lldb::ScriptInterpreterObjectSP();
+    
+    if (!process_sp)
+        return lldb::ScriptInterpreterObjectSP();
+        
+    void* ret_val;
+    
+    {
+        Locker py_lock(this);
+        ret_val = g_swig_create_os_plugin    (class_name,
+                                              m_dictionary_name.c_str(),
+                                              process_sp);
+    }
+    
+    return MakeScriptObject(ret_val);
+}
+
+lldb::ScriptInterpreterObjectSP
+ScriptInterpreterPython::OSPlugin_QueryForRegisterInfo (lldb::ScriptInterpreterObjectSP object)
+{
+    static char callee_name[] = "get_register_info";
+    
+    if (!object)
+        return lldb::ScriptInterpreterObjectSP();
+    
+    PyObject* implementor = (PyObject*)object->GetObject();
+    
+    if (implementor == NULL || implementor == Py_None)
+        return lldb::ScriptInterpreterObjectSP();
+    
+    PyObject* pmeth  = PyObject_GetAttrString(implementor, callee_name);
+    
+    if (PyErr_Occurred())
+    {
+        PyErr_Clear();
+    }
+    
+    if (pmeth == NULL || pmeth == Py_None)
+    {
+        Py_XDECREF(pmeth);
+        return lldb::ScriptInterpreterObjectSP();
+    }
+    
+    if (PyCallable_Check(pmeth) == 0)
+    {
+        if (PyErr_Occurred())
+        {
+            PyErr_Clear();
+        }
+        
+        Py_XDECREF(pmeth);
+        return lldb::ScriptInterpreterObjectSP();
+    }
+    
+    if (PyErr_Occurred())
+    {
+        PyErr_Clear();
+    }
+    
+    Py_XDECREF(pmeth);
+    
+    // right now we know this function exists and is callable..
+    PyObject* py_return = PyObject_CallMethod(implementor, callee_name, NULL);
+    
+    // if it fails, print the error but otherwise go on
+    if (PyErr_Occurred())
+    {
+        PyErr_Print();
+        PyErr_Clear();
+    }
+    
+    return MakeScriptObject(py_return);
+}
+
+lldb::ScriptInterpreterObjectSP
 ScriptInterpreterPython::CreateSyntheticScriptedProvider (std::string class_name,
                                                           lldb::ValueObjectSP valobj)
 {
@@ -2366,6 +2453,7 @@
     g_swig_update_provider = LLDBSwigPython_UpdateSynthProviderInstance;
     g_swig_call_command = LLDBSwigPythonCallCommand;
     g_swig_call_module_init = LLDBSwigPythonCallModuleInit;
+    g_swig_create_os_plugin = LLDBSWIGPythonCreateOSPlugin;
 }
 
 void
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index 761da1f..ad86f8c 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -16,10 +16,13 @@
 
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Core/RegisterValue.h"
 #include "lldb/Core/ValueObjectVariable.h"
+#include "lldb/Interpreter/CommandInterpreter.h"
+#include "lldb/Interpreter/PythonDataObjects.h"
 #include "lldb/Symbol/ClangNamespaceDecl.h"
 #include "lldb/Symbol/ObjectFile.h"
 #include "lldb/Symbol/VariableList.h"
@@ -53,7 +56,7 @@
 OperatingSystemPython::CreateInstance (Process *process, bool force)
 {
     // Python OperatingSystem plug-ins must be requested by name, so force must be true
-    if (force)
+    //if (force)
         return new OperatingSystemPython (process);
     return NULL;
 }
@@ -75,14 +78,23 @@
 OperatingSystemPython::OperatingSystemPython (lldb_private::Process *process) :
     OperatingSystem (process),
     m_thread_list_valobj_sp (),
-    m_register_info_ap ()
+    m_register_info_ap (),
+    m_interpreter(NULL),
+    m_python_object(NULL)
 {
-    // TODO: python: create a new python class the implements the necessary
-    // python class that will cache a SBProcess that contains the "process"
-    // argument above and implements:
-    // dict get_thread_info()
-    // dict get_register_info()
-    // Bytes get_register_context_data(SBThread thread)
+    if (!process)
+        return;
+    lldb::TargetSP target_sp = process->CalculateTarget();
+    if (!target_sp)
+        return;
+    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)
+            m_python_object = object_sp->GetObject();
+    }
 }
 
 OperatingSystemPython::~OperatingSystemPython ()
@@ -92,10 +104,17 @@
 DynamicRegisterInfo *
 OperatingSystemPython::GetDynamicRegisterInfo ()
 {
-    // TODO: python: call get_register_info() on the python object that
-    // represents our instance of the OperatingSystem plug-in
+    if (!m_interpreter || !m_python_object)
+        return NULL;
+    auto object_sp = m_interpreter->OSPlugin_QueryForRegisterInfo(m_interpreter->MakeScriptObject(m_python_object));
+    if (!object_sp)
+        return NULL;
+    PythonDataObject dictionary_data_obj((PyObject*)object_sp->GetObject());
+    PythonDataDictionary dictionary = dictionary_data_obj.GetDictionaryObject();
+    if(!dictionary)
+        return NULL;
     
-    // Example code below shows creating a new DynamicRegisterInfo()
+    // TODO: iterate over the dictionary
     if (m_register_info_ap.get() == NULL && m_thread_list_valobj_sp)
     {
 //        static ConstString g_gpr_member_name("gpr");
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
index 850ec64..5711426 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
@@ -14,6 +14,7 @@
 // C Includes
 // C++ Includes
 // Other libraries and framework includes
+#include "lldb/Interpreter/ScriptInterpreter.h"
 #include "lldb/Target/OperatingSystem.h"
 
 class DynamicRegisterInfo;
@@ -82,6 +83,8 @@
 
     lldb::ValueObjectSP m_thread_list_valobj_sp;
     std::auto_ptr<DynamicRegisterInfo> m_register_info_ap;
+    lldb_private::ScriptInterpreter *m_interpreter;
+    void* m_python_object;
     
 };