From a4d8747d0f52e12b905b1dd61b117605021b14db Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Fri, 18 Jan 2013 23:41:08 +0000 Subject: [PATCH] Added the ability for OS plug-ins to lazily populate the thread this. The python OS plug-in classes can now implement the following method: class OperatingSystemPlugin: def create_thread(self, tid, context): # Return a dictionary for a new thread to create it on demand This will add a new thread to the thread list if it doesn't already exist. The example code in lldb/examples/python/operating_system.py has been updated to show how this call us used. Cleaned up the code in PythonDataObjects.cpp/h: - renamed all classes that started with PythonData* to be Python*. - renamed PythonArray to PythonList. Cleaned up the code to use inheritance where - Centralized the code that does ref counting in the PythonObject class to a single function. - Made the "bool PythonObject::Reset(PyObject *)" function be virtual so each subclass can correctly check to ensure a PyObject is of the right type before adopting the object. - Cleaned up all APIs and added new constructors for the Python* classes to they can all construct form: - PyObject * - const PythonObject & - const lldb::ScriptInterpreterObjectSP & Cleaned up code in ScriptInterpreterPython: - Made calling python functions safer by templatizing the production of value formats. Python specifies the value formats based on built in C types (long, long long, etc), and code often uses typedefs for uint32_t, uint64_t, etc when passing arguments down to python. We will now always produce correct value formats as the templatized code will "do the right thing" all the time. - Fixed issues with the ScriptInterpreterPython::Locker where entering the session and leaving the session had a bunch of issues that could cause the "lldb" module globals lldb.debugger, lldb.target, lldb.process, lldb.thread, and lldb.frame to not be initialized. llvm-svn: 172873 --- lldb/examples/python/operating_system.py | 12 + lldb/include/lldb/API/SBProcess.h | 9 + lldb/include/lldb/Interpreter/PythonDataObjects.h | 243 +++++++--------- lldb/include/lldb/Interpreter/ScriptInterpreter.h | 22 +- .../lldb/Interpreter/ScriptInterpreterPython.h | 21 +- lldb/include/lldb/Target/OperatingSystem.h | 5 + lldb/include/lldb/Target/Process.h | 3 + lldb/include/lldb/lldb-forward.h | 10 +- lldb/scripts/Python/interface/SBProcess.i | 6 + lldb/source/API/SBProcess.cpp | 21 ++ lldb/source/Interpreter/PythonDataObjects.cpp | 314 ++++++++++++--------- .../source/Interpreter/ScriptInterpreterPython.cpp | 271 ++++++++++++------ .../Python/OperatingSystemPython.cpp | 148 ++++++---- .../OperatingSystem/Python/OperatingSystemPython.h | 16 +- .../Process/Utility/DynamicRegisterInfo.cpp | 35 +-- .../Plugins/Process/Utility/DynamicRegisterInfo.h | 4 +- lldb/source/Target/Process.cpp | 11 + 17 files changed, 690 insertions(+), 461 deletions(-) diff --git a/lldb/examples/python/operating_system.py b/lldb/examples/python/operating_system.py index b0ce05d..2040632 100644 --- a/lldb/examples/python/operating_system.py +++ b/lldb/examples/python/operating_system.py @@ -23,6 +23,13 @@ class OperatingSystemPlugIn(object): # tracks the current target in the LLDB command interpreter which isn't the # correct thing to use for this plug-in. return self.process.target + + def create_thread(self, tid, context): + if tid == 0x444444444: + thread_info = { 'tid' : 0x444444444, 'name' : 'four' , 'queue' : 'queue4', 'state' : 'stopped', 'stop_reason' : 'none' } + self.threads.append(thread_info) + return thread_info + return None def get_thread_info(self): if not self.threads: @@ -89,4 +96,9 @@ class OperatingSystemPlugIn(object): return struct.pack('21Q',11,12,13,14,15,16,17,18,19,110,111,112,113,114,115,116,117,118,119,120,121); elif tid == 0x333333333: return struct.pack('21Q',21,22,23,24,25,26,27,28,29,210,211,212,213,214,215,216,217,218,219,220,221); + elif tid == 0x444444444: + return struct.pack('21Q',31,32,33,34,35,36,37,38,39,310,311,312,313,314,315,316,317,318,319,320,321); + else: + return struct.pack('21Q',41,42,43,44,45,46,47,48,49,410,411,412,413,414,415,416,417,418,419,420,421); + return None diff --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h index caf9fd8..572e154 100644 --- a/lldb/include/lldb/API/SBProcess.h +++ b/lldb/include/lldb/API/SBProcess.h @@ -122,6 +122,15 @@ public: lldb::SBThread GetSelectedThread () const; + //------------------------------------------------------------------ + // Function for lazily creating a thread using the current OS + // plug-in. This function will be removed in the future when there + // are APIs to create SBThread objects through the interface and add + // them to the process through the SBProcess API. + //------------------------------------------------------------------ + lldb::SBThread + CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context); + bool SetSelectedThread (const lldb::SBThread &thread); diff --git a/lldb/include/lldb/Interpreter/PythonDataObjects.h b/lldb/include/lldb/Interpreter/PythonDataObjects.h index 7b17286..f978b68 100644 --- a/lldb/include/lldb/Interpreter/PythonDataObjects.h +++ b/lldb/include/lldb/Interpreter/PythonDataObjects.h @@ -27,68 +27,98 @@ namespace lldb_private { - class PythonRefCountedObject + class PythonObject { public: - PythonRefCountedObject (PyObject* obj = NULL) : m_object(obj) + PythonObject () : + m_py_obj(NULL) { - Py_XINCREF(m_object); } - PythonRefCountedObject (const PythonRefCountedObject &rhs) : - m_object(rhs.m_object) + PythonObject (PyObject* py_obj) : + m_py_obj(NULL) { - Py_XINCREF(m_object); + Reset (py_obj); } - ~PythonRefCountedObject () + PythonObject (const PythonObject &rhs) : + m_py_obj(NULL) { - Py_XDECREF(m_object); + Reset (rhs.m_py_obj); } + + PythonObject (const lldb::ScriptInterpreterObjectSP &script_object_sp); - const PythonRefCountedObject & - operator = (const PythonRefCountedObject &rhs) + virtual + ~PythonObject () + { + Reset (NULL); + } + + const PythonObject & + operator = (const PythonObject &rhs) { if (this != &rhs) - Reset (rhs.m_object); + Reset (rhs.m_py_obj); return *this; } - void - Reset (PyObject* object = NULL) + bool + Reset (const PythonObject &object) { - if (object != m_object) + return Reset(object.GetPythonObject()); + } + + virtual bool + Reset (PyObject* py_obj = NULL) + { + if (py_obj != m_py_obj) { - Py_XDECREF(m_object); - m_object = object; - Py_XINCREF(m_object); + Py_XDECREF(m_py_obj); + m_py_obj = py_obj; + Py_XINCREF(m_py_obj); } + return true; } + void + Dump () const + { + if (m_py_obj) + _PyObject_Dump (m_py_obj); + else + puts ("NULL"); + } + PyObject* - GetPyhonObject () const + GetPythonObject () const { - return m_object; + return m_py_obj; } operator bool () const { - return m_object != NULL; + return m_py_obj != NULL; } - private: - PyObject* m_object; + protected: + PyObject* m_py_obj; }; - class PythonDataString + class PythonString: public PythonObject { public: - PythonDataString (bool create_empty); - PythonDataString (PyObject* object = NULL); - PythonDataString (const char* string); - ~PythonDataString (); + PythonString (); + PythonString (PyObject *o); + PythonString (const PythonObject &object); + PythonString (const lldb::ScriptInterpreterObjectSP &script_object_sp); + PythonString (const char* string); + virtual ~PythonString (); + virtual bool + Reset (PyObject* py_obj = NULL); + const char* GetString() const; @@ -96,170 +126,97 @@ namespace lldb_private { GetSize() const; void - SetString (const char* string); - - operator bool () const - { - return m_object.operator bool(); - } - - PyObject* - GetPythonObject() const - { - return m_object.GetPyhonObject(); - } - private: - PythonRefCountedObject m_object; + SetString (const char* string); }; - class PythonDataInteger + class PythonInteger: public PythonObject { public: - PythonDataInteger (bool create_empty = true); - PythonDataInteger (PyObject* object); - PythonDataInteger (int64_t value); - ~PythonDataInteger (); + PythonInteger (); + PythonInteger (PyObject* py_obj); + PythonInteger (const PythonObject &object); + PythonInteger (const lldb::ScriptInterpreterObjectSP &script_object_sp); + PythonInteger (int64_t value); + virtual ~PythonInteger (); + + virtual bool + Reset (PyObject* py_obj = NULL); int64_t GetInteger(); void SetInteger (int64_t value); - - operator bool () const - { - return m_object.operator bool(); - } - - PyObject* - GetPythonObject() const - { - return m_object.GetPyhonObject(); - } - private: - PythonRefCountedObject m_object; }; - class PythonDataArray + class PythonList: public PythonObject { public: - PythonDataArray (bool create_empty = true); - PythonDataArray (PyObject* object); - PythonDataArray (uint32_t count); - ~PythonDataArray (); + PythonList (); + PythonList (PyObject* py_obj); + PythonList (const PythonObject &object); + PythonList (const lldb::ScriptInterpreterObjectSP &script_object_sp); + PythonList (uint32_t count); + virtual ~PythonList (); + + virtual bool + Reset (PyObject* py_obj = NULL); uint32_t GetSize(); - PythonDataObject + PythonObject GetItemAtIndex (uint32_t index); void - SetItemAtIndex (uint32_t index, const PythonDataObject &object); + SetItemAtIndex (uint32_t index, const PythonObject &object); void - AppendItem (const PythonDataObject &object); - - operator bool () const - { - return m_object.operator bool(); - } - - PyObject* - GetPythonObject() const - { - return m_object.GetPyhonObject(); - } - private: - PythonRefCountedObject m_object; + AppendItem (const PythonObject &object); }; - class PythonDataDictionary + class PythonDictionary: public PythonObject { public: - PythonDataDictionary (bool create_empty = true); - PythonDataDictionary (PyObject* object); - ~PythonDataDictionary (); + PythonDictionary (); + PythonDictionary (PyObject* object); + PythonDictionary (const PythonObject &object); + PythonDictionary (const lldb::ScriptInterpreterObjectSP &script_object_sp); + virtual ~PythonDictionary (); + + virtual bool + Reset (PyObject* object = NULL); uint32_t GetSize(); - PythonDataObject - GetItemForKey (const PythonDataString &key) const; + PythonObject + GetItemForKey (const PythonString &key) const; const char * - GetItemForKeyAsString (const PythonDataString &key, const char *fail_value = NULL) const; + GetItemForKeyAsString (const PythonString &key, const char *fail_value = NULL) const; int64_t - GetItemForKeyAsInteger (const PythonDataString &key, int64_t fail_value = 0) const; + GetItemForKeyAsInteger (const PythonString &key, int64_t fail_value = 0) const; - PythonDataObject + PythonObject GetItemForKey (const char *key) const; - typedef bool (*DictionaryIteratorCallback)(PythonDataString* key, PythonDataDictionary* dict); + typedef bool (*DictionaryIteratorCallback)(PythonString* key, PythonDictionary* dict); - PythonDataArray + PythonList GetKeys () const; - PythonDataString + PythonString GetKeyAtPosition (uint32_t pos) const; - PythonDataObject + PythonObject GetValueAtPosition (uint32_t pos) const; void - SetItemForKey (const PythonDataString &key, const PythonDataObject& value); - - operator bool () const - { - return m_object.operator bool(); - } - - PyObject* - GetPythonObject() const - { - return m_object.GetPyhonObject(); - } - private: - PythonRefCountedObject m_object; - }; - - class PythonDataObject - { - public: - - PythonDataObject (); - PythonDataObject (PyObject* object); - - ~PythonDataObject (); - - PythonDataString - GetStringObject (); - - PythonDataInteger - GetIntegerObject (); - - PythonDataArray - GetArrayObject(); - - PythonDataDictionary - GetDictionaryObject(); - - operator bool () const - { - return m_object.operator bool(); - } - - PyObject* - GetPythonObject() const - { - return m_object.GetPyhonObject(); - } - - private: - PythonRefCountedObject m_object; + SetItemForKey (const PythonString &key, const PythonObject& value); }; } // namespace lldb_private diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index c41b261..420f7b3 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -268,31 +268,39 @@ public: } virtual lldb::ScriptInterpreterObjectSP - CreateOSPlugin (const char *class_name, - lldb::ProcessSP process_sp) + OSPlugin_CreatePluginObject (const char *class_name, + lldb::ProcessSP process_sp) { return lldb::ScriptInterpreterObjectSP(); } virtual lldb::ScriptInterpreterObjectSP - OSPlugin_QueryForRegisterInfo (lldb::ScriptInterpreterObjectSP object) + OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) { return lldb::ScriptInterpreterObjectSP(); } virtual lldb::ScriptInterpreterObjectSP - OSPlugin_QueryForThreadsInfo (lldb::ScriptInterpreterObjectSP object) + OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) { return lldb::ScriptInterpreterObjectSP(); } virtual lldb::ScriptInterpreterObjectSP - OSPlugin_QueryForRegisterContextData (lldb::ScriptInterpreterObjectSP object, - lldb::tid_t thread_id) + OSPlugin_RegisterContextData (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, + lldb::tid_t thread_id) { return lldb::ScriptInterpreterObjectSP(); } - + + virtual lldb::ScriptInterpreterObjectSP + OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, + lldb::tid_t tid, + lldb::addr_t context) + { + return lldb::ScriptInterpreterObjectSP(); + } + virtual bool GenerateFunction(const char *signature, const StringList &input) { diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h index 11e1a92..9914287 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreterPython.h @@ -80,18 +80,23 @@ public: lldb::ValueObjectSP valobj); virtual lldb::ScriptInterpreterObjectSP - CreateOSPlugin (const char *class_name, - lldb::ProcessSP process_sp); + OSPlugin_CreatePluginObject (const char *class_name, + lldb::ProcessSP process_sp); virtual lldb::ScriptInterpreterObjectSP - OSPlugin_QueryForRegisterInfo (lldb::ScriptInterpreterObjectSP object); + OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp); virtual lldb::ScriptInterpreterObjectSP - OSPlugin_QueryForThreadsInfo (lldb::ScriptInterpreterObjectSP object); + OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp); virtual lldb::ScriptInterpreterObjectSP - OSPlugin_QueryForRegisterContextData (lldb::ScriptInterpreterObjectSP object, - lldb::tid_t thread_id); + OSPlugin_RegisterContextData (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, + lldb::tid_t thread_id); + + virtual lldb::ScriptInterpreterObjectSP + OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, + lldb::tid_t tid, + lldb::addr_t context); virtual uint32_t CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor); @@ -211,7 +216,7 @@ public: protected: - void + bool EnterSession (bool init_lldb_globals); void @@ -308,7 +313,7 @@ private: static void ReleasePythonLock (); - bool m_need_session; + bool m_teardown_session; ScriptInterpreterPython *m_python_interpreter; FILE* m_tmp_fh; PyGILState_STATE m_GILState; diff --git a/lldb/include/lldb/Target/OperatingSystem.h b/lldb/include/lldb/Target/OperatingSystem.h index 600e36b..c568a40 100644 --- a/lldb/include/lldb/Target/OperatingSystem.h +++ b/lldb/include/lldb/Target/OperatingSystem.h @@ -76,6 +76,11 @@ public: virtual lldb::StopInfoSP CreateThreadStopReason (Thread *thread) = 0; + virtual lldb::ThreadSP + CreateThread (lldb::tid_t tid, lldb::addr_t context) + { + return lldb::ThreadSP(); + } protected: //------------------------------------------------------------------ // Member variables. diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index a2fc51a..c765f6c 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -3170,6 +3170,9 @@ public: uint32_t GetNextThreadIndexID (uint64_t thread_id); + lldb::ThreadSP + CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context); + // Returns true if an index id has been assigned to a thread. bool HasAssignedIndexIDToThread(uint64_t sb_thread_id); diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index a436d1a..8d08c52 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -166,11 +166,11 @@ class ProcessInstanceInfoMatch; class ProcessLaunchInfo; class Property; struct PropertyDefinition; -class PythonDataArray; -class PythonDataDictionary; -class PythonDataInteger; -class PythonDataObject; -class PythonDataString; +class PythonArray; +class PythonDictionary; +class PythonInteger; +class PythonObject; +class PythonString; class RegisterContext; class RegisterLocation; class RegisterLocationList; diff --git a/lldb/scripts/Python/interface/SBProcess.i b/lldb/scripts/Python/interface/SBProcess.i index 684d2aa..9303e9f 100644 --- a/lldb/scripts/Python/interface/SBProcess.i +++ b/lldb/scripts/Python/interface/SBProcess.i @@ -164,6 +164,12 @@ public: lldb::SBThread GetSelectedThread () const; + %feature("autodoc", " + Lazily create a thread on demand through the current OperatingSystem plug-in, if the current OperatingSystem plug-in supports it. + ") CreateOSPluginThread; + lldb::SBThread + CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context); + bool SetSelectedThread (const lldb::SBThread &thread); diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp index 6c128b7..dfd799c 100644 --- a/lldb/source/API/SBProcess.cpp +++ b/lldb/source/API/SBProcess.cpp @@ -278,6 +278,27 @@ SBProcess::GetSelectedThread () const return sb_thread; } +SBThread +SBProcess::CreateOSPluginThread (lldb::tid_t tid, lldb::addr_t context) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + SBThread sb_thread; + ThreadSP thread_sp; + ProcessSP process_sp(GetSP()); + if (process_sp) + { + Mutex::Locker api_locker (process_sp->GetTarget().GetAPIMutex()); + thread_sp = process_sp->CreateOSPluginThread(tid, context); + sb_thread.SetThread (thread_sp); + } + + if (log) + log->Printf ("SBProcess(%p)::CreateOSPluginThread (tid=0x%" PRIx64 ", context=0x%" PRIx64 ") => SBThread(%p)", process_sp.get(), tid, context, thread_sp.get()); + + return sb_thread; +} + SBTarget SBProcess::GetTarget() const { diff --git a/lldb/source/Interpreter/PythonDataObjects.cpp b/lldb/source/Interpreter/PythonDataObjects.cpp index 44584e9..5b8ec52 100644 --- a/lldb/source/Interpreter/PythonDataObjects.cpp +++ b/lldb/source/Interpreter/PythonDataObjects.cpp @@ -22,294 +22,352 @@ #endif #include "lldb/Interpreter/PythonDataObjects.h" +#include "lldb/Interpreter/ScriptInterpreter.h" using namespace lldb_private; using namespace lldb; -PythonDataObject::PythonDataObject (PyObject* object) : - m_object(object) +//---------------------------------------------------------------------- +// PythonObject +//---------------------------------------------------------------------- +PythonObject::PythonObject (const lldb::ScriptInterpreterObjectSP &script_object_sp) : + m_py_obj (NULL) { + if (script_object_sp) + Reset ((PyObject *)script_object_sp->GetObject()); } -PythonDataObject::PythonDataObject () : - m_object() +//---------------------------------------------------------------------- +// PythonString +//---------------------------------------------------------------------- + +PythonString::PythonString (PyObject *py_obj) : + PythonObject(py_obj) { } -PythonDataObject::~PythonDataObject () +PythonString::PythonString (const PythonObject &object) : + PythonObject(object.GetPythonObject()) { } -PythonDataString -PythonDataObject::GetStringObject () +PythonString::PythonString (const lldb::ScriptInterpreterObjectSP &script_object_sp) : + PythonObject (script_object_sp) { - return PythonDataString(GetPythonObject()); } - -PythonDataInteger -PythonDataObject::GetIntegerObject () + +PythonString::PythonString (const char* string) : + PythonObject(PyString_FromString(string)) +{ +} + +PythonString::PythonString () : + PythonObject() { - return PythonDataInteger(GetPythonObject()); } -PythonDataArray -PythonDataObject::GetArrayObject() +PythonString::~PythonString () { - return PythonDataArray(GetPythonObject()); } -PythonDataDictionary -PythonDataObject::GetDictionaryObject() +bool +PythonString::Reset (PyObject *py_obj) { - return PythonDataDictionary(GetPythonObject()); + if (py_obj && PyString_Check(py_obj)) + return PythonObject::Reset(py_obj); + + PythonObject::Reset(NULL); + return py_obj == NULL; } -PythonDataInteger::PythonDataInteger (bool create_empty) : - m_object(create_empty ? PyInt_FromLong(0) : NULL) +const char* +PythonString::GetString() const { + if (m_py_obj) + return PyString_AsString(m_py_obj); + return NULL; } -PythonDataInteger::PythonDataInteger (PyObject* object) : - m_object(object) +size_t +PythonString::GetSize() const { - if (object && !PyInt_Check(GetPythonObject())) - m_object.Reset(); + if (m_py_obj) + return PyString_Size(m_py_obj); + return 0; } -PythonDataInteger::PythonDataInteger (int64_t value) : - m_object(PyInt_FromLong(value)) +void +PythonString::SetString (const char* string) { + PythonObject::Reset(PyString_FromString(string)); } +//---------------------------------------------------------------------- +// PythonInteger +//---------------------------------------------------------------------- -PythonDataInteger::~PythonDataInteger () +PythonInteger::PythonInteger (PyObject *py_obj) : + PythonObject(py_obj) { } -int64_t -PythonDataInteger::GetInteger() +PythonInteger::PythonInteger (const PythonObject &object) : + PythonObject(object.GetPythonObject()) { - if (m_object) - return PyInt_AsLong(GetPythonObject()); - else - return UINT64_MAX; } -void -PythonDataInteger::SetInteger (int64_t value) +PythonInteger::PythonInteger (const lldb::ScriptInterpreterObjectSP &script_object_sp) : + PythonObject (script_object_sp) { - m_object.Reset(PyInt_FromLong(value)); } -PythonDataString::PythonDataString (bool create_empty) : - m_object(create_empty ? PyString_FromString("") : NULL) +PythonInteger::PythonInteger (int64_t value) : + PythonObject(PyInt_FromLong(value)) { } -PythonDataString::PythonDataString (PyObject* object) : - m_object(object) + +PythonInteger::~PythonInteger () { - if (object && !PyString_Check(GetPythonObject())) - m_object.Reset(); } -PythonDataString::PythonDataString (const char* string) : - m_object(PyString_FromString(string)) +bool +PythonInteger::Reset (PyObject *py_obj) { + if (py_obj && PyInt_Check(py_obj)) + return PythonObject::Reset(py_obj); + + PythonObject::Reset(NULL); + return py_obj == NULL; } -PythonDataString::~PythonDataString () +int64_t +PythonInteger::GetInteger() { + if (m_py_obj) + return PyInt_AsLong(m_py_obj); + else + return UINT64_MAX; } -const char* -PythonDataString::GetString() const +void +PythonInteger::SetInteger (int64_t value) { - if (m_object) - return PyString_AsString(GetPythonObject()); - return NULL; + PythonObject::Reset(PyInt_FromLong(value)); } -size_t -PythonDataString::GetSize() const +//---------------------------------------------------------------------- +// PythonList +//---------------------------------------------------------------------- + +PythonList::PythonList () : + PythonObject(PyList_New(0)) { - if (m_object) - return PyString_Size(GetPythonObject()); - return 0; } -void -PythonDataString::SetString (const char* string) +PythonList::PythonList (uint32_t count) : + PythonObject(PyList_New(count)) { - m_object.Reset(PyString_FromString(string)); } -PythonDataArray::PythonDataArray (bool create_empty) : - m_object(create_empty ? PyList_New(0) : NULL) +PythonList::PythonList (PyObject *py_obj) : + PythonObject(py_obj) { } -PythonDataArray::PythonDataArray (uint32_t count) : - m_object(PyList_New(count)) + +PythonList::PythonList (const PythonObject &object) : + PythonObject(object.GetPythonObject()) { } -PythonDataArray::PythonDataArray (PyObject* object) : - m_object(object) +PythonList::PythonList (const lldb::ScriptInterpreterObjectSP &script_object_sp) : + PythonObject (script_object_sp) { - if (object && !PyList_Check(GetPythonObject())) - m_object.Reset(); } -PythonDataArray::~PythonDataArray () +PythonList::~PythonList () { } +bool +PythonList::Reset (PyObject *py_obj) +{ + if (py_obj && PyList_Check(py_obj)) + return PythonObject::Reset(py_obj); + + PythonObject::Reset(NULL); + return py_obj == NULL; +} + uint32_t -PythonDataArray::GetSize() +PythonList::GetSize() { - if (m_object) - return PyList_GET_SIZE(GetPythonObject()); + if (m_py_obj) + return PyList_GET_SIZE(m_py_obj); return 0; } -PythonDataObject -PythonDataArray::GetItemAtIndex (uint32_t index) +PythonObject +PythonList::GetItemAtIndex (uint32_t index) { - if (m_object) - return PythonDataObject(PyList_GetItem(GetPythonObject(), index)); + if (m_py_obj) + return PythonObject(PyList_GetItem(m_py_obj, index)); return NULL; } void -PythonDataArray::SetItemAtIndex (uint32_t index, const PythonDataObject & object) +PythonList::SetItemAtIndex (uint32_t index, const PythonObject & object) { - if (m_object && object) - PyList_SetItem(GetPythonObject(), index, object.GetPythonObject()); + if (m_py_obj && object) + PyList_SetItem(m_py_obj, index, object.GetPythonObject()); } void -PythonDataArray::AppendItem (const PythonDataObject &object) +PythonList::AppendItem (const PythonObject &object) +{ + if (m_py_obj && object) + PyList_Append(m_py_obj, object.GetPythonObject()); +} + +//---------------------------------------------------------------------- +// PythonDictionary +//---------------------------------------------------------------------- + +PythonDictionary::PythonDictionary () : + PythonObject(PyDict_New()) { - if (m_object && object) - PyList_Append(GetPythonObject(), object.GetPythonObject()); } -PythonDataDictionary::PythonDataDictionary (bool create_empty) : - m_object(create_empty ? PyDict_New() : NULL) +PythonDictionary::PythonDictionary (PyObject *py_obj) : + PythonObject(py_obj) { } -PythonDataDictionary::PythonDataDictionary (PyObject* object) : - m_object(object) + +PythonDictionary::PythonDictionary (const PythonObject &object) : + PythonObject(object.GetPythonObject()) { - if (object && !PyDict_Check(GetPythonObject())) - m_object.Reset(); } -PythonDataDictionary::~PythonDataDictionary () +PythonDictionary::PythonDictionary (const lldb::ScriptInterpreterObjectSP &script_object_sp) : + PythonObject (script_object_sp) { } +PythonDictionary::~PythonDictionary () +{ +} + +bool +PythonDictionary::Reset (PyObject *py_obj) +{ + if (py_obj && PyDict_Check(py_obj)) + return PythonObject::Reset(py_obj); + + PythonObject::Reset(NULL); + return py_obj == NULL; +} + uint32_t -PythonDataDictionary::GetSize() +PythonDictionary::GetSize() { - if (m_object) - return PyDict_Size(GetPythonObject()); + if (m_py_obj) + return PyDict_Size(m_py_obj); return 0; } -PythonDataObject -PythonDataDictionary::GetItemForKey (const char *key) const +PythonObject +PythonDictionary::GetItemForKey (const char *key) const { if (key && key[0]) { - PythonDataString python_key(key); + PythonString python_key(key); return GetItemForKey(python_key); } return NULL; } -PythonDataObject -PythonDataDictionary::GetItemForKey (const PythonDataString &key) const +PythonObject +PythonDictionary::GetItemForKey (const PythonString &key) const { - if (m_object && key) - return PythonDataObject(PyDict_GetItem(GetPythonObject(), key.GetPythonObject())); - return PythonDataObject(); + if (m_py_obj && key) + return PythonObject(PyDict_GetItem(m_py_obj, key.GetPythonObject())); + return PythonObject(); } const char * -PythonDataDictionary::GetItemForKeyAsString (const PythonDataString &key, const char *fail_value) const +PythonDictionary::GetItemForKeyAsString (const PythonString &key, const char *fail_value) const { - if (m_object && key) + if (m_py_obj && key) { - PyObject *object = PyDict_GetItem(GetPythonObject(), key.GetPythonObject()); - if (object && PyString_Check(object)) - return PyString_AsString(object); + PyObject *py_obj = PyDict_GetItem(m_py_obj, key.GetPythonObject()); + if (py_obj && PyString_Check(py_obj)) + return PyString_AsString(py_obj); } return fail_value; } int64_t -PythonDataDictionary::GetItemForKeyAsInteger (const PythonDataString &key, int64_t fail_value) const +PythonDictionary::GetItemForKeyAsInteger (const PythonString &key, int64_t fail_value) const { - if (m_object && key) + if (m_py_obj && key) { - PyObject *object = PyDict_GetItem(GetPythonObject(), key.GetPythonObject()); - if (object && PyInt_Check(object)) - return PyInt_AsLong(object); + PyObject *py_obj = PyDict_GetItem(m_py_obj, key.GetPythonObject()); + if (py_obj && PyInt_Check(py_obj)) + return PyInt_AsLong(py_obj); } return fail_value; } -PythonDataArray -PythonDataDictionary::GetKeys () const +PythonList +PythonDictionary::GetKeys () const { - if (m_object) - return PythonDataArray(PyDict_Keys(GetPythonObject())); - return PythonDataArray(); + if (m_py_obj) + return PythonList(PyDict_Keys(m_py_obj)); + return PythonList(); } -PythonDataString -PythonDataDictionary::GetKeyAtPosition (uint32_t pos) const +PythonString +PythonDictionary::GetKeyAtPosition (uint32_t pos) const { PyObject *key, *value; Py_ssize_t pos_iter = 0; - if (m_object) + if (m_py_obj) { - while (PyDict_Next(GetPythonObject(), &pos_iter, &key, &value)) + while (PyDict_Next(m_py_obj, &pos_iter, &key, &value)) { if (pos-- == 0) - return PythonDataString(key); + return PythonString(key); } } - return PythonDataString(); + return PythonString(); } -PythonDataObject -PythonDataDictionary::GetValueAtPosition (uint32_t pos) const +PythonObject +PythonDictionary::GetValueAtPosition (uint32_t pos) const { PyObject *key, *value; Py_ssize_t pos_iter = 0; - if (!m_object) + if (!m_py_obj) return NULL; - while (PyDict_Next(GetPythonObject(), &pos_iter, &key, &value)) { + while (PyDict_Next(m_py_obj, &pos_iter, &key, &value)) { if (pos-- == 0) - return PythonDataObject(value); + return PythonObject(value); } - return PythonDataObject(); + return PythonObject(); } void -PythonDataDictionary::SetItemForKey (const PythonDataString &key, const PythonDataObject &value) +PythonDictionary::SetItemForKey (const PythonString &key, const PythonObject &value) { - if (m_object && key && value) - PyDict_SetItem(GetPythonObject(), key.GetPythonObject(), value.GetPythonObject()); + if (m_py_obj && key && value) + PyDict_SetItem(m_py_obj, key.GetPythonObject(), value.GetPythonObject()); } #endif diff --git a/lldb/source/Interpreter/ScriptInterpreterPython.cpp b/lldb/source/Interpreter/ScriptInterpreterPython.cpp index d3b9cf9..3dce1c5 100644 --- a/lldb/source/Interpreter/ScriptInterpreterPython.cpp +++ b/lldb/source/Interpreter/ScriptInterpreterPython.cpp @@ -135,7 +135,7 @@ ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter uint16_t on_entry, uint16_t on_leave, FILE* wait_msg_handle) : - m_need_session( (on_leave & TearDownSession) == TearDownSession ), + m_teardown_session( (on_leave & TearDownSession) == TearDownSession ), m_python_interpreter(py_interpreter), m_tmp_fh(wait_msg_handle) { @@ -144,7 +144,13 @@ ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter DoAcquireLock(); if ((on_entry & InitSession) == InitSession) - DoInitSession((on_entry & InitGlobals) == InitGlobals); + { + if (DoInitSession((on_entry & InitGlobals) == InitGlobals) == false) + { + // Don't teardown the session if we didn't init it. + m_teardown_session = false; + } + } } bool @@ -162,8 +168,7 @@ ScriptInterpreterPython::Locker::DoInitSession(bool init_lldb_globals) { if (!m_python_interpreter) return false; - m_python_interpreter->EnterSession (init_lldb_globals); - return true; + return m_python_interpreter->EnterSession (init_lldb_globals); } bool @@ -187,7 +192,7 @@ ScriptInterpreterPython::Locker::DoTearDownSession() ScriptInterpreterPython::Locker::~Locker() { - if (m_need_session) + if (m_teardown_session) DoTearDownSession(); DoFreeLock(); } @@ -254,14 +259,11 @@ ScriptInterpreterPython::PythonInputReaderManager::~PythonInputReaderManager() } size_t -ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback -( - void *baton, - InputReader &reader, - InputReaderAction notification, - const char *bytes, - size_t bytes_len - ) +ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback (void *baton, + InputReader &reader, + InputReaderAction notification, + const char *bytes, + size_t bytes_len) { lldb::thread_t embedded_interpreter_thread; LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); @@ -364,22 +366,22 @@ ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback break; case eInputReaderInterrupt: - { - PyThreadState* state = _PyThreadState_Current; - if (!state) - state = script_interpreter->m_command_thread_state; - if (state) { - long tid = state->thread_id; - _PyThreadState_Current = state; - int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); - if (log) - log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, tid = %ld, num_threads = %d, state = %p", - tid,num_threads,state); + PyThreadState* state = _PyThreadState_Current; + if (!state) + state = script_interpreter->m_command_thread_state; + if (state) + { + long tid = state->thread_id; + _PyThreadState_Current = state; + int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt); + if (log) + log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, tid = %ld, num_threads = %d, state = %p", + tid,num_threads,state); + } + else if (log) + log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, state = NULL"); } - else if (log) - log->Printf("ScriptInterpreterPython::NonInteractiveInputReaderCallback, eInputReaderInterrupt, state = NULL"); - } break; case eInputReaderEndOfFile: @@ -404,36 +406,30 @@ ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback bytes_len); reader.SetIsDone (true); } - break; case eInputReaderDone: - { - StreamString run_string; - char error_str[1024]; - const char *pty_slave_name = script_interpreter->m_embedded_thread_pty.GetSlaveName (error_str, sizeof (error_str)); - if (pty_slave_name != NULL && PyThreadState_GetDict() != NULL) { - ScriptInterpreterPython::Locker locker(script_interpreter, - ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession, - ScriptInterpreterPython::Locker::FreeAcquiredLock); - run_string.Printf ("run_one_line (%s, 'sys.stdin = save_stdin')", script_interpreter->m_dictionary_name.c_str()); - PyRun_SimpleString (run_string.GetData()); - run_string.Clear(); + StreamString run_string; + char error_str[1024]; + const char *pty_slave_name = script_interpreter->m_embedded_thread_pty.GetSlaveName (error_str, sizeof (error_str)); + if (pty_slave_name != NULL && PyThreadState_GetDict() != NULL) + { + ScriptInterpreterPython::Locker locker(script_interpreter, + ScriptInterpreterPython::Locker::AcquireLock, + ScriptInterpreterPython::Locker::FreeAcquiredLock); + run_string.Printf ("run_one_line (%s, 'sys.stdin = save_stdin; sys.stderr = save_stderr')", script_interpreter->m_dictionary_name.c_str()); + PyRun_SimpleString (run_string.GetData()); + run_string.Clear(); + } + // Restore terminal settings if they were validly saved + if (log) + log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Done, closing down input reader."); - run_string.Printf ("run_one_line (%s, 'sys.stderr = save_stderr')", script_interpreter->m_dictionary_name.c_str()); - PyRun_SimpleString (run_string.GetData()); - run_string.Clear(); - } - } - - // Restore terminal settings if they were validly saved - if (log) - log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Done, closing down input reader."); - - script_interpreter->RestoreTerminalState (); - - script_interpreter->m_embedded_thread_pty.CloseMasterFileDescriptor(); + script_interpreter->RestoreTerminalState (); + + script_interpreter->m_embedded_thread_pty.CloseMasterFileDescriptor(); + } break; } @@ -586,6 +582,10 @@ ScriptInterpreterPython::RestoreTerminalState () void ScriptInterpreterPython::LeaveSession () { + LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); + if (log) + log->PutCString("ScriptInterpreterPython::LeaveSession()"); + // checking that we have a valid thread state - since we use our own threading and locking // in some (rare) cases during cleanup Python may end up believing we have no thread state // and PyImport_AddModule will crash if that is the case - since that seems to only happen @@ -610,14 +610,22 @@ ScriptInterpreterPython::LeaveSession () m_session_is_active = false; } -void +bool ScriptInterpreterPython::EnterSession (bool init_lldb_globals) { // If we have already entered the session, without having officially 'left' it, then there is no need to // 'enter' it again. - + LogSP log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT)); if (m_session_is_active) - return; + { + if (log) + log->Printf("ScriptInterpreterPython::EnterSession(init_lldb_globals=%i) session is already active, returning without doing anything", init_lldb_globals); + return false; + } + + if (log) + log->Printf("ScriptInterpreterPython::EnterSession(init_lldb_globals=%i)", init_lldb_globals); + m_session_is_active = true; @@ -660,6 +668,8 @@ ScriptInterpreterPython::EnterSession (bool init_lldb_globals) if (PyErr_Occurred()) PyErr_Clear (); + + return true; } static PyObject* @@ -733,7 +743,7 @@ ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObjec Locker locker(this, ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0), - ScriptInterpreterPython::Locker::FreeAcquiredLock | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::TearDownSession : 0)); + ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); bool success = false; @@ -854,9 +864,7 @@ ScriptInterpreterPython::InputReaderCallback { ScriptInterpreterPython::Locker locker(script_interpreter, - ScriptInterpreterPython::Locker::AcquireLock - | ScriptInterpreterPython::Locker::InitSession - | ScriptInterpreterPython::Locker::InitGlobals, + ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals, ScriptInterpreterPython::Locker::FreeAcquiredLock); } @@ -900,11 +908,9 @@ ScriptInterpreterPython::InputReaderCallback case eInputReaderReactivate: { - ScriptInterpreterPython::Locker locker(script_interpreter, - ScriptInterpreterPython::Locker::AcquireLock - | ScriptInterpreterPython::Locker::InitSession - | ScriptInterpreterPython::Locker::InitGlobals, - ScriptInterpreterPython::Locker::FreeAcquiredLock); + ScriptInterpreterPython::Locker locker (script_interpreter, + ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession, + ScriptInterpreterPython::Locker::FreeAcquiredLock); } break; @@ -1008,10 +1014,8 @@ ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string, { Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock - | ScriptInterpreterPython::Locker::InitSession - | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0), - ScriptInterpreterPython::Locker::FreeAcquiredLock | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::TearDownSession : 0)); + ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0), + ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); PyObject *py_return = NULL; PyObject *mainmod = PyImport_AddModule ("__main__"); @@ -1177,10 +1181,8 @@ ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const Exec Locker locker(this, - ScriptInterpreterPython::Locker::AcquireLock - | ScriptInterpreterPython::Locker::InitSession - | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0), - ScriptInterpreterPython::Locker::FreeAcquiredLock | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::TearDownSession : 0)); + ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0), + ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession); bool success = false; PyObject *py_return = NULL; @@ -1719,7 +1721,7 @@ ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::st } lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::CreateOSPlugin (const char *class_name, lldb::ProcessSP process_sp) +ScriptInterpreterPython::OSPlugin_CreatePluginObject (const char *class_name, lldb::ProcessSP process_sp) { if (class_name == NULL || class_name[0] == '\0') return lldb::ScriptInterpreterObjectSP(); @@ -1740,16 +1742,16 @@ ScriptInterpreterPython::CreateOSPlugin (const char *class_name, lldb::ProcessSP } lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::OSPlugin_QueryForRegisterInfo (lldb::ScriptInterpreterObjectSP object) +ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) { Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock); static char callee_name[] = "get_register_info"; - if (!object) + if (!os_plugin_object_sp) return lldb::ScriptInterpreterObjectSP(); - PyObject* implementor = (PyObject*)object->GetObject(); + PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject(); if (implementor == NULL || implementor == Py_None) return lldb::ScriptInterpreterObjectSP(); @@ -1799,16 +1801,16 @@ ScriptInterpreterPython::OSPlugin_QueryForRegisterInfo (lldb::ScriptInterpreterO } lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::OSPlugin_QueryForThreadsInfo (lldb::ScriptInterpreterObjectSP object) +ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp) { Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock); static char callee_name[] = "get_thread_info"; - if (!object) + if (!os_plugin_object_sp) return lldb::ScriptInterpreterObjectSP(); - PyObject* implementor = (PyObject*)object->GetObject(); + PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject(); if (implementor == NULL || implementor == Py_None) return lldb::ScriptInterpreterObjectSP(); @@ -1857,19 +1859,45 @@ ScriptInterpreterPython::OSPlugin_QueryForThreadsInfo (lldb::ScriptInterpreterOb return MakeScriptObject(py_return); } +// GetPythonValueFormatString provides a system independent type safe way to +// convert a variable's type into a python value format. Python value formats +// are defined in terms of builtin C types and could change from system to +// as the underlying typedef for uint* types, size_t, off_t and other values +// change. + +template +const char *GetPythonValueFormatString(T t) +{ + assert(!"Unhandled type passed to GetPythonValueFormatString(T), make a specialization of GetPythonValueFormatString() to support this type."); + return NULL; +} +template <> const char *GetPythonValueFormatString (char *) { return "s"; } +template <> const char *GetPythonValueFormatString (char) { return "b"; } +template <> const char *GetPythonValueFormatString (unsigned char) { return "B"; } +template <> const char *GetPythonValueFormatString (short) { return "h"; } +template <> const char *GetPythonValueFormatString (unsigned short) { return "H"; } +template <> const char *GetPythonValueFormatString (int) { return "i"; } +template <> const char *GetPythonValueFormatString (unsigned int) { return "I"; } +template <> const char *GetPythonValueFormatString (long) { return "l"; } +template <> const char *GetPythonValueFormatString (unsigned long) { return "k"; } +template <> const char *GetPythonValueFormatString (long long) { return "L"; } +template <> const char *GetPythonValueFormatString (unsigned long long) { return "K"; } +template <> const char *GetPythonValueFormatString (float t) { return "f"; } +template <> const char *GetPythonValueFormatString (double t) { return "d"; } + lldb::ScriptInterpreterObjectSP -ScriptInterpreterPython::OSPlugin_QueryForRegisterContextData (lldb::ScriptInterpreterObjectSP object, - lldb::tid_t thread_id) +ScriptInterpreterPython::OSPlugin_RegisterContextData (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, + lldb::tid_t tid) { Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock); static char callee_name[] = "get_register_data"; - static char param_format[] = "l"; + static char *param_format = const_cast(GetPythonValueFormatString(tid)); - if (!object) + if (!os_plugin_object_sp) return lldb::ScriptInterpreterObjectSP(); - PyObject* implementor = (PyObject*)object->GetObject(); + PyObject* implementor = (PyObject*)os_plugin_object_sp->GetObject(); if (implementor == NULL || implementor == Py_None) return lldb::ScriptInterpreterObjectSP(); @@ -1906,8 +1934,72 @@ ScriptInterpreterPython::OSPlugin_QueryForRegisterContextData (lldb::ScriptInter Py_XDECREF(pmeth); // right now we know this function exists and is callable.. - PyObject* py_return = PyObject_CallMethod(implementor, callee_name, param_format, thread_id); + PyObject* py_return = PyObject_CallMethod(implementor, callee_name, param_format, tid); + + // if it fails, print the error but otherwise go on + if (PyErr_Occurred()) + { + PyErr_Print(); + PyErr_Clear(); + } + + return MakeScriptObject(py_return); +} +lldb::ScriptInterpreterObjectSP +ScriptInterpreterPython::OSPlugin_CreateThread (lldb::ScriptInterpreterObjectSP os_plugin_object_sp, + lldb::tid_t tid, + lldb::addr_t context) +{ + Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock); + + static char callee_name[] = "create_thread"; + std::string param_format; + param_format += GetPythonValueFormatString(tid); + param_format += GetPythonValueFormatString(context); + + if (!os_plugin_object_sp) + return lldb::ScriptInterpreterObjectSP(); + + PyObject* implementor = (PyObject*)os_plugin_object_sp->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, ¶m_format[0], tid, context); + // if it fails, print the error but otherwise go on if (PyErr_Occurred()) { @@ -2651,8 +2743,8 @@ ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function, { Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::InitGlobals, - Locker::FreeLock | Locker::TearDownSession); + Locker::AcquireLock | Locker::InitSession, + Locker::FreeLock | Locker::TearDownSession); SynchronicityHandler synch_handler(debugger_sp, synchronicity); @@ -2697,8 +2789,9 @@ ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string& char* result_ptr = NULL; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully if (ExecuteOneLineWithReturn (command.c_str(), - ScriptInterpreter::eScriptReturnTypeCharStrOrNone, - &result_ptr, ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false) /*.SetSetLLDBGlobals(false)*/)) + ScriptInterpreter::eScriptReturnTypeCharStrOrNone, + &result_ptr, + ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false))) { if (result_ptr) dest.assign(result_ptr); diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp index 668799c..ddc5467f 100644 --- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp +++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp @@ -20,7 +20,6 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" -#include "lldb/Interpreter/PythonDataObjects.h" #include "lldb/Core/RegisterValue.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -87,11 +86,11 @@ OperatingSystemPython::OperatingSystemPython (lldb_private::Process *process, co m_thread_list_valobj_sp (), m_register_info_ap (), m_interpreter (NULL), - m_python_object (NULL) + m_python_object_sp () { if (!process) return; - lldb::TargetSP target_sp = process->CalculateTarget(); + TargetSP target_sp = process->CalculateTarget(); if (!target_sp) return; m_interpreter = target_sp->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); @@ -114,9 +113,9 @@ OperatingSystemPython::OperatingSystemPython (lldb_private::Process *process, co 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(); + ScriptInterpreterObjectSP object_sp = m_interpreter->OSPlugin_CreatePluginObject(os_plugin_class_name.c_str(), process->CalculateProcess()); + if (object_sp && object_sp->GetObject()) + m_python_object_sp = object_sp; } } } @@ -131,18 +130,14 @@ OperatingSystemPython::GetDynamicRegisterInfo () { if (m_register_info_ap.get() == NULL) { - if (!m_interpreter || !m_python_object) + if (!m_interpreter || !m_python_object_sp) return NULL; LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); if (log) log->Printf ("OperatingSystemPython::GetDynamicRegisterInfo() fetching thread register definitions from python for pid %" PRIu64, m_process->GetID()); - 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(); + PythonDictionary dictionary(m_interpreter->OSPlugin_RegisterInfo(m_python_object_sp)); if (!dictionary) return NULL; @@ -177,7 +172,7 @@ OperatingSystemPython::GetPluginVersion() bool OperatingSystemPython::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list) { - if (!m_interpreter || !m_python_object) + if (!m_interpreter || !m_python_object_sp) return false; LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); @@ -191,50 +186,18 @@ OperatingSystemPython::UpdateThreadList (ThreadList &old_thread_list, ThreadList if (log) log->Printf ("OperatingSystemPython::UpdateThreadList() fetching thread data from python for pid %" PRIu64, m_process->GetID()); - auto object_sp = m_interpreter->OSPlugin_QueryForThreadsInfo(m_interpreter->MakeScriptObject(m_python_object)); - if (!object_sp) - return false; - PythonDataObject pyobj((PyObject*)object_sp->GetObject()); - PythonDataArray threads_array (pyobj.GetArrayObject()); - if (threads_array) + PythonList threads_list(m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp)); + if (threads_list) { -// const uint32_t num_old_threads = old_thread_list.GetSize(false); -// for (uint32_t i=0; iGetID() < 0x10000) -// new_thread_list.AddThread (old_thread_sp); -// } - - PythonDataString tid_pystr("tid"); - PythonDataString name_pystr("name"); - PythonDataString queue_pystr("queue"); - PythonDataString state_pystr("state"); - PythonDataString stop_reason_pystr("stop_reason"); - PythonDataString reg_data_addr_pystr ("register_data_addr"); - - const uint32_t num_threads = threads_array.GetSize(); + const uint32_t num_threads = threads_list.GetSize(); for (uint32_t i=0; i 0; } +ThreadSP +OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict, ThreadList *old_thread_list_ptr, bool *did_create_ptr) +{ + ThreadSP thread_sp; + if (thread_dict) + { + PythonString tid_pystr("tid"); + PythonString name_pystr("name"); + PythonString queue_pystr("queue"); + PythonString state_pystr("state"); + PythonString stop_reason_pystr("stop_reason"); + PythonString reg_data_addr_pystr ("register_data_addr"); + + const tid_t tid = thread_dict.GetItemForKeyAsInteger (tid_pystr, LLDB_INVALID_THREAD_ID); + const addr_t reg_data_addr = thread_dict.GetItemForKeyAsInteger (reg_data_addr_pystr, LLDB_INVALID_ADDRESS); + const char *name = thread_dict.GetItemForKeyAsString (name_pystr); + const char *queue = thread_dict.GetItemForKeyAsString (queue_pystr); + //const char *state = thread_dict.GetItemForKeyAsString (state_pystr); + //const char *stop_reason = thread_dict.GetItemForKeyAsString (stop_reason_pystr); + + if (old_thread_list_ptr) + thread_sp = old_thread_list_ptr->FindThreadByID (tid, false); + if (!thread_sp) + { + if (did_create_ptr) + *did_create_ptr = true; + thread_sp.reset (new ThreadMemory (*m_process, + tid, + name, + queue, + reg_data_addr)); + } + } + return thread_sp; +} + + + void OperatingSystemPython::ThreadWasSelected (Thread *thread) { } RegisterContextSP -OperatingSystemPython::CreateRegisterContextForThread (Thread *thread, lldb::addr_t reg_data_addr) +OperatingSystemPython::CreateRegisterContextForThread (Thread *thread, addr_t reg_data_addr) { RegisterContextSP reg_ctx_sp; - if (!m_interpreter || !m_python_object || !thread) + if (!m_interpreter || !m_python_object_sp || !thread) return RegisterContextSP(); // First thing we have to do is get the API lock, and the run lock. We're going to change the thread @@ -280,13 +281,7 @@ OperatingSystemPython::CreateRegisterContextForThread (Thread *thread, lldb::add if (log) log->Printf ("OperatingSystemPython::CreateRegisterContextForThread (tid = 0x%" PRIx64 ") fetching register data from python", thread->GetID()); - auto object_sp = m_interpreter->OSPlugin_QueryForRegisterContextData (m_interpreter->MakeScriptObject(m_python_object), - thread->GetID()); - - if (!object_sp) - return RegisterContextSP(); - - PythonDataString reg_context_data((PyObject*)object_sp->GetObject()); + PythonString reg_context_data(m_interpreter->OSPlugin_RegisterContextData (m_python_object_sp, thread->GetID())); if (reg_context_data) { DataBufferSP data_sp (new DataBufferHeap (reg_context_data.GetString(), @@ -315,5 +310,36 @@ OperatingSystemPython::CreateThreadStopReason (lldb_private::Thread *thread) return stop_info_sp; } +lldb::ThreadSP +OperatingSystemPython::CreateThread (lldb::tid_t tid, addr_t context) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD)); + + if (log) + log->Printf ("OperatingSystemPython::CreateThread (tid = 0x%" PRIx64 ", context = 0x%" PRIx64 ") fetching register data from python", tid, context); + + if (m_interpreter && m_python_object_sp) + { + // First thing we have to do is get the API lock, and the run lock. We're going to change the thread + // content of the process, and we're going to use python, which requires the API lock to do it. + // So get & hold that. This is a recursive lock so we can grant it to any Python code called on the stack below us. + Target &target = m_process->GetTarget(); + Mutex::Locker api_locker (target.GetAPIMutex()); + + PythonDictionary thread_info_dict (m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context)); + if (thread_info_dict) + { + ThreadList &thread_list = m_process->GetThreadList(); + bool did_create = false; + ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_info_dict, &thread_list, &did_create)); + if (did_create) + thread_list.AddThread(thread_sp); + return thread_sp; + } + } + return ThreadSP(); +} + + #endif // #ifndef LLDB_DISABLE_PYTHON diff --git a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h index d89a7ab..27cff90 100644 --- a/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h +++ b/lldb/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h @@ -78,19 +78,31 @@ public: virtual lldb::StopInfoSP CreateThreadStopReason (lldb_private::Thread *thread); + //------------------------------------------------------------------ + // Method for lazy creation of threads on demand + //------------------------------------------------------------------ + virtual lldb::ThreadSP + CreateThread (lldb::tid_t tid, lldb::addr_t context); + protected: bool IsValid() const { - return m_python_object != NULL; + return m_python_object_sp && m_python_object_sp->GetObject() != NULL; } + + lldb::ThreadSP + CreateThreadFromThreadInfo (lldb_private::PythonDictionary &thread_dict, + lldb_private::ThreadList *old_thread_list_ptr, + bool *did_create_ptr); + DynamicRegisterInfo * GetDynamicRegisterInfo (); lldb::ValueObjectSP m_thread_list_valobj_sp; std::auto_ptr m_register_info_ap; lldb_private::ScriptInterpreter *m_interpreter; - void* m_python_object; + lldb::ScriptInterpreterObjectSP m_python_object_sp; }; diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index c39bece..0c95d66 100644 --- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -33,7 +33,7 @@ DynamicRegisterInfo::DynamicRegisterInfo () : { } -DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDataDictionary &dict) : +DynamicRegisterInfo::DynamicRegisterInfo (const lldb_private::PythonDictionary &dict) : m_regs (), m_sets (), m_set_reg_nums (), @@ -49,16 +49,19 @@ DynamicRegisterInfo::~DynamicRegisterInfo () size_t -DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDataDictionary &dict) +DynamicRegisterInfo::SetRegisterInfo (const lldb_private::PythonDictionary &dict) { #ifndef LLDB_DISABLE_PYTHON - PythonDataArray sets (dict.GetItemForKey("sets").GetArrayObject()); + PythonList sets (dict.GetItemForKey("sets")); if (sets) { const uint32_t num_sets = sets.GetSize(); for (uint32_t i=0; iCreateThread(tid, context); + return ThreadSP(); +} + + + // This is obsoleted. Staged removal for Xcode. uint32_t Process::GetNextThreadIndexID () -- 2.7.4