mirror-llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp

3249 lines
117 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.
//
//===----------------------------------------------------------------------===//
#ifdef LLDB_DISABLE_PYTHON
// Python is disabled in this build
#else
#include "lldb-python.h"
#include "ScriptInterpreterPython.h"
#include "PythonDataObjects.h"
#include <stdlib.h>
#include <stdio.h>
#include <mutex>
#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 11:20:51 -08:00
#include "lldb/API/SBValue.h"
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Breakpoint/WatchpointOptions.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/Pipe.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
#if defined(_WIN32)
#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
#endif
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/STLExtras.h"
using namespace lldb;
using namespace lldb_private;
static ScriptInterpreterPython::SWIGInitCallback g_swig_init_callback = nullptr;
static ScriptInterpreterPython::SWIGBreakpointCallbackFunction g_swig_breakpoint_callback = nullptr;
static ScriptInterpreterPython::SWIGWatchpointCallbackFunction g_swig_watchpoint_callback = nullptr;
static ScriptInterpreterPython::SWIGPythonTypeScriptCallbackFunction g_swig_typescript_callback = nullptr;
static ScriptInterpreterPython::SWIGPythonCreateSyntheticProvider g_swig_synthetic_script = nullptr;
static ScriptInterpreterPython::SWIGPythonCreateCommandObject g_swig_create_cmd = nullptr;
static ScriptInterpreterPython::SWIGPythonCalculateNumChildren g_swig_calc_children = nullptr;
static ScriptInterpreterPython::SWIGPythonGetChildAtIndex g_swig_get_child_index = nullptr;
static ScriptInterpreterPython::SWIGPythonGetIndexOfChildWithName g_swig_get_index_child = nullptr;
static ScriptInterpreterPython::SWIGPythonCastPyObjectToSBValue g_swig_cast_to_sbvalue = nullptr;
static ScriptInterpreterPython::SWIGPythonGetValueObjectSPFromSBValue g_swig_get_valobj_sp_from_sbvalue = nullptr;
static ScriptInterpreterPython::SWIGPythonUpdateSynthProviderInstance g_swig_update_provider = nullptr;
static ScriptInterpreterPython::SWIGPythonMightHaveChildrenSynthProviderInstance g_swig_mighthavechildren_provider = nullptr;
static ScriptInterpreterPython::SWIGPythonGetValueSynthProviderInstance g_swig_getvalue_provider = nullptr;
static ScriptInterpreterPython::SWIGPythonCallCommand g_swig_call_command = nullptr;
static ScriptInterpreterPython::SWIGPythonCallCommandObject g_swig_call_command_object = nullptr;
static ScriptInterpreterPython::SWIGPythonCallModuleInit g_swig_call_module_init = nullptr;
static ScriptInterpreterPython::SWIGPythonCreateOSPlugin g_swig_create_os_plugin = nullptr;
static ScriptInterpreterPython::SWIGPythonScriptKeyword_Process g_swig_run_script_keyword_process = nullptr;
static ScriptInterpreterPython::SWIGPythonScriptKeyword_Thread g_swig_run_script_keyword_thread = nullptr;
static ScriptInterpreterPython::SWIGPythonScriptKeyword_Target g_swig_run_script_keyword_target = nullptr;
static ScriptInterpreterPython::SWIGPythonScriptKeyword_Frame g_swig_run_script_keyword_frame = nullptr;
static ScriptInterpreterPython::SWIGPythonScriptKeyword_Value g_swig_run_script_keyword_value = nullptr;
static ScriptInterpreterPython::SWIGPython_GetDynamicSetting g_swig_plugin_get = nullptr;
static ScriptInterpreterPython::SWIGPythonCreateScriptedThreadPlan g_swig_thread_plan_script = nullptr;
static ScriptInterpreterPython::SWIGPythonCallThreadPlan g_swig_call_thread_plan = nullptr;
static bool g_initialized = false;
namespace
{
// Initializing Python is not a straightforward process. We cannot control what
// external code may have done before getting to this point in LLDB, including
// potentially having already initialized Python, so we need to do a lot of work
// to ensure that the existing state of the system is maintained across our
// initialization. We do this by using an RAII pattern where we save off initial
// state at the beginning, and restore it at the end
struct InitializePythonRAII
{
public:
InitializePythonRAII() :
m_gil_state(PyGILState_UNLOCKED),
m_was_already_initialized(false)
{
// Python will muck with STDIN terminal state, so save off any current TTY
// settings so we can restore them.
m_stdin_tty_state.Save(STDIN_FILENO, false);
InitializePythonHome();
// Python < 3.2 and Python >= 3.2 reversed the ordering requirements for
// calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you
// call `PyEval_InitThreads` first, and >= 3.2 requires that you call it last.
#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 2) || (PY_MAJOR_VERSION > 3)
Py_InitializeEx(0);
InitializeThreadsPrivate();
#else
InitializeThreadsPrivate();
Py_InitializeEx(0);
#endif
}
~InitializePythonRAII()
{
if (m_was_already_initialized)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
if (log)
{
log->Printf("Releasing PyGILState. Returning to state = %slocked\n",
m_was_already_initialized == PyGILState_UNLOCKED ? "un" : "");
}
PyGILState_Release(m_gil_state);
}
else
{
// We initialized the threads in this function, just unlock the GIL.
PyEval_SaveThread();
}
m_stdin_tty_state.Restore();
}
private:
void InitializePythonHome()
{
#if defined(LLDB_PYTHON_HOME)
#if PY_MAJOR_VERSION >= 3
size_t size = 0;
static wchar_t *g_python_home = Py_DecodeLocale(LLDB_PYTHON_HOME, &size);
#else
static char *g_python_home = LLDB_PYTHON_HOME;
#endif
Py_SetPythonHome(g_python_home);
#endif
}
void InitializeThreadsPrivate()
{
if (PyEval_ThreadsInitialized())
{
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT | LIBLLDB_LOG_VERBOSE));
m_was_already_initialized = true;
m_gil_state = PyGILState_Ensure();
if (log)
{
log->Printf("Ensured PyGILState. Previous state = %slocked\n",
m_gil_state == PyGILState_UNLOCKED ? "un" : "");
}
return;
}
// InitThreads acquires the GIL if it hasn't been called before.
PyEval_InitThreads();
}
TerminalState m_stdin_tty_state;
PyGILState_STATE m_gil_state;
bool m_was_already_initialized;
};
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
static std::string ReadPythonBacktrace(PythonObject py_backtrace);
ScriptInterpreterPython::Locker::Locker (ScriptInterpreterPython *py_interpreter,
uint16_t on_entry,
uint16_t on_leave,
FILE *in,
FILE *out,
FILE *err) :
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 14:41:08 -09:00
m_teardown_session( (on_leave & TearDownSession) == TearDownSession ),
m_python_interpreter(py_interpreter)
{
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 14:41:08 -09:00
{
if (DoInitSession(on_entry, in, out, err) == 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 14:41:08 -09:00
{
// 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 11:20:51 -08: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" : "");
// 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_python_interpreter->SetThreadState(PyThreadState_Get());
m_python_interpreter->IncrementLockCount();
return true;
}
bool
ScriptInterpreterPython::Locker::DoInitSession(uint16_t on_entry_flags, FILE *in, FILE *out, FILE *err)
{
if (!m_python_interpreter)
return false;
return m_python_interpreter->EnterSession (on_entry_flags, in, out, err);
}
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);
m_python_interpreter->DecrementLockCount();
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 11:20:51 -08: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 14:41:08 -09: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 11:20:51 -08:00
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
ScriptInterpreterPython::ScriptInterpreterPython(CommandInterpreter &interpreter) :
ScriptInterpreter(interpreter, eScriptLanguagePython),
IOHandlerDelegateMultiline("DONE"),
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
m_saved_stdin(),
m_saved_stdout(),
m_saved_stderr(),
m_main_module(),
m_lldb_module(),
m_session_dict(PyInitialValue::Invalid),
m_sys_module_dict(PyInitialValue::Invalid),
m_run_one_line_function(),
m_run_one_line_str_global(),
m_dictionary_name(interpreter.GetDebugger().GetInstanceName().AsCString()),
m_terminal_state(),
m_active_io_handler(eIOHandlerNone),
m_session_is_active(false),
m_pty_slave_is_open(false),
m_valid_session(true),
m_lock_count(0),
m_command_thread_state(nullptr)
{
assert(g_initialized && "ScriptInterpreterPython created but InitializePrivate has not been called!");
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();
run_string.Printf ("run_one_line (%s, 'import copy, keyword, 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());
run_string.Clear();
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-01-31 23:09:32 -09:00
run_string.Printf ("run_one_line (%s, 'import lldb.embedded_interpreter; from lldb.embedded_interpreter import run_python_interpreter; from lldb.embedded_interpreter import run_one_line')", m_dictionary_name.c_str());
PyRun_SimpleString (run_string.GetData());
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());
}
ScriptInterpreterPython::~ScriptInterpreterPython ()
{
// the session dictionary may hold objects with complex state
// which means that they may need to be torn down with some level of smarts
// and that, in turn, requires a valid thread state
// force Python to procure itself such a thread state, nuke the session dictionary
// and then release it for others to use and proceed with the rest of the shutdown
auto gil_state = PyGILState_Ensure();
m_session_dict.Reset();
PyGILState_Release(gil_state);
}
void
ScriptInterpreterPython::Initialize()
{
static std::once_flag g_once_flag;
std::call_once(g_once_flag, []()
{
InitializePrivate();
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(),
lldb::eScriptLanguagePython,
CreateInstance);
});
}
void
ScriptInterpreterPython::Terminate()
{
}
lldb::ScriptInterpreterSP
ScriptInterpreterPython::CreateInstance(CommandInterpreter &interpreter)
{
return std::make_shared<ScriptInterpreterPython>(interpreter);
}
lldb_private::ConstString
ScriptInterpreterPython::GetPluginNameStatic()
{
static ConstString g_name("script-python");
return g_name;
}
const char *
ScriptInterpreterPython::GetPluginDescriptionStatic()
{
return "Embedded Python interpreter";
}
lldb_private::ConstString
ScriptInterpreterPython::GetPluginName()
{
return GetPluginNameStatic();
}
uint32_t
ScriptInterpreterPython::GetPluginVersion()
{
return 1;
}
void
ScriptInterpreterPython::IOHandlerActivated (IOHandler &io_handler)
{
const char *instructions = nullptr;
switch (m_active_io_handler)
{
case eIOHandlerNone:
break;
case eIOHandlerBreakpoint:
instructions = R"(Enter your Python command(s). Type 'DONE' to end.
def function (frame, bp_loc, internal_dict):
"""frame: the lldb.SBFrame for the location at which you stopped
bp_loc: an lldb.SBBreakpointLocation for the breakpoint location information
internal_dict: an LLDB support object not to be used"""
)";
break;
case eIOHandlerWatchpoint:
instructions = "Enter your Python command(s). Type 'DONE' to end.\n";
break;
}
if (instructions)
{
StreamFileSP output_sp(io_handler.GetOutputStreamFile());
if (output_sp)
{
output_sp->PutCString(instructions);
output_sp->Flush();
}
}
}
void
ScriptInterpreterPython::IOHandlerInputComplete (IOHandler &io_handler, std::string &data)
{
io_handler.SetIsDone(true);
bool batch_mode = m_interpreter.GetBatchCommandMode();
switch (m_active_io_handler)
{
case eIOHandlerNone:
break;
case eIOHandlerBreakpoint:
{
std::vector<BreakpointOptions *> *bp_options_vec = (std::vector<BreakpointOptions *> *)io_handler.GetUserData();
for (auto bp_options : *bp_options_vec)
{
if (!bp_options)
continue;
std::unique_ptr<BreakpointOptions::CommandData> data_ap(new BreakpointOptions::CommandData());
if (data_ap.get())
{
data_ap->user_source.SplitIntoLines(data);
if (GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source).Success())
{
BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
}
else if (!batch_mode)
{
StreamFileSP error_sp = io_handler.GetErrorStreamFile();
if (error_sp)
{
error_sp->Printf ("Warning: No command attached to breakpoint.\n");
error_sp->Flush();
}
}
}
}
m_active_io_handler = eIOHandlerNone;
}
break;
case eIOHandlerWatchpoint:
{
WatchpointOptions *wp_options = (WatchpointOptions *)io_handler.GetUserData();
std::unique_ptr<WatchpointOptions::CommandData> data_ap(new WatchpointOptions::CommandData());
if (data_ap.get())
{
data_ap->user_source.SplitIntoLines(data);
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);
}
else if (!batch_mode)
{
StreamFileSP error_sp = io_handler.GetErrorStreamFile();
if (error_sp)
{
error_sp->Printf ("Warning: No command attached to breakpoint.\n");
error_sp->Flush();
}
}
}
m_active_io_handler = eIOHandlerNone;
}
break;
}
}
void
ScriptInterpreterPython::ResetOutputFileHandle (FILE *fh)
{
}
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 14:41:08 -09: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())
{
PythonDictionary &sys_module_dict = GetSysModuleDictionary ();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (sys_module_dict.IsValid())
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (m_saved_stdin.IsValid())
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin);
m_saved_stdin.Reset ();
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (m_saved_stdout.IsValid())
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout);
m_saved_stdout.Reset ();
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (m_saved_stderr.IsValid())
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr);
m_saved_stderr.Reset ();
}
}
}
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 14:41:08 -09:00
bool
ScriptInterpreterPython::EnterSession (uint16_t on_entry_flags,
FILE *in,
FILE *out,
FILE *err)
{
// 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 14:41:08 -09:00
{
if (log)
log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ") session is already active, returning without doing anything", on_entry_flags);
<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 14:41:08 -09:00
return false;
}
if (log)
log->Printf("ScriptInterpreterPython::EnterSession(on_entry_flags=0x%" PRIx16 ")", on_entry_flags);
<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 14:41:08 -09:00
m_session_is_active = true;
StreamString run_string;
if (on_entry_flags & Locker::InitGlobals)
{
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();
PythonDictionary &sys_module_dict = GetSysModuleDictionary ();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (sys_module_dict.IsValid())
{
File in_file(in, false);
File out_file(out, false);
File err_file(err, false);
lldb::StreamFileSP in_sp;
lldb::StreamFileSP out_sp;
lldb::StreamFileSP err_sp;
if (!in_file.IsValid() || !out_file.IsValid() || !err_file.IsValid())
m_interpreter.GetDebugger().AdoptTopIOHandlerFilesIfInvalid (in_sp, out_sp, err_sp);
m_saved_stdin.Reset();
if ((on_entry_flags & Locker::NoSTDIN) == 0)
{
// STDIN is enabled
if (!in_file.IsValid() && in_sp)
in_file = in_sp->GetFile();
if (in_file.IsValid())
{
// Flush the file before giving it to python to avoid interleaved output.
in_file.Flush();
m_saved_stdin = sys_module_dict.GetItemForKey(PythonString("stdin")).AsType<PythonFile>();
// This call can deadlock your process if the file is locked
PythonFile new_file(in_file, "r");
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
sys_module_dict.SetItemForKey (PythonString("stdin"), new_file);
}
}
if (!out_file.IsValid() && out_sp)
out_file = out_sp->GetFile();
if (out_file.IsValid())
{
// Flush the file before giving it to python to avoid interleaved output.
out_file.Flush();
m_saved_stdout = sys_module_dict.GetItemForKey(PythonString("stdout")).AsType<PythonFile>();
PythonFile new_file(out_file, "w");
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
sys_module_dict.SetItemForKey (PythonString("stdout"), new_file);
}
else
m_saved_stdout.Reset();
if (!err_file.IsValid() && err_sp)
err_file = err_sp->GetFile();
if (err_file.IsValid())
{
// Flush the file before giving it to python to avoid interleaved output.
err_file.Flush();
m_saved_stderr = sys_module_dict.GetItemForKey(PythonString("stderr")).AsType<PythonFile>();
PythonFile new_file(err_file, "w");
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
sys_module_dict.SetItemForKey (PythonString("stderr"), new_file);
}
else
m_saved_stderr.Reset();
}
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 14:41:08 -09:00
return true;
}
PythonObject &
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
ScriptInterpreterPython::GetMainModule()
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!m_main_module.IsValid())
m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__"));
return m_main_module;
}
PythonDictionary &
ScriptInterpreterPython::GetSessionDictionary ()
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (m_session_dict.IsValid())
return m_session_dict;
PythonObject &main_module = GetMainModule();
if (!main_module.IsValid())
return m_session_dict;
PythonDictionary main_dict(PyRefType::Borrowed, PyModule_GetDict(main_module.get()));
if (!main_dict.IsValid())
return m_session_dict;
PythonObject item = main_dict.GetItemForKey(PythonString(m_dictionary_name));
m_session_dict.Reset(PyRefType::Borrowed, item.get());
return m_session_dict;
}
PythonDictionary &
ScriptInterpreterPython::GetSysModuleDictionary ()
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (m_sys_module_dict.IsValid())
return m_sys_module_dict;
PythonObject sys_module(PyRefType::Borrowed, PyImport_AddModule("sys"));
if (sys_module.IsValid())
m_sys_module_dict.Reset(PyRefType::Borrowed, PyModule_GetDict(sys_module.get()));
return m_sys_module_dict;
}
static std::string
GenerateUniqueName (const char* base_name_wanted,
uint32_t& functions_counter,
const void* name_token = nullptr)
{
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::GetEmbeddedInterpreterModuleObjects ()
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (m_run_one_line_function.IsValid())
return true;
PythonObject module(PyRefType::Borrowed, PyImport_AddModule ("lldb.embedded_interpreter"));
if (!module.IsValid())
return false;
PythonDictionary module_dict(PyRefType::Borrowed, PyModule_GetDict(module.get()));
if (!module_dict.IsValid())
return false;
m_run_one_line_function = module_dict.GetItemForKey(PythonString("run_one_line"));
m_run_one_line_str_global = module_dict.GetItemForKey(PythonString("g_run_one_line_str"));
return m_run_one_line_function.IsValid();
}
static void
ReadThreadBytesReceived(void *baton, const void *src, size_t src_len)
{
if (src && src_len)
{
Stream *strm = (Stream *)baton;
strm->Write(src, src_len);
strm->Flush();
}
}
bool
ScriptInterpreterPython::ExecuteOneLine (const char *command, CommandReturnObject *result, const ExecuteScriptOptions &options)
{
if (!m_valid_session)
return false;
if (command && command[0])
{
// 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.
Debugger &debugger = m_interpreter.GetDebugger();
StreamFileSP input_file_sp;
StreamFileSP output_file_sp;
StreamFileSP error_file_sp;
Communication output_comm ("lldb.ScriptInterpreterPython.ExecuteOneLine.comm");
bool join_read_thread = false;
if (options.GetEnableIO())
{
if (result)
{
input_file_sp = debugger.GetInputFile();
// Set output to a temporary file so we can forward the results on to the result object
Pipe pipe;
Error pipe_result = pipe.CreateNew(false);
if (pipe_result.Success())
{
#if defined(_WIN32)
lldb::file_t read_file = pipe.GetReadNativeHandle();
pipe.ReleaseReadFileDescriptor();
std::unique_ptr<ConnectionGenericFile> conn_ap(new ConnectionGenericFile(read_file, true));
#else
std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(), true));
#endif
if (conn_ap->IsConnected())
{
output_comm.SetConnection(conn_ap.release());
output_comm.SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived, &result->GetOutputStream());
output_comm.StartReadThread();
join_read_thread = true;
FILE *outfile_handle = fdopen (pipe.ReleaseWriteFileDescriptor(), "w");
output_file_sp.reset(new StreamFile(outfile_handle, true));
error_file_sp = output_file_sp;
if (outfile_handle)
::setbuf (outfile_handle, nullptr);
result->SetImmediateOutputFile(debugger.GetOutputFile()->GetFile().GetStream());
result->SetImmediateErrorFile(debugger.GetErrorFile()->GetFile().GetStream());
}
}
}
if (!input_file_sp || !output_file_sp || !error_file_sp)
debugger.AdoptTopIOHandlerFilesIfInvalid(input_file_sp, output_file_sp, error_file_sp);
}
else
{
input_file_sp.reset (new StreamFile ());
input_file_sp->GetFile().Open(FileSystem::DEV_NULL, File::eOpenOptionRead);
output_file_sp.reset (new StreamFile ());
output_file_sp->GetFile().Open(FileSystem::DEV_NULL, File::eOpenOptionWrite);
error_file_sp = output_file_sp;
}
FILE *in_file = input_file_sp->GetFile().GetStream();
FILE *out_file = output_file_sp->GetFile().GetStream();
FILE *err_file = error_file_sp->GetFile().GetStream();
bool success = false;
{
// WARNING! It's imperative that this RAII scope be as tight as possible. In particular, the
// scope must end *before* we try to join the read thread. The reason for this is that a
// pre-requisite for joining the read thread is that we close the write handle (to break the
// pipe and cause it to wake up and exit). But acquiring the GIL as below will redirect Python's
// stdio to use this same handle. If we close the handle while Python is still using it, bad
// things will happen.
Locker locker(this,
ScriptInterpreterPython::Locker::AcquireLock |
ScriptInterpreterPython::Locker::InitSession |
(options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) |
((result && result->GetInteractive()) ? 0: Locker::NoSTDIN),
ScriptInterpreterPython::Locker::FreeAcquiredLock |
ScriptInterpreterPython::Locker::TearDownSession,
in_file,
out_file,
err_file);
// Find the correct script interpreter dictionary in the main module.
PythonDictionary &session_dict = GetSessionDictionary ();
if (session_dict.IsValid())
{
if (GetEmbeddedInterpreterModuleObjects ())
{
if (PyCallable_Check(m_run_one_line_function.get()))
{
PythonObject pargs(PyRefType::Owned, Py_BuildValue("(Os)", session_dict.get(), command));
if (pargs.IsValid())
{
PythonObject return_value(PyRefType::Owned,
PyObject_CallObject(m_run_one_line_function.get(), pargs.get()));
if (return_value.IsValid())
success = true;
else if (options.GetMaskoutErrors() && PyErr_Occurred ())
{
PyErr_Print();
PyErr_Clear();
}
}
}
}
}
// Flush our output and error file handles
::fflush (out_file);
if (out_file != err_file)
::fflush (err_file);
}
if (join_read_thread)
{
// Close the write end of the pipe since we are done with our
// one line script. This should cause the read thread that
// output_comm is using to exit
output_file_sp->GetFile().Close();
// The close above should cause this thread to exit when it gets
// to the end of file, so let it get all its data
output_comm.JoinReadThread();
// Now we can close the read end of the pipe
output_comm.Disconnect();
}
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;
}
class IOHandlerPythonInterpreter :
public IOHandler
{
public:
IOHandlerPythonInterpreter (Debugger &debugger,
ScriptInterpreterPython *python) :
IOHandler (debugger, IOHandler::Type::PythonInterpreter),
m_python(python)
{
}
~IOHandlerPythonInterpreter() override
{
}
ConstString
GetControlSequence (char ch) override
{
if (ch == 'd')
return ConstString("quit()\n");
return ConstString();
}
void
Run () override
{
if (m_python)
{
int stdin_fd = GetInputFD();
if (stdin_fd >= 0)
{
Terminal terminal(stdin_fd);
TerminalState terminal_state;
const bool is_a_tty = terminal.IsATerminal();
if (is_a_tty)
{
terminal_state.Save (stdin_fd, false);
terminal.SetCanonical(false);
terminal.SetEcho(true);
}
ScriptInterpreterPython::Locker locker (m_python,
ScriptInterpreterPython::Locker::AcquireLock |
ScriptInterpreterPython::Locker::InitSession |
ScriptInterpreterPython::Locker::InitGlobals,
ScriptInterpreterPython::Locker::FreeAcquiredLock |
ScriptInterpreterPython::Locker::TearDownSession);
// 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).
StreamString run_string;
run_string.Printf ("run_python_interpreter (%s)", m_python->GetDictionaryName ());
PyRun_SimpleString (run_string.GetData());
if (is_a_tty)
terminal_state.Restore();
}
}
SetIsDone(true);
}
void
Cancel () override
{
}
bool
Interrupt () override
{
return m_python->Interrupt();
}
void
GotEOF() override
{
}
protected:
ScriptInterpreterPython *m_python;
};
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()->GetFile().IsValid())
return;
IOHandlerSP io_handler_sp (new IOHandlerPythonInterpreter (debugger, this));
if (io_handler_sp)
{
debugger.PushIOHandler(io_handler_sp);
}
}
bool
ScriptInterpreterPython::Interrupt()
{
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SCRIPT));
if (IsExecutingPython())
{
PyThreadState *state = PyThreadState_Get();
if (!state)
state = GetThreadState();
if (state)
{
long tid = state->thread_id;
PyThreadState_Swap(state);
int num_threads = PyThreadState_SetAsyncExc(tid, PyExc_KeyboardInterrupt);
if (log)
log->Printf("ScriptInterpreterPython::Interrupt() sending PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...", tid, num_threads);
return true;
}
}
if (log)
log->Printf("ScriptInterpreterPython::Interrupt() python code not running, can't interrupt");
return false;
}
bool
ScriptInterpreterPython::ExecuteOneLineWithReturn (const char *in_string,
ScriptInterpreter::ScriptReturnType return_type,
void *ret_value,
const ExecuteScriptOptions &options)
{
Locker locker(this,
ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN,
<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 14:41:08 -09:00
ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject py_return;
PythonObject &main_module = GetMainModule();
PythonDictionary globals(PyRefType::Borrowed, PyModule_GetDict(main_module.get()));
PythonObject py_error;
bool ret_success = false;
int success;
PythonDictionary locals = GetSessionDictionary ();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!locals.IsValid())
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
locals.Reset(PyRefType::Owned, PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!locals.IsValid())
locals = globals;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
if (py_error.IsValid())
PyErr_Clear();
if (in_string != nullptr)
{
{ // scope for PythonInputReaderManager
//PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
py_return.Reset(PyRefType::Owned, PyRun_String(in_string, Py_eval_input, globals.get(), locals.get()));
if (!py_return.IsValid())
{
py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
if (py_error.IsValid())
PyErr_Clear();
py_return.Reset(PyRefType::Owned, PyRun_String(in_string, Py_single_input, globals.get(), locals.get()));
}
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (py_return.IsValid())
{
switch (return_type)
{
case eScriptReturnTypeCharPtr: // "char *"
{
const char format[3] = "s#";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (char **) ret_value);
break;
}
case eScriptReturnTypeCharStrOrNone: // char* or NULL if py_return == Py_None
{
const char format[3] = "z";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (char **) ret_value);
break;
}
case eScriptReturnTypeBool:
{
const char format[2] = "b";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (bool *) ret_value);
break;
}
case eScriptReturnTypeShortInt:
{
const char format[2] = "h";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (short *) ret_value);
break;
}
case eScriptReturnTypeShortIntUnsigned:
{
const char format[2] = "H";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (unsigned short *) ret_value);
break;
}
case eScriptReturnTypeInt:
{
const char format[2] = "i";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (int *) ret_value);
break;
}
case eScriptReturnTypeIntUnsigned:
{
const char format[2] = "I";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (unsigned int *) ret_value);
break;
}
case eScriptReturnTypeLongInt:
{
const char format[2] = "l";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (long *) ret_value);
break;
}
case eScriptReturnTypeLongIntUnsigned:
{
const char format[2] = "k";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (unsigned long *) ret_value);
break;
}
case eScriptReturnTypeLongLong:
{
const char format[2] = "L";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (long long *) ret_value);
break;
}
case eScriptReturnTypeLongLongUnsigned:
{
const char format[2] = "K";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (unsigned long long *) ret_value);
break;
}
case eScriptReturnTypeFloat:
{
const char format[2] = "f";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (float *) ret_value);
break;
}
case eScriptReturnTypeDouble:
{
const char format[2] = "d";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (double *) ret_value);
break;
}
case eScriptReturnTypeChar:
{
const char format[2] = "c";
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
success = PyArg_Parse (py_return.get(), format, (char *) ret_value);
break;
}
case eScriptReturnTypeOpaqueObject:
{
success = true;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PyObject *saved_value = py_return.get();
Py_XINCREF(saved_value);
*((PyObject **)ret_value) = saved_value;
break;
}
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (success)
ret_success = true;
else
ret_success = false;
}
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
if (py_error.IsValid())
{
ret_success = false;
if (options.GetMaskoutErrors())
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (PyErr_GivenExceptionMatches (py_error.get(), PyExc_SyntaxError))
PyErr_Print ();
PyErr_Clear();
}
}
return ret_success;
}
Error
ScriptInterpreterPython::ExecuteMultipleLines (const char *in_string, const ExecuteScriptOptions &options)
{
Error error;
Locker locker(this,
ScriptInterpreterPython::Locker::AcquireLock | ScriptInterpreterPython::Locker::InitSession | (options.GetSetLLDBGlobals() ? ScriptInterpreterPython::Locker::InitGlobals : 0) | Locker::NoSTDIN,
<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 14:41:08 -09:00
ScriptInterpreterPython::Locker::FreeAcquiredLock | ScriptInterpreterPython::Locker::TearDownSession);
PythonObject return_value;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject &main_module = GetMainModule();
PythonDictionary globals(PyRefType::Borrowed, PyModule_GetDict(main_module.get()));
PythonObject py_error;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonDictionary locals = GetSessionDictionary();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!locals.IsValid())
locals.Reset(PyRefType::Owned, PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
if (!locals.IsValid())
locals = globals;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
if (py_error.IsValid())
PyErr_Clear();
if (in_string != nullptr)
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject code_object;
code_object.Reset(PyRefType::Owned, Py_CompileString(in_string, "temp.py", Py_file_input));
if (code_object.IsValid())
{
// In Python 2.x, PyEval_EvalCode takes a PyCodeObject, but in Python 3.x, it takes
// a PyObject. They are convertible (hence the function PyCode_Check(PyObject*), so
// we have to do the cast for Python 2.x
#if PY_MAJOR_VERSION >= 3
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PyObject *py_code_obj = code_object.get();
#else
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PyCodeObject *py_code_obj = reinterpret_cast<PyCodeObject *>(code_object.get());
#endif
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
return_value.Reset(PyRefType::Owned, PyEval_EvalCode(py_code_obj, globals.get(), locals.get()));
}
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
if (py_error.IsValid())
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
// puts(in_string);
// _PyObject_Dump (py_error);
// PyErr_Print();
// success = false;
PyObject *py_type = nullptr;
PyObject *py_value = nullptr;
PyObject *py_traceback = nullptr;
PyErr_Fetch(&py_type, &py_value, &py_traceback);
PythonObject type(PyRefType::Owned, py_type);
PythonObject value(PyRefType::Owned, py_value);
PythonObject traceback(PyRefType::Owned, py_traceback);
// get the backtrace
std::string bt = ReadPythonBacktrace(traceback);
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (value.IsAllocated())
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonString str = value.Str();
llvm::StringRef value_str(str.GetString());
error.SetErrorStringWithFormat("%s\n%s", value_str.str().c_str(), bt.c_str());
}
else
error.SetErrorStringWithFormat("%s",bt.c_str());
if (options.GetMaskoutErrors())
PyErr_Clear();
}
return error;
}
void
ScriptInterpreterPython::CollectDataForBreakpointCommandCallback (std::vector<BreakpointOptions *> &bp_options_vec,
CommandReturnObject &result)
{
m_active_io_handler = eIOHandlerBreakpoint;
m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, &bp_options_vec);
}
void
ScriptInterpreterPython::CollectDataForWatchpointCommandCallback (WatchpointOptions *wp_options,
CommandReturnObject &result)
{
m_active_io_handler = eIOHandlerWatchpoint;
m_interpreter.GetPythonCommandsFromIOHandler (" ", *this, true, wp_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 10:21:10 -08:00
void
ScriptInterpreterPython::SetBreakpointCommandCallbackFunction (BreakpointOptions *bp_options,
const char *function_name)
{
// For now just cons up a oneliner that calls the provided function.
std::string oneliner("return ");
oneliner += function_name;
oneliner += "(frame, bp_loc, internal_dict)";
m_interpreter.GetScriptInterpreter()->SetBreakpointCommandCallback (bp_options,
oneliner.c_str());
}
// Set a Python one-liner as the callback for the breakpoint.
Error
ScriptInterpreterPython::SetBreakpointCommandCallback (BreakpointOptions *bp_options,
const char *command_body_text)
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 10:21:10 -08:00
{
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 10:21:10 -08:00
// Split the command_body_text into lines, and pass that to GenerateBreakpointCommandCallbackData. That will
// wrap the body in an auto-generated function, and return the function name in script_source. That is what
// the callback will actually invoke.
data_ap->user_source.SplitIntoLines(command_body_text);
Error error = GenerateBreakpointCommandCallbackData (data_ap->user_source, data_ap->script_source);
if (error.Success())
{
BatonSP baton_sp (new BreakpointOptions::CommandBaton (data_ap.release()));
bp_options->SetCallback (ScriptInterpreterPython::BreakpointCallbackFunction, baton_sp);
return error;
}
else
return error;
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 10:21:10 -08:00
}
// 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;
}
Error
ScriptInterpreterPython::ExportFunctionDefinitionToInterpreter (StringList &function_def)
{
// Convert StringList to one long, newline delimited, const char *.
std::string function_def_string(function_def.CopyList());
Error error = ExecuteMultipleLines (function_def_string.c_str(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false));
return error;
}
Error
ScriptInterpreterPython::GenerateFunction(const char *signature, const StringList &input)
{
Error error;
int num_lines = input.GetSize ();
if (num_lines == 0)
{
error.SetErrorString ("No input data.");
return error;
}
if (!signature || *signature == 0)
{
error.SetErrorString("No output function name.");
return error;
}
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.
error = ExportFunctionDefinitionToInterpreter (auto_generated_function);
return error;
}
bool
ScriptInterpreterPython::GenerateTypeScriptFunction (StringList &user_input, std::string& output, const 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).Success())
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).Success())
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, const 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).Success())
return false;
// Store the name of the auto-generated class
output.assign(auto_generated_class_name);
return true;
}
StructuredData::GenericSP
ScriptInterpreterPython::OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp)
{
if (class_name == nullptr || class_name[0] == '\0')
return StructuredData::GenericSP();
if (!process_sp)
return StructuredData::GenericSP();
void* ret_val;
{
Locker py_lock (this,
Locker::AcquireLock | Locker::NoSTDIN,
Locker::FreeLock);
ret_val = g_swig_create_os_plugin (class_name,
m_dictionary_name.c_str(),
process_sp);
}
return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
}
StructuredData::DictionarySP
ScriptInterpreterPython::OSPlugin_RegisterInfo(StructuredData::ObjectSP os_plugin_object_sp)
{
Locker py_lock(this,
Locker::AcquireLock | Locker::NoSTDIN,
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 14:41:08 -09:00
if (!os_plugin_object_sp)
return StructuredData::DictionarySP();
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
if (!generic)
return nullptr;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!implementor.IsAllocated())
return StructuredData::DictionarySP();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
if (PyErr_Occurred())
PyErr_Clear();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!pmeth.IsAllocated())
return StructuredData::DictionarySP();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
PyErr_Clear();
return StructuredData::DictionarySP();
}
if (PyErr_Occurred())
PyErr_Clear();
// right now we know this function exists and is callable..
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
assert(PythonDictionary::Check(py_return.get()) && "get_register_info returned unknown object type!");
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
return result_dict.CreateStructuredDictionary();
}
StructuredData::ArraySP
ScriptInterpreterPython::OSPlugin_ThreadsInfo(StructuredData::ObjectSP os_plugin_object_sp)
{
Locker py_lock (this,
Locker::AcquireLock | Locker::NoSTDIN,
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 14:41:08 -09:00
if (!os_plugin_object_sp)
return StructuredData::ArraySP();
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
if (!generic)
return nullptr;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
if (!implementor.IsAllocated())
return StructuredData::ArraySP();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
if (PyErr_Occurred())
PyErr_Clear();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!pmeth.IsAllocated())
return StructuredData::ArraySP();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
PyErr_Clear();
return StructuredData::ArraySP();
}
if (PyErr_Occurred())
PyErr_Clear();
// right now we know this function exists and is callable..
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
assert(PythonList::Check(py_return.get()) && "get_thread_info returned unknown object type!");
PythonList result_list(PyRefType::Borrowed, py_return.get());
return result_list.CreateStructuredArray();
}
<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 14:41:08 -09: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 nullptr;
<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 14:41:08 -09:00
}
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"; }
StructuredData::StringSP
ScriptInterpreterPython::OSPlugin_RegisterContextData(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid)
{
Locker py_lock (this,
Locker::AcquireLock | Locker::NoSTDIN,
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 14:41:08 -09: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 14:41:08 -09:00
if (!os_plugin_object_sp)
return StructuredData::StringSP();
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
if (!generic)
return nullptr;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!implementor.IsAllocated())
return StructuredData::StringSP();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
if (PyErr_Occurred())
PyErr_Clear();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!pmeth.IsAllocated())
return StructuredData::StringSP();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
PyErr_Clear();
return StructuredData::StringSP();
}
if (PyErr_Occurred())
PyErr_Clear();
// right now we know this function exists and is callable..
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, param_format, 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 14:41:08 -09:00
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
assert(PythonString::Check(py_return.get()) && "get_register_data returned unknown object type!");
PythonString result_string(PyRefType::Borrowed, py_return.get());
return result_string.CreateStructuredString();
<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 14:41:08 -09:00
}
StructuredData::DictionarySP
ScriptInterpreterPython::OSPlugin_CreateThread(StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid, lldb::addr_t context)
<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 14:41:08 -09:00
{
Locker py_lock(this,
Locker::AcquireLock | Locker::NoSTDIN,
Locker::FreeLock);
<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 14:41:08 -09:00
static char callee_name[] = "create_thread";
std::string param_format;
param_format += GetPythonValueFormatString(tid);
param_format += GetPythonValueFormatString(context);
if (!os_plugin_object_sp)
return StructuredData::DictionarySP();
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
if (!generic)
return nullptr;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue());
if (!implementor.IsAllocated())
return StructuredData::DictionarySP();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
<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 14:41:08 -09:00
if (PyErr_Occurred())
PyErr_Clear();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!pmeth.IsAllocated())
return StructuredData::DictionarySP();
<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 14:41:08 -09:00
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (PyCallable_Check(pmeth.get()) == 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 14:41:08 -09:00
{
if (PyErr_Occurred())
PyErr_Clear();
return StructuredData::DictionarySP();
<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 14:41:08 -09:00
}
if (PyErr_Occurred())
PyErr_Clear();
// right now we know this function exists and is callable..
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, &param_format[0], tid, context));
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
assert(PythonDictionary::Check(py_return.get()) && "create_thread returned unknown object type!");
PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
return result_dict.CreateStructuredDictionary();
}
StructuredData::ObjectSP
ScriptInterpreterPython::CreateScriptedThreadPlan(const char *class_name, lldb::ThreadPlanSP thread_plan_sp)
{
if (class_name == nullptr || class_name[0] == '\0')
return StructuredData::ObjectSP();
if (!thread_plan_sp.get())
return StructuredData::ObjectSP();
Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger();
ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
ScriptInterpreterPython *python_interpreter = static_cast<ScriptInterpreterPython *>(script_interpreter);
if (!script_interpreter)
return StructuredData::ObjectSP();
void* ret_val;
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_thread_plan_script (class_name,
python_interpreter->m_dictionary_name.c_str(),
thread_plan_sp);
}
return StructuredData::ObjectSP(new StructuredPythonObject(ret_val));
}
bool
ScriptInterpreterPython::ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error)
{
bool explains_stop = true;
StructuredData::Generic *generic = nullptr;
if (implementor_sp)
generic = implementor_sp->GetAsGeneric();
if (generic)
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
explains_stop = g_swig_call_thread_plan(generic->GetValue(), "explains_stop", event, script_error);
if (script_error)
return true;
}
return explains_stop;
}
bool
ScriptInterpreterPython::ScriptedThreadPlanShouldStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error)
{
bool should_stop = true;
StructuredData::Generic *generic = nullptr;
if (implementor_sp)
generic = implementor_sp->GetAsGeneric();
if (generic)
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
should_stop = g_swig_call_thread_plan(generic->GetValue(), "should_stop", event, script_error);
if (script_error)
return true;
}
return should_stop;
}
lldb::StateType
ScriptInterpreterPython::ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error)
{
bool should_step = false;
StructuredData::Generic *generic = nullptr;
if (implementor_sp)
generic = implementor_sp->GetAsGeneric();
if (generic)
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
should_step = g_swig_call_thread_plan(generic->GetValue(), "should_step", NULL, script_error);
if (script_error)
should_step = true;
}
if (should_step)
return lldb::eStateStepping;
else
return lldb::eStateRunning;
}
StructuredData::ObjectSP
ScriptInterpreterPython::LoadPluginModule(const FileSpec &file_spec, lldb_private::Error &error)
{
if (!file_spec.Exists())
{
error.SetErrorString("no such file");
return StructuredData::ObjectSP();
}
StructuredData::ObjectSP module_sp;
if (LoadScriptingModule(file_spec.GetPath().c_str(),true,true,error,&module_sp))
return module_sp;
return StructuredData::ObjectSP();
}
StructuredData::DictionarySP
ScriptInterpreterPython::GetDynamicSettings(StructuredData::ObjectSP plugin_module_sp, Target *target, const char *setting_name,
lldb_private::Error &error)
{
if (!plugin_module_sp || !target || !setting_name || !setting_name[0] || !g_swig_plugin_get)
return StructuredData::DictionarySP();
StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric();
if (!generic)
return StructuredData::DictionarySP();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject reply_pyobj;
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
TargetSP target_sp(target->shared_from_this());
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
reply_pyobj.Reset(PyRefType::Owned,
(PyObject *)g_swig_plugin_get(generic->GetValue(), setting_name, target_sp));
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get());
return py_dict.CreateStructuredDictionary();
}
StructuredData::ObjectSP
ScriptInterpreterPython::CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj)
{
if (class_name == nullptr || class_name[0] == '\0')
return StructuredData::ObjectSP();
if (!valobj.get())
return StructuredData::ObjectSP();
ExecutionContext exe_ctx (valobj->GetExecutionContextRef());
Target *target = exe_ctx.GetTargetPtr();
if (!target)
return StructuredData::ObjectSP();
Debugger &debugger = target->GetDebugger();
ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter();
ScriptInterpreterPython *python_interpreter = (ScriptInterpreterPython *) script_interpreter;
if (!script_interpreter)
return StructuredData::ObjectSP();
void *ret_val = nullptr;
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_synthetic_script (class_name,
python_interpreter->m_dictionary_name.c_str(),
valobj);
}
return StructuredData::ObjectSP(new StructuredPythonObject(ret_val));
}
StructuredData::GenericSP
ScriptInterpreterPython::CreateScriptCommandObject (const char *class_name)
{
DebuggerSP debugger_sp(GetCommandInterpreter().GetDebugger().shared_from_this());
if (class_name == nullptr || class_name[0] == '\0')
return StructuredData::GenericSP();
if (!debugger_sp.get())
return StructuredData::GenericSP();
void* ret_val;
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_create_cmd (class_name,
m_dictionary_name.c_str(),
debugger_sp);
}
return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
}
bool
ScriptInterpreterPython::GenerateTypeScriptFunction (const char* oneliner, std::string& output, const 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, const void* name_token)
{
StringList input;
input.SplitIntoLines(oneliner, strlen(oneliner));
return GenerateTypeSynthClass(input, output, name_token);
}
Error
ScriptInterpreterPython::GenerateBreakpointCommandCallbackData (StringList &user_input, std::string& output)
{
static uint32_t num_created_functions = 0;
user_input.RemoveBlankLines ();
StreamString sstr;
Error error;
if (user_input.GetSize() == 0)
{
error.SetErrorString("No input data.");
return error;
}
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());
error = GenerateFunction(sstr.GetData(), user_input);
if (!error.Success())
return error;
// Store the name of the auto-generated function to be called.
output.assign(auto_generated_function_name);
return error;
}
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).Success())
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,
StructuredData::ObjectSP &callee_wrapper_sp, const TypeSummaryOptions &options,
std::string &retval)
{
Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
if (!valobj.get())
{
retval.assign("<no object>");
return false;
}
void *old_callee = nullptr;
StructuredData::Generic *generic = nullptr;
if (callee_wrapper_sp)
{
generic = callee_wrapper_sp->GetAsGeneric();
if (generic)
old_callee = generic->GetValue();
}
void* new_callee = old_callee;
bool ret_val;
if (python_function_name && *python_function_name)
{
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
{
TypeSummaryOptionsSP options_sp(new TypeSummaryOptions(options));
Timer scoped_timer ("g_swig_typescript_callback","g_swig_typescript_callback");
ret_val = g_swig_typescript_callback (python_function_name,
GetSessionDictionary().get(),
valobj,
&new_callee,
options_sp,
retval);
}
}
}
else
{
retval.assign("<no function name>");
return false;
}
if (new_callee && old_callee != new_callee)
callee_wrapper_sp.reset(new StructuredPythonObject(new_callee));
return ret_val;
}
void
ScriptInterpreterPython::Clear ()
{
// Release any global variables that might have strong references to
// LLDB objects when clearing the python script interpreter.
Locker locker(this,
ScriptInterpreterPython::Locker::AcquireLock,
ScriptInterpreterPython::Locker::FreeAcquiredLock);
// This may be called as part of Py_Finalize. In that case the modules are destroyed in random
// order and we can't guarantee that we can access these.
if (Py_IsInitialized())
PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process = None; lldb.thread = None; lldb.frame = None");
}
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 && python_function_name[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, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
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 && python_function_name[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, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
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;
}
size_t
ScriptInterpreterPython::CalculateNumChildren(const StructuredData::ObjectSP &implementor_sp)
{
if (!implementor_sp)
return 0;
StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
if (!generic)
return 0;
void *implementor = generic->GetValue();
if (!implementor)
return 0;
if (!g_swig_calc_children)
return 0;
size_t ret_val = 0;
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
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 11:20:51 -08:00
lldb::ValueObjectSP
ScriptInterpreterPython::GetChildAtIndex(const StructuredData::ObjectSP &implementor_sp, uint32_t idx)
{
if (!implementor_sp)
return lldb::ValueObjectSP();
StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
if (!generic)
return lldb::ValueObjectSP();
void *implementor = generic->GetValue();
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 11:20:51 -08: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 11:20:51 -08: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 11:20:51 -08:00
lldb::ValueObjectSP ret_val;
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
void* child_ptr = g_swig_get_child_index (implementor,idx);
if (child_ptr != nullptr && child_ptr != Py_None)
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 11:20:51 -08:00
{
lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
if (sb_value_ptr == nullptr)
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 11:20:51 -08: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 11:20:51 -08:00
}
else
{
Py_XDECREF(child_ptr);
}
}
return ret_val;
}
int
ScriptInterpreterPython::GetIndexOfChildWithName(const StructuredData::ObjectSP &implementor_sp, const char *child_name)
{
if (!implementor_sp)
return UINT32_MAX;
StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
if (!generic)
return UINT32_MAX;
void *implementor = generic->GetValue();
if (!implementor)
return UINT32_MAX;
if (!g_swig_get_index_child)
return UINT32_MAX;
int ret_val = UINT32_MAX;
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_get_index_child (implementor, child_name);
}
return ret_val;
}
bool
ScriptInterpreterPython::UpdateSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp)
{
bool ret_val = false;
if (!implementor_sp)
return ret_val;
StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
if (!generic)
return ret_val;
void *implementor = generic->GetValue();
if (!implementor)
return ret_val;
if (!g_swig_update_provider)
return ret_val;
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_update_provider (implementor);
}
return ret_val;
}
bool
ScriptInterpreterPython::MightHaveChildrenSynthProviderInstance(const StructuredData::ObjectSP &implementor_sp)
{
bool ret_val = false;
if (!implementor_sp)
return ret_val;
StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
if (!generic)
return ret_val;
void *implementor = generic->GetValue();
if (!implementor)
return ret_val;
if (!g_swig_mighthavechildren_provider)
return ret_val;
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_mighthavechildren_provider (implementor);
}
return ret_val;
}
lldb::ValueObjectSP
ScriptInterpreterPython::GetSyntheticValue(const StructuredData::ObjectSP &implementor_sp)
{
lldb::ValueObjectSP ret_val(nullptr);
if (!implementor_sp)
return ret_val;
StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
if (!generic)
return ret_val;
void *implementor = generic->GetValue();
if (!implementor)
return ret_val;
if (!g_swig_getvalue_provider || !g_swig_cast_to_sbvalue || !g_swig_get_valobj_sp_from_sbvalue)
return ret_val;
{
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
void* child_ptr = g_swig_getvalue_provider (implementor);
if (child_ptr != nullptr && child_ptr != Py_None)
{
lldb::SBValue* sb_value_ptr = (lldb::SBValue*)g_swig_cast_to_sbvalue(child_ptr);
if (sb_value_ptr == nullptr)
Py_XDECREF(child_ptr);
else
ret_val = g_swig_get_valobj_sp_from_sbvalue (sb_value_ptr);
}
else
{
Py_XDECREF(child_ptr);
}
}
return ret_val;
}
static std::string
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
ReadPythonBacktrace(PythonObject py_backtrace)
{
PythonObject traceback_module;
PythonObject stringIO_module;
PythonObject stringIO_builder;
PythonObject stringIO_buffer;
PythonObject printTB;
PythonObject printTB_args;
PythonObject printTB_result;
PythonObject stringIO_getvalue;
PythonObject printTB_string;
std::string retval("backtrace unavailable");
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!py_backtrace.IsAllocated())
return retval;
traceback_module.Reset(PyRefType::Owned, PyImport_ImportModule("traceback"));
stringIO_module.Reset(PyRefType::Owned, PyImport_ImportModule("StringIO"));
if (!traceback_module.IsAllocated() || !stringIO_module.IsAllocated())
return retval;
stringIO_builder.Reset(PyRefType::Owned, PyObject_GetAttrString(stringIO_module.get(), "StringIO"));
if (!stringIO_builder.IsAllocated())
return retval;
stringIO_buffer.Reset(PyRefType::Owned, PyObject_CallObject(stringIO_builder.get(), nullptr));
if (!stringIO_buffer.IsAllocated())
return retval;
printTB.Reset(PyRefType::Owned, PyObject_GetAttrString(traceback_module.get(), "print_tb"));
if (!printTB.IsAllocated())
return retval;
printTB_args.Reset(PyRefType::Owned, Py_BuildValue("OOO", py_backtrace.get(), Py_None, stringIO_buffer.get()));
printTB_result.Reset(PyRefType::Owned, PyObject_CallObject(printTB.get(), printTB_args.get()));
stringIO_getvalue.Reset(PyRefType::Owned, PyObject_GetAttrString(stringIO_buffer.get(), "getvalue"));
if (!stringIO_getvalue.IsAllocated())
return retval;
printTB_string.Reset(PyRefType::Owned, PyObject_CallObject(stringIO_getvalue.get(), nullptr));
if (!printTB_string.IsAllocated())
return retval;
PythonString str(PyRefType::Borrowed, printTB_string.get());
llvm::StringRef string_data(str.GetString());
retval.assign(string_data.data(), string_data.size());
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, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
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, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
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, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
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, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
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;
}
bool
ScriptInterpreterPython::RunScriptFormatKeyword (const char* impl_function,
ValueObject *value,
std::string& output,
Error& error)
{
bool ret_val;
if (!value)
{
error.SetErrorString("no value");
return false;
}
if (!impl_function || !impl_function[0])
{
error.SetErrorString("no function to execute");
return false;
}
if (!g_swig_run_script_keyword_value)
{
error.SetErrorString("internal helper function missing");
return false;
}
{
ValueObjectSP value_sp(value->GetSP());
Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
ret_val = g_swig_run_script_keyword_value (impl_function, m_dictionary_name.c_str(), value_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,
StructuredData::ObjectSP *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::NoSTDIN,
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)).Success();
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;
// 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());
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
bool was_imported_locally = GetSessionDictionary().GetItemForKey(PythonString(basename)).IsAllocated();
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());
error = ExecuteMultipleLines(command_stream.GetData(), ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false).SetSetLLDBGlobals(false));
if (error.Fail())
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->reset(new StructuredPythonObject(module_pyobj));
}
return true;
}
}
bool
ScriptInterpreterPython::IsReservedWord (const char* word)
{
if (!word || !word[0])
return false;
llvm::StringRef word_sr(word);
// filter out a few characters that would just confuse us
// and that are clearly not keyword material anyway
if (word_sr.find_first_of("'\"") != llvm::StringRef::npos)
return false;
StreamString command_stream;
command_stream.Printf("keyword.iskeyword('%s')", word);
bool result;
ExecuteScriptOptions options;
options.SetEnableIO(false);
options.SetMaskoutErrors(true);
options.SetSetLLDBGlobals(false);
if (ExecuteOneLineWithReturn(command_stream.GetData(), ScriptInterpreter::eScriptReturnTypeBool, &result, options))
return result;
return false;
}
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,
const lldb_private::ExecutionContext& exe_ctx)
{
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();
lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));
if (!debugger_sp.get())
{
error.SetErrorString("invalid Debugger pointer");
return false;
}
bool ret_val = false;
std::string err_msg;
{
Locker py_lock(this,
Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
<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 14:41:08 -09:00
Locker::FreeLock | Locker::TearDownSession);
SynchronicityHandler synch_handler(debugger_sp,
synchronicity);
ret_val = g_swig_call_command (impl_function,
m_dictionary_name.c_str(),
debugger_sp,
args,
cmd_retobj,
exe_ctx_ref_sp);
}
if (!ret_val)
error.SetErrorString("unable to execute script function");
else
error.Clear();
return ret_val;
}
bool
ScriptInterpreterPython::RunScriptBasedCommand (StructuredData::GenericSP impl_obj_sp,
const char* args,
ScriptedCommandSynchronicity synchronicity,
lldb_private::CommandReturnObject& cmd_retobj,
Error& error,
const lldb_private::ExecutionContext& exe_ctx)
{
if (!impl_obj_sp || !impl_obj_sp->IsValid())
{
error.SetErrorString("no function to execute");
return false;
}
if (!g_swig_call_command_object)
{
error.SetErrorString("no helper function to run scripted commands");
return false;
}
lldb::DebuggerSP debugger_sp = m_interpreter.GetDebugger().shared_from_this();
lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));
if (!debugger_sp.get())
{
error.SetErrorString("invalid Debugger pointer");
return false;
}
bool ret_val = false;
std::string err_msg;
{
Locker py_lock(this,
Locker::AcquireLock | Locker::InitSession | (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
Locker::FreeLock | Locker::TearDownSession);
SynchronicityHandler synch_handler(debugger_sp,
synchronicity);
ret_val = g_swig_call_command_object (impl_obj_sp->GetValue(),
debugger_sp,
args,
cmd_retobj,
exe_ctx_ref_sp);
}
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 = nullptr; // 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 14:41:08 -09: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;
}
}
bool
ScriptInterpreterPython::GetShortHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp,
std::string& dest)
{
bool got_string = false;
dest.clear();
Locker py_lock (this,
Locker::AcquireLock | Locker::NoSTDIN,
Locker::FreeLock);
static char callee_name[] = "get_short_help";
if (!cmd_obj_sp)
return false;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue());
if (!implementor.IsAllocated())
return false;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
if (PyErr_Occurred())
PyErr_Clear();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!pmeth.IsAllocated())
return false;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
PyErr_Clear();
return false;
}
if (PyErr_Occurred())
PyErr_Clear();
// right now we know this function exists and is callable..
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (py_return.IsAllocated() && PythonString::Check(py_return.get()))
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonString py_string(PyRefType::Borrowed, py_return.get());
llvm::StringRef return_data(py_string.GetString());
dest.assign(return_data.data(), return_data.size());
got_string = true;
}
return got_string;
}
uint32_t
ScriptInterpreterPython::GetFlagsForCommandObject (StructuredData::GenericSP cmd_obj_sp)
{
uint32_t result = 0;
Locker py_lock (this,
Locker::AcquireLock | Locker::NoSTDIN,
Locker::FreeLock);
static char callee_name[] = "get_flags";
if (!cmd_obj_sp)
return result;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue());
if (!implementor.IsAllocated())
return result;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
if (PyErr_Occurred())
PyErr_Clear();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!pmeth.IsAllocated())
return result;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
PyErr_Clear();
return result;
}
if (PyErr_Occurred())
PyErr_Clear();
// right now we know this function exists and is callable..
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (py_return.IsAllocated() && PythonInteger::Check(py_return.get()))
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonInteger int_value(PyRefType::Borrowed, py_return.get());
result = int_value.GetInteger();
}
return result;
}
bool
ScriptInterpreterPython::GetLongHelpForCommandObject (StructuredData::GenericSP cmd_obj_sp,
std::string& dest)
{
bool got_string = false;
dest.clear();
Locker py_lock (this,
Locker::AcquireLock | Locker::NoSTDIN,
Locker::FreeLock);
static char callee_name[] = "get_long_help";
if (!cmd_obj_sp)
return false;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject implementor(PyRefType::Borrowed, (PyObject *)cmd_obj_sp->GetValue());
if (!implementor.IsAllocated())
return false;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject pmeth(PyRefType::Owned, PyObject_GetAttrString(implementor.get(), callee_name));
if (PyErr_Occurred())
PyErr_Clear();
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (!pmeth.IsAllocated())
return false;
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (PyCallable_Check(pmeth.get()) == 0)
{
if (PyErr_Occurred())
PyErr_Clear();
return false;
}
if (PyErr_Occurred())
PyErr_Clear();
// right now we know this function exists and is callable..
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonObject py_return(PyRefType::Owned, PyObject_CallMethod(implementor.get(), callee_name, nullptr));
// if it fails, print the error but otherwise go on
if (PyErr_Occurred())
{
PyErr_Print();
PyErr_Clear();
}
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
if (py_return.IsAllocated() && PythonString::Check(py_return.get()))
{
Fix ref counting of Python objects. PythonObjects were being incorrectly ref-counted. This problem was pervasive throughout the codebase, leading to an unknown number of memory leaks and potentially use-after-free. The issue stems from the fact that Python native methods can either return "borrowed" references or "owned" references. For the former category, you *must* incref it prior to decrefing it. And for the latter category, you should not incref it before decrefing it. This is mostly an issue when a Python C API method returns a `PyObject` to you, but it can also happen with a method accepts a `PyObject`. Notably, this happens in `PyList_SetItem`, which is documented to "steal" the reference that you give it. So if you pass something to `PyList_SetItem`, you cannot hold onto it unless you incref it first. But since this is one of only two exceptions in the entire API, it's confusing and difficult to remember. Our `PythonObject` class was indiscriminantely increfing every object it received, which means that if you passed it an owned reference, you now have a dangling reference since owned references should not be increfed. We were doing this in quite a few places. There was also a fair amount of manual increfing and decrefing prevalent throughout the codebase, which is easy to get wrong. This patch solves the problem by making any construction of a `PythonObject` from a `PyObject` take a flag which indicates whether it is an owned reference or a borrowed reference. There is no way to construct a `PythonObject` without this flag, and it does not offer a default value, forcing the user to make an explicit decision every time. All manual uses of `PyObject` have been cleaned up throughout the codebase and replaced with `PythonObject` in order to make RAII the predominant pattern when dealing with native Python objects. Differential Revision: http://reviews.llvm.org/D13617 Reviewed By: Greg Clayton llvm-svn: 250195
2015-10-13 10:16:15 -08:00
PythonString str(PyRefType::Borrowed, py_return.get());
llvm::StringRef str_data(str.GetString());
dest.assign(str_data.data(), str_data.size());
got_string = true;
}
return got_string;
}
std::unique_ptr<ScriptInterpreterLocker>
ScriptInterpreterPython::AcquireInterpreterLock ()
{
std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(this,
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
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,
SWIGPythonCreateCommandObject swig_create_cmd,
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,
SWIGPythonGetValueSynthProviderInstance swig_getvalue_provider,
SWIGPythonCallCommand swig_call_command,
SWIGPythonCallCommandObject swig_call_command_object,
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,
SWIGPythonScriptKeyword_Value swig_run_script_keyword_value,
SWIGPython_GetDynamicSetting swig_plugin_get,
SWIGPythonCreateScriptedThreadPlan swig_thread_plan_script,
SWIGPythonCallThreadPlan swig_call_thread_plan)
{
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_create_cmd = swig_create_cmd;
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_getvalue_provider = swig_getvalue_provider;
g_swig_call_command = swig_call_command;
g_swig_call_command_object = swig_call_command_object;
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_run_script_keyword_value = swig_run_script_keyword_value;
g_swig_plugin_get = swig_plugin_get;
g_swig_thread_plan_script = swig_thread_plan_script;
g_swig_call_thread_plan = swig_call_thread_plan;
}
void
ScriptInterpreterPython::InitializePrivate ()
{
assert(!g_initialized && "ScriptInterpreterPython::InitializePrivate() called more than once!");
g_initialized = true;
Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__);
// RAII-based initialization which correctly handles multiple-initialization, version-
// specific differences among Python 2 and Python 3, and saving and restoring various
// other pieces of state that can get mucked with during initialization.
InitializePythonRAII initialize_guard;
if (g_swig_init_callback)
g_swig_init_callback ();
// Update the path python uses to search for modules to include the current directory.
PyRun_SimpleString ("import sys");
AddToSysPath(AddLocation::End, ".");
FileSpec file_spec;
// Don't denormalize paths when calling file_spec.GetPath(). On platforms that use
// a backslash as the path separator, this will result in executing python code containing
// paths with unescaped backslashes. But Python also accepts forward slashes, so to make
// life easier we just use that.
if (HostInfo::GetLLDBPath(ePathTypePythonDir, file_spec))
AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
if (HostInfo::GetLLDBPath(ePathTypeLLDBShlibDir, file_spec))
AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
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");
}
void
ScriptInterpreterPython::AddToSysPath(AddLocation location, std::string path)
{
std::string path_copy;
std::string statement;
if (location == AddLocation::Beginning)
{
statement.assign("sys.path.insert(0,\"");
statement.append (path);
statement.append ("\")");
}
else
{
statement.assign("sys.path.append(\"");
statement.append(path);
statement.append("\")");
}
PyRun_SimpleString (statement.c_str());
}
//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