Files
llvm/lldb/source/Interpreter/ScriptInterpreterPython.cpp

3154 lines
118 KiB
C++
Raw Normal View History

//===-- ScriptInterpreterPython.cpp -----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
// In order to guarantee correct working with Python, Python.h *MUST* be
// the *FIRST* header file included here.
#ifdef LLDB_DISABLE_PYTHON
// Python is disabled in this build
#else
#include "lldb/lldb-python.h"
#include "lldb/Interpreter/ScriptInterpreterPython.h"
#include <stdlib.h>
#include <stdio.h>
#include <string>
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-06 19:20:51 +00:00
#include "lldb/API/SBValue.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/WatchpointOptions.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Timer.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Thread.h"
using namespace lldb;
using namespace lldb_private;
static ScriptInterpreter::SWIGInitCallback g_swig_init_callback = NULL;
static ScriptInterpreter::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = NULL;
static ScriptInterpreter::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = NULL;
static ScriptInterpreter::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = NULL;
static ScriptInterpreter::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = NULL;
static ScriptInterpreter::SWIGPythonCalculateNumChildren g_swig_calc_children = NULL;
static ScriptInterpreter::SWIGPythonGetChildAtIndex g_swig_get_child_index = NULL;
static ScriptInterpreter::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = NULL;
static ScriptInterpreter::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = NULL;
static ScriptInterpreter::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = NULL;
static ScriptInterpreter::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = NULL;
static ScriptInterpreter::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_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;
static ScriptInterpreter::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = NULL;
static ScriptInterpreter::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = NULL;
static ScriptInterpreter::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = NULL;
static ScriptInterpreter::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = NULL;
<rdar://problem/14972424> When debugging with the GDB remote in LLDB, LLDB uses special packets to discover the registers on the remote server. When those packets aren't supported, LLDB doesn't know what the registers look like. This checkin implements a setting that can be used to specify a python file that contains the registers definitions. The setting is: (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/module.py Inside module there should be a function: def get_dynamic_setting(target, setting_name): This dynamic setting function is handed the "target" which is a SBTarget, and the "setting_name", which is the name of the dynamic setting to retrieve. For the GDB remote target definition the setting name is 'gdb-server-target-definition'. The return value is a dictionary that follows the same format as the OperatingSystem plugins follow. I have checked in an example file that implements the x86_64 GDB register set for people to see: examples/python/x86_64_target_definition.py This allows LLDB to debug to any archticture that is support and allows users to define the registers contexts when the discovery packets (qRegisterInfo, qHostInfo) are not supported by the remote GDB server. A few benefits of doing this in Python: 1 - The dynamic register context was already supported in the OperatingSystem plug-in 2 - Register contexts can use all of the LLDB enumerations and definitions for things like lldb::Format, lldb::Encoding, generic register numbers, invalid registers numbers, etc. 3 - The code that generates the register context can use the program to calculate the register context contents (like offsets, register numbers, and more) 4 - True dynamic detection could be used where variables and types could be read from the target program itself in order to determine which registers are available since the target is passed into the python function. This is designed to be used instead of XML since it is more dynamic and code flow and functions can be used to make the dictionary. llvm-svn: 192646
2013-10-15 00:14:28 +00:00
static ScriptInterpreter::SWIGPython_GetDynamicSetting g_swig_plugin_get = NULL;
static int
_check_and_flush (FILE *stream)
{
int prev_fail = ferror (stream);
return fflush (stream) || prev_fail ? EOF : 0;
}
ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter,
uint16_t on_entry,
uint16_t on_leave,
FILE* wait_msg_handle) :
ScriptInterpreterLocker (),
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
m_teardown_session( (on_leave & TearDownSession) == TearDownSession ),
m_python_interpreter(py_interpreter),
m_tmp_fh(wait_msg_handle)
{
if (m_python_interpreter && !m_tmp_fh)
m_tmp_fh = (m_python_interpreter->m_dbg_stdout ? m_python_interpreter->m_dbg_stdout : stdout);
DoAcquireLock();
if ((on_entry & InitSession) == InitSession)
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
{
if (DoInitSession((on_entry & InitGlobals) == InitGlobals) == false)
{
// Don't teardown the session if we didn't init it.
m_teardown_session = false;
}
}
}
bool
ScriptInterpreterPython::Locker::DoAcquireLock()
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-06 19:20:51 +00:00
{
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
m_GILState = PyGILState_Ensure();
if (log)
log->Printf("Ensured PyGILState. Previous state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : "");
return true;
}
bool
ScriptInterpreterPython::Locker::DoInitSession(bool init_lldb_globals)
{
if (!m_python_interpreter)
return false;
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
return m_python_interpreter->EnterSession (init_lldb_globals);
}
bool
ScriptInterpreterPython::Locker::DoFreeLock()
{
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
if (log)
log->Printf("Releasing PyGILState. Returning to state = %slocked\n", m_GILState == PyGILState_UNLOCKED ? "un" : "");
PyGILState_Release(m_GILState);
return true;
}
bool
ScriptInterpreterPython::Locker::DoTearDownSession()
{
if (!m_python_interpreter)
return false;
m_python_interpreter->LeaveSession ();
return true;
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-06 19:20:51 +00:00
}
ScriptInterpreterPython::Locker::~Locker()
{
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
if (m_teardown_session)
DoTearDownSession();
DoFreeLock();
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-06 19:20:51 +00:00
}
ScriptInterpreterPython::PythonInputReaderManager::PythonInputReaderManager (ScriptInterpreterPython *interpreter) :
m_interpreter(interpreter),
m_debugger_sp(),
m_reader_sp(),
m_error(false)
{
if (m_interpreter == NULL)
{
m_error = true;
return;
}
m_debugger_sp = m_interpreter->GetCommandInterpreter().GetDebugger().shared_from_this();
if (!m_debugger_sp)
{
m_error = true;
return;
}
m_reader_sp = InputReaderSP(new InputReader(*m_debugger_sp.get()));
if (!m_reader_sp)
{
m_error = true;
return;
}
Error error (m_reader_sp->Initialize (ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback,
m_interpreter, // baton
eInputReaderGranularityLine, // token size, to pass to callback function
NULL, // end token
NULL, // prompt
true)); // echo input
if (error.Fail())
m_error = true;
else
{
m_debugger_sp->PushInputReader (m_reader_sp);
m_interpreter->m_embedded_thread_input_reader_sp = m_reader_sp;
}
}
ScriptInterpreterPython::PythonInputReaderManager::~PythonInputReaderManager()
{
// Nothing to do if either m_interpreter or m_reader_sp is invalid.
if (!m_interpreter || !m_reader_sp)
return;
m_reader_sp->SetIsDone (true);
if (m_debugger_sp)
m_debugger_sp->PopInputReader(m_reader_sp);
// Only mess with m_interpreter's counterpart if, indeed, they are the same object.
if (m_reader_sp.get() == m_interpreter->m_embedded_thread_input_reader_sp.get())
{
m_interpreter->m_embedded_thread_pty.CloseSlaveFileDescriptor();
m_interpreter->m_embedded_thread_input_reader_sp.reset();
}
}
size_t
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
ScriptInterpreterPython::PythonInputReaderManager::InputReaderCallback (void *baton,
InputReader &reader,
InputReaderAction notification,
const char *bytes,
size_t bytes_len)
{
lldb::thread_t embedded_interpreter_thread;
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
if (baton == NULL)
return 0;
ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
if (script_interpreter->m_script_lang != eScriptLanguagePython)
return 0;
switch (notification)
{
case eInputReaderActivate:
{
// Save terminal settings if we can
int input_fd = reader.GetDebugger().GetInputFile().GetDescriptor();
if (input_fd == File::kInvalidDescriptor)
input_fd = STDIN_FILENO;
script_interpreter->SaveTerminalState(input_fd);
char error_str[1024];
if (script_interpreter->m_embedded_thread_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str,
sizeof(error_str)))
{
if (log)
log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, succeeded in opening master pty (fd = %d).",
script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor());
{
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::InitGlobals,
ScriptInterpreterPython::Locker::FreeAcquiredLock);
run_string.Printf ("run_one_line (%s, 'save_stderr = sys.stderr')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
run_string.Printf ("run_one_line (%s, 'sys.stderr = sys.stdout')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
run_string.Printf ("run_one_line (%s, 'save_stdin = sys.stdin')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
run_string.Printf ("run_one_line (%s, \"sys.stdin = open ('%s', 'r')\")", script_interpreter->m_dictionary_name.c_str(),
pty_slave_name);
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
}
}
embedded_interpreter_thread = Host::ThreadCreate ("<lldb.script-interpreter.noninteractive-python>",
ScriptInterpreterPython::PythonInputReaderManager::RunPythonInputReader,
script_interpreter, NULL);
if (IS_VALID_LLDB_HOST_THREAD(embedded_interpreter_thread))
{
if (log)
log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, succeeded in creating thread (thread_t = %p)", (void *)embedded_interpreter_thread);
Error detach_error;
Host::ThreadDetach (embedded_interpreter_thread, &detach_error);
}
else
{
if (log)
log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, failed in creating thread");
reader.SetIsDone (true);
}
}
else
{
if (log)
log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, Activate, failed to open master pty ");
reader.SetIsDone (true);
}
}
break;
case eInputReaderDeactivate:
// When another input reader is pushed, don't leave the session...
//script_interpreter->LeaveSession ();
break;
case eInputReaderReactivate:
// {
// ScriptInterpreterPython::Locker locker(script_interpreter,
// ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
// ScriptInterpreterPython::Locker::FreeAcquiredLock);
// }
break;
case eInputReaderAsynchronousOutputWritten:
break;
case eInputReaderInterrupt:
{
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
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");
}
break;
case eInputReaderEndOfFile:
reader.SetIsDone(true);
break;
case eInputReaderGotToken:
if (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor() != -1)
{
if (log)
log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, GotToken, bytes='%s', byte_len = %zu", bytes,
bytes_len);
if (bytes && bytes_len)
::write (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor(), bytes, bytes_len);
::write (script_interpreter->m_embedded_thread_pty.GetMasterFileDescriptor(), "\n", 1);
}
else
{
if (log)
log->Printf ("ScriptInterpreterPython::NonInteractiveInputReaderCallback, GotToken, bytes='%s', byte_len = %zu, Master File Descriptor is bad.",
bytes,
bytes_len);
reader.SetIsDone (true);
}
break;
case eInputReaderDone:
{
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
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.");
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
script_interpreter->RestoreTerminalState ();
script_interpreter->m_embedded_thread_pty.CloseMasterFileDescriptor();
}
break;
}
return bytes_len;
}
ScriptInterpreterPython::ScriptInterpreterPython (CommandInterpreter &interpreter) :
ScriptInterpreter (interpreter, eScriptLanguagePython),
m_embedded_thread_pty (),
m_embedded_python_pty (),
m_embedded_thread_input_reader_sp (),
m_embedded_python_input_reader_sp (),
m_dbg_stdout (interpreter.GetDebugger().GetOutputFile().GetStream()),
m_new_sysout (NULL),
m_old_sysout (NULL),
m_old_syserr (NULL),
m_run_one_line (NULL),
m_dictionary_name (interpreter.GetDebugger().GetInstanceName().AsCString()),
m_terminal_state (),
m_session_is_active (false),
m_valid_session (true),
m_command_thread_state (NULL)
{
static int g_initialized = false;
if (!g_initialized)
{
g_initialized = true;
ScriptInterpreterPython::InitializePrivate ();
}
m_dictionary_name.append("_dict");
StreamString run_string;
run_string.Printf ("%s = dict()", m_dictionary_name.c_str());
Locker locker(this,
ScriptInterpreterPython::Locker::AcquireLock,
ScriptInterpreterPython::Locker::FreeAcquiredLock);
PyRun_SimpleString (run_string.GetData());
run_string.Clear();
// Importing 'lldb' module calls SBDebugger::Initialize, which calls Debugger::Initialize, which increments a
// global debugger ref-count; therefore we need to check the ref-count before and after importing lldb, and if the
// ref-count increased we need to call Debugger::Terminate here to decrement the ref-count so that when the final
// call to Debugger::Terminate is made, the ref-count has the correct value.
//
// Bonus question: Why doesn't the ref-count always increase? Because sometimes lldb has already been imported, in
// which case the code inside it, including the call to SBDebugger::Initialize(), does not get executed.
int old_count = Debugger::TestDebuggerRefCount();
Added many more python convenience accessors: You can now access a frame in a thread using: lldb.SBThread.frame[int] -> lldb.SBFrame object for a frame in a thread Where "int" is an integer index. You can also access a list object with all of the frames using: lldb.SBThread.frames => list() of lldb.SBFrame objects All SB objects that give out SBAddress objects have properties named "addr" lldb.SBInstructionList now has the following convenience accessors for len() and instruction access using an index: insts = lldb.frame.function.instructions for idx in range(len(insts)): print insts[idx] Instruction lists can also lookup an isntruction using a lldb.SBAddress as the key: pc_inst = lldb.frame.function.instructions[lldb.frame.addr] lldb.SBProcess now exposes: lldb.SBProcess.is_alive => BOOL Check if a process is exists and is alive lldb.SBProcess.is_running => BOOL check if a process is running (or stepping): lldb.SBProcess.is_running => BOOL check if a process is currently stopped or crashed: lldb.SBProcess.thread[int] => lldb.SBThreads for a given "int" zero based index lldb.SBProcess.threads => list() containing all lldb.SBThread objects in a process SBInstruction now exposes: lldb.SBInstruction.mnemonic => python string for instruction mnemonic lldb.SBInstruction.operands => python string for instruction operands lldb.SBInstruction.command => python string for instruction comment SBModule now exposes: lldb.SBModule.uuid => uuid.UUID(), an UUID object from the "uuid" python module lldb.SBModule.symbol[int] => lldb.Symbol, lookup symbol by zero based index lldb.SBModule.symbol[str] => list() of lldb.Symbol objects that match "str" lldb.SBModule.symbol[re] => list() of lldb.Symbol objecxts that match the regex lldb.SBModule.symbols => list() of all symbols in a module SBAddress objects can now access the current load address with the "lldb.SBAddress.load_addr" property. The current "lldb.target" will be used to try and resolve the load address. Load addresses can also be set using this accessor: addr = lldb.SBAddress() addd.load_addr = 0x123023 Then you can check the section and offset to see if the address got resolved. SBTarget now exposes: lldb.SBTarget.module[int] => lldb.SBModule from zero based module index lldb.SBTarget.module[str] => lldb.SBModule by basename or fullpath or uuid string lldb.SBTarget.module[uuid.UUID()] => lldb.SBModule whose UUID matches lldb.SBTarget.module[re] => list() of lldb.SBModule objects that match the regex lldb.SBTarget.modules => list() of all lldb.SBModule objects in the target SBSymbol now exposes: lldb.SBSymbol.name => python string for demangled symbol name lldb.SBSymbol.mangled => python string for mangled symbol name or None if there is none lldb.SBSymbol.type => lldb.eSymbolType enum value lldb.SBSymbol.addr => SBAddress object that represents the start address for this symbol (if there is one) lldb.SBSymbol.end_addr => SBAddress for the end address of the symbol (if there is one) lldb.SBSymbol.prologue_size => pythin int containing The size of the prologue in bytes lldb.SBSymbol.instructions => SBInstructionList containing all instructions for this symbol SBFunction now also has these new properties in addition to what is already has: lldb.SBFunction.addr => SBAddress object that represents the start address for this function lldb.SBFunction.end_addr => SBAddress for the end address of the function lldb.SBFunction.instructions => SBInstructionList containing all instructions for this function SBFrame now exposes the SBAddress for the frame: lldb.SBFrame.addr => SBAddress which is the section offset address for the current frame PC These are all in addition to what was already added. Documentation and website updates coming soon. llvm-svn: 149489
2012-02-01 08:09:32 +00:00
run_string.Printf ("run_one_line (%s, 'import copy, os, re, sys, uuid, lldb')", m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
// WARNING: temporary code that loads Cocoa formatters - this should be done on a per-platform basis rather than loading the whole set
// and letting the individual formatter classes exploit APIs to check whether they can/cannot do their task
run_string.Clear();
run_string.Printf ("run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')", m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
Added many more python convenience accessors: You can now access a frame in a thread using: lldb.SBThread.frame[int] -> lldb.SBFrame object for a frame in a thread Where "int" is an integer index. You can also access a list object with all of the frames using: lldb.SBThread.frames => list() of lldb.SBFrame objects All SB objects that give out SBAddress objects have properties named "addr" lldb.SBInstructionList now has the following convenience accessors for len() and instruction access using an index: insts = lldb.frame.function.instructions for idx in range(len(insts)): print insts[idx] Instruction lists can also lookup an isntruction using a lldb.SBAddress as the key: pc_inst = lldb.frame.function.instructions[lldb.frame.addr] lldb.SBProcess now exposes: lldb.SBProcess.is_alive => BOOL Check if a process is exists and is alive lldb.SBProcess.is_running => BOOL check if a process is running (or stepping): lldb.SBProcess.is_running => BOOL check if a process is currently stopped or crashed: lldb.SBProcess.thread[int] => lldb.SBThreads for a given "int" zero based index lldb.SBProcess.threads => list() containing all lldb.SBThread objects in a process SBInstruction now exposes: lldb.SBInstruction.mnemonic => python string for instruction mnemonic lldb.SBInstruction.operands => python string for instruction operands lldb.SBInstruction.command => python string for instruction comment SBModule now exposes: lldb.SBModule.uuid => uuid.UUID(), an UUID object from the "uuid" python module lldb.SBModule.symbol[int] => lldb.Symbol, lookup symbol by zero based index lldb.SBModule.symbol[str] => list() of lldb.Symbol objects that match "str" lldb.SBModule.symbol[re] => list() of lldb.Symbol objecxts that match the regex lldb.SBModule.symbols => list() of all symbols in a module SBAddress objects can now access the current load address with the "lldb.SBAddress.load_addr" property. The current "lldb.target" will be used to try and resolve the load address. Load addresses can also be set using this accessor: addr = lldb.SBAddress() addd.load_addr = 0x123023 Then you can check the section and offset to see if the address got resolved. SBTarget now exposes: lldb.SBTarget.module[int] => lldb.SBModule from zero based module index lldb.SBTarget.module[str] => lldb.SBModule by basename or fullpath or uuid string lldb.SBTarget.module[uuid.UUID()] => lldb.SBModule whose UUID matches lldb.SBTarget.module[re] => list() of lldb.SBModule objects that match the regex lldb.SBTarget.modules => list() of all lldb.SBModule objects in the target SBSymbol now exposes: lldb.SBSymbol.name => python string for demangled symbol name lldb.SBSymbol.mangled => python string for mangled symbol name or None if there is none lldb.SBSymbol.type => lldb.eSymbolType enum value lldb.SBSymbol.addr => SBAddress object that represents the start address for this symbol (if there is one) lldb.SBSymbol.end_addr => SBAddress for the end address of the symbol (if there is one) lldb.SBSymbol.prologue_size => pythin int containing The size of the prologue in bytes lldb.SBSymbol.instructions => SBInstructionList containing all instructions for this symbol SBFunction now also has these new properties in addition to what is already has: lldb.SBFunction.addr => SBAddress object that represents the start address for this function lldb.SBFunction.end_addr => SBAddress for the end address of the function lldb.SBFunction.instructions => SBInstructionList containing all instructions for this function SBFrame now exposes the SBAddress for the frame: lldb.SBFrame.addr => SBAddress which is the section offset address for the current frame PC These are all in addition to what was already added. Documentation and website updates coming soon. llvm-svn: 149489
2012-02-01 08:09:32 +00:00
int new_count = Debugger::TestDebuggerRefCount();
if (new_count > old_count)
Debugger::Terminate();
run_string.Clear();
run_string.Printf ("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64 "; pydoc.pager = pydoc.plainpager')", m_dictionary_name.c_str(),
interpreter.GetDebugger().GetID());
PyRun_SimpleString (run_string.GetData());
if (m_dbg_stdout != NULL)
{
m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush);
}
// get the output file handle from the debugger (if any)
File& out_file = interpreter.GetDebugger().GetOutputFile();
if (out_file.IsValid())
ResetOutputFileHandle(out_file.GetStream());
}
ScriptInterpreterPython::~ScriptInterpreterPython ()
{
Debugger &debugger = GetCommandInterpreter().GetDebugger();
if (m_embedded_thread_input_reader_sp.get() != NULL)
{
m_embedded_thread_input_reader_sp->SetIsDone (true);
m_embedded_thread_pty.CloseSlaveFileDescriptor();
const InputReaderSP reader_sp = m_embedded_thread_input_reader_sp;
debugger.PopInputReader (reader_sp);
m_embedded_thread_input_reader_sp.reset();
}
if (m_embedded_python_input_reader_sp.get() != NULL)
{
m_embedded_python_input_reader_sp->SetIsDone (true);
m_embedded_python_pty.CloseSlaveFileDescriptor();
const InputReaderSP reader_sp = m_embedded_python_input_reader_sp;
debugger.PopInputReader (reader_sp);
m_embedded_python_input_reader_sp.reset();
}
if (m_new_sysout)
{
Locker locker(this,
ScriptInterpreterPython::Locker::AcquireLock,
ScriptInterpreterPython::Locker::FreeLock);
Py_XDECREF ((PyObject*)m_new_sysout);
}
}
void
ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh)
{
if (fh == NULL)
return;
m_dbg_stdout = fh;
Locker locker(this,
ScriptInterpreterPython::Locker::AcquireLock,
ScriptInterpreterPython::Locker::FreeAcquiredLock);
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-06 19:20:51 +00:00
m_new_sysout = PyFile_FromFile (m_dbg_stdout, (char *) "", (char *) "w", _check_and_flush);
}
void
ScriptInterpreterPython::SaveTerminalState (int fd)
{
// Python mucks with the terminal state of STDIN. If we can possibly avoid
// this by setting the file handles up correctly prior to entering the
// interpreter we should. For now we save and restore the terminal state
// on the input file handle.
m_terminal_state.Save (fd, false);
}
void
ScriptInterpreterPython::RestoreTerminalState ()
{
// Python mucks with the terminal state of STDIN. If we can possibly avoid
// this by setting the file handles up correctly prior to entering the
// interpreter we should. For now we save and restore the terminal state
// on the input file handle.
m_terminal_state.Restore();
}
void
ScriptInterpreterPython::LeaveSession ()
{
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
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
// when destroying the SBDebugger, we can make do without clearing up stdout and stderr
// rdar://problem/11292882
// When the current thread state is NULL, PyThreadState_Get() issues a fatal error.
if (PyThreadState_GetDict())
{
PyObject *sysmod = PyImport_AddModule ("sys");
PyObject *sysdict = PyModule_GetDict (sysmod);
if (m_new_sysout && sysmod && sysdict)
{
if (m_old_sysout)
PyDict_SetItemString (sysdict, "stdout", (PyObject*)m_old_sysout);
if (m_old_syserr)
PyDict_SetItemString (sysdict, "stderr", (PyObject*)m_old_syserr);
}
}
m_session_is_active = false;
}
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
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.
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
if (m_session_is_active)
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
{
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;
StreamString run_string;
if (init_lldb_globals)
{
run_string.Printf ( "run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID());
run_string.PutCString ("; lldb.target = lldb.debugger.GetSelectedTarget()");
run_string.PutCString ("; lldb.process = lldb.target.GetProcess()");
run_string.PutCString ("; lldb.thread = lldb.process.GetSelectedThread ()");
run_string.PutCString ("; lldb.frame = lldb.thread.GetSelectedFrame ()");
run_string.PutCString ("')");
}
else
{
// If we aren't initing the globals, we should still always set the debugger (since that is always unique.)
run_string.Printf ( "run_one_line (%s, \"lldb.debugger_unique_id = %" PRIu64, m_dictionary_name.c_str(), GetCommandInterpreter().GetDebugger().GetID());
run_string.Printf ( "; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")", GetCommandInterpreter().GetDebugger().GetID());
run_string.PutCString ("\")");
}
PyRun_SimpleString (run_string.GetData());
run_string.Clear();
PyObject *sysmod = PyImport_AddModule ("sys");
PyObject *sysdict = PyModule_GetDict (sysmod);
if (m_new_sysout && sysmod && sysdict)
{
m_old_sysout = PyDict_GetItemString(sysdict, "stdout");
m_old_syserr = PyDict_GetItemString(sysdict, "stderr");
if (m_new_sysout)
{
PyDict_SetItemString (sysdict, "stdout", (PyObject*)m_new_sysout);
PyDict_SetItemString (sysdict, "stderr", (PyObject*)m_new_sysout);
}
}
if (PyErr_Occurred())
PyErr_Clear ();
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
return true;
}
static PyObject*
FindSessionDictionary (const char* dict_name)
{
static std::map<ConstString,PyObject*> g_dict_map;
ConstString dict(dict_name);
std::map<ConstString,PyObject*>::iterator iter = g_dict_map.find(dict);
if (iter != g_dict_map.end())
return iter->second;
PyObject *main_mod = PyImport_AddModule ("__main__");
if (main_mod != NULL)
{
PyObject *main_dict = PyModule_GetDict (main_mod);
if ((main_dict != NULL)
&& PyDict_Check (main_dict))
{
// Go through the main dictionary looking for the correct python script interpreter dictionary
PyObject *key, *value;
Py_ssize_t pos = 0;
while (PyDict_Next (main_dict, &pos, &key, &value))
{
// We have stolen references to the key and value objects in the dictionary; we need to increment
// them now so that Python's garbage collector doesn't collect them out from under us.
Py_INCREF (key);
Py_INCREF (value);
if (strcmp (PyString_AsString (key), dict_name) == 0)
{
g_dict_map[dict] = value;
return value;
}
}
}
}
return NULL;
}
static std::string
GenerateUniqueName (const char* base_name_wanted,
uint32_t& functions_counter,
void* name_token = NULL)
{
StreamString sstr;
if (!base_name_wanted)
return std::string();
if (!name_token)
sstr.Printf ("%s_%d", base_name_wanted, functions_counter++);
else
sstr.Printf ("%s_%p", base_name_wanted, name_token);
return sstr.GetString();
}
bool
ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options)
{
if (!m_valid_session)
return false;
// We want to call run_one_line, passing in the dictionary and the command string. We cannot do this through
// PyRun_SimpleString here because the command string may contain escaped characters, and putting it inside
// another string to pass to PyRun_SimpleString messes up the escaping. So we use the following more complicated
// method to pass the command string directly down to Python.
Locker locker(this,
ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0),
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
bool success = false;
if (command)
{
// Find the correct script interpreter dictionary in the main module.
PyObject *script_interpreter_dict = FindSessionDictionary(m_dictionary_name.c_str());
if (script_interpreter_dict != NULL)
{
PyObject *pfunc = (PyObject*)m_run_one_line;
PyObject *pmod = PyImport_AddModule ("lldb.embedded_interpreter");
if (pmod != NULL)
{
PyObject *pmod_dict = PyModule_GetDict (pmod);
if ((pmod_dict != NULL)
&& PyDict_Check (pmod_dict))
{
if (!pfunc)
{
PyObject *key, *value;
Py_ssize_t pos = 0;
while (PyDict_Next (pmod_dict, &pos, &key, &value))
{
Py_INCREF (key);
Py_INCREF (value);
if (strcmp (PyString_AsString (key), "run_one_line") == 0)
{
pfunc = value;
break;
}
}
m_run_one_line = pfunc;
}
if (pfunc && PyCallable_Check (pfunc))
{
PyObject *pargs = Py_BuildValue("(Os)",script_interpreter_dict,command);
if (pargs != NULL)
{
PyObject *pvalue = NULL;
{ // scope for PythonInputReaderManager
PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
pvalue = PyObject_CallObject (pfunc, pargs);
}
Py_XDECREF (pargs);
if (pvalue != NULL)
{
Py_XDECREF (pvalue);
success = true;
}
else if (options.GetMaskoutErrors() && PyErr_Occurred ())
{
PyErr_Print();
PyErr_Clear();
}
}
}
}
}
Py_INCREF (script_interpreter_dict);
}
if (success)
return true;
// The one-liner failed. Append the error message.
if (result)
result->AppendErrorWithFormat ("python failed attempting to evaluate '%s'\n", command);
return false;
}
if (result)
result->AppendError ("empty command passed to python\n");
return false;
}
size_t
ScriptInterpreterPython::InputReaderCallback
(
void *baton,
InputReader &reader,
InputReaderAction notification,
const char *bytes,
size_t bytes_len
)
{
lldb::thread_t embedded_interpreter_thread;
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
if (baton == NULL)
return 0;
ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
if (script_interpreter->m_script_lang != eScriptLanguagePython)
return 0;
switch (notification)
{
case eInputReaderActivate:
{
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
if (!batch_mode)
{
out_stream->Printf ("Python Interactive Interpreter. To exit, type 'quit()', 'exit()' or Ctrl-D.\n");
out_stream->Flush();
}
// Save terminal settings if we can
int input_fd = reader.GetDebugger().GetInputFile().GetDescriptor();
if (input_fd == File::kInvalidDescriptor)
Added a new Host call to find LLDB related paths: static bool Host::GetLLDBPath (lldb::PathType path_type, FileSpec &file_spec); This will fill in "file_spec" with an appropriate path that is appropriate for the current Host OS. MacOSX will return paths within the LLDB.framework, and other unixes will return the paths they want. The current PathType enums are: typedef enum PathType { ePathTypeLLDBShlibDir, // The directory where the lldb.so (unix) or LLDB mach-o file in LLDB.framework (MacOSX) exists ePathTypeSupportExecutableDir, // Find LLDB support executable directory (debugserver, etc) ePathTypeHeaderDir, // Find LLDB header file directory ePathTypePythonDir // Find Python modules (PYTHONPATH) directory } PathType; All places that were finding executables are and python paths are now updated to use this Host call. Added another new host call to launch the inferior in a terminal. This ability will be very host specific and doesn't need to be supported on all systems. MacOSX currently will create a new .command file and tell Terminal.app to open the .command file. It also uses the new "darwin-debug" app which is a small app that uses posix to exec (no fork) and stop at the entry point of the program. The GDB remote plug-in is almost able launch a process and attach to it, it currently will spawn the process, but it won't attach to it just yet. This will let LLDB not have to share the terminal with another process and a new terminal window will pop up when you launch. This won't get hooked up until we work out all of the kinks. The new Host function is: static lldb::pid_t Host::LaunchInNewTerminal ( const char **argv, // argv[0] is executable const char **envp, const ArchSpec *arch_spec, bool stop_at_entry, bool disable_aslr); Cleaned up FileSpec::GetPath to not use strncpy() as it was always zero filling the entire path buffer. Fixed an issue with the dynamic checker function where I missed a '$' prefix that should have been added. llvm-svn: 116690
2010-10-17 22:03:32 +00:00
input_fd = STDIN_FILENO;
script_interpreter->SaveTerminalState(input_fd);
{
ScriptInterpreterPython::Locker locker(script_interpreter,
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals,
ScriptInterpreterPython::Locker::FreeAcquiredLock);
}
char error_str[1024];
if (script_interpreter->m_embedded_python_pty.OpenFirstAvailableMaster (O_RDWR|O_NOCTTY, error_str,
sizeof(error_str)))
{
if (log)
log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, succeeded in opening master pty (fd = %d).",
script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor());
embedded_interpreter_thread = Host::ThreadCreate ("<lldb.script-interpreter.embedded-python-loop>",
ScriptInterpreterPython::RunEmbeddedPythonInterpreter,
script_interpreter, NULL);
if (IS_VALID_LLDB_HOST_THREAD(embedded_interpreter_thread))
{
if (log)
log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, succeeded in creating thread (thread_t = %p)", (void *)embedded_interpreter_thread);
Error detach_error;
Host::ThreadDetach (embedded_interpreter_thread, &detach_error);
}
else
{
if (log)
log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, failed in creating thread");
reader.SetIsDone (true);
}
}
else
{
if (log)
log->Printf ("ScriptInterpreterPython::InputReaderCallback, Activate, failed to open master pty ");
reader.SetIsDone (true);
}
}
break;
case eInputReaderDeactivate:
// When another input reader is pushed, don't leave the session...
//script_interpreter->LeaveSession ();
break;
case eInputReaderReactivate:
{
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
ScriptInterpreterPython::Locker locker (script_interpreter,
ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession,
ScriptInterpreterPython::Locker::FreeAcquiredLock);
}
break;
case eInputReaderAsynchronousOutputWritten:
break;
case eInputReaderInterrupt:
::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "raise KeyboardInterrupt\n", 24);
break;
case eInputReaderEndOfFile:
::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "quit()\n", 7);
break;
case eInputReaderGotToken:
if (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor() != -1)
{
if (log)
log->Printf ("ScriptInterpreterPython::InputReaderCallback, GotToken, bytes='%s', byte_len = %zu", bytes,
bytes_len);
if (bytes && bytes_len)
{
if ((int) bytes[0] == 4)
::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "quit()", 6);
else
::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), bytes, bytes_len);
}
::write (script_interpreter->m_embedded_python_pty.GetMasterFileDescriptor(), "\n", 1);
}
else
{
if (log)
log->Printf ("ScriptInterpreterPython::InputReaderCallback, GotToken, bytes='%s', byte_len = %zu, Master File Descriptor is bad.",
bytes,
bytes_len);
reader.SetIsDone (true);
}
break;
case eInputReaderDone:
{
Locker locker(script_interpreter,
ScriptInterpreterPython::Locker::AcquireLock,
ScriptInterpreterPython::Locker::FreeAcquiredLock);
script_interpreter->LeaveSession ();
}
// Restore terminal settings if they were validly saved
if (log)
log->Printf ("ScriptInterpreterPython::InputReaderCallback, Done, closing down input reader.");
script_interpreter->RestoreTerminalState ();
script_interpreter->m_embedded_python_pty.CloseMasterFileDescriptor();
break;
}
return bytes_len;
}
void
ScriptInterpreterPython::ExecuteInterpreterLoop ()
{
Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
Debugger &debugger = GetCommandInterpreter().GetDebugger();
// At the moment, the only time the debugger does not have an input file handle is when this is called
// directly from Python, in which case it is both dangerous and unnecessary (not to mention confusing) to
// try to embed a running interpreter loop inside the already running Python interpreter loop, so we won't
// do it.
if (!debugger.GetInputFile().IsValid())
return;
InputReaderSP reader_sp (new InputReader(debugger));
if (reader_sp)
{
Error error (reader_sp->Initialize (ScriptInterpreterPython::InputReaderCallback,
this, // baton
eInputReaderGranularityLine, // token size, to pass to callback function
NULL, // end token
NULL, // prompt
true)); // echo input
if (error.Success())
{
debugger.PushInputReader (reader_sp);
m_embedded_python_input_reader_sp = reader_sp;
}
}
}
bool
ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
ScriptInterpreter::ScriptReturnType return_type,
void *ret_value,
const ExecuteScriptOptions &options)
{
Locker locker(this,
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
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__");
PyObject *globals = PyModule_GetDict (mainmod);
PyObject *locals = NULL;
PyObject *py_error = NULL;
bool ret_success = false;
bool should_decrement_locals = false;
int success;
locals = FindSessionDictionary(m_dictionary_name.c_str());
if (locals == NULL)
{
locals = PyObject_GetAttrString (globals, m_dictionary_name.c_str());
should_decrement_locals = true;
}
if (locals == NULL)
{
locals = globals;
should_decrement_locals = false;
}
py_error = PyErr_Occurred();
if (py_error != NULL)
PyErr_Clear();
if (in_string != NULL)
{
{ // scope for PythonInputReaderManager
PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
py_return = PyRun_String (in_string, Py_eval_input, globals, locals);
if (py_return == NULL)
{
py_error = PyErr_Occurred ();
if (py_error != NULL)
PyErr_Clear ();
py_return = PyRun_String (in_string, Py_single_input, globals, locals);
}
}
if (locals != NULL
&& should_decrement_locals)
Py_XDECREF (locals);
if (py_return != NULL)
{
switch (return_type)
{
case eScriptReturnTypeCharPtr: // "char *"
{
const char format[3] = "s#";
success = PyArg_Parse (py_return, format, (char **) ret_value);
break;
}
case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == Py_None
{
const char format[3] = "z";
success = PyArg_Parse (py_return, format, (char **) ret_value);
break;
}
case eScriptReturnTypeBool:
{
const char format[2] = "b";
success = PyArg_Parse (py_return, format, (bool *) ret_value);
break;
}
case eScriptReturnTypeShortInt:
{
const char format[2] = "h";
success = PyArg_Parse (py_return, format, (short *) ret_value);
break;
}
case eScriptReturnTypeShortIntUnsigned:
{
const char format[2] = "H";
success = PyArg_Parse (py_return, format, (unsigned short *) ret_value);
break;
}
case eScriptReturnTypeInt:
{
const char format[2] = "i";
success = PyArg_Parse (py_return, format, (int *) ret_value);
break;
}
case eScriptReturnTypeIntUnsigned:
{
const char format[2] = "I";
success = PyArg_Parse (py_return, format, (unsigned int *) ret_value);
break;
}
case eScriptReturnTypeLongInt:
{
const char format[2] = "l";
success = PyArg_Parse (py_return, format, (long *) ret_value);
break;
}
case eScriptReturnTypeLongIntUnsigned:
{
const char format[2] = "k";
success = PyArg_Parse (py_return, format, (unsigned long *) ret_value);
break;
}
case eScriptReturnTypeLongLong:
{
const char format[2] = "L";
success = PyArg_Parse (py_return, format, (long long *) ret_value);
break;
}
case eScriptReturnTypeLongLongUnsigned:
{
const char format[2] = "K";
success = PyArg_Parse (py_return, format, (unsigned long long *) ret_value);
break;
}
case eScriptReturnTypeFloat:
{
const char format[2] = "f";
success = PyArg_Parse (py_return, format, (float *) ret_value);
break;
}
case eScriptReturnTypeDouble:
{
const char format[2] = "d";
success = PyArg_Parse (py_return, format, (double *) ret_value);
break;
}
case eScriptReturnTypeChar:
{
const char format[2] = "c";
success = PyArg_Parse (py_return, format, (char *) ret_value);
break;
}
case eScriptReturnTypeOpaqueObject:
{
success = true;
Py_XINCREF(py_return);
*((PyObject**)ret_value) = py_return;
break;
}
}
Py_XDECREF (py_return);
if (success)
ret_success = true;
else
ret_success = false;
}
}
py_error = PyErr_Occurred();
if (py_error != NULL)
{
ret_success = false;
if (options.GetMaskoutErrors())
{
if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
PyErr_Print ();
PyErr_Clear();
}
}
return ret_success;
}
bool
ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const ExecuteScriptOptions &options)
{
Locker locker(this,
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
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;
PyObject *mainmod = PyImport_AddModule ("__main__");
PyObject *globals = PyModule_GetDict (mainmod);
PyObject *locals = NULL;
PyObject *py_error = NULL;
bool should_decrement_locals = false;
locals = FindSessionDictionary(m_dictionary_name.c_str());
if (locals == NULL)
{
locals = PyObject_GetAttrString (globals, m_dictionary_name.c_str());
should_decrement_locals = true;
}
if (locals == NULL)
{
locals = globals;
should_decrement_locals = false;
}
py_error = PyErr_Occurred();
if (py_error != NULL)
PyErr_Clear();
if (in_string != NULL)
{
struct _node *compiled_node = PyParser_SimpleParseString (in_string, Py_file_input);
if (compiled_node)
{
PyCodeObject *compiled_code = PyNode_Compile (compiled_node, "temp.py");
if (compiled_code)
{
{ // scope for PythonInputReaderManager
PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
py_return = PyEval_EvalCode (compiled_code, globals, locals);
}
if (py_return != NULL)
{
success = true;
Py_XDECREF (py_return);
}
if (locals && should_decrement_locals)
Py_XDECREF (locals);
}
}
}
py_error = PyErr_Occurred ();
if (py_error != NULL)
{
success = false;
if (options.GetMaskoutErrors())
{
if (PyErr_GivenExceptionMatches (py_error, PyExc_SyntaxError))
PyErr_Print ();
PyErr_Clear();
}
}
return success;
}
static const char *g_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.";
static const char *g_bkpt_command_reader_instructions = "Enter your Python command(s). Type 'DONE' to end.\n"
"def function(frame,bp_loc,internal_dict):\n"
" \"\"\"frame: the SBFrame for the location at which you stopped\n"
" bp_loc: an SBBreakpointLocation for the breakpoint location information\n"
" internal_dict: an LLDB support object not to be used\"\"\"";
size_t
ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback
(
void *baton,
InputReader &reader,
InputReaderAction notification,
const char *bytes,
size_t bytes_len
)
{
static StringList commands_in_progress;
switch (notification)
{
case eInputReaderActivate:
{
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
commands_in_progress.Clear();
if (!batch_mode)
{
out_stream->Printf ("%s\n", g_bkpt_command_reader_instructions);
if (reader.GetPrompt())
out_stream->Printf ("%s", reader.GetPrompt());
out_stream->Flush ();
}
}
break;
case eInputReaderDeactivate:
break;
case eInputReaderReactivate:
{
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
if (reader.GetPrompt() && !batch_mode)
{
out_stream->Printf ("%s", reader.GetPrompt());
out_stream->Flush ();
}
}
break;
case eInputReaderAsynchronousOutputWritten:
break;
case eInputReaderGotToken:
{
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
std::string temp_string (bytes, bytes_len);
commands_in_progress.AppendString (temp_string.c_str());
if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
{
out_stream->Printf ("%s", reader.GetPrompt());
out_stream->Flush ();
}
}
break;
case eInputReaderEndOfFile:
case eInputReaderInterrupt:
// Control-c (SIGINT) & control-d both mean finish & exit.
reader.SetIsDone(true);
// Control-c (SIGINT) ALSO means cancel; do NOT create a breakpoint command.
if (notification == eInputReaderInterrupt)
commands_in_progress.Clear();
// Fall through here...
case eInputReaderDone:
{
bool batch_mode = notification == eInputReaderDone ?
reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode() :
true;
BreakpointOptions *bp_options = (BreakpointOptions *)baton;
std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
data_ap->user_source.AppendList (commands_in_progress);
if (data_ap.get())
{
ScriptInterpreter *interpreter = reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
if (interpreter)
{
if (interpreter->GenerateBreakpointCommandCallbackData (data_ap->user_source,
data_ap->script_source))
{
BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
}
else if (!batch_mode)
{
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
out_stream->Printf ("Warning: No command attached to breakpoint.\n");
out_stream->Flush();
}
}
else
{
if (!batch_mode)
{
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
out_stream->Printf ("Warning: Unable to find script intepreter; no command attached to breakpoint.\n");
out_stream->Flush();
}
}
}
}
break;
}
return bytes_len;
}
size_t
ScriptInterpreterPython::GenerateWatchpointOptionsCommandCallback
(
void *baton,
InputReader &reader,
InputReaderAction notification,
const char *bytes,
size_t bytes_len
)
{
static StringList commands_in_progress;
switch (notification)
{
case eInputReaderActivate:
{
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
commands_in_progress.Clear();
if (!batch_mode)
{
out_stream->Printf ("%s\n", g_reader_instructions);
if (reader.GetPrompt())
out_stream->Printf ("%s", reader.GetPrompt());
out_stream->Flush ();
}
}
break;
case eInputReaderDeactivate:
break;
case eInputReaderReactivate:
{
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
if (reader.GetPrompt() && !batch_mode)
{
out_stream->Printf ("%s", reader.GetPrompt());
out_stream->Flush ();
}
}
break;
case eInputReaderAsynchronousOutputWritten:
break;
case eInputReaderGotToken:
{
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
bool batch_mode = reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode();
std::string temp_string (bytes, bytes_len);
commands_in_progress.AppendString (temp_string.c_str());
if (!reader.IsDone() && reader.GetPrompt() && !batch_mode)
{
out_stream->Printf ("%s", reader.GetPrompt());
out_stream->Flush ();
}
}
break;
case eInputReaderEndOfFile:
case eInputReaderInterrupt:
// Control-c (SIGINT) & control-d both mean finish & exit.
reader.SetIsDone(true);
// Control-c (SIGINT) ALSO means cancel; do NOT create a breakpoint command.
if (notification == eInputReaderInterrupt)
commands_in_progress.Clear();
// Fall through here...
case eInputReaderDone:
{
bool batch_mode = notification == eInputReaderDone ?
reader.GetDebugger().GetCommandInterpreter().GetBatchCommandMode() :
true;
WatchpointOptions *wp_options = (WatchpointOptions *)baton;
std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
data_ap->user_source.AppendList (commands_in_progress);
if (data_ap.get())
{
ScriptInterpreter *interpreter = reader.GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
if (interpreter)
{
if (interpreter->GenerateWatchpointCommandCallbackData (data_ap->user_source,
data_ap->script_source))
{
BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp);
}
else if (!batch_mode)
{
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
out_stream->Printf ("Warning: No command attached to breakpoint.\n");
out_stream->Flush();
}
}
else
{
if (!batch_mode)
{
StreamSP out_stream = reader.GetDebugger().GetAsyncOutputStream();
out_stream->Printf ("Warning: Unable to find script intepreter; no command attached to breakpoint.\n");
out_stream->Flush();
}
}
}
}
break;
}
return bytes_len;
}
void
ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (BreakpointOptions *bp_options,
CommandReturnObject &result)
{
Debugger &debugger = GetCommandInterpreter().GetDebugger();
InputReaderSP reader_sp (new InputReader (debugger));
if (reader_sp)
{
Error err = reader_sp->Initialize (
ScriptInterpreterPython::GenerateBreakpointOptionsCommandCallback,
bp_options, // baton
eInputReaderGranularityLine, // token size, for feeding data to callback function
"DONE", // end token
" ", // prompt
true); // echo input
if (err.Success())
debugger.PushInputReader (reader_sp);
else
{
result.AppendError (err.AsCString());
result.SetStatus (eReturnStatusFailed);
}
}
else
{
result.AppendError("out of memory");
result.SetStatus (eReturnStatusFailed);
}
}
void
ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
CommandReturnObject &result)
{
Debugger &debugger = GetCommandInterpreter().GetDebugger();
InputReaderSP reader_sp (new InputReader (debugger));
if (reader_sp)
{
Error err = reader_sp->Initialize (
ScriptInterpreterPython::GenerateWatchpointOptionsCommandCallback,
wp_options, // baton
eInputReaderGranularityLine, // token size, for feeding data to callback function
"DONE", // end token
"> ", // prompt
true); // echo input
if (err.Success())
debugger.PushInputReader (reader_sp);
else
{
result.AppendError (err.AsCString());
result.SetStatus (eReturnStatusFailed);
}
}
else
{
result.AppendError("out of memory");
result.SetStatus (eReturnStatusFailed);
}
}
2010-09-11 00:23:59 +00:00
// Set a Python one-liner as the callback for the breakpoint.
Added the capability to specify a one-liner Python script as the callback command for a breakpoint, for example: (lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()" The ScriptInterpreter interface has an extra method: /// Set a one-liner as the callback for the breakpoint command. virtual void SetBreakpointCommandCallback (CommandInterpreter &interpreter, BreakpointOptions *bp_options, const char *oneliner); to accomplish the above. Also added a test case to demonstrate lldb's use of breakpoint callback command to stop at function c() only when its immediate caller is function a(). The following session shows the user entering the following commands: 1) command source .lldb (set up executable, breakpoint, and breakpoint command) 2) run (the callback mechanism will skip two breakpoints where c()'s immeidate caller is not a()) 3) bt (to see that indeed c()'s immediate caller is a()) 4) c (to continue and finish the program) test/conditional_break $ ../../build/Debug/lldb (lldb) command source .lldb Executing commands in '.lldb'. (lldb) file a.out Current executable set to 'a.out' (x86_64). (lldb) breakpoint set -n c Breakpoint created: 1: name = 'c', locations = 1 (lldb) script import sys, os (lldb) script sys.path.append(os.path.join(os.getcwd(), os.pardir)) (lldb) script import conditional_break (lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()" (lldb) run run Launching '/Volumes/data/lldb/svn/trunk/test/conditional_break/a.out' (x86_64) (lldb) Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`b at main.c:34 frame #2: a.out`a at main.c:25 frame #3: a.out`main at main.c:44 frame #4: a.out`start c called from b Continuing... Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`b at main.c:34 frame #2: a.out`main at main.c:47 frame #3: a.out`start c called from b Continuing... Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`a at main.c:27 frame #2: a.out`main at main.c:50 frame #3: a.out`start c called from a Stopped at c() with immediate caller as a(). a(1) returns 4 b(2) returns 5 Process 20420 Stopped * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread 36 37 int c(int val) 38 { 39 -> return val + 3; 40 } 41 42 int main (int argc, char const *argv[]) (lldb) bt bt thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread frame #0: 0x0000000100000de8 a.out`c + 7 at main.c:39 frame #1: 0x0000000100000dbc a.out`a + 44 at main.c:27 frame #2: 0x0000000100000e4b a.out`main + 91 at main.c:50 frame #3: 0x0000000100000d88 a.out`start + 52 (lldb) c c Resuming process 20420 Process 20420 Exited a(3) returns 6 (lldb) llvm-svn: 113596
2010-09-10 18:21:10 +00:00
void
ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
Added the capability to specify a one-liner Python script as the callback command for a breakpoint, for example: (lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()" The ScriptInterpreter interface has an extra method: /// Set a one-liner as the callback for the breakpoint command. virtual void SetBreakpointCommandCallback (CommandInterpreter &interpreter, BreakpointOptions *bp_options, const char *oneliner); to accomplish the above. Also added a test case to demonstrate lldb's use of breakpoint callback command to stop at function c() only when its immediate caller is function a(). The following session shows the user entering the following commands: 1) command source .lldb (set up executable, breakpoint, and breakpoint command) 2) run (the callback mechanism will skip two breakpoints where c()'s immeidate caller is not a()) 3) bt (to see that indeed c()'s immediate caller is a()) 4) c (to continue and finish the program) test/conditional_break $ ../../build/Debug/lldb (lldb) command source .lldb Executing commands in '.lldb'. (lldb) file a.out Current executable set to 'a.out' (x86_64). (lldb) breakpoint set -n c Breakpoint created: 1: name = 'c', locations = 1 (lldb) script import sys, os (lldb) script sys.path.append(os.path.join(os.getcwd(), os.pardir)) (lldb) script import conditional_break (lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()" (lldb) run run Launching '/Volumes/data/lldb/svn/trunk/test/conditional_break/a.out' (x86_64) (lldb) Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`b at main.c:34 frame #2: a.out`a at main.c:25 frame #3: a.out`main at main.c:44 frame #4: a.out`start c called from b Continuing... Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`b at main.c:34 frame #2: a.out`main at main.c:47 frame #3: a.out`start c called from b Continuing... Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`a at main.c:27 frame #2: a.out`main at main.c:50 frame #3: a.out`start c called from a Stopped at c() with immediate caller as a(). a(1) returns 4 b(2) returns 5 Process 20420 Stopped * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread 36 37 int c(int val) 38 { 39 -> return val + 3; 40 } 41 42 int main (int argc, char const *argv[]) (lldb) bt bt thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread frame #0: 0x0000000100000de8 a.out`c + 7 at main.c:39 frame #1: 0x0000000100000dbc a.out`a + 44 at main.c:27 frame #2: 0x0000000100000e4b a.out`main + 91 at main.c:50 frame #3: 0x0000000100000d88 a.out`start + 52 (lldb) c c Resuming process 20420 Process 20420 Exited a(3) returns 6 (lldb) llvm-svn: 113596
2010-09-10 18:21:10 +00:00
const char *oneliner)
{
std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
Added the capability to specify a one-liner Python script as the callback command for a breakpoint, for example: (lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()" The ScriptInterpreter interface has an extra method: /// Set a one-liner as the callback for the breakpoint command. virtual void SetBreakpointCommandCallback (CommandInterpreter &interpreter, BreakpointOptions *bp_options, const char *oneliner); to accomplish the above. Also added a test case to demonstrate lldb's use of breakpoint callback command to stop at function c() only when its immediate caller is function a(). The following session shows the user entering the following commands: 1) command source .lldb (set up executable, breakpoint, and breakpoint command) 2) run (the callback mechanism will skip two breakpoints where c()'s immeidate caller is not a()) 3) bt (to see that indeed c()'s immediate caller is a()) 4) c (to continue and finish the program) test/conditional_break $ ../../build/Debug/lldb (lldb) command source .lldb Executing commands in '.lldb'. (lldb) file a.out Current executable set to 'a.out' (x86_64). (lldb) breakpoint set -n c Breakpoint created: 1: name = 'c', locations = 1 (lldb) script import sys, os (lldb) script sys.path.append(os.path.join(os.getcwd(), os.pardir)) (lldb) script import conditional_break (lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()" (lldb) run run Launching '/Volumes/data/lldb/svn/trunk/test/conditional_break/a.out' (x86_64) (lldb) Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`b at main.c:34 frame #2: a.out`a at main.c:25 frame #3: a.out`main at main.c:44 frame #4: a.out`start c called from b Continuing... Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`b at main.c:34 frame #2: a.out`main at main.c:47 frame #3: a.out`start c called from b Continuing... Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`a at main.c:27 frame #2: a.out`main at main.c:50 frame #3: a.out`start c called from a Stopped at c() with immediate caller as a(). a(1) returns 4 b(2) returns 5 Process 20420 Stopped * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread 36 37 int c(int val) 38 { 39 -> return val + 3; 40 } 41 42 int main (int argc, char const *argv[]) (lldb) bt bt thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread frame #0: 0x0000000100000de8 a.out`c + 7 at main.c:39 frame #1: 0x0000000100000dbc a.out`a + 44 at main.c:27 frame #2: 0x0000000100000e4b a.out`main + 91 at main.c:50 frame #3: 0x0000000100000d88 a.out`start + 52 (lldb) c c Resuming process 20420 Process 20420 Exited a(3) returns 6 (lldb) llvm-svn: 113596
2010-09-10 18:21:10 +00:00
// It's necessary to set both user_source and script_source to the oneliner.
// The former is used to generate callback description (as in breakpoint command list)
// while the latter is used for Python to interpret during the actual callback.
data_ap->user_source.AppendString (oneliner);
data_ap->script_source.assign (oneliner);
Added the capability to specify a one-liner Python script as the callback command for a breakpoint, for example: (lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()" The ScriptInterpreter interface has an extra method: /// Set a one-liner as the callback for the breakpoint command. virtual void SetBreakpointCommandCallback (CommandInterpreter &interpreter, BreakpointOptions *bp_options, const char *oneliner); to accomplish the above. Also added a test case to demonstrate lldb's use of breakpoint callback command to stop at function c() only when its immediate caller is function a(). The following session shows the user entering the following commands: 1) command source .lldb (set up executable, breakpoint, and breakpoint command) 2) run (the callback mechanism will skip two breakpoints where c()'s immeidate caller is not a()) 3) bt (to see that indeed c()'s immediate caller is a()) 4) c (to continue and finish the program) test/conditional_break $ ../../build/Debug/lldb (lldb) command source .lldb Executing commands in '.lldb'. (lldb) file a.out Current executable set to 'a.out' (x86_64). (lldb) breakpoint set -n c Breakpoint created: 1: name = 'c', locations = 1 (lldb) script import sys, os (lldb) script sys.path.append(os.path.join(os.getcwd(), os.pardir)) (lldb) script import conditional_break (lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()" (lldb) run run Launching '/Volumes/data/lldb/svn/trunk/test/conditional_break/a.out' (x86_64) (lldb) Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`b at main.c:34 frame #2: a.out`a at main.c:25 frame #3: a.out`main at main.c:44 frame #4: a.out`start c called from b Continuing... Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`b at main.c:34 frame #2: a.out`main at main.c:47 frame #3: a.out`start c called from b Continuing... Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`a at main.c:27 frame #2: a.out`main at main.c:50 frame #3: a.out`start c called from a Stopped at c() with immediate caller as a(). a(1) returns 4 b(2) returns 5 Process 20420 Stopped * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread 36 37 int c(int val) 38 { 39 -> return val + 3; 40 } 41 42 int main (int argc, char const *argv[]) (lldb) bt bt thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread frame #0: 0x0000000100000de8 a.out`c + 7 at main.c:39 frame #1: 0x0000000100000dbc a.out`a + 44 at main.c:27 frame #2: 0x0000000100000e4b a.out`main + 91 at main.c:50 frame #3: 0x0000000100000d88 a.out`start + 52 (lldb) c c Resuming process 20420 Process 20420 Exited a(3) returns 6 (lldb) llvm-svn: 113596
2010-09-10 18:21:10 +00:00
if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source))
{
BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
}
Added the capability to specify a one-liner Python script as the callback command for a breakpoint, for example: (lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()" The ScriptInterpreter interface has an extra method: /// Set a one-liner as the callback for the breakpoint command. virtual void SetBreakpointCommandCallback (CommandInterpreter &interpreter, BreakpointOptions *bp_options, const char *oneliner); to accomplish the above. Also added a test case to demonstrate lldb's use of breakpoint callback command to stop at function c() only when its immediate caller is function a(). The following session shows the user entering the following commands: 1) command source .lldb (set up executable, breakpoint, and breakpoint command) 2) run (the callback mechanism will skip two breakpoints where c()'s immeidate caller is not a()) 3) bt (to see that indeed c()'s immediate caller is a()) 4) c (to continue and finish the program) test/conditional_break $ ../../build/Debug/lldb (lldb) command source .lldb Executing commands in '.lldb'. (lldb) file a.out Current executable set to 'a.out' (x86_64). (lldb) breakpoint set -n c Breakpoint created: 1: name = 'c', locations = 1 (lldb) script import sys, os (lldb) script sys.path.append(os.path.join(os.getcwd(), os.pardir)) (lldb) script import conditional_break (lldb) breakpoint command add -p 1 "conditional_break.stop_if_called_from_a()" (lldb) run run Launching '/Volumes/data/lldb/svn/trunk/test/conditional_break/a.out' (x86_64) (lldb) Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`b at main.c:34 frame #2: a.out`a at main.c:25 frame #3: a.out`main at main.c:44 frame #4: a.out`start c called from b Continuing... Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`b at main.c:34 frame #2: a.out`main at main.c:47 frame #3: a.out`start c called from b Continuing... Checking call frames... Stack trace for thread id=0x2e03 name=None queue=com.apple.main-thread: frame #0: a.out`c at main.c:39 frame #1: a.out`a at main.c:27 frame #2: a.out`main at main.c:50 frame #3: a.out`start c called from a Stopped at c() with immediate caller as a(). a(1) returns 4 b(2) returns 5 Process 20420 Stopped * thread #1: tid = 0x2e03, 0x0000000100000de8 a.out`c + 7 at main.c:39, stop reason = breakpoint 1.1, queue = com.apple.main-thread 36 37 int c(int val) 38 { 39 -> return val + 3; 40 } 41 42 int main (int argc, char const *argv[]) (lldb) bt bt thread #1: tid = 0x2e03, stop reason = breakpoint 1.1, queue = com.apple.main-thread frame #0: 0x0000000100000de8 a.out`c + 7 at main.c:39 frame #1: 0x0000000100000dbc a.out`a + 44 at main.c:27 frame #2: 0x0000000100000e4b a.out`main + 91 at main.c:50 frame #3: 0x0000000100000d88 a.out`start + 52 (lldb) c c Resuming process 20420 Process 20420 Exited a(3) returns 6 (lldb) llvm-svn: 113596
2010-09-10 18:21:10 +00:00
return;
}
// Set a Python one-liner as the callback for the watchpoint.
void
ScriptInterpreterPython::SetWatchpointCommandCallback (WatchpointOptions *wp_options,
const char *oneliner)
{
std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
// It's necessary to set both user_source and script_source to the oneliner.
// The former is used to generate callback description (as in watchpoint command list)
// while the latter is used for Python to interpret during the actual callback.
data_ap->user_source.AppendString (oneliner);
data_ap->script_source.assign (oneliner);
if (GenerateWatchpointCommandCallbackData (data_ap->user_source, data_ap->script_source))
{
BatonSP baton_sp (new WatchpointOptions::CommandBaton (data_ap.release()));
wp_options->SetCallback (ScriptInterpreterPython::WatchpointCallbackFunction, baton_sp);
}
return;
}
bool
ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def)
{
// Convert StringList to one long, newline delimited, const char *.
std::string function_def_string(function_def.CopyList());
return ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false));
}
bool
ScriptInterpreterPython::GenerateFunction(const char *signature, const StringList &input)
{
int num_lines = input.GetSize ();
if (num_lines == 0)
return false;
if (!signature || *signature == 0)
return false;
StreamString sstr;
StringList auto_generated_function;
auto_generated_function.AppendString (signature);
auto_generated_function.AppendString (" global_dict = globals()"); // Grab the global dictionary
auto_generated_function.AppendString (" new_keys = internal_dict.keys()"); // Make a list of keys in the session dict
auto_generated_function.AppendString (" old_keys = global_dict.keys()"); // Save list of keys in global dict
auto_generated_function.AppendString (" global_dict.update (internal_dict)"); // Add the session dictionary to the
// global dictionary.
// Wrap everything up inside the function, increasing the indentation.
auto_generated_function.AppendString(" if True:");
for (int i = 0; i < num_lines; ++i)
{
sstr.Clear ();
sstr.Printf (" %s", input.GetStringAtIndex (i));
auto_generated_function.AppendString (sstr.GetData());
}
auto_generated_function.AppendString (" for key in new_keys:"); // Iterate over all the keys from session dict
auto_generated_function.AppendString (" internal_dict[key] = global_dict[key]"); // Update session dict values
auto_generated_function.AppendString (" if key not in old_keys:"); // If key was not originally in global dict
auto_generated_function.AppendString (" del global_dict[key]"); // ...then remove key/value from global dict
// Verify that the results are valid Python.
if (!ExportFunctionDefinitionToInterpreter (auto_generated_function))
return false;
return true;
}
bool
ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std::string& output, void* name_token)
{
static uint32_t num_created_functions = 0;
user_input.RemoveBlankLines ();
StreamString sstr;
// Check to see if we have any data; if not, just return.
if (user_input.GetSize() == 0)
return false;
// Take what the user wrote, wrap it all up inside one big auto-generated Python function, passing in the
// ValueObject as parameter to the function.
std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_type_print_func", num_created_functions, name_token));
sstr.Printf ("def %s (valobj, internal_dict):", auto_generated_function_name.c_str());
if (!GenerateFunction(sstr.GetData(), user_input))
return false;
// Store the name of the auto-generated function to be called.
output.assign(auto_generated_function_name);
return true;
}
bool
ScriptInterpreterPython::GenerateScriptAliasFunction (StringList &user_input, std::string &output)
{
static uint32_t num_created_functions = 0;
user_input.RemoveBlankLines ();
StreamString sstr;
// Check to see if we have any data; if not, just return.
if (user_input.GetSize() == 0)
return false;
std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_cmd_alias_func", num_created_functions));
sstr.Printf ("def %s (debugger, args, result, internal_dict):", auto_generated_function_name.c_str());
if (!GenerateFunction(sstr.GetData(),user_input))
return false;
// Store the name of the auto-generated function to be called.
output.assign(auto_generated_function_name);
return true;
}
bool
ScriptInterpreterPython::GenerateTypeSynthClass (StringList &user_input, std::string &output, void* name_token)
{
static uint32_t num_created_classes = 0;
user_input.RemoveBlankLines ();
int num_lines = user_input.GetSize ();
StreamString sstr;
// Check to see if we have any data; if not, just return.
if (user_input.GetSize() == 0)
return false;
// Wrap all user input into a Python class
std::string auto_generated_class_name(GenerateUniqueName("lldb_autogen_python_type_synth_class",num_created_classes,name_token));
StringList auto_generated_class;
// Create the function name & definition string.
sstr.Printf ("class %s:", auto_generated_class_name.c_str());
auto_generated_class.AppendString (sstr.GetData());
// Wrap everything up inside the class, increasing the indentation.
// we don't need to play any fancy indentation tricks here because there is no
// surrounding code whose indentation we need to honor
for (int i = 0; i < num_lines; ++i)
{
sstr.Clear ();
sstr.Printf (" %s", user_input.GetStringAtIndex (i));
auto_generated_class.AppendString (sstr.GetData());
}
// Verify that the results are valid Python.
// (even though the method is ExportFunctionDefinitionToInterpreter, a class will actually be exported)
// (TODO: rename that method to ExportDefinitionToInterpreter)
if (!ExportFunctionDefinitionToInterpreter (auto_generated_class))
return false;
// Store the name of the auto-generated class
output.assign(auto_generated_class_name);
return true;
}
lldb::ScriptInterpreterObjectSP
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
ScriptInterpreterPython::OSPlugin_CreatePluginObject (const char *class_name, lldb::ProcessSP process_sp)
{
if (class_name == NULL || class_name[0] == '\0')
return lldb::ScriptInterpreterObjectSP();
if (!process_sp)
return lldb::ScriptInterpreterObjectSP();
void* ret_val;
{
Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
ret_val = g_swig_create_os_plugin (class_name,
m_dictionary_name.c_str(),
process_sp);
}
return MakeScriptObject(ret_val);
}
lldb::ScriptInterpreterObjectSP
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
ScriptInterpreterPython::OSPlugin_RegisterInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp)
{
Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
static char callee_name[] = "get_register_info";
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
if (!os_plugin_object_sp)
return lldb::ScriptInterpreterObjectSP();
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
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, NULL);
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
return MakeScriptObject(py_return);
}
lldb::ScriptInterpreterObjectSP
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
ScriptInterpreterPython::OSPlugin_ThreadsInfo (lldb::ScriptInterpreterObjectSP os_plugin_object_sp)
{
Locker py_lock(this,Locker::AcquireLock,Locker::FreeLock);
static char callee_name[] = "get_thread_info";
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
if (!os_plugin_object_sp)
return lldb::ScriptInterpreterObjectSP();
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
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, NULL);
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
return MakeScriptObject(py_return);
}
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
// 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 <typename T>
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
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
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";
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
static char *param_format = const_cast<char *>(GetPythonValueFormatString(tid));
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
if (!os_plugin_object_sp)
return lldb::ScriptInterpreterObjectSP();
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
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..
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
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);
}
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
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, &param_format[0], tid, context);
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
return MakeScriptObject(py_return);
}
lldb::ScriptInterpreterObjectSP
<rdar://problem/14972424> When debugging with the GDB remote in LLDB, LLDB uses special packets to discover the registers on the remote server. When those packets aren't supported, LLDB doesn't know what the registers look like. This checkin implements a setting that can be used to specify a python file that contains the registers definitions. The setting is: (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/module.py Inside module there should be a function: def get_dynamic_setting(target, setting_name): This dynamic setting function is handed the "target" which is a SBTarget, and the "setting_name", which is the name of the dynamic setting to retrieve. For the GDB remote target definition the setting name is 'gdb-server-target-definition'. The return value is a dictionary that follows the same format as the OperatingSystem plugins follow. I have checked in an example file that implements the x86_64 GDB register set for people to see: examples/python/x86_64_target_definition.py This allows LLDB to debug to any archticture that is support and allows users to define the registers contexts when the discovery packets (qRegisterInfo, qHostInfo) are not supported by the remote GDB server. A few benefits of doing this in Python: 1 - The dynamic register context was already supported in the OperatingSystem plug-in 2 - Register contexts can use all of the LLDB enumerations and definitions for things like lldb::Format, lldb::Encoding, generic register numbers, invalid registers numbers, etc. 3 - The code that generates the register context can use the program to calculate the register context contents (like offsets, register numbers, and more) 4 - True dynamic detection could be used where variables and types could be read from the target program itself in order to determine which registers are available since the target is passed into the python function. This is designed to be used instead of XML since it is more dynamic and code flow and functions can be used to make the dictionary. llvm-svn: 192646
2013-10-15 00:14:28 +00:00
ScriptInterpreterPython::LoadPluginModule (const FileSpec& file_spec,
lldb_private::Error& error)
{
if (!file_spec.Exists())
{
error.SetErrorString("no such file");
return lldb::ScriptInterpreterObjectSP();
}
ScriptInterpreterObjectSP module_sp;
if (LoadScriptingModule(file_spec.GetPath().c_str(),true,true,error,&module_sp))
return module_sp;
return lldb::ScriptInterpreterObjectSP();
}
lldb::ScriptInterpreterObjectSP
<rdar://problem/14972424> When debugging with the GDB remote in LLDB, LLDB uses special packets to discover the registers on the remote server. When those packets aren't supported, LLDB doesn't know what the registers look like. This checkin implements a setting that can be used to specify a python file that contains the registers definitions. The setting is: (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/module.py Inside module there should be a function: def get_dynamic_setting(target, setting_name): This dynamic setting function is handed the "target" which is a SBTarget, and the "setting_name", which is the name of the dynamic setting to retrieve. For the GDB remote target definition the setting name is 'gdb-server-target-definition'. The return value is a dictionary that follows the same format as the OperatingSystem plugins follow. I have checked in an example file that implements the x86_64 GDB register set for people to see: examples/python/x86_64_target_definition.py This allows LLDB to debug to any archticture that is support and allows users to define the registers contexts when the discovery packets (qRegisterInfo, qHostInfo) are not supported by the remote GDB server. A few benefits of doing this in Python: 1 - The dynamic register context was already supported in the OperatingSystem plug-in 2 - Register contexts can use all of the LLDB enumerations and definitions for things like lldb::Format, lldb::Encoding, generic register numbers, invalid registers numbers, etc. 3 - The code that generates the register context can use the program to calculate the register context contents (like offsets, register numbers, and more) 4 - True dynamic detection could be used where variables and types could be read from the target program itself in order to determine which registers are available since the target is passed into the python function. This is designed to be used instead of XML since it is more dynamic and code flow and functions can be used to make the dictionary. llvm-svn: 192646
2013-10-15 00:14:28 +00:00
ScriptInterpreterPython::GetDynamicSettings (lldb::ScriptInterpreterObjectSP plugin_module_sp,
Target* target,
const char* setting_name,
lldb_private::Error& error)
{
<rdar://problem/14972424> When debugging with the GDB remote in LLDB, LLDB uses special packets to discover the registers on the remote server. When those packets aren't supported, LLDB doesn't know what the registers look like. This checkin implements a setting that can be used to specify a python file that contains the registers definitions. The setting is: (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/module.py Inside module there should be a function: def get_dynamic_setting(target, setting_name): This dynamic setting function is handed the "target" which is a SBTarget, and the "setting_name", which is the name of the dynamic setting to retrieve. For the GDB remote target definition the setting name is 'gdb-server-target-definition'. The return value is a dictionary that follows the same format as the OperatingSystem plugins follow. I have checked in an example file that implements the x86_64 GDB register set for people to see: examples/python/x86_64_target_definition.py This allows LLDB to debug to any archticture that is support and allows users to define the registers contexts when the discovery packets (qRegisterInfo, qHostInfo) are not supported by the remote GDB server. A few benefits of doing this in Python: 1 - The dynamic register context was already supported in the OperatingSystem plug-in 2 - Register contexts can use all of the LLDB enumerations and definitions for things like lldb::Format, lldb::Encoding, generic register numbers, invalid registers numbers, etc. 3 - The code that generates the register context can use the program to calculate the register context contents (like offsets, register numbers, and more) 4 - True dynamic detection could be used where variables and types could be read from the target program itself in order to determine which registers are available since the target is passed into the python function. This is designed to be used instead of XML since it is more dynamic and code flow and functions can be used to make the dictionary. llvm-svn: 192646
2013-10-15 00:14:28 +00:00
if (!plugin_module_sp || !target || !setting_name || !setting_name[0])
return lldb::ScriptInterpreterObjectSP();
<rdar://problem/14972424> When debugging with the GDB remote in LLDB, LLDB uses special packets to discover the registers on the remote server. When those packets aren't supported, LLDB doesn't know what the registers look like. This checkin implements a setting that can be used to specify a python file that contains the registers definitions. The setting is: (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/module.py Inside module there should be a function: def get_dynamic_setting(target, setting_name): This dynamic setting function is handed the "target" which is a SBTarget, and the "setting_name", which is the name of the dynamic setting to retrieve. For the GDB remote target definition the setting name is 'gdb-server-target-definition'. The return value is a dictionary that follows the same format as the OperatingSystem plugins follow. I have checked in an example file that implements the x86_64 GDB register set for people to see: examples/python/x86_64_target_definition.py This allows LLDB to debug to any archticture that is support and allows users to define the registers contexts when the discovery packets (qRegisterInfo, qHostInfo) are not supported by the remote GDB server. A few benefits of doing this in Python: 1 - The dynamic register context was already supported in the OperatingSystem plug-in 2 - Register contexts can use all of the LLDB enumerations and definitions for things like lldb::Format, lldb::Encoding, generic register numbers, invalid registers numbers, etc. 3 - The code that generates the register context can use the program to calculate the register context contents (like offsets, register numbers, and more) 4 - True dynamic detection could be used where variables and types could be read from the target program itself in order to determine which registers are available since the target is passed into the python function. This is designed to be used instead of XML since it is more dynamic and code flow and functions can be used to make the dictionary. llvm-svn: 192646
2013-10-15 00:14:28 +00:00
if (!g_swig_plugin_get)
return lldb::ScriptInterpreterObjectSP();
PyObject *reply_pyobj = nullptr;
{
Locker py_lock(this);
TargetSP target_sp(target->shared_from_this());
<rdar://problem/14972424> When debugging with the GDB remote in LLDB, LLDB uses special packets to discover the registers on the remote server. When those packets aren't supported, LLDB doesn't know what the registers look like. This checkin implements a setting that can be used to specify a python file that contains the registers definitions. The setting is: (lldb) settings set plugin.process.gdb-remote.target-definition-file /path/to/module.py Inside module there should be a function: def get_dynamic_setting(target, setting_name): This dynamic setting function is handed the "target" which is a SBTarget, and the "setting_name", which is the name of the dynamic setting to retrieve. For the GDB remote target definition the setting name is 'gdb-server-target-definition'. The return value is a dictionary that follows the same format as the OperatingSystem plugins follow. I have checked in an example file that implements the x86_64 GDB register set for people to see: examples/python/x86_64_target_definition.py This allows LLDB to debug to any archticture that is support and allows users to define the registers contexts when the discovery packets (qRegisterInfo, qHostInfo) are not supported by the remote GDB server. A few benefits of doing this in Python: 1 - The dynamic register context was already supported in the OperatingSystem plug-in 2 - Register contexts can use all of the LLDB enumerations and definitions for things like lldb::Format, lldb::Encoding, generic register numbers, invalid registers numbers, etc. 3 - The code that generates the register context can use the program to calculate the register context contents (like offsets, register numbers, and more) 4 - True dynamic detection could be used where variables and types could be read from the target program itself in order to determine which registers are available since the target is passed into the python function. This is designed to be used instead of XML since it is more dynamic and code flow and functions can be used to make the dictionary. llvm-svn: 192646
2013-10-15 00:14:28 +00:00
reply_pyobj = (PyObject*)g_swig_plugin_get(plugin_module_sp->GetObject(),setting_name,target_sp);
}
return MakeScriptObject(reply_pyobj);
}
lldb::ScriptInterpreterObjectSP
ScriptInterpreterPython::CreateSyntheticScriptedProvider (const char *class_name,
lldb::ValueObjectSP valobj)
{
if (class_name == NULL || class_name[0] == '\0')
return lldb::ScriptInterpreterObjectSP();
if (!valobj.get())
return lldb::ScriptInterpreterObjectSP();
ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
Target *target = exe_ctx.GetTargetPtr();
if (!target)
return lldb::ScriptInterpreterObjectSP();
Debugger &debugger = target->GetDebugger();
ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
if (!script_interpreter)
return lldb::ScriptInterpreterObjectSP();
void* ret_val;
{
Locker py_lock(this);
ret_val = g_swig_synthetic_script (class_name,
python_interpreter->m_dictionary_name.c_str(),
valobj);
}
return MakeScriptObject(ret_val);
}
bool
ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, std::string& output, void* name_token)
{
StringList input;
input.SplitIntoLines(oneliner, strlen(oneliner));
return GenerateTypeScriptFunction(input, output, name_token);
}
bool
ScriptInterpreterPython::GenerateTypeSynthClass (const char* oneliner, std::string& output, void* name_token)
{
StringList input;
input.SplitIntoLines(oneliner, strlen(oneliner));
return GenerateTypeSynthClass(input, output, name_token);
}
bool
ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, std::string& output)
{
static uint32_t num_created_functions = 0;
user_input.RemoveBlankLines ();
StreamString sstr;
if (user_input.GetSize() == 0)
return false;
std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_bp_callback_func_",num_created_functions));
sstr.Printf ("def %s (frame, bp_loc, internal_dict):", auto_generated_function_name.c_str());
if (!GenerateFunction(sstr.GetData(), user_input))
return false;
// Store the name of the auto-generated function to be called.
output.assign(auto_generated_function_name);
return true;
}
bool
ScriptInterpreterPython::GenerateWatchpointCommandCallbackData (StringList &user_input, std::string& output)
{
static uint32_t num_created_functions = 0;
user_input.RemoveBlankLines ();
StreamString sstr;
if (user_input.GetSize() == 0)
return false;
std::string auto_generated_function_name(GenerateUniqueName("lldb_autogen_python_wp_callback_func_",num_created_functions));
sstr.Printf ("def %s (frame, wp, internal_dict):", auto_generated_function_name.c_str());
if (!GenerateFunction(sstr.GetData(), user_input))
return false;
// Store the name of the auto-generated function to be called.
output.assign(auto_generated_function_name);
return true;
}
bool
ScriptInterpreterPython::GetScriptedSummary (const char *python_function_name,
lldb::ValueObjectSP valobj,
lldb::ScriptInterpreterObjectSP& callee_wrapper_sp,
std::string& retval)
{
Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
if (!valobj.get())
{
retval.assign("<no object>");
return false;
}
void* old_callee = (callee_wrapper_sp ? callee_wrapper_sp->GetObject() : NULL);
void* new_callee = old_callee;
bool ret_val;
if (python_function_name
&& *python_function_name)
{
{
Locker py_lock(this);
{
Timer scoped_timer ("g_swig_typescript_callback","g_swig_typescript_callback");
ret_val = g_swig_typescript_callback (python_function_name,
FindSessionDictionary(m_dictionary_name.c_str()),
valobj,
&new_callee,
retval);
}
}
}
else
{
retval.assign("<no function name>");
return false;
}
if (new_callee && old_callee != new_callee)
callee_wrapper_sp = MakeScriptObject(new_callee);
return ret_val;
}
bool
ScriptInterpreterPython::BreakpointCallbackFunction
(
void *baton,
StoppointCallbackContext *context,
user_id_t break_id,
user_id_t break_loc_id
)
{
BreakpointOptions::CommandData *bp_option_data = (BreakpointOptions::CommandData *) baton;
const char *python_function_name = bp_option_data->script_source.c_str();
if (!context)
return true;
ExecutionContext exe_ctx (context->exe_ctx_ref);
Target *target = exe_ctx.GetTargetPtr();
if (!target)
return true;
Debugger &debugger = target->GetDebugger();
ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
if (!script_interpreter)
return true;
if (python_function_name != NULL
&& python_function_name[0] != '\0')
{
const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP());
BreakpointSP breakpoint_sp = target->GetBreakpointByID (break_id);
if (breakpoint_sp)
{
const BreakpointLocationSP bp_loc_sp (breakpoint_sp->FindLocationByID (break_loc_id));
if (stop_frame_sp && bp_loc_sp)
{
bool ret_val = true;
{
Locker py_lock(python_interpreter);
ret_val = g_swig_breakpoint_callback (python_function_name,
python_interpreter->m_dictionary_name.c_str(),
stop_frame_sp,
bp_loc_sp);
}
return ret_val;
}
}
}
// We currently always true so we stop in case anything goes wrong when
// trying to call the script function
return true;
}
bool
ScriptInterpreterPython::WatchpointCallbackFunction
(
void *baton,
StoppointCallbackContext *context,
user_id_t watch_id
)
{
WatchpointOptions::CommandData *wp_option_data = (WatchpointOptions::CommandData *) baton;
const char *python_function_name = wp_option_data->script_source.c_str();
if (!context)
return true;
ExecutionContext exe_ctx (context->exe_ctx_ref);
Target *target = exe_ctx.GetTargetPtr();
if (!target)
return true;
Debugger &debugger = target->GetDebugger();
ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
if (!script_interpreter)
return true;
if (python_function_name != NULL
&& python_function_name[0] != '\0')
{
const StackFrameSP stop_frame_sp (exe_ctx.GetFrameSP());
WatchpointSP wp_sp = target->GetWatchpointList().FindByID (watch_id);
if (wp_sp)
{
if (stop_frame_sp && wp_sp)
{
bool ret_val = true;
{
Locker py_lock(python_interpreter);
ret_val = g_swig_watchpoint_callback (python_function_name,
python_interpreter->m_dictionary_name.c_str(),
stop_frame_sp,
wp_sp);
}
return ret_val;
}
}
}
// We currently always true so we stop in case anything goes wrong when
// trying to call the script function
return true;
}
lldb::thread_result_t
ScriptInterpreterPython::RunEmbeddedPythonInterpreter (lldb::thread_arg_t baton)
{
ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
if (log)
log->Printf ("%p ScriptInterpreterPython::RunEmbeddedPythonInterpreter () thread starting...", baton);
char error_str[1024];
const char *pty_slave_name = script_interpreter->m_embedded_python_pty.GetSlaveName (error_str, sizeof (error_str));
if (pty_slave_name != NULL)
{
StreamString run_string;
// Ensure we have the GIL before running any Python code.
// Since we're only running a few one-liners and then dropping to the interpreter (which will release the GIL when needed),
// we can just release the GIL after finishing our work.
// If finer-grained locking is desirable, we can lock and unlock the GIL only when calling a python function.
Locker locker(script_interpreter,
ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | ScriptInterpreterPython::Locker::InitGlobals,
ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
run_string.Printf ("run_one_line (%s, 'save_stderr = sys.stderr')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
run_string.Printf ("run_one_line (%s, 'sys.stderr = sys.stdout')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
run_string.Printf ("run_one_line (%s, 'save_stdin = sys.stdin')", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
run_string.Printf ("run_one_line (%s, \"sys.stdin = open ('%s', 'r')\")", script_interpreter->m_dictionary_name.c_str(),
pty_slave_name);
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
// The following call drops into the embedded interpreter loop and stays there until the
// user chooses to exit from the Python interpreter.
// This embedded interpreter will, as any Python code that performs I/O, unlock the GIL before
// a system call that can hang, and lock it when the syscall has returned.
// We need to surround the call to the embedded interpreter with calls to PyGILState_Ensure and
// PyGILState_Release (using the Locker above). This is because Python has a global lock which must be held whenever we want
// to touch any Python objects. Otherwise, if the user calls Python code, the interpreter state will be off,
// and things could hang (it's happened before).
run_string.Printf ("run_python_interpreter (%s)", script_interpreter->m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
run_string.Clear ();
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();
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();
}
if (script_interpreter->m_embedded_python_input_reader_sp)
script_interpreter->m_embedded_python_input_reader_sp->SetIsDone (true);
script_interpreter->m_embedded_python_pty.CloseSlaveFileDescriptor();
log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT);
if (log)
log->Printf ("%p ScriptInterpreterPython::RunEmbeddedPythonInterpreter () thread exiting...", baton);
// Clean up the input reader and make the debugger pop it off the stack.
Debugger &debugger = script_interpreter->GetCommandInterpreter().GetDebugger();
const InputReaderSP reader_sp = script_interpreter->m_embedded_python_input_reader_sp;
if (reader_sp)
{
debugger.PopInputReader (reader_sp);
script_interpreter->m_embedded_python_input_reader_sp.reset();
}
return NULL;
}
lldb::thread_result_t
ScriptInterpreterPython::PythonInputReaderManager::RunPythonInputReader (lldb::thread_arg_t baton)
{
ScriptInterpreterPython *script_interpreter = (ScriptInterpreterPython *) baton;
const InputReaderSP reader_sp = script_interpreter->m_embedded_thread_input_reader_sp;
if (reader_sp)
reader_sp->WaitOnReaderIsDone();
return NULL;
}
size_t
ScriptInterpreterPython::CalculateNumChildren (const lldb::ScriptInterpreterObjectSP& implementor_sp)
{
if (!implementor_sp)
return 0;
void* implementor = implementor_sp->GetObject();
if (!implementor)
return 0;
if (!g_swig_calc_children)
return 0;
uint32_t ret_val = 0;
{
Locker py_lock(this);
ret_val = g_swig_calc_children (implementor);
}
return ret_val;
}
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-06 19:20:51 +00:00
lldb::ValueObjectSP
ScriptInterpreterPython::GetChildAtIndex (const lldb::ScriptInterpreterObjectSP& implementor_sp, uint32_t idx)
{
if (!implementor_sp)
return lldb::ValueObjectSP();
void* implementor = implementor_sp->GetObject();
if (!implementor)
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-06 19:20:51 +00:00
return lldb::ValueObjectSP();
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-06 19:20:51 +00:00
if (!g_swig_get_child_index || !g_swig_cast_to_sbvalue)
return lldb::ValueObjectSP();
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-06 19:20:51 +00:00
lldb::ValueObjectSP ret_val;
{
Locker py_lock(this);
void* child_ptr = g_swig_get_child_index (implementor,idx);
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-06 19:20:51 +00:00
if (child_ptr != NULL && child_ptr != Py_None)
{
lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
if (sb_value_ptr == NULL)
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-06 19:20:51 +00:00
Py_XDECREF(child_ptr);
else
ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr);
Redesign of the interaction between Python and frozen objects: - introduced two new classes ValueObjectConstResultChild and ValueObjectConstResultImpl: the first one is a ValueObjectChild obtained from a ValueObjectConstResult, the second is a common implementation backend for VOCR and VOCRCh of method calls meant to read through pointers stored in frozen objects ; now such reads transparently move from host to target as required - as a consequence of the above, removed code that made target-memory copies of expression results in several places throughout LLDB, and also removed code that enabled to recognize an expression result VO as such - introduced a new GetPointeeData() method in ValueObject that lets you read a given amount of objects of type T from a VO representing a T* or T[], and doing dereferences transparently in private layer it returns a DataExtractor ; in public layer it returns an instance of a newly created lldb::SBData - as GetPointeeData() does the right thing for both frozen and non-frozen ValueObject's, reimplemented ReadPointedString() to use it en lieu of doing the raw read itself - introduced a new GetData() method in ValueObject that lets you get a copy of the data that backs the ValueObject (for pointers, this returns the address without any previous dereferencing steps ; for arrays it actually reads the whole chunk of memory) in public layer this returns an SBData, just like GetPointeeData() - introduced a new CreateValueFromData() method in SBValue that lets you create a new SBValue from a chunk of data wrapped in an SBData the limitation to remember for this kind of SBValue is that they have no address: extracting the address-of for these objects (with any of GetAddress(), GetLoadAddress() and AddressOf()) will return invalid values - added several tests to check that "p"-ing objects (STL classes, char* and char[]) will do the right thing Solved a bug where global pointers to global variables were not dereferenced correctly for display New target setting "max-string-summary-length" gives the maximum number of characters to show in a string when summarizing it, instead of the hardcoded 128 Solved a bug where the summary for char[] and char* would not be shown if the ValueObject's were dumped via the "p" command Removed m_pointers_point_to_load_addrs from ValueObject. Introduced a new m_address_type_of_children, which each ValueObject can set to tell the address type of any pointers and/or references it creates. In the current codebase, this is load address most of the time (the only notable exception being file addresses that generate file address children UNLESS we have a live process) Updated help text for summary-string Fixed an issue in STL formatters where std::stlcontainer::iterator would match the container's synthetic children providers Edited the syntax and help for some commands to have proper argument types llvm-svn: 139160
2011-09-06 19:20:51 +00:00
}
else
{
Py_XDECREF(child_ptr);
}
}
return ret_val;
}
int
ScriptInterpreterPython::GetIndexOfChildWithName (const lldb::ScriptInterpreterObjectSP& implementor_sp, const char* child_name)
{
if (!implementor_sp)
return UINT32_MAX;
void* implementor = implementor_sp->GetObject();
if (!implementor)
return UINT32_MAX;
if (!g_swig_get_index_child)
return UINT32_MAX;
int ret_val = UINT32_MAX;
{
Locker py_lock(this);
ret_val = g_swig_get_index_child (implementor, child_name);
}
return ret_val;
}
bool
ScriptInterpreterPython::UpdateSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor_sp)
{
bool ret_val = false;
if (!implementor_sp)
return ret_val;
void* implementor = implementor_sp->GetObject();
if (!implementor)
return ret_val;
if (!g_swig_update_provider)
return ret_val;
{
Locker py_lock(this);
ret_val = g_swig_update_provider (implementor);
}
return ret_val;
}
bool
ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance (const lldb::ScriptInterpreterObjectSP& implementor_sp)
{
bool ret_val = false;
if (!implementor_sp)
return ret_val;
void* implementor = implementor_sp->GetObject();
if (!implementor)
return ret_val;
if (!g_swig_mighthavechildren_provider)
return ret_val;
{
Locker py_lock(this);
ret_val = g_swig_mighthavechildren_provider (implementor);
}
return ret_val;
}
static std::string
ReadPythonBacktrace (PyObject* py_backtrace)
{
PyObject* traceback_module = NULL,
*stringIO_module = NULL,
*stringIO_builder = NULL,
*stringIO_buffer = NULL,
*printTB = NULL,
*printTB_args = NULL,
*printTB_result = NULL,
*stringIO_getvalue = NULL,
*printTB_string = NULL;
std::string retval("backtrace unavailable");
if (py_backtrace && py_backtrace != Py_None)
{
traceback_module = PyImport_ImportModule("traceback");
stringIO_module = PyImport_ImportModule("StringIO");
if (traceback_module && traceback_module != Py_None && stringIO_module && stringIO_module != Py_None)
{
stringIO_builder = PyObject_GetAttrString(stringIO_module, "StringIO");
if (stringIO_builder && stringIO_builder != Py_None)
{
stringIO_buffer = PyObject_CallObject(stringIO_builder, NULL);
if (stringIO_buffer && stringIO_buffer != Py_None)
{
printTB = PyObject_GetAttrString(traceback_module, "print_tb");
if (printTB && printTB != Py_None)
{
printTB_args = Py_BuildValue("OOO",py_backtrace,Py_None,stringIO_buffer);
printTB_result = PyObject_CallObject(printTB, printTB_args);
stringIO_getvalue = PyObject_GetAttrString(stringIO_buffer, "getvalue");
if (stringIO_getvalue && stringIO_getvalue != Py_None)
{
printTB_string = PyObject_CallObject (stringIO_getvalue,NULL);
if (printTB_string && printTB_string != Py_None && PyString_Check(printTB_string))
retval.assign(PyString_AsString(printTB_string));
}
}
}
}
}
}
Py_XDECREF(traceback_module);
Py_XDECREF(stringIO_module);
Py_XDECREF(stringIO_builder);
Py_XDECREF(stringIO_buffer);
Py_XDECREF(printTB);
Py_XDECREF(printTB_args);
Py_XDECREF(printTB_result);
Py_XDECREF(stringIO_getvalue);
Py_XDECREF(printTB_string);
return retval;
}
bool
ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
Process* process,
std::string& output,
Error& error)
{
bool ret_val;
if (!process)
{
error.SetErrorString("no process");
return false;
}
if (!impl_function || !impl_function[0])
{
error.SetErrorString("no function to execute");
return false;
}
if (!g_swig_run_script_keyword_process)
{
error.SetErrorString("internal helper function missing");
return false;
}
{
ProcessSP process_sp(process->shared_from_this());
Locker py_lock(this);
ret_val = g_swig_run_script_keyword_process (impl_function, m_dictionary_name.c_str(), process_sp, output);
if (!ret_val)
error.SetErrorString("python script evaluation failed");
}
return ret_val;
}
bool
ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
Thread* thread,
std::string& output,
Error& error)
{
bool ret_val;
if (!thread)
{
error.SetErrorString("no thread");
return false;
}
if (!impl_function || !impl_function[0])
{
error.SetErrorString("no function to execute");
return false;
}
if (!g_swig_run_script_keyword_thread)
{
error.SetErrorString("internal helper function missing");
return false;
}
{
ThreadSP thread_sp(thread->shared_from_this());
Locker py_lock(this);
ret_val = g_swig_run_script_keyword_thread (impl_function, m_dictionary_name.c_str(), thread_sp, output);
if (!ret_val)
error.SetErrorString("python script evaluation failed");
}
return ret_val;
}
bool
ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
Target* target,
std::string& output,
Error& error)
{
bool ret_val;
if (!target)
{
error.SetErrorString("no thread");
return false;
}
if (!impl_function || !impl_function[0])
{
error.SetErrorString("no function to execute");
return false;
}
if (!g_swig_run_script_keyword_target)
{
error.SetErrorString("internal helper function missing");
return false;
}
{
TargetSP target_sp(target->shared_from_this());
Locker py_lock(this);
ret_val = g_swig_run_script_keyword_target (impl_function, m_dictionary_name.c_str(), target_sp, output);
if (!ret_val)
error.SetErrorString("python script evaluation failed");
}
return ret_val;
}
bool
ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
StackFrame* frame,
std::string& output,
Error& error)
{
bool ret_val;
if (!frame)
{
error.SetErrorString("no frame");
return false;
}
if (!impl_function || !impl_function[0])
{
error.SetErrorString("no function to execute");
return false;
}
if (!g_swig_run_script_keyword_frame)
{
error.SetErrorString("internal helper function missing");
return false;
}
{
StackFrameSP frame_sp(frame->shared_from_this());
Locker py_lock(this);
ret_val = g_swig_run_script_keyword_frame (impl_function, m_dictionary_name.c_str(), frame_sp, output);
if (!ret_val)
error.SetErrorString("python script evaluation failed");
}
return ret_val;
}
uint64_t replace_all(std::string& str, const std::string& oldStr, const std::string& newStr)
{
size_t pos = 0;
uint64_t matches = 0;
while((pos = str.find(oldStr, pos)) != std::string::npos)
{
matches++;
str.replace(pos, oldStr.length(), newStr);
pos += newStr.length();
}
return matches;
}
bool
ScriptInterpreterPython::LoadScriptingModule (const char* pathname,
bool can_reload,
bool init_session,
lldb_private::Error& error,
lldb::ScriptInterpreterObjectSP* module_sp)
{
if (!pathname || !pathname[0])
{
error.SetErrorString("invalid pathname");
return false;
}
if (!g_swig_call_module_init)
{
error.SetErrorString("internal helper function missing");
return false;
}
lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
{
FileSpec target_file(pathname, true);
std::string basename(target_file.GetFilename().GetCString());
StreamString command_stream;
// Before executing Pyton code, lock the GIL.
Locker py_lock (this,
Locker::AcquireLock | (init_session ? Locker::InitSession : 0),
Locker::FreeAcquiredLock | (init_session ? Locker::TearDownSession : 0));
if (target_file.GetFileType() == FileSpec::eFileTypeInvalid ||
target_file.GetFileType() == FileSpec::eFileTypeUnknown)
{
// if not a valid file of any sort, check if it might be a filename still
// dot can't be used but / and \ can, and if either is found, reject
if (strchr(pathname,'\\') || strchr(pathname,'/'))
{
error.SetErrorString("invalid pathname");
return false;
}
basename = pathname; // not a filename, probably a package of some sort, let it go through
}
else if (target_file.GetFileType() == FileSpec::eFileTypeDirectory ||
target_file.GetFileType() == FileSpec::eFileTypeRegular ||
target_file.GetFileType() == FileSpec::eFileTypeSymbolicLink)
{
std::string directory(target_file.GetDirectory().GetCString());
replace_all(directory,"'","\\'");
// 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.insert(1,'%s');\n\n",
directory.c_str(),
directory.c_str());
bool syspath_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false));
if (!syspath_retval)
{
error.SetErrorString("Python sys.path handling failed");
return false;
}
// strip .py or .pyc extension
ConstString extension = target_file.GetFileNameExtension();
if (extension)
{
if (::strcmp(extension.GetCString(), "py") == 0)
basename.resize(basename.length()-3);
else if(::strcmp(extension.GetCString(), "pyc") == 0)
basename.resize(basename.length()-4);
}
}
else
{
error.SetErrorString("no known way to import this module specification");
return false;
}
// check if the module is already import-ed
command_stream.Clear();
command_stream.Printf("sys.modules.__contains__('%s')",basename.c_str());
bool does_contain = false;
int refcount = 0;
// this call will succeed if the module was ever imported in any Debugger in the lifetime of the process
// in which this LLDB framework is living
bool was_imported_globally = (ExecuteOneLineWithReturn(command_stream.GetData(),
ScriptInterpreterPython::eScriptReturnTypeBool,
&does_contain,
ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)) && does_contain);
// this call will fail if the module was not imported in this Debugger before
command_stream.Clear();
command_stream.Printf("sys.getrefcount(%s)",basename.c_str());
bool was_imported_locally = (ExecuteOneLineWithReturn(command_stream.GetData(),
ScriptInterpreterPython::eScriptReturnTypeInt,
&refcount,
ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false)) && refcount > 0);
bool was_imported = (was_imported_globally || was_imported_locally);
if (was_imported == true && can_reload == false)
{
error.SetErrorString("module already imported");
return false;
}
// now actually do the import
command_stream.Clear();
if (was_imported)
{
if (!was_imported_locally)
command_stream.Printf("import %s ; reload(%s)",basename.c_str(),basename.c_str());
else
command_stream.Printf("reload(%s)",basename.c_str());
}
else
command_stream.Printf("import %s",basename.c_str());
bool import_retval = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false).SetMaskoutErrors(false));
PyObject* py_error = PyErr_Occurred(); // per Python docs: "you do not need to Py_DECREF()" the return of this function
if (py_error || !import_retval) // check for failure of the import
{
if (py_error) // if we have a Python error..
{
PyObject *type = NULL,*value = NULL,*traceback = NULL;
PyErr_Fetch (&type,&value,&traceback);
if (PyErr_GivenExceptionMatches (py_error, PyExc_ImportError)) // and it is an ImportError
{
if (value && value != Py_None)
error.SetErrorString(PyString_AsString(PyObject_Str(value)));
else
error.SetErrorString("ImportError raised by imported module");
}
else // any other error
{
// get the backtrace
std::string bt = ReadPythonBacktrace(traceback);
if (value && value != Py_None)
error.SetErrorStringWithFormat("Python error raised while importing module: %s - traceback: %s", PyString_AsString(PyObject_Str(value)),bt.c_str());
else
error.SetErrorStringWithFormat("Python raised an error while importing module - traceback: %s",bt.c_str());
}
Py_XDECREF(type);
Py_XDECREF(value);
Py_XDECREF(traceback);
}
else // we failed but have no error to explain why
{
error.SetErrorString("unknown error while importing module");
}
// anyway, clear the error indicator and return false
PyErr_Clear();
return false;
}
// if we are here, everything worked
// call __lldb_init_module(debugger,dict)
if (!g_swig_call_module_init (basename.c_str(),
m_dictionary_name.c_str(),
debugger_sp))
{
error.SetErrorString("calling __lldb_init_module failed");
return false;
}
if (module_sp)
{
// everything went just great, now set the module object
command_stream.Clear();
command_stream.Printf("%s",basename.c_str());
void* module_pyobj = nullptr;
if (ExecuteOneLineWithReturn(command_stream.GetData(),ScriptInterpreter::eScriptReturnTypeOpaqueObject,&module_pyobj) && module_pyobj)
*module_sp = MakeScriptObject(module_pyobj);
}
return true;
}
}
lldb::ScriptInterpreterObjectSP
ScriptInterpreterPython::MakeScriptObject (void* object)
{
return lldb::ScriptInterpreterObjectSP(new ScriptInterpreterPythonObject(object));
}
ScriptInterpreterPython::SynchronicityHandler::SynchronicityHandler (lldb::DebuggerSP debugger_sp,
ScriptedCommandSynchronicity synchro) :
m_debugger_sp(debugger_sp),
m_synch_wanted(synchro),
m_old_asynch(debugger_sp->GetAsyncExecution())
{
if (m_synch_wanted == eScriptedCommandSynchronicitySynchronous)
m_debugger_sp->SetAsyncExecution(false);
else if (m_synch_wanted == eScriptedCommandSynchronicityAsynchronous)
m_debugger_sp->SetAsyncExecution(true);
}
ScriptInterpreterPython::SynchronicityHandler::~SynchronicityHandler()
{
if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue)
m_debugger_sp->SetAsyncExecution(m_old_asynch);
}
bool
ScriptInterpreterPython::RunScriptBasedCommand(const char* impl_function,
const char* args,
ScriptedCommandSynchronicity synchronicity,
lldb_private::CommandReturnObject& cmd_retobj,
Error& error)
{
if (!impl_function)
{
error.SetErrorString("no function to execute");
return false;
}
if (!g_swig_call_command)
{
error.SetErrorString("no helper function to run scripted commands");
return false;
}
lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
if (!debugger_sp.get())
{
error.SetErrorString("invalid Debugger pointer");
return false;
}
bool ret_val = false;
std::string err_msg;
{
Locker py_lock(this,
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
Locker::AcquireLock | Locker::InitSession,
Locker::FreeLock | Locker::TearDownSession);
SynchronicityHandler synch_handler(debugger_sp,
synchronicity);
// we need to save the thread state when we first start the command
// because we might decide to interrupt it while some action is taking
// place outside of Python (e.g. printing to screen, waiting for the network, ...)
// in that case, _PyThreadState_Current will be NULL - and we would be unable
// to set the asynchronous exception - not a desirable situation
m_command_thread_state = _PyThreadState_Current;
PythonInputReaderManager py_input(this);
ret_val = g_swig_call_command (impl_function,
m_dictionary_name.c_str(),
debugger_sp,
args,
cmd_retobj);
}
if (!ret_val)
error.SetErrorString("unable to execute script function");
else
error.Clear();
return ret_val;
}
// in Python, a special attribute __doc__ contains the docstring
// for an object (function, method, class, ...) if any is defined
// Otherwise, the attribute's value is None
bool
ScriptInterpreterPython::GetDocumentationForItem(const char* item, std::string& dest)
{
dest.clear();
if (!item || !*item)
return false;
std::string command(item);
command += ".__doc__";
char* result_ptr = NULL; // Python is going to point this to valid data if ExecuteOneLineWithReturn returns successfully
if (ExecuteOneLineWithReturn (command.c_str(),
<rdar://problem/13010007> 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
2013-01-18 23:41:08 +00:00
ScriptInterpreter::eScriptReturnTypeCharStrOrNone,
&result_ptr,
ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false)))
{
if (result_ptr)
dest.assign(result_ptr);
return true;
}
else
{
StreamString str_stream;
str_stream.Printf("Function %s was not found. Containing module might be missing.",item);
dest.assign(str_stream.GetData());
return false;
}
}
std::unique_ptr<ScriptInterpreterLocker>
ScriptInterpreterPython::AcquireInterpreterLock ()
{
std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(this,
Locker::AcquireLock | Locker::InitSession,
Locker::FreeLock | Locker::TearDownSession));
return py_lock;
}
void
ScriptInterpreterPython::InitializeInterpreter (SWIGInitCallback swig_init_callback,
SWIGBreakpointCallbackFunction swig_breakpoint_callback,
SWIGWatchpointCallbackFunction swig_watchpoint_callback,
SWIGPythonTypeScriptCallbackFunction swig_typescript_callback,
SWIGPythonCreateSyntheticProvider swig_synthetic_script,
SWIGPythonCalculateNumChildren swig_calc_children,
SWIGPythonGetChildAtIndex swig_get_child_index,
SWIGPythonGetIndexOfChildWithName swig_get_index_child,
SWIGPythonCastPyObjectToSBValue swig_cast_to_sbvalue ,
SWIGPythonGetValueObjectSPFromSBValue swig_get_valobj_sp_from_sbvalue,
SWIGPythonUpdateSynthProviderInstance swig_update_provider,
SWIGPythonMightHaveChildrenSynthProviderInstance swig_mighthavechildren_provider,
SWIGPythonCallCommand swig_call_command,
SWIGPythonCallModuleInit swig_call_module_init,
SWIGPythonCreateOSPlugin swig_create_os_plugin,
SWIGPythonScriptKeyword_Process swig_run_script_keyword_process,
SWIGPythonScriptKeyword_Thread swig_run_script_keyword_thread,
SWIGPythonScriptKeyword_Target swig_run_script_keyword_target,
SWIGPythonScriptKeyword_Frame swig_run_script_keyword_frame,
SWIGPython_GetDynamicSetting swig_plugin_get)
{
g_swig_init_callback = swig_init_callback;
g_swig_breakpoint_callback = swig_breakpoint_callback;
g_swig_watchpoint_callback = swig_watchpoint_callback;
g_swig_typescript_callback = swig_typescript_callback;
g_swig_synthetic_script = swig_synthetic_script;
g_swig_calc_children = swig_calc_children;
g_swig_get_child_index = swig_get_child_index;
g_swig_get_index_child = swig_get_index_child;
g_swig_cast_to_sbvalue = swig_cast_to_sbvalue;
g_swig_get_valobj_sp_from_sbvalue = swig_get_valobj_sp_from_sbvalue;
g_swig_update_provider = swig_update_provider;
g_swig_mighthavechildren_provider = swig_mighthavechildren_provider;
g_swig_call_command = swig_call_command;
g_swig_call_module_init = swig_call_module_init;
g_swig_create_os_plugin = swig_create_os_plugin;
g_swig_run_script_keyword_process = swig_run_script_keyword_process;
g_swig_run_script_keyword_thread = swig_run_script_keyword_thread;
g_swig_run_script_keyword_target = swig_run_script_keyword_target;
g_swig_run_script_keyword_frame = swig_run_script_keyword_frame;
g_swig_plugin_get = swig_plugin_get;
}
void
ScriptInterpreterPython::InitializePrivate ()
{
Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
// Python will muck with STDIN terminal state, so save off any current TTY
// settings so we can restore them.
TerminalState stdin_tty_state;
stdin_tty_state.Save(STDIN_FILENO, false);
PyGILState_STATE gstate;
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
bool threads_already_initialized = false;
if (PyEval_ThreadsInitialized ()) {
gstate = PyGILState_Ensure ();
if (log)
log->Printf("Ensured PyGILState. Previous state = %slocked\n", gstate == PyGILState_UNLOCKED ? "un" : "");
threads_already_initialized = true;
} else {
// InitThreads acquires the GIL if it hasn't been called before.
PyEval_InitThreads ();
}
Py_InitializeEx (0);
// Initialize SWIG after setting up python
assert (g_swig_init_callback != NULL);
g_swig_init_callback ();
// Update the path python uses to search for modules to include the current directory.
PyRun_SimpleString ("import sys");
PyRun_SimpleString ("sys.path.append ('.')");
// Find the module that owns this code and use that path we get to
// set the sys.path appropriately.
FileSpec file_spec;
char python_dir_path[PATH_MAX];
if (Host::GetLLDBPath (ePathTypePythonDir, file_spec))
{
std::string python_path("sys.path.insert(0,\"");
size_t orig_len = python_path.length();
if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path)))
{
python_path.append (python_dir_path);
python_path.append ("\")");
PyRun_SimpleString (python_path.c_str());
python_path.resize (orig_len);
}
if (Host::GetLLDBPath (ePathTypeLLDBShlibDir, file_spec))
{
if (file_spec.GetPath(python_dir_path, sizeof (python_dir_path)))
{
python_path.append (python_dir_path);
python_path.append ("\")");
PyRun_SimpleString (python_path.c_str());
python_path.resize (orig_len);
}
}
}
PyRun_SimpleString ("sys.dont_write_bytecode = 1; import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line; from termios import *");
if (threads_already_initialized) {
if (log)
log->Printf("Releasing PyGILState. Returning to state = %slocked\n", gstate == PyGILState_UNLOCKED ? "un" : "");
PyGILState_Release (gstate);
} else {
// We initialized the threads in this function, just unlock the GIL.
PyEval_SaveThread();
}
stdin_tty_state.Restore();
}
//void
//ScriptInterpreterPython::Terminate ()
//{
// // We are intentionally NOT calling Py_Finalize here (this would be the logical place to call it). Calling
// // Py_Finalize here causes test suite runs to seg fault: The test suite runs in Python. It registers
// // SBDebugger::Terminate to be called 'at_exit'. When the test suite Python harness finishes up, it calls
// // Py_Finalize, which calls all the 'at_exit' registered functions. SBDebugger::Terminate calls Debugger::Terminate,
// // which calls lldb::Terminate, which calls ScriptInterpreter::Terminate, which calls
// // ScriptInterpreterPython::Terminate. So if we call Py_Finalize here, we end up with Py_Finalize being called from
// // within Py_Finalize, which results in a seg fault.
// //
// // Since this function only gets called when lldb is shutting down and going away anyway, the fact that we don't
// // actually call Py_Finalize should not cause any problems (everything should shut down/go away anyway when the
// // process exits).
// //
//// Py_Finalize ();
//}
#endif // #ifdef LLDB_DISABLE_PYTHON