2010-06-08 08:52:24 -08:00
|
|
|
//===-- ScriptInterpreterPython.cpp -----------------------------*- C++ -*-===//
|
|
|
|
|
//
|
2019-01-18 23:50:56 -09:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2010-06-08 08:52:24 -08:00
|
|
|
//
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
2018-06-21 09:36:32 -08:00
|
|
|
#ifdef LLDB_DISABLE_PYTHON
|
|
|
|
|
|
|
|
|
|
// Python is disabled in this build
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
2016-08-19 12:44:07 -08:00
|
|
|
// LLDB Python header must be included first
|
2015-07-30 12:28:07 -08:00
|
|
|
#include "lldb-python.h"
|
2016-08-19 12:44:07 -08:00
|
|
|
|
2015-07-30 12:28:07 -08:00
|
|
|
#include "PythonDataObjects.h"
|
2015-11-12 16:24:52 -09:00
|
|
|
#include "PythonExceptionState.h"
|
2019-03-29 12:17:20 -08:00
|
|
|
#include "ScriptInterpreterPythonImpl.h"
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2018-10-30 20:00:22 -08:00
|
|
|
#include "lldb/API/SBFrame.h"
|
2019-03-29 12:17:20 -08:00
|
|
|
#include "lldb/API/SBValue.h"
|
2010-06-22 17:19:29 -08:00
|
|
|
#include "lldb/Breakpoint/StoppointCallbackContext.h"
|
2012-08-09 15:09:42 -08:00
|
|
|
#include "lldb/Breakpoint/WatchpointOptions.h"
|
2014-01-27 14:43:24 -09:00
|
|
|
#include "lldb/Core/Communication.h"
|
2010-06-08 08:52:24 -08:00
|
|
|
#include "lldb/Core/Debugger.h"
|
2015-07-30 12:28:07 -08:00
|
|
|
#include "lldb/Core/PluginManager.h"
|
2015-03-03 14:11:11 -09:00
|
|
|
#include "lldb/Core/ValueObject.h"
|
|
|
|
|
#include "lldb/DataFormatters/TypeSummary.h"
|
2014-10-06 13:22:36 -08:00
|
|
|
#include "lldb/Host/ConnectionFileDescriptor.h"
|
2015-10-14 13:37:36 -08:00
|
|
|
#include "lldb/Host/FileSystem.h"
|
2014-08-21 09:29:12 -08:00
|
|
|
#include "lldb/Host/HostInfo.h"
|
2014-07-02 13:10:39 -08:00
|
|
|
#include "lldb/Host/Pipe.h"
|
2010-06-08 08:52:24 -08:00
|
|
|
#include "lldb/Interpreter/CommandInterpreter.h"
|
|
|
|
|
#include "lldb/Interpreter/CommandReturnObject.h"
|
2010-10-07 09:14:24 -08:00
|
|
|
#include "lldb/Target/Thread.h"
|
2014-09-29 15:17:18 -08:00
|
|
|
#include "lldb/Target/ThreadPlan.h"
|
2017-06-29 06:32:17 -08:00
|
|
|
#include "lldb/Utility/Timer.h"
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2014-10-08 12:38:41 -08:00
|
|
|
#if defined(_WIN32)
|
|
|
|
|
#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
Port native Python-API to 3.x
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x. This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes. Primarily, these are:
1) PyString doesn't exist in Python 3. Everything is a PyUnicode.
To account for this, PythonString now stores a PyBytes instead
of a PyString. In Python 2, this is equivalent to a PyUnicode,
and in Python 3, we do a conversion from PyUnicode to PyBytes
and store the PyBytes.
2) PyInt doesn't exist in Python 3. Everything is a PyLong. To
account for this, PythonInteger stores a PyLong instead of a
PyInt. In Python 2.x, this requires doing a conversion to
PyLong when creating a PythonInteger from a PyInt. In 3.x,
there is no PyInt anyway, so we can assume everything is a
PyLong.
3) PyFile_FromFile doesn't exist in Python 3. Instead there is a
PyFile_FromFd. This is not addressed in this patch because it
will require quite a large change to plumb fd's all the way
through the system into the ScriptInterpreter. This is the only
remaining piece of the puzzle to get LLDB supporting Python 3.x.
Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.
llvm-svn: 249886
2015-10-09 11:45:41 -08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2016-09-06 12:57:50 -08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
2017-03-08 08:56:08 -09:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
2015-06-15 15:12:29 -08:00
|
|
|
|
2019-03-27 13:45:11 -08:00
|
|
|
#include <memory>
|
|
|
|
|
#include <mutex>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string>
|
|
|
|
|
|
2010-06-08 08:52:24 -08:00
|
|
|
using namespace lldb;
|
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
|
2019-03-25 12:14:31 -08:00
|
|
|
// Defined in the SWIG source file
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
extern "C" PyObject *PyInit__lldb(void);
|
|
|
|
|
|
|
|
|
|
#define LLDBSwigPyInit PyInit__lldb
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
extern "C" void init_lldb(void);
|
|
|
|
|
|
|
|
|
|
#define LLDBSwigPyInit init_lldb
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-03-26 13:57:02 -08:00
|
|
|
// These prototypes are the Pythonic implementations of the required callbacks.
|
|
|
|
|
// Although these are scripting-language specific, their definition depends on
|
|
|
|
|
// the public API.
|
2019-03-25 12:14:31 -08:00
|
|
|
extern "C" bool LLDBSwigPythonBreakpointCallbackFunction(
|
|
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
const lldb::StackFrameSP &sb_frame,
|
|
|
|
|
const lldb::BreakpointLocationSP &sb_bp_loc);
|
|
|
|
|
|
|
|
|
|
extern "C" bool LLDBSwigPythonWatchpointCallbackFunction(
|
|
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
const lldb::StackFrameSP &sb_frame, const lldb::WatchpointSP &sb_wp);
|
|
|
|
|
|
|
|
|
|
extern "C" bool LLDBSwigPythonCallTypeScript(
|
|
|
|
|
const char *python_function_name, void *session_dictionary,
|
|
|
|
|
const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper,
|
|
|
|
|
const lldb::TypeSummaryOptionsSP &options_sp, std::string &retval);
|
|
|
|
|
|
|
|
|
|
extern "C" void *
|
|
|
|
|
LLDBSwigPythonCreateSyntheticProvider(const char *python_class_name,
|
|
|
|
|
const char *session_dictionary_name,
|
|
|
|
|
const lldb::ValueObjectSP &valobj_sp);
|
|
|
|
|
|
|
|
|
|
extern "C" void *
|
|
|
|
|
LLDBSwigPythonCreateCommandObject(const char *python_class_name,
|
|
|
|
|
const char *session_dictionary_name,
|
|
|
|
|
const lldb::DebuggerSP debugger_sp);
|
|
|
|
|
|
|
|
|
|
extern "C" void *LLDBSwigPythonCreateScriptedThreadPlan(
|
|
|
|
|
const char *python_class_name, const char *session_dictionary_name,
|
|
|
|
|
const lldb::ThreadPlanSP &thread_plan_sp);
|
|
|
|
|
|
|
|
|
|
extern "C" bool LLDBSWIGPythonCallThreadPlan(void *implementor,
|
|
|
|
|
const char *method_name,
|
|
|
|
|
Event *event_sp, bool &got_error);
|
|
|
|
|
|
|
|
|
|
extern "C" void *LLDBSwigPythonCreateScriptedBreakpointResolver(
|
|
|
|
|
const char *python_class_name, const char *session_dictionary_name,
|
|
|
|
|
lldb_private::StructuredDataImpl *args, lldb::BreakpointSP &bkpt_sp);
|
|
|
|
|
|
|
|
|
|
extern "C" unsigned int
|
|
|
|
|
LLDBSwigPythonCallBreakpointResolver(void *implementor, const char *method_name,
|
|
|
|
|
lldb_private::SymbolContext *sym_ctx);
|
|
|
|
|
|
|
|
|
|
extern "C" size_t LLDBSwigPython_CalculateNumChildren(void *implementor,
|
|
|
|
|
uint32_t max);
|
|
|
|
|
|
|
|
|
|
extern "C" void *LLDBSwigPython_GetChildAtIndex(void *implementor,
|
|
|
|
|
uint32_t idx);
|
|
|
|
|
|
|
|
|
|
extern "C" int LLDBSwigPython_GetIndexOfChildWithName(void *implementor,
|
|
|
|
|
const char *child_name);
|
|
|
|
|
|
|
|
|
|
extern "C" void *LLDBSWIGPython_CastPyObjectToSBValue(void *data);
|
|
|
|
|
|
|
|
|
|
extern lldb::ValueObjectSP
|
|
|
|
|
LLDBSWIGPython_GetValueObjectSPFromSBValue(void *data);
|
|
|
|
|
|
|
|
|
|
extern "C" bool LLDBSwigPython_UpdateSynthProviderInstance(void *implementor);
|
|
|
|
|
|
|
|
|
|
extern "C" bool
|
|
|
|
|
LLDBSwigPython_MightHaveChildrenSynthProviderInstance(void *implementor);
|
|
|
|
|
|
|
|
|
|
extern "C" void *
|
|
|
|
|
LLDBSwigPython_GetValueSynthProviderInstance(void *implementor);
|
|
|
|
|
|
|
|
|
|
extern "C" bool
|
|
|
|
|
LLDBSwigPythonCallCommand(const char *python_function_name,
|
|
|
|
|
const char *session_dictionary_name,
|
|
|
|
|
lldb::DebuggerSP &debugger, const char *args,
|
|
|
|
|
lldb_private::CommandReturnObject &cmd_retobj,
|
|
|
|
|
lldb::ExecutionContextRefSP exe_ctx_ref_sp);
|
|
|
|
|
|
|
|
|
|
extern "C" bool
|
|
|
|
|
LLDBSwigPythonCallCommandObject(void *implementor, lldb::DebuggerSP &debugger,
|
|
|
|
|
const char *args,
|
|
|
|
|
lldb_private::CommandReturnObject &cmd_retobj,
|
|
|
|
|
lldb::ExecutionContextRefSP exe_ctx_ref_sp);
|
|
|
|
|
|
|
|
|
|
extern "C" bool
|
|
|
|
|
LLDBSwigPythonCallModuleInit(const char *python_module_name,
|
|
|
|
|
const char *session_dictionary_name,
|
|
|
|
|
lldb::DebuggerSP &debugger);
|
|
|
|
|
|
|
|
|
|
extern "C" void *
|
|
|
|
|
LLDBSWIGPythonCreateOSPlugin(const char *python_class_name,
|
|
|
|
|
const char *session_dictionary_name,
|
|
|
|
|
const lldb::ProcessSP &process_sp);
|
|
|
|
|
|
|
|
|
|
extern "C" void *
|
|
|
|
|
LLDBSWIGPython_CreateFrameRecognizer(const char *python_class_name,
|
|
|
|
|
const char *session_dictionary_name);
|
|
|
|
|
|
|
|
|
|
extern "C" void *
|
|
|
|
|
LLDBSwigPython_GetRecognizedArguments(void *implementor,
|
|
|
|
|
const lldb::StackFrameSP &frame_sp);
|
|
|
|
|
|
|
|
|
|
extern "C" bool LLDBSWIGPythonRunScriptKeywordProcess(
|
|
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
lldb::ProcessSP &process, std::string &output);
|
|
|
|
|
|
|
|
|
|
extern "C" bool LLDBSWIGPythonRunScriptKeywordThread(
|
|
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
lldb::ThreadSP &thread, std::string &output);
|
|
|
|
|
|
|
|
|
|
extern "C" bool LLDBSWIGPythonRunScriptKeywordTarget(
|
|
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
lldb::TargetSP &target, std::string &output);
|
|
|
|
|
|
|
|
|
|
extern "C" bool LLDBSWIGPythonRunScriptKeywordFrame(
|
|
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
lldb::StackFrameSP &frame, std::string &output);
|
|
|
|
|
|
|
|
|
|
extern "C" bool LLDBSWIGPythonRunScriptKeywordValue(
|
|
|
|
|
const char *python_function_name, const char *session_dictionary_name,
|
|
|
|
|
lldb::ValueObjectSP &value, std::string &output);
|
|
|
|
|
|
|
|
|
|
extern "C" void *
|
|
|
|
|
LLDBSWIGPython_GetDynamicSetting(void *module, const char *setting,
|
|
|
|
|
const lldb::TargetSP &target_sp);
|
|
|
|
|
|
2015-03-31 13:03:22 -08:00
|
|
|
static bool g_initialized = false;
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
namespace {
|
2015-10-14 09:51:29 -08:00
|
|
|
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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
|
2016-09-06 12:57:50 -08:00
|
|
|
struct InitializePythonRAII {
|
2015-10-14 09:51:29 -08:00
|
|
|
public:
|
2016-09-06 12:57:50 -08:00
|
|
|
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);
|
2015-10-14 09:51:29 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
InitializePythonHome();
|
2015-10-14 09:51:29 -08:00
|
|
|
|
2018-10-13 23:24:56 -08:00
|
|
|
// Register _lldb as a built-in module.
|
2019-03-26 13:57:02 -08:00
|
|
|
PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
|
2018-10-13 23:24:56 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// 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.
|
2015-10-14 09:51:29 -08:00
|
|
|
#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 2) || (PY_MAJOR_VERSION > 3)
|
2016-09-06 12:57:50 -08:00
|
|
|
Py_InitializeEx(0);
|
|
|
|
|
InitializeThreadsPrivate();
|
Port native Python-API to 3.x
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x. This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes. Primarily, these are:
1) PyString doesn't exist in Python 3. Everything is a PyUnicode.
To account for this, PythonString now stores a PyBytes instead
of a PyString. In Python 2, this is equivalent to a PyUnicode,
and in Python 3, we do a conversion from PyUnicode to PyBytes
and store the PyBytes.
2) PyInt doesn't exist in Python 3. Everything is a PyLong. To
account for this, PythonInteger stores a PyLong instead of a
PyInt. In Python 2.x, this requires doing a conversion to
PyLong when creating a PythonInteger from a PyInt. In 3.x,
there is no PyInt anyway, so we can assume everything is a
PyLong.
3) PyFile_FromFile doesn't exist in Python 3. Instead there is a
PyFile_FromFd. This is not addressed in this patch because it
will require quite a large change to plumb fd's all the way
through the system into the ScriptInterpreter. This is the only
remaining piece of the puzzle to get LLDB supporting Python 3.x.
Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.
llvm-svn: 249886
2015-10-09 11:45:41 -08:00
|
|
|
#else
|
2016-09-06 12:57:50 -08:00
|
|
|
InitializeThreadsPrivate();
|
|
|
|
|
Py_InitializeEx(0);
|
Port native Python-API to 3.x
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x. This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes. Primarily, these are:
1) PyString doesn't exist in Python 3. Everything is a PyUnicode.
To account for this, PythonString now stores a PyBytes instead
of a PyString. In Python 2, this is equivalent to a PyUnicode,
and in Python 3, we do a conversion from PyUnicode to PyBytes
and store the PyBytes.
2) PyInt doesn't exist in Python 3. Everything is a PyLong. To
account for this, PythonInteger stores a PyLong instead of a
PyInt. In Python 2.x, this requires doing a conversion to
PyLong when creating a PythonInteger from a PyInt. In 3.x,
there is no PyInt anyway, so we can assume everything is a
PyLong.
3) PyFile_FromFile doesn't exist in Python 3. Instead there is a
PyFile_FromFd. This is not addressed in this patch because it
will require quite a large change to plumb fd's all the way
through the system into the ScriptInterpreter. This is the only
remaining piece of the puzzle to get LLDB supporting Python 3.x.
Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.
llvm-svn: 249886
2015-10-09 11:45:41 -08:00
|
|
|
#endif
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
Port native Python-API to 3.x
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x. This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes. Primarily, these are:
1) PyString doesn't exist in Python 3. Everything is a PyUnicode.
To account for this, PythonString now stores a PyBytes instead
of a PyString. In Python 2, this is equivalent to a PyUnicode,
and in Python 3, we do a conversion from PyUnicode to PyBytes
and store the PyBytes.
2) PyInt doesn't exist in Python 3. Everything is a PyLong. To
account for this, PythonInteger stores a PyLong instead of a
PyInt. In Python 2.x, this requires doing a conversion to
PyLong when creating a PythonInteger from a PyInt. In 3.x,
there is no PyInt anyway, so we can assume everything is a
PyLong.
3) PyFile_FromFile doesn't exist in Python 3. Instead there is a
PyFile_FromFd. This is not addressed in this patch because it
will require quite a large change to plumb fd's all the way
through the system into the ScriptInterpreter. This is the only
remaining piece of the puzzle to get LLDB supporting Python 3.x.
Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.
llvm-svn: 249886
2015-10-09 11:45:41 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
~InitializePythonRAII() {
|
|
|
|
|
if (m_was_already_initialized) {
|
2017-02-04 15:44:54 -09:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
|
|
|
|
|
LLDB_LOGV(log, "Releasing PyGILState. Returning to state = {0}locked",
|
2019-03-06 08:27:40 -09:00
|
|
|
m_gil_state == PyGILState_UNLOCKED ? "un" : "");
|
2016-09-06 12:57:50 -08:00
|
|
|
PyGILState_Release(m_gil_state);
|
|
|
|
|
} else {
|
|
|
|
|
// We initialized the threads in this function, just unlock the GIL.
|
|
|
|
|
PyEval_SaveThread();
|
2015-10-14 09:51:29 -08:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
m_stdin_tty_state.Restore();
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-14 09:51:29 -08:00
|
|
|
private:
|
2016-09-06 12:57:50 -08:00
|
|
|
void InitializePythonHome() {
|
Port native Python-API to 3.x
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x. This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes. Primarily, these are:
1) PyString doesn't exist in Python 3. Everything is a PyUnicode.
To account for this, PythonString now stores a PyBytes instead
of a PyString. In Python 2, this is equivalent to a PyUnicode,
and in Python 3, we do a conversion from PyUnicode to PyBytes
and store the PyBytes.
2) PyInt doesn't exist in Python 3. Everything is a PyLong. To
account for this, PythonInteger stores a PyLong instead of a
PyInt. In Python 2.x, this requires doing a conversion to
PyLong when creating a PythonInteger from a PyInt. In 3.x,
there is no PyInt anyway, so we can assume everything is a
PyLong.
3) PyFile_FromFile doesn't exist in Python 3. Instead there is a
PyFile_FromFd. This is not addressed in this patch because it
will require quite a large change to plumb fd's all the way
through the system into the ScriptInterpreter. This is the only
remaining piece of the puzzle to get LLDB supporting Python 3.x.
Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.
llvm-svn: 249886
2015-10-09 11:45:41 -08:00
|
|
|
#if defined(LLDB_PYTHON_HOME)
|
|
|
|
|
#if PY_MAJOR_VERSION >= 3
|
2016-09-06 12:57:50 -08:00
|
|
|
size_t size = 0;
|
|
|
|
|
static wchar_t *g_python_home = Py_DecodeLocale(LLDB_PYTHON_HOME, &size);
|
Port native Python-API to 3.x
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x. This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes. Primarily, these are:
1) PyString doesn't exist in Python 3. Everything is a PyUnicode.
To account for this, PythonString now stores a PyBytes instead
of a PyString. In Python 2, this is equivalent to a PyUnicode,
and in Python 3, we do a conversion from PyUnicode to PyBytes
and store the PyBytes.
2) PyInt doesn't exist in Python 3. Everything is a PyLong. To
account for this, PythonInteger stores a PyLong instead of a
PyInt. In Python 2.x, this requires doing a conversion to
PyLong when creating a PythonInteger from a PyInt. In 3.x,
there is no PyInt anyway, so we can assume everything is a
PyLong.
3) PyFile_FromFile doesn't exist in Python 3. Instead there is a
PyFile_FromFd. This is not addressed in this patch because it
will require quite a large change to plumb fd's all the way
through the system into the ScriptInterpreter. This is the only
remaining piece of the puzzle to get LLDB supporting Python 3.x.
Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.
llvm-svn: 249886
2015-10-09 11:45:41 -08:00
|
|
|
#else
|
2016-09-06 12:57:50 -08:00
|
|
|
static char g_python_home[] = LLDB_PYTHON_HOME;
|
Port native Python-API to 3.x
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x. This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes. Primarily, these are:
1) PyString doesn't exist in Python 3. Everything is a PyUnicode.
To account for this, PythonString now stores a PyBytes instead
of a PyString. In Python 2, this is equivalent to a PyUnicode,
and in Python 3, we do a conversion from PyUnicode to PyBytes
and store the PyBytes.
2) PyInt doesn't exist in Python 3. Everything is a PyLong. To
account for this, PythonInteger stores a PyLong instead of a
PyInt. In Python 2.x, this requires doing a conversion to
PyLong when creating a PythonInteger from a PyInt. In 3.x,
there is no PyInt anyway, so we can assume everything is a
PyLong.
3) PyFile_FromFile doesn't exist in Python 3. Instead there is a
PyFile_FromFd. This is not addressed in this patch because it
will require quite a large change to plumb fd's all the way
through the system into the ScriptInterpreter. This is the only
remaining piece of the puzzle to get LLDB supporting Python 3.x.
Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.
llvm-svn: 249886
2015-10-09 11:45:41 -08:00
|
|
|
#endif
|
2016-09-06 12:57:50 -08:00
|
|
|
Py_SetPythonHome(g_python_home);
|
2019-03-22 14:19:57 -08:00
|
|
|
#else
|
|
|
|
|
#if defined(__APPLE__) && PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 7
|
2019-03-29 12:17:20 -08:00
|
|
|
// For Darwin, the only Python version supported is the one shipped in the
|
|
|
|
|
// OS OS and linked with lldb. Other installation of Python may have higher
|
2019-03-22 14:38:49 -08:00
|
|
|
// priorities in the path, overriding PYTHONHOME and causing
|
|
|
|
|
// problems/incompatibilities. In order to avoid confusion, always hardcode
|
|
|
|
|
// the PythonHome to be right, as it's not going to change.
|
2019-03-29 12:17:20 -08:00
|
|
|
static char path[] =
|
|
|
|
|
"/System/Library/Frameworks/Python.framework/Versions/2.7";
|
2019-03-22 14:38:49 -08:00
|
|
|
Py_SetPythonHome(path);
|
2019-03-22 14:19:57 -08:00
|
|
|
#endif
|
Port native Python-API to 3.x
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x. This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes. Primarily, these are:
1) PyString doesn't exist in Python 3. Everything is a PyUnicode.
To account for this, PythonString now stores a PyBytes instead
of a PyString. In Python 2, this is equivalent to a PyUnicode,
and in Python 3, we do a conversion from PyUnicode to PyBytes
and store the PyBytes.
2) PyInt doesn't exist in Python 3. Everything is a PyLong. To
account for this, PythonInteger stores a PyLong instead of a
PyInt. In Python 2.x, this requires doing a conversion to
PyLong when creating a PythonInteger from a PyInt. In 3.x,
there is no PyInt anyway, so we can assume everything is a
PyLong.
3) PyFile_FromFile doesn't exist in Python 3. Instead there is a
PyFile_FromFd. This is not addressed in this patch because it
will require quite a large change to plumb fd's all the way
through the system into the ScriptInterpreter. This is the only
remaining piece of the puzzle to get LLDB supporting Python 3.x.
Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.
llvm-svn: 249886
2015-10-09 11:45:41 -08:00
|
|
|
#endif
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
2015-10-14 09:51:29 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
void InitializeThreadsPrivate() {
|
2019-03-06 08:27:40 -09:00
|
|
|
// Since Python 3.7 `Py_Initialize` calls `PyEval_InitThreads` inside itself,
|
|
|
|
|
// so there is no way to determine whether the embedded interpreter
|
|
|
|
|
// was already initialized by some external code. `PyEval_ThreadsInitialized`
|
|
|
|
|
// would always return `true` and `PyGILState_Ensure/Release` flow would be
|
|
|
|
|
// executed instead of unlocking GIL with `PyEval_SaveThread`. When
|
|
|
|
|
// an another thread calls `PyGILState_Ensure` it would get stuck in deadlock.
|
|
|
|
|
#if (PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 7) || (PY_MAJOR_VERSION > 3)
|
2019-03-29 12:17:20 -08:00
|
|
|
// The only case we should go further and acquire the GIL: it is unlocked.
|
2019-03-06 08:27:40 -09:00
|
|
|
if (PyGILState_Check())
|
|
|
|
|
return;
|
|
|
|
|
#endif
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyEval_ThreadsInitialized()) {
|
2017-02-04 15:44:54 -09:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
|
2015-10-14 09:51:29 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
m_was_already_initialized = true;
|
|
|
|
|
m_gil_state = PyGILState_Ensure();
|
2017-02-04 15:44:54 -09:00
|
|
|
LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked\n",
|
|
|
|
|
m_gil_state == PyGILState_UNLOCKED ? "un" : "");
|
2016-09-06 12:57:50 -08:00
|
|
|
return;
|
2015-10-14 09:51:29 -08:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// InitThreads acquires the GIL if it hasn't been called before.
|
|
|
|
|
PyEval_InitThreads();
|
|
|
|
|
}
|
2015-10-14 09:51:29 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
TerminalState m_stdin_tty_state;
|
|
|
|
|
PyGILState_STATE m_gil_state;
|
|
|
|
|
bool m_was_already_initialized;
|
|
|
|
|
};
|
2019-03-29 12:17:20 -08:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
void ScriptInterpreterPython::ComputePythonDirForApple(
|
|
|
|
|
llvm::SmallVectorImpl<char> &path) {
|
|
|
|
|
auto style = llvm::sys::path::Style::posix;
|
|
|
|
|
|
|
|
|
|
llvm::StringRef path_ref(path.begin(), path.size());
|
|
|
|
|
auto rbegin = llvm::sys::path::rbegin(path_ref, style);
|
|
|
|
|
auto rend = llvm::sys::path::rend(path_ref);
|
|
|
|
|
auto framework = std::find(rbegin, rend, "LLDB.framework");
|
|
|
|
|
if (framework == rend) {
|
|
|
|
|
ComputePythonDirForPosix(path);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
path.resize(framework - rend);
|
|
|
|
|
llvm::sys::path::append(path, style, "LLDB.framework", "Resources", "Python");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScriptInterpreterPython::ComputePythonDirForPosix(
|
|
|
|
|
llvm::SmallVectorImpl<char> &path) {
|
|
|
|
|
auto style = llvm::sys::path::Style::posix;
|
|
|
|
|
#if defined(LLDB_PYTHON_RELATIVE_LIBDIR)
|
|
|
|
|
// Build the path by backing out of the lib dir, then building with whatever
|
|
|
|
|
// the real python interpreter uses. (e.g. lib for most, lib64 on RHEL
|
|
|
|
|
// x86_64).
|
|
|
|
|
llvm::sys::path::remove_filename(path, style);
|
|
|
|
|
llvm::sys::path::append(path, style, LLDB_PYTHON_RELATIVE_LIBDIR);
|
|
|
|
|
#else
|
|
|
|
|
llvm::sys::path::append(path, style,
|
|
|
|
|
"python" + llvm::Twine(PY_MAJOR_VERSION) + "." +
|
|
|
|
|
llvm::Twine(PY_MINOR_VERSION),
|
|
|
|
|
"site-packages");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScriptInterpreterPython::ComputePythonDirForWindows(
|
|
|
|
|
llvm::SmallVectorImpl<char> &path) {
|
|
|
|
|
auto style = llvm::sys::path::Style::windows;
|
|
|
|
|
llvm::sys::path::remove_filename(path, style);
|
|
|
|
|
llvm::sys::path::append(path, style, "lib", "site-packages");
|
|
|
|
|
|
|
|
|
|
// This will be injected directly through FileSpec.GetDirectory().SetString(),
|
|
|
|
|
// so we need to normalize manually.
|
|
|
|
|
std::replace(path.begin(), path.end(), '\\', '/');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FileSpec ScriptInterpreterPython::GetPythonDir() {
|
|
|
|
|
static FileSpec g_spec = []() {
|
|
|
|
|
FileSpec spec = HostInfo::GetShlibDir();
|
|
|
|
|
if (!spec)
|
|
|
|
|
return FileSpec();
|
|
|
|
|
llvm::SmallString<64> path;
|
|
|
|
|
spec.GetPath(path);
|
|
|
|
|
|
|
|
|
|
#if defined(__APPLE__)
|
|
|
|
|
ComputePythonDirForApple(path);
|
|
|
|
|
#elif defined(_WIN32)
|
|
|
|
|
ComputePythonDirForWindows(path);
|
|
|
|
|
#else
|
|
|
|
|
ComputePythonDirForPosix(path);
|
|
|
|
|
#endif
|
|
|
|
|
spec.GetDirectory().SetString(path);
|
|
|
|
|
return spec;
|
|
|
|
|
}();
|
|
|
|
|
return g_spec;
|
Port native Python-API to 3.x
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x. This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes. Primarily, these are:
1) PyString doesn't exist in Python 3. Everything is a PyUnicode.
To account for this, PythonString now stores a PyBytes instead
of a PyString. In Python 2, this is equivalent to a PyUnicode,
and in Python 3, we do a conversion from PyUnicode to PyBytes
and store the PyBytes.
2) PyInt doesn't exist in Python 3. Everything is a PyLong. To
account for this, PythonInteger stores a PyLong instead of a
PyInt. In Python 2.x, this requires doing a conversion to
PyLong when creating a PythonInteger from a PyInt. In 3.x,
there is no PyInt anyway, so we can assume everything is a
PyLong.
3) PyFile_FromFile doesn't exist in Python 3. Instead there is a
PyFile_FromFd. This is not addressed in this patch because it
will require quite a large change to plumb fd's all the way
through the system into the ScriptInterpreter. This is the only
remaining piece of the puzzle to get LLDB supporting Python 3.x.
Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.
llvm-svn: 249886
2015-10-09 11:45:41 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
lldb_private::ConstString ScriptInterpreterPython::GetPluginNameStatic() {
|
|
|
|
|
static ConstString g_name("script-python");
|
|
|
|
|
return g_name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const char *ScriptInterpreterPython::GetPluginDescriptionStatic() {
|
|
|
|
|
return "Embedded Python interpreter";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScriptInterpreterPython::Initialize() {
|
|
|
|
|
static llvm::once_flag g_once_flag;
|
|
|
|
|
|
|
|
|
|
llvm::call_once(g_once_flag, []() {
|
|
|
|
|
PluginManager::RegisterPlugin(GetPluginNameStatic(),
|
|
|
|
|
GetPluginDescriptionStatic(),
|
|
|
|
|
lldb::eScriptLanguagePython,
|
|
|
|
|
ScriptInterpreterPythonImpl::CreateInstance);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ScriptInterpreterPython::Terminate() {}
|
|
|
|
|
|
|
|
|
|
ScriptInterpreterPythonImpl::Locker::Locker(
|
|
|
|
|
ScriptInterpreterPythonImpl *py_interpreter, uint16_t on_entry,
|
|
|
|
|
uint16_t on_leave, FILE *in, FILE *out, FILE *err)
|
2016-09-06 12:57:50 -08:00
|
|
|
: ScriptInterpreterLocker(),
|
|
|
|
|
m_teardown_session((on_leave & TearDownSession) == TearDownSession),
|
|
|
|
|
m_python_interpreter(py_interpreter) {
|
|
|
|
|
DoAcquireLock();
|
|
|
|
|
if ((on_entry & InitSession) == InitSession) {
|
2018-12-14 15:15:33 -09:00
|
|
|
if (!DoInitSession(on_entry, in, out, err)) {
|
2016-09-06 12:57:50 -08:00
|
|
|
// Don't teardown the session if we didn't init it.
|
|
|
|
|
m_teardown_session = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::Locker::DoAcquireLock() {
|
2017-02-04 15:44:54 -09:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
|
2016-09-06 12:57:50 -08:00
|
|
|
m_GILState = PyGILState_Ensure();
|
2017-02-04 15:44:54 -09:00
|
|
|
LLDB_LOGV(log, "Ensured PyGILState. Previous state = {0}locked",
|
|
|
|
|
m_GILState == PyGILState_UNLOCKED ? "un" : "");
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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
|
2016-09-06 12:57:50 -08:00
|
|
|
m_python_interpreter->SetThreadState(PyThreadState_Get());
|
|
|
|
|
m_python_interpreter->IncrementLockCount();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::Locker::DoInitSession(uint16_t on_entry_flags,
|
|
|
|
|
FILE *in, FILE *out,
|
|
|
|
|
FILE *err) {
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!m_python_interpreter)
|
|
|
|
|
return false;
|
|
|
|
|
return m_python_interpreter->EnterSession(on_entry_flags, in, out, err);
|
2011-10-24 09:22:21 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::Locker::DoFreeLock() {
|
2017-02-04 15:44:54 -09:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
|
|
|
|
|
LLDB_LOGV(log, "Releasing PyGILState. Returning to state = {0}locked",
|
|
|
|
|
m_GILState == PyGILState_UNLOCKED ? "un" : "");
|
2016-09-06 12:57:50 -08:00
|
|
|
PyGILState_Release(m_GILState);
|
|
|
|
|
m_python_interpreter->DecrementLockCount();
|
|
|
|
|
return true;
|
2011-10-24 09:22:21 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::Locker::DoTearDownSession() {
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!m_python_interpreter)
|
|
|
|
|
return false;
|
|
|
|
|
m_python_interpreter->LeaveSession();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::Locker::~Locker() {
|
2016-09-06 12:57:50 -08:00
|
|
|
if (m_teardown_session)
|
|
|
|
|
DoTearDownSession();
|
|
|
|
|
DoFreeLock();
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-26 09:58:19 -08:00
|
|
|
ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger)
|
|
|
|
|
: ScriptInterpreterPython(debugger), m_saved_stdin(), m_saved_stdout(),
|
2019-03-29 09:58:07 -08:00
|
|
|
m_saved_stderr(), m_main_module(),
|
2016-09-06 12:57:50 -08:00
|
|
|
m_session_dict(PyInitialValue::Invalid),
|
|
|
|
|
m_sys_module_dict(PyInitialValue::Invalid), m_run_one_line_function(),
|
|
|
|
|
m_run_one_line_str_global(),
|
2019-04-26 09:58:19 -08:00
|
|
|
m_dictionary_name(m_debugger.GetInstanceName().AsCString()),
|
2016-09-06 12:57:50 -08:00
|
|
|
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) {
|
|
|
|
|
InitializePrivate();
|
|
|
|
|
|
|
|
|
|
m_dictionary_name.append("_dict");
|
|
|
|
|
StreamString run_string;
|
|
|
|
|
run_string.Printf("%s = dict()", m_dictionary_name.c_str());
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
Locker locker(this, Locker::AcquireLock, Locker::FreeAcquiredLock);
|
2016-09-06 12:57:50 -08:00
|
|
|
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());
|
|
|
|
|
|
|
|
|
|
// Reloading modules requires a different syntax in Python 2 and Python 3.
|
2018-04-30 08:49:04 -08:00
|
|
|
// This provides a consistent syntax no matter what version of Python.
|
2016-09-06 12:57:50 -08:00
|
|
|
run_string.Clear();
|
|
|
|
|
run_string.Printf("run_one_line (%s, 'from six.moves import reload_module')",
|
|
|
|
|
m_dictionary_name.c_str());
|
|
|
|
|
PyRun_SimpleString(run_string.GetData());
|
|
|
|
|
|
|
|
|
|
// WARNING: temporary code that loads Cocoa formatters - this should be done
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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
|
2016-09-06 12:57:50 -08:00
|
|
|
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();
|
|
|
|
|
|
|
|
|
|
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')",
|
2019-04-26 09:58:19 -08:00
|
|
|
m_dictionary_name.c_str(), m_debugger.GetID());
|
2016-09-06 12:57:50 -08:00
|
|
|
PyRun_SimpleString(run_string.GetData());
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::~ScriptInterpreterPythonImpl() {
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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
|
2016-09-06 12:57:50 -08:00
|
|
|
auto gil_state = PyGILState_Ensure();
|
|
|
|
|
m_session_dict.Reset();
|
|
|
|
|
PyGILState_Release(gil_state);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
lldb_private::ConstString ScriptInterpreterPythonImpl::GetPluginName() {
|
2016-09-06 12:57:50 -08:00
|
|
|
return GetPluginNameStatic();
|
2015-07-30 12:28:07 -08:00
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
uint32_t ScriptInterpreterPythonImpl::GetPluginVersion() { return 1; }
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::IOHandlerActivated(IOHandler &io_handler,
|
|
|
|
|
bool interactive) {
|
2016-09-06 12:57:50 -08:00
|
|
|
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.
|
2014-01-27 14:43:24 -09:00
|
|
|
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"""
|
|
|
|
|
)";
|
2016-09-06 12:57:50 -08:00
|
|
|
break;
|
|
|
|
|
case eIOHandlerWatchpoint:
|
|
|
|
|
instructions = "Enter your Python command(s). Type 'DONE' to end.\n";
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (instructions) {
|
|
|
|
|
StreamFileSP output_sp(io_handler.GetOutputStreamFile());
|
Quiet command regex instructions during batch execution
Summary:
Within .lldbinit, regex commands can be structured as a list of substitutions over
multiple lines. It's possible that this is uninentional, but it works and has
benefits.
For example:
command regex <command-name>
s/pat1/repl1/
s/pat2/repl2/
...
I use this form of `command regex` in my `~/.lldbinit`, because it makes it
clearer to write and read compared to a single line definition, because
multiline substitutions don't need to be quoted, and are broken up one per line.
However, multiline definitions result in usage instructions being printed for
each use. The result is that every time I run `lldb`, I get a dozen or more
lines of noise. With this change, the instructions are only printed when
`command regex` is invoked interactively, or from a terminal, neither of which
are true when lldb is sourcing `~/.lldbinit`.
Reviewers: clayborg, jingham
Reviewed By: clayborg
Subscribers: jdoerfert, kastiglione, xiaobai, keith, lldb-commits
Differential Revision: https://reviews.llvm.org/D48752
llvm-svn: 355793
2019-03-10 15:15:48 -08:00
|
|
|
if (output_sp && interactive) {
|
2016-09-06 12:57:50 -08:00
|
|
|
output_sp->PutCString(instructions);
|
|
|
|
|
output_sp->Flush();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,
|
|
|
|
|
std::string &data) {
|
2016-09-06 12:57:50 -08:00
|
|
|
io_handler.SetIsDone(true);
|
2019-04-26 09:58:19 -08:00
|
|
|
bool batch_mode = m_debugger.GetCommandInterpreter().GetBatchCommandMode();
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
2019-02-12 21:25:41 -09:00
|
|
|
auto data_up = llvm::make_unique<CommandDataPython>();
|
|
|
|
|
if (!data_up)
|
2016-09-13 09:53:38 -08:00
|
|
|
break;
|
2019-02-12 21:25:41 -09:00
|
|
|
data_up->user_source.SplitIntoLines(data);
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2019-02-12 21:25:41 -09:00
|
|
|
if (GenerateBreakpointCommandCallbackData(data_up->user_source,
|
|
|
|
|
data_up->script_source)
|
2016-09-13 09:53:38 -08:00
|
|
|
.Success()) {
|
|
|
|
|
auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(
|
2019-02-12 21:25:41 -09:00
|
|
|
std::move(data_up));
|
2016-09-13 09:53:38 -08:00
|
|
|
bp_options->SetCallback(
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
|
2016-09-06 12:57:50 -08:00
|
|
|
} 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();
|
2014-01-27 14:43:24 -09:00
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_active_io_handler = eIOHandlerNone;
|
|
|
|
|
} break;
|
2016-09-13 09:53:38 -08:00
|
|
|
case eIOHandlerWatchpoint: {
|
|
|
|
|
WatchpointOptions *wp_options =
|
|
|
|
|
(WatchpointOptions *)io_handler.GetUserData();
|
2019-02-12 21:25:41 -09:00
|
|
|
auto data_up = llvm::make_unique<WatchpointOptions::CommandData>();
|
|
|
|
|
data_up->user_source.SplitIntoLines(data);
|
2016-09-13 09:53:38 -08:00
|
|
|
|
2019-02-12 21:25:41 -09:00
|
|
|
if (GenerateWatchpointCommandCallbackData(data_up->user_source,
|
|
|
|
|
data_up->script_source)) {
|
2016-09-13 09:53:38 -08:00
|
|
|
auto baton_sp =
|
2019-02-12 21:25:41 -09:00
|
|
|
std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
|
2016-09-13 09:53:38 -08:00
|
|
|
wp_options->SetCallback(
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp);
|
2016-09-13 09:53:38 -08:00
|
|
|
} 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;
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
lldb::ScriptInterpreterSP
|
2019-04-26 09:58:19 -08:00
|
|
|
ScriptInterpreterPythonImpl::CreateInstance(Debugger &debugger) {
|
|
|
|
|
return std::make_shared<ScriptInterpreterPythonImpl>(debugger);
|
2019-03-29 12:17:20 -08:00
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::ResetOutputFileHandle(FILE *fh) {}
|
|
|
|
|
|
|
|
|
|
void ScriptInterpreterPythonImpl::SaveTerminalState(int fd) {
|
2016-09-06 12:57:50 -08:00
|
|
|
// 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
|
2018-04-30 08:49:04 -08:00
|
|
|
// interpreter we should. For now we save and restore the terminal state on
|
|
|
|
|
// the input file handle.
|
2016-09-06 12:57:50 -08:00
|
|
|
m_terminal_state.Save(fd, false);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::RestoreTerminalState() {
|
2016-09-06 12:57:50 -08:00
|
|
|
// 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
|
2018-04-30 08:49:04 -08:00
|
|
|
// interpreter we should. For now we save and restore the terminal state on
|
|
|
|
|
// the input file handle.
|
2016-09-06 12:57:50 -08:00
|
|
|
m_terminal_state.Restore();
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::LeaveSession() {
|
2016-09-06 12:57:50 -08:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
|
|
|
|
|
if (log)
|
2019-03-29 12:17:20 -08:00
|
|
|
log->PutCString("ScriptInterpreterPythonImpl::LeaveSession()");
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
// rdar://problem/11292882
|
|
|
|
|
// When the current thread state is NULL, PyThreadState_Get() issues a fatal
|
|
|
|
|
// error.
|
|
|
|
|
if (PyThreadState_GetDict()) {
|
|
|
|
|
PythonDictionary &sys_module_dict = GetSysModuleDictionary();
|
|
|
|
|
if (sys_module_dict.IsValid()) {
|
|
|
|
|
if (m_saved_stdin.IsValid()) {
|
|
|
|
|
sys_module_dict.SetItemForKey(PythonString("stdin"), m_saved_stdin);
|
|
|
|
|
m_saved_stdin.Reset();
|
|
|
|
|
}
|
|
|
|
|
if (m_saved_stdout.IsValid()) {
|
|
|
|
|
sys_module_dict.SetItemForKey(PythonString("stdout"), m_saved_stdout);
|
|
|
|
|
m_saved_stdout.Reset();
|
|
|
|
|
}
|
|
|
|
|
if (m_saved_stderr.IsValid()) {
|
|
|
|
|
sys_module_dict.SetItemForKey(PythonString("stderr"), m_saved_stderr);
|
|
|
|
|
m_saved_stderr.Reset();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_session_is_active = false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::SetStdHandle(File &file, const char *py_name,
|
|
|
|
|
PythonFile &save_file,
|
|
|
|
|
const char *mode) {
|
2016-09-06 12:57:50 -08:00
|
|
|
if (file.IsValid()) {
|
|
|
|
|
// Flush the file before giving it to python to avoid interleaved output.
|
|
|
|
|
file.Flush();
|
|
|
|
|
|
|
|
|
|
PythonDictionary &sys_module_dict = GetSysModuleDictionary();
|
|
|
|
|
|
2017-11-01 19:17:07 -08:00
|
|
|
save_file = sys_module_dict.GetItemForKey(PythonString(py_name))
|
|
|
|
|
.AsType<PythonFile>();
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
PythonFile new_file(file, mode);
|
|
|
|
|
sys_module_dict.SetItemForKey(PythonString(py_name), new_file);
|
|
|
|
|
return true;
|
|
|
|
|
} else
|
|
|
|
|
save_file.Reset();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::EnterSession(uint16_t on_entry_flags,
|
|
|
|
|
FILE *in, FILE *out, FILE *err) {
|
2016-09-06 12:57:50 -08:00
|
|
|
// If we have already entered the session, without having officially 'left'
|
2018-04-30 08:49:04 -08:00
|
|
|
// it, then there is no need to 'enter' it again.
|
2016-09-06 12:57:50 -08:00
|
|
|
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SCRIPT));
|
|
|
|
|
if (m_session_is_active) {
|
|
|
|
|
if (log)
|
|
|
|
|
log->Printf(
|
2019-03-29 12:17:20 -08:00
|
|
|
"ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16
|
2016-09-06 12:57:50 -08:00
|
|
|
") session is already active, returning without doing anything",
|
|
|
|
|
on_entry_flags);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (log)
|
|
|
|
|
log->Printf(
|
2019-03-29 12:17:20 -08:00
|
|
|
"ScriptInterpreterPythonImpl::EnterSession(on_entry_flags=0x%" PRIx16
|
|
|
|
|
")",
|
2016-09-06 12:57:50 -08:00
|
|
|
on_entry_flags);
|
|
|
|
|
|
|
|
|
|
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,
|
2019-04-26 09:58:19 -08:00
|
|
|
m_dictionary_name.c_str(), m_debugger.GetID());
|
2016-09-06 12:57:50 -08:00
|
|
|
run_string.Printf(
|
|
|
|
|
"; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",
|
2019-04-26 09:58:19 -08:00
|
|
|
m_debugger.GetID());
|
2016-09-06 12:57:50 -08:00
|
|
|
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 {
|
2018-04-30 08:49:04 -08:00
|
|
|
// If we aren't initing the globals, we should still always set the
|
|
|
|
|
// debugger (since that is always unique.)
|
2016-09-06 12:57:50 -08:00
|
|
|
run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64,
|
2019-04-26 09:58:19 -08:00
|
|
|
m_dictionary_name.c_str(), m_debugger.GetID());
|
2016-09-06 12:57:50 -08:00
|
|
|
run_string.Printf(
|
|
|
|
|
"; lldb.debugger = lldb.SBDebugger.FindDebuggerWithID (%" PRIu64 ")",
|
2019-04-26 09:58:19 -08:00
|
|
|
m_debugger.GetID());
|
2016-09-06 12:57:50 -08:00
|
|
|
run_string.PutCString("')");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PyRun_SimpleString(run_string.GetData());
|
|
|
|
|
run_string.Clear();
|
|
|
|
|
|
|
|
|
|
PythonDictionary &sys_module_dict = GetSysModuleDictionary();
|
|
|
|
|
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())
|
2019-04-26 09:58:19 -08:00
|
|
|
m_debugger.AdoptTopIOHandlerFilesIfInvalid(in_sp, out_sp, err_sp);
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
if (on_entry_flags & Locker::NoSTDIN) {
|
|
|
|
|
m_saved_stdin.Reset();
|
|
|
|
|
} else {
|
|
|
|
|
if (!SetStdHandle(in_file, "stdin", m_saved_stdin, "r")) {
|
|
|
|
|
if (in_sp)
|
|
|
|
|
SetStdHandle(in_sp->GetFile(), "stdin", m_saved_stdin, "r");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!SetStdHandle(out_file, "stdout", m_saved_stdout, "w")) {
|
|
|
|
|
if (out_sp)
|
|
|
|
|
SetStdHandle(out_sp->GetFile(), "stdout", m_saved_stdout, "w");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!SetStdHandle(err_file, "stderr", m_saved_stderr, "w")) {
|
|
|
|
|
if (err_sp)
|
|
|
|
|
SetStdHandle(err_sp->GetFile(), "stderr", m_saved_stderr, "w");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
PythonObject &ScriptInterpreterPythonImpl::GetMainModule() {
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!m_main_module.IsValid())
|
|
|
|
|
m_main_module.Reset(PyRefType::Borrowed, PyImport_AddModule("__main__"));
|
|
|
|
|
return m_main_module;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
PythonDictionary &ScriptInterpreterPythonImpl::GetSessionDictionary() {
|
2016-09-06 12:57:50 -08:00
|
|
|
if (m_session_dict.IsValid())
|
|
|
|
|
return m_session_dict;
|
2012-03-08 11:53:04 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject &main_module = GetMainModule();
|
|
|
|
|
if (!main_module.IsValid())
|
|
|
|
|
return m_session_dict;
|
2014-01-27 14:43:24 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonDictionary main_dict(PyRefType::Borrowed,
|
|
|
|
|
PyModule_GetDict(main_module.get()));
|
|
|
|
|
if (!main_dict.IsValid())
|
|
|
|
|
return m_session_dict;
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject item = main_dict.GetItemForKey(PythonString(m_dictionary_name));
|
|
|
|
|
m_session_dict.Reset(PyRefType::Borrowed, item.get());
|
|
|
|
|
return m_session_dict;
|
2011-02-07 14:24:47 -09:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
PythonDictionary &ScriptInterpreterPythonImpl::GetSysModuleDictionary() {
|
2016-09-06 12:57:50 -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;
|
2011-02-07 14:24:47 -09:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
static std::string GenerateUniqueName(const char *base_name_wanted,
|
|
|
|
|
uint32_t &functions_counter,
|
|
|
|
|
const void *name_token = nullptr) {
|
|
|
|
|
StreamString sstr;
|
<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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!base_name_wanted)
|
|
|
|
|
return std::string();
|
2012-05-04 12:37:11 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!name_token)
|
|
|
|
|
sstr.Printf("%s_%d", base_name_wanted, functions_counter++);
|
|
|
|
|
else
|
|
|
|
|
sstr.Printf("%s_%p", base_name_wanted, name_token);
|
2012-02-28 16:52:13 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
return sstr.GetString();
|
2011-01-13 15:29:16 -09:00
|
|
|
}
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::GetEmbeddedInterpreterModuleObjects() {
|
2016-09-06 12:57:50 -08:00
|
|
|
if (m_run_one_line_function.IsValid())
|
|
|
|
|
return true;
|
2016-03-10 11:49:32 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject module(PyRefType::Borrowed,
|
|
|
|
|
PyImport_AddModule("lldb.embedded_interpreter"));
|
|
|
|
|
if (!module.IsValid())
|
|
|
|
|
return false;
|
2016-03-10 11:49:32 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonDictionary module_dict(PyRefType::Borrowed,
|
|
|
|
|
PyModule_GetDict(module.get()));
|
|
|
|
|
if (!module_dict.IsValid())
|
2016-03-10 11:49:32 -09:00
|
|
|
return false;
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
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();
|
|
|
|
|
}
|
<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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-10-18 10:24:17 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::ExecuteOneLine(
|
2018-07-12 14:28:52 -08:00
|
|
|
llvm::StringRef command, CommandReturnObject *result,
|
2016-09-06 12:57:50 -08:00
|
|
|
const ExecuteScriptOptions &options) {
|
2018-07-13 10:13:46 -08:00
|
|
|
std::string command_str = command.str();
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!m_valid_session)
|
|
|
|
|
return false;
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2018-07-12 14:28:52 -08:00
|
|
|
if (!command.empty()) {
|
2016-09-06 12:57:50 -08:00
|
|
|
// We want to call run_one_line, passing in the dictionary and the command
|
2018-04-30 08:49:04 -08:00
|
|
|
// string. We cannot do this through PyRun_SimpleString here because the
|
|
|
|
|
// command string may contain escaped characters, and putting it inside
|
2016-09-06 12:57:50 -08:00
|
|
|
// another string to pass to PyRun_SimpleString messes up the escaping. So
|
2018-04-30 08:49:04 -08:00
|
|
|
// we use the following more complicated method to pass the command string
|
|
|
|
|
// directly down to Python.
|
2019-04-26 09:58:19 -08:00
|
|
|
Debugger &debugger = m_debugger;
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
StreamFileSP input_file_sp;
|
|
|
|
|
StreamFileSP output_file_sp;
|
|
|
|
|
StreamFileSP error_file_sp;
|
|
|
|
|
Communication output_comm(
|
2019-03-29 12:17:20 -08:00
|
|
|
"lldb.ScriptInterpreterPythonImpl.ExecuteOneLine.comm");
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
2017-05-11 20:51:55 -08:00
|
|
|
Status pipe_result = pipe.CreateNew(false);
|
2016-09-06 12:57:50 -08:00
|
|
|
if (pipe_result.Success()) {
|
|
|
|
|
#if defined(_WIN32)
|
|
|
|
|
lldb::file_t read_file = pipe.GetReadNativeHandle();
|
|
|
|
|
pipe.ReleaseReadFileDescriptor();
|
2019-02-12 21:25:41 -09:00
|
|
|
std::unique_ptr<ConnectionGenericFile> conn_up(
|
2016-09-06 12:57:50 -08:00
|
|
|
new ConnectionGenericFile(read_file, true));
|
|
|
|
|
#else
|
2019-02-12 21:25:41 -09:00
|
|
|
std::unique_ptr<ConnectionFileDescriptor> conn_up(
|
2016-09-06 12:57:50 -08:00
|
|
|
new ConnectionFileDescriptor(pipe.ReleaseReadFileDescriptor(),
|
|
|
|
|
true));
|
|
|
|
|
#endif
|
2019-02-12 21:25:41 -09:00
|
|
|
if (conn_up->IsConnected()) {
|
|
|
|
|
output_comm.SetConnection(conn_up.release());
|
2016-09-06 12:57:50 -08:00
|
|
|
output_comm.SetReadThreadBytesReceivedCallback(
|
|
|
|
|
ReadThreadBytesReceived, &result->GetOutputStream());
|
|
|
|
|
output_comm.StartReadThread();
|
|
|
|
|
join_read_thread = true;
|
|
|
|
|
FILE *outfile_handle =
|
|
|
|
|
fdopen(pipe.ReleaseWriteFileDescriptor(), "w");
|
2019-02-11 14:13:08 -09:00
|
|
|
output_file_sp = std::make_shared<StreamFile>(outfile_handle, true);
|
2016-09-06 12:57:50 -08:00
|
|
|
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 {
|
2019-02-11 14:13:08 -09:00
|
|
|
input_file_sp = std::make_shared<StreamFile>();
|
2018-11-02 14:34:51 -08:00
|
|
|
FileSystem::Instance().Open(input_file_sp->GetFile(),
|
|
|
|
|
FileSpec(FileSystem::DEV_NULL),
|
|
|
|
|
File::eOpenOptionRead);
|
|
|
|
|
|
2019-02-11 14:13:08 -09:00
|
|
|
output_file_sp = std::make_shared<StreamFile>();
|
2018-11-02 14:34:51 -08:00
|
|
|
FileSystem::Instance().Open(output_file_sp->GetFile(),
|
|
|
|
|
FileSpec(FileSystem::DEV_NULL),
|
|
|
|
|
File::eOpenOptionWrite);
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
|
|
|
|
{
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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.
|
2016-09-06 12:57:50 -08:00
|
|
|
Locker locker(
|
|
|
|
|
this,
|
2019-03-29 12:17:20 -08:00
|
|
|
Locker::AcquireLock | Locker::InitSession |
|
|
|
|
|
(options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
|
2016-09-06 12:57:50 -08:00
|
|
|
((result && result->GetInteractive()) ? 0 : Locker::NoSTDIN),
|
2019-03-29 12:17:20 -08:00
|
|
|
Locker::FreeAcquiredLock | Locker::TearDownSession, in_file, out_file,
|
|
|
|
|
err_file);
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
// 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,
|
2018-07-13 10:13:46 -08:00
|
|
|
Py_BuildValue("(Os)", session_dict.get(), command_str.c_str()));
|
2016-09-06 12:57:50 -08:00
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-01-17 12:55:19 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// Flush our output and error file handles
|
|
|
|
|
::fflush(out_file);
|
|
|
|
|
if (out_file != err_file)
|
|
|
|
|
::fflush(err_file);
|
2012-12-07 17:02:04 -09:00
|
|
|
}
|
2011-05-03 13:21:50 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (join_read_thread) {
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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
|
2016-09-06 12:57:50 -08:00
|
|
|
output_file_sp->GetFile().Close();
|
2018-04-30 08:49:04 -08:00
|
|
|
// The close above should cause this thread to exit when it gets to the
|
|
|
|
|
// end of file, so let it get all its data
|
2016-09-06 12:57:50 -08:00
|
|
|
output_comm.JoinReadThread();
|
|
|
|
|
// Now we can close the read end of the pipe
|
|
|
|
|
output_comm.Disconnect();
|
|
|
|
|
}
|
2012-02-28 16:52:13 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (success)
|
|
|
|
|
return true;
|
2015-10-15 11:35:48 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// The one-liner failed. Append the error message.
|
2018-07-12 14:28:52 -08:00
|
|
|
if (result) {
|
2016-09-06 12:57:50 -08:00
|
|
|
result->AppendErrorWithFormat(
|
2018-07-12 14:28:52 -08:00
|
|
|
"python failed attempting to evaluate '%s'\n", command_str.c_str());
|
|
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
2014-01-27 14:43:24 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (result)
|
|
|
|
|
result->AppendError("empty command passed to python\n");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-01-30 11:19:22 -09:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::ExecuteInterpreterLoop() {
|
2017-05-15 05:02:37 -08:00
|
|
|
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
|
|
|
|
|
Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
|
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
|
|
|
|
2019-04-26 09:58:19 -08:00
|
|
|
Debugger &debugger = m_debugger;
|
2012-03-06 14:42:15 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// At the moment, the only time the debugger does not have an input file
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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.
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!debugger.GetInputFile()->GetFile().IsValid())
|
|
|
|
|
return;
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
IOHandlerSP io_handler_sp(new IOHandlerPythonInterpreter(debugger, this));
|
|
|
|
|
if (io_handler_sp) {
|
|
|
|
|
debugger.PushIOHandler(io_handler_sp);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::Interrupt() {
|
2016-09-06 12:57:50 -08:00
|
|
|
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)
|
2019-03-29 12:17:20 -08:00
|
|
|
log->Printf("ScriptInterpreterPythonImpl::Interrupt() sending "
|
2016-09-06 12:57:50 -08:00
|
|
|
"PyExc_KeyboardInterrupt (tid = %li, num_threads = %i)...",
|
|
|
|
|
tid, num_threads);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (log)
|
2019-03-29 12:17:20 -08:00
|
|
|
log->Printf(
|
|
|
|
|
"ScriptInterpreterPythonImpl::Interrupt() python code not running, "
|
|
|
|
|
"can't interrupt");
|
2016-09-06 12:57:50 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::ExecuteOneLineWithReturn(
|
2018-07-12 14:28:52 -08:00
|
|
|
llvm::StringRef in_string, ScriptInterpreter::ScriptReturnType return_type,
|
2016-09-06 12:57:50 -08:00
|
|
|
void *ret_value, const ExecuteScriptOptions &options) {
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
Locker locker(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession |
|
|
|
|
|
(options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
|
|
|
|
|
Locker::NoSTDIN,
|
|
|
|
|
Locker::FreeAcquiredLock | Locker::TearDownSession);
|
2016-09-06 12:57:50 -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();
|
|
|
|
|
|
|
|
|
|
if (!locals.IsValid()) {
|
|
|
|
|
locals.Reset(
|
|
|
|
|
PyRefType::Owned,
|
|
|
|
|
PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!locals.IsValid())
|
|
|
|
|
locals = globals;
|
|
|
|
|
|
|
|
|
|
py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
|
|
|
|
|
if (py_error.IsValid())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
|
2018-07-12 14:28:52 -08:00
|
|
|
std::string as_string = in_string.str();
|
|
|
|
|
{ // scope for PythonInputReaderManager
|
|
|
|
|
// PythonInputReaderManager py_input(options.GetEnableIO() ? this : NULL);
|
|
|
|
|
py_return.Reset(PyRefType::Owned,
|
|
|
|
|
PyRun_String(as_string.c_str(), 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(as_string.c_str(), Py_single_input,
|
|
|
|
|
globals.get(), locals.get()));
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
2018-07-12 14:28:52 -08:00
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2018-07-12 14:28:52 -08:00
|
|
|
if (py_return.IsValid()) {
|
|
|
|
|
switch (return_type) {
|
|
|
|
|
case eScriptReturnTypeCharPtr: // "char *"
|
|
|
|
|
{
|
|
|
|
|
const char format[3] = "s#";
|
|
|
|
|
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";
|
|
|
|
|
success = PyArg_Parse(py_return.get(), format, (char **)ret_value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eScriptReturnTypeBool: {
|
|
|
|
|
const char format[2] = "b";
|
|
|
|
|
success = PyArg_Parse(py_return.get(), format, (bool *)ret_value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eScriptReturnTypeShortInt: {
|
|
|
|
|
const char format[2] = "h";
|
|
|
|
|
success = PyArg_Parse(py_return.get(), format, (short *)ret_value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eScriptReturnTypeShortIntUnsigned: {
|
|
|
|
|
const char format[2] = "H";
|
|
|
|
|
success =
|
|
|
|
|
PyArg_Parse(py_return.get(), format, (unsigned short *)ret_value);
|
|
|
|
|
break;
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
2018-07-12 14:28:52 -08:00
|
|
|
case eScriptReturnTypeInt: {
|
|
|
|
|
const char format[2] = "i";
|
|
|
|
|
success = PyArg_Parse(py_return.get(), format, (int *)ret_value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eScriptReturnTypeIntUnsigned: {
|
|
|
|
|
const char format[2] = "I";
|
|
|
|
|
success = PyArg_Parse(py_return.get(), format, (unsigned int *)ret_value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eScriptReturnTypeLongInt: {
|
|
|
|
|
const char format[2] = "l";
|
|
|
|
|
success = PyArg_Parse(py_return.get(), format, (long *)ret_value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eScriptReturnTypeLongIntUnsigned: {
|
|
|
|
|
const char format[2] = "k";
|
|
|
|
|
success =
|
|
|
|
|
PyArg_Parse(py_return.get(), format, (unsigned long *)ret_value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eScriptReturnTypeLongLong: {
|
|
|
|
|
const char format[2] = "L";
|
|
|
|
|
success = PyArg_Parse(py_return.get(), format, (long long *)ret_value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eScriptReturnTypeLongLongUnsigned: {
|
|
|
|
|
const char format[2] = "K";
|
|
|
|
|
success =
|
|
|
|
|
PyArg_Parse(py_return.get(), format, (unsigned long long *)ret_value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eScriptReturnTypeFloat: {
|
|
|
|
|
const char format[2] = "f";
|
|
|
|
|
success = PyArg_Parse(py_return.get(), format, (float *)ret_value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eScriptReturnTypeDouble: {
|
|
|
|
|
const char format[2] = "d";
|
|
|
|
|
success = PyArg_Parse(py_return.get(), format, (double *)ret_value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eScriptReturnTypeChar: {
|
|
|
|
|
const char format[2] = "c";
|
|
|
|
|
success = PyArg_Parse(py_return.get(), format, (char *)ret_value);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case eScriptReturnTypeOpaqueObject: {
|
|
|
|
|
success = true;
|
|
|
|
|
PyObject *saved_value = py_return.get();
|
|
|
|
|
Py_XINCREF(saved_value);
|
|
|
|
|
*((PyObject **)ret_value) = saved_value;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-07-23 12:56:49 -08:00
|
|
|
ret_success = success;
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
|
|
|
|
|
if (py_error.IsValid()) {
|
|
|
|
|
ret_success = false;
|
|
|
|
|
if (options.GetMaskoutErrors()) {
|
|
|
|
|
if (PyErr_GivenExceptionMatches(py_error.get(), PyExc_SyntaxError))
|
|
|
|
|
PyErr_Print();
|
|
|
|
|
PyErr_Clear();
|
2014-01-27 14:43:24 -09:00
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret_success;
|
2014-01-27 14:43:24 -09:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
Status ScriptInterpreterPythonImpl::ExecuteMultipleLines(
|
2016-09-06 12:57:50 -08:00
|
|
|
const char *in_string, const ExecuteScriptOptions &options) {
|
2017-05-11 20:51:55 -08:00
|
|
|
Status error;
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
Locker locker(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession |
|
|
|
|
|
(options.GetSetLLDBGlobals() ? Locker::InitGlobals : 0) |
|
|
|
|
|
Locker::NoSTDIN,
|
|
|
|
|
Locker::FreeAcquiredLock | Locker::TearDownSession);
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
PythonObject return_value;
|
|
|
|
|
PythonObject &main_module = GetMainModule();
|
|
|
|
|
PythonDictionary globals(PyRefType::Borrowed,
|
|
|
|
|
PyModule_GetDict(main_module.get()));
|
|
|
|
|
PythonObject py_error;
|
|
|
|
|
|
|
|
|
|
PythonDictionary locals = GetSessionDictionary();
|
|
|
|
|
|
|
|
|
|
if (!locals.IsValid())
|
|
|
|
|
locals.Reset(
|
|
|
|
|
PyRefType::Owned,
|
|
|
|
|
PyObject_GetAttrString(globals.get(), m_dictionary_name.c_str()));
|
|
|
|
|
|
|
|
|
|
if (!locals.IsValid())
|
|
|
|
|
locals = globals;
|
|
|
|
|
|
|
|
|
|
py_error.Reset(PyRefType::Borrowed, PyErr_Occurred());
|
|
|
|
|
if (py_error.IsValid())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
|
|
|
|
|
if (in_string != nullptr) {
|
|
|
|
|
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
|
2018-04-30 08:49:04 -08:00
|
|
|
// takes a PyObject. They are convertible (hence the function
|
|
|
|
|
// PyCode_Check(PyObject*), so we have to do the cast for Python 2.x
|
2016-09-06 12:57:50 -08:00
|
|
|
#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
PyObject *py_code_obj = code_object.get();
|
2014-10-08 12:38:41 -08:00
|
|
|
#else
|
2016-09-06 12:57:50 -08:00
|
|
|
PyCodeObject *py_code_obj =
|
|
|
|
|
reinterpret_cast<PyCodeObject *>(code_object.get());
|
2014-10-08 12:38:41 -08:00
|
|
|
#endif
|
2016-09-06 12:57:50 -08:00
|
|
|
return_value.Reset(
|
|
|
|
|
PyRefType::Owned,
|
|
|
|
|
PyEval_EvalCode(py_code_obj, globals.get(), locals.get()));
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-01-14 12:09:29 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonExceptionState exception_state(!options.GetMaskoutErrors());
|
|
|
|
|
if (exception_state.IsError())
|
|
|
|
|
error.SetErrorString(exception_state.Format().c_str());
|
2010-06-22 17:19:29 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
return error;
|
|
|
|
|
}
|
2010-07-30 14:33:14 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::CollectDataForBreakpointCommandCallback(
|
2016-09-06 12:57:50 -08:00
|
|
|
std::vector<BreakpointOptions *> &bp_options_vec,
|
|
|
|
|
CommandReturnObject &result) {
|
|
|
|
|
m_active_io_handler = eIOHandlerBreakpoint;
|
2019-04-26 09:58:19 -08:00
|
|
|
m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
|
|
|
|
|
" ", *this, true, &bp_options_vec);
|
2010-06-08 08:52:24 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::CollectDataForWatchpointCommandCallback(
|
2016-09-06 12:57:50 -08:00
|
|
|
WatchpointOptions *wp_options, CommandReturnObject &result) {
|
|
|
|
|
m_active_io_handler = eIOHandlerWatchpoint;
|
2019-04-26 09:58:19 -08:00
|
|
|
m_debugger.GetCommandInterpreter().GetPythonCommandsFromIOHandler(
|
|
|
|
|
" ", *this, true, wp_options);
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
2010-11-10 10:18:14 -09:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction(
|
2016-09-06 12:57:50 -08:00
|
|
|
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)";
|
2019-04-26 14:43:16 -08:00
|
|
|
m_debugger.GetScriptInterpreter()->SetBreakpointCommandCallback(
|
|
|
|
|
bp_options, oneliner.c_str());
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
2011-01-17 12:55:19 -09:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
|
2016-09-26 11:47:37 -08:00
|
|
|
BreakpointOptions *bp_options,
|
|
|
|
|
std::unique_ptr<BreakpointOptions::CommandData> &cmd_data_up) {
|
2017-05-11 20:51:55 -08:00
|
|
|
Status error;
|
2016-09-26 11:47:37 -08:00
|
|
|
error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source,
|
|
|
|
|
cmd_data_up->script_source);
|
|
|
|
|
if (error.Fail()) {
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
auto baton_sp =
|
|
|
|
|
std::make_shared<BreakpointOptions::CommandBaton>(std::move(cmd_data_up));
|
2019-03-29 12:17:20 -08:00
|
|
|
bp_options->SetCallback(
|
|
|
|
|
ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
|
2016-09-26 11:47:37 -08:00
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// Set a Python one-liner as the callback for the breakpoint.
|
2019-03-29 12:17:20 -08:00
|
|
|
Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback(
|
2016-09-06 12:57:50 -08:00
|
|
|
BreakpointOptions *bp_options, const char *command_body_text) {
|
2019-02-12 21:25:41 -09:00
|
|
|
auto data_up = llvm::make_unique<CommandDataPython>();
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
// Split the command_body_text into lines, and pass that to
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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.
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2019-02-12 21:25:41 -09:00
|
|
|
data_up->user_source.SplitIntoLines(command_body_text);
|
|
|
|
|
Status error = GenerateBreakpointCommandCallbackData(data_up->user_source,
|
|
|
|
|
data_up->script_source);
|
2016-09-06 12:57:50 -08:00
|
|
|
if (error.Success()) {
|
2016-09-13 09:53:38 -08:00
|
|
|
auto baton_sp =
|
2019-02-12 21:25:41 -09:00
|
|
|
std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up));
|
2019-03-29 12:17:20 -08:00
|
|
|
bp_options->SetCallback(
|
|
|
|
|
ScriptInterpreterPythonImpl::BreakpointCallbackFunction, baton_sp);
|
2016-09-06 12:57:50 -08:00
|
|
|
return error;
|
|
|
|
|
} else
|
|
|
|
|
return error;
|
|
|
|
|
}
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// Set a Python one-liner as the callback for the watchpoint.
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback(
|
2016-09-06 12:57:50 -08:00
|
|
|
WatchpointOptions *wp_options, const char *oneliner) {
|
2019-02-12 21:25:41 -09:00
|
|
|
auto data_up = llvm::make_unique<WatchpointOptions::CommandData>();
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
// It's necessary to set both user_source and script_source to the oneliner.
|
|
|
|
|
// The former is used to generate callback description (as in watchpoint
|
2018-04-30 08:49:04 -08:00
|
|
|
// command list) while the latter is used for Python to interpret during the
|
|
|
|
|
// actual callback.
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2019-02-12 21:25:41 -09:00
|
|
|
data_up->user_source.AppendString(oneliner);
|
|
|
|
|
data_up->script_source.assign(oneliner);
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2019-02-12 21:25:41 -09:00
|
|
|
if (GenerateWatchpointCommandCallbackData(data_up->user_source,
|
|
|
|
|
data_up->script_source)) {
|
2016-09-13 09:53:38 -08:00
|
|
|
auto baton_sp =
|
2019-02-12 21:25:41 -09:00
|
|
|
std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up));
|
2019-03-29 12:17:20 -08:00
|
|
|
wp_options->SetCallback(
|
|
|
|
|
ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp);
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter(
|
2016-09-06 12:57:50 -08:00
|
|
|
StringList &function_def) {
|
|
|
|
|
// Convert StringList to one long, newline delimited, const char *.
|
|
|
|
|
std::string function_def_string(function_def.CopyList());
|
|
|
|
|
|
2017-05-11 20:51:55 -08:00
|
|
|
Status error = ExecuteMultipleLines(
|
2016-09-06 12:57:50 -08:00
|
|
|
function_def_string.c_str(),
|
|
|
|
|
ScriptInterpreter::ExecuteScriptOptions().SetEnableIO(false));
|
|
|
|
|
return error;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
Status ScriptInterpreterPythonImpl::GenerateFunction(const char *signature,
|
|
|
|
|
const StringList &input) {
|
2017-05-11 20:51:55 -08:00
|
|
|
Status error;
|
2016-09-06 12:57:50 -08:00
|
|
|
int num_lines = input.GetSize();
|
|
|
|
|
if (num_lines == 0) {
|
|
|
|
|
error.SetErrorString("No input data.");
|
|
|
|
|
return error;
|
|
|
|
|
}
|
2014-02-24 13:50:57 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction(
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// Take what the user wrote, wrap it all up inside one big auto-generated
|
2018-04-30 08:49:04 -08:00
|
|
|
// Python function, passing in the ValueObject as parameter to the function.
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
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());
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!GenerateFunction(sstr.GetData(), user_input).Success())
|
|
|
|
|
return false;
|
2010-09-14 14:49:06 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// Store the name of the auto-generated function to be called.
|
|
|
|
|
output.assign(auto_generated_function_name);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2010-09-14 14:49:06 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::GenerateScriptAliasFunction(
|
2016-09-06 12:57:50 -08:00
|
|
|
StringList &user_input, std::string &output) {
|
|
|
|
|
static uint32_t num_created_functions = 0;
|
|
|
|
|
user_input.RemoveBlankLines();
|
|
|
|
|
StreamString sstr;
|
2010-09-14 14:49:06 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// Check to see if we have any data; if not, just return.
|
|
|
|
|
if (user_input.GetSize() == 0)
|
|
|
|
|
return false;
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
std::string auto_generated_function_name(GenerateUniqueName(
|
|
|
|
|
"lldb_autogen_python_cmd_alias_func", num_created_functions));
|
2015-01-26 16:58:22 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
sstr.Printf("def %s (debugger, args, result, internal_dict):",
|
|
|
|
|
auto_generated_function_name.c_str());
|
|
|
|
|
|
|
|
|
|
if (!GenerateFunction(sstr.GetData(), user_input).Success())
|
2015-01-26 16:58:22 -09:00
|
|
|
return false;
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// Store the name of the auto-generated function to be called.
|
|
|
|
|
output.assign(auto_generated_function_name);
|
|
|
|
|
return true;
|
2015-01-26 16:58:22 -09:00
|
|
|
}
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass(
|
|
|
|
|
StringList &user_input, std::string &output, const void *name_token) {
|
2016-09-06 12:57:50 -08:00
|
|
|
static uint32_t num_created_classes = 0;
|
|
|
|
|
user_input.RemoveBlankLines();
|
|
|
|
|
int num_lines = user_input.GetSize();
|
|
|
|
|
StreamString sstr;
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// Check to see if we have any data; if not, just return.
|
|
|
|
|
if (user_input.GetSize() == 0)
|
|
|
|
|
return false;
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// Wrap all user input into a Python class
|
2011-01-17 12:55:19 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
std::string auto_generated_class_name(GenerateUniqueName(
|
|
|
|
|
"lldb_autogen_python_type_synth_class", num_created_classes, name_token));
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
StringList auto_generated_class;
|
2011-01-13 15:29:16 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// Create the function name & definition string.
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
sstr.Printf("class %s:", auto_generated_class_name.c_str());
|
2016-11-16 12:15:24 -09:00
|
|
|
auto_generated_class.AppendString(sstr.GetString());
|
2011-01-13 15:29:16 -09:00
|
|
|
|
2018-04-30 08:49:04 -08:00
|
|
|
// Wrap everything up inside the class, increasing the indentation. we don't
|
|
|
|
|
// need to play any fancy indentation tricks here because there is no
|
2016-09-06 12:57:50 -08:00
|
|
|
// 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));
|
2016-11-16 12:15:24 -09:00
|
|
|
auto_generated_class.AppendString(sstr.GetString());
|
2016-09-06 12:57:50 -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
|
|
|
|
2018-04-30 08:49:04 -08:00
|
|
|
// Verify that the results are valid Python. (even though the method is
|
|
|
|
|
// ExportFunctionDefinitionToInterpreter, a class will actually be exported)
|
2016-09-06 12:57:50 -08:00
|
|
|
// (TODO: rename that method to ExportDefinitionToInterpreter)
|
|
|
|
|
if (!ExportFunctionDefinitionToInterpreter(auto_generated_class).Success())
|
|
|
|
|
return false;
|
2011-01-13 15:29:16 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// Store the name of the auto-generated class
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
output.assign(auto_generated_class_name);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
StructuredData::GenericSP
|
|
|
|
|
ScriptInterpreterPythonImpl::CreateFrameRecognizer(const char *class_name) {
|
2018-10-30 20:00:22 -08:00
|
|
|
if (class_name == nullptr || class_name[0] == '\0')
|
|
|
|
|
return StructuredData::GenericSP();
|
|
|
|
|
|
|
|
|
|
void *ret_val;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN,
|
|
|
|
|
Locker::FreeLock);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSWIGPython_CreateFrameRecognizer(class_name,
|
|
|
|
|
m_dictionary_name.c_str());
|
2018-10-30 20:00:22 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
lldb::ValueObjectListSP ScriptInterpreterPythonImpl::GetRecognizedArguments(
|
2018-10-30 20:00:22 -08:00
|
|
|
const StructuredData::ObjectSP &os_plugin_object_sp,
|
|
|
|
|
lldb::StackFrameSP frame_sp) {
|
|
|
|
|
Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
if (!os_plugin_object_sp)
|
|
|
|
|
return ValueObjectListSP();
|
2018-10-30 20:00:22 -08:00
|
|
|
|
|
|
|
|
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
|
2019-03-29 12:17:20 -08:00
|
|
|
if (!generic)
|
|
|
|
|
return nullptr;
|
2018-10-30 20:00:22 -08:00
|
|
|
|
|
|
|
|
PythonObject implementor(PyRefType::Borrowed,
|
|
|
|
|
(PyObject *)generic->GetValue());
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
if (!implementor.IsAllocated())
|
|
|
|
|
return ValueObjectListSP();
|
2018-10-30 20:00:22 -08:00
|
|
|
|
2019-03-26 13:57:02 -08:00
|
|
|
PythonObject py_return(PyRefType::Owned,
|
|
|
|
|
(PyObject *)LLDBSwigPython_GetRecognizedArguments(
|
|
|
|
|
implementor.get(), frame_sp));
|
2018-10-30 20:00:22 -08:00
|
|
|
|
|
|
|
|
// if it fails, print the error but otherwise go on
|
|
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
|
PyErr_Print();
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
}
|
|
|
|
|
if (py_return.get()) {
|
|
|
|
|
PythonList result_list(PyRefType::Borrowed, py_return.get());
|
|
|
|
|
ValueObjectListSP result = ValueObjectListSP(new ValueObjectList());
|
2018-10-31 10:03:36 -08:00
|
|
|
for (size_t i = 0; i < result_list.GetSize(); i++) {
|
2018-10-30 20:00:22 -08:00
|
|
|
PyObject *item = result_list.GetItemAtIndex(i).get();
|
|
|
|
|
lldb::SBValue *sb_value_ptr =
|
2019-03-26 13:57:02 -08:00
|
|
|
(lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(item);
|
|
|
|
|
auto valobj_sp = LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr);
|
2019-03-29 12:17:20 -08:00
|
|
|
if (valobj_sp)
|
|
|
|
|
result->Append(valobj_sp);
|
2018-10-30 20:00:22 -08:00
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
return ValueObjectListSP();
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
StructuredData::GenericSP
|
|
|
|
|
ScriptInterpreterPythonImpl::OSPlugin_CreatePluginObject(
|
2016-09-06 12:57:50 -08:00
|
|
|
const char *class_name, lldb::ProcessSP process_sp) {
|
|
|
|
|
if (class_name == nullptr || class_name[0] == '\0')
|
|
|
|
|
return StructuredData::GenericSP();
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!process_sp)
|
|
|
|
|
return StructuredData::GenericSP();
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
void *ret_val;
|
2012-08-09 15:09:42 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
{
|
|
|
|
|
Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN,
|
|
|
|
|
Locker::FreeLock);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSWIGPythonCreateOSPlugin(
|
|
|
|
|
class_name, m_dictionary_name.c_str(), process_sp);
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
|
2012-08-09 15:09:42 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_RegisterInfo(
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::ObjectSP os_plugin_object_sp) {
|
|
|
|
|
Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
|
2014-04-01 17:04:55 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
static char callee_name[] = "get_register_info";
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!os_plugin_object_sp)
|
|
|
|
|
return StructuredData::DictionarySP();
|
2012-08-09 15:09:42 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
|
|
|
|
|
if (!generic)
|
|
|
|
|
return nullptr;
|
2012-08-09 15:09:42 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject implementor(PyRefType::Borrowed,
|
|
|
|
|
(PyObject *)generic->GetValue());
|
2012-08-09 15:09:42 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!implementor.IsAllocated())
|
|
|
|
|
return StructuredData::DictionarySP();
|
2012-08-09 15:09:42 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject pmeth(PyRefType::Owned,
|
|
|
|
|
PyObject_GetAttrString(implementor.get(), callee_name));
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
2010-06-08 08:52:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!pmeth.IsAllocated())
|
|
|
|
|
return StructuredData::DictionarySP();
|
2012-03-06 14:42:15 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyCallable_Check(pmeth.get()) == 0) {
|
|
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
2011-07-14 18:26:42 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
return StructuredData::DictionarySP();
|
|
|
|
|
}
|
2012-03-06 14:42:15 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
2011-07-14 18:26:42 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// right now we know this function exists and is callable..
|
|
|
|
|
PythonObject py_return(
|
|
|
|
|
PyRefType::Owned,
|
|
|
|
|
PyObject_CallMethod(implementor.get(), callee_name, nullptr));
|
2012-03-06 14:42:15 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// if it fails, print the error but otherwise go on
|
|
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
|
PyErr_Print();
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
}
|
|
|
|
|
if (py_return.get()) {
|
|
|
|
|
PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
|
|
|
|
|
return result_dict.CreateStructuredDictionary();
|
|
|
|
|
}
|
|
|
|
|
return StructuredData::DictionarySP();
|
2011-08-16 08:49:25 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
StructuredData::ArraySP ScriptInterpreterPythonImpl::OSPlugin_ThreadsInfo(
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::ObjectSP os_plugin_object_sp) {
|
|
|
|
|
Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
|
2011-08-16 08:49:25 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
static char callee_name[] = "get_thread_info";
|
2011-07-25 08:59:05 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!os_plugin_object_sp)
|
|
|
|
|
return StructuredData::ArraySP();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
|
|
|
|
|
if (!generic)
|
|
|
|
|
return nullptr;
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject implementor(PyRefType::Borrowed,
|
|
|
|
|
(PyObject *)generic->GetValue());
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!implementor.IsAllocated())
|
|
|
|
|
return StructuredData::ArraySP();
|
2012-08-23 16:30:47 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject pmeth(PyRefType::Owned,
|
|
|
|
|
PyObject_GetAttrString(implementor.get(), callee_name));
|
|
|
|
|
|
|
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
|
|
|
|
|
if (!pmeth.IsAllocated())
|
|
|
|
|
return StructuredData::ArraySP();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyCallable_Check(pmeth.get()) == 0) {
|
|
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
return StructuredData::ArraySP();
|
|
|
|
|
}
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// right now we know this function exists and is callable..
|
|
|
|
|
PythonObject py_return(
|
|
|
|
|
PyRefType::Owned,
|
|
|
|
|
PyObject_CallMethod(implementor.get(), callee_name, 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
|
|
|
|
2016-09-06 12:57:50 -08: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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (py_return.get()) {
|
|
|
|
|
PythonList result_list(PyRefType::Borrowed, py_return.get());
|
|
|
|
|
return result_list.CreateStructuredArray();
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// GetPythonValueFormatString provides a system independent type safe way to
|
|
|
|
|
// convert a variable's type into a python value format. Python value formats
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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
|
2016-09-06 12:57:50 -08:00
|
|
|
// change.
|
|
|
|
|
|
2017-01-06 01:20:32 -09:00
|
|
|
template <typename T> const char *GetPythonValueFormatString(T t);
|
2016-09-06 12:57:50 -08: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";
|
2012-08-23 16:30:47 -08:00
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
template <> const char *GetPythonValueFormatString(float t) { return "f"; }
|
|
|
|
|
template <> const char *GetPythonValueFormatString(double t) { return "d"; }
|
2012-08-23 16:30:47 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
StructuredData::StringSP
|
|
|
|
|
ScriptInterpreterPythonImpl::OSPlugin_RegisterContextData(
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) {
|
|
|
|
|
Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
|
2012-08-23 17:34:39 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
static char callee_name[] = "get_register_data";
|
|
|
|
|
static char *param_format =
|
|
|
|
|
const_cast<char *>(GetPythonValueFormatString(tid));
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!os_plugin_object_sp)
|
|
|
|
|
return StructuredData::StringSP();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
|
|
|
|
|
if (!generic)
|
|
|
|
|
return nullptr;
|
|
|
|
|
PythonObject implementor(PyRefType::Borrowed,
|
|
|
|
|
(PyObject *)generic->GetValue());
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject pmeth(PyRefType::Owned,
|
|
|
|
|
PyObject_GetAttrString(implementor.get(), callee_name));
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08: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
|
|
|
|
2016-09-06 12:57:50 -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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyCallable_Check(pmeth.get()) == 0) {
|
2012-08-23 16:51:29 -08:00
|
|
|
if (PyErr_Occurred())
|
2016-09-06 12:57:50 -08:00
|
|
|
PyErr_Clear();
|
|
|
|
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// right now we know this function exists and is callable..
|
|
|
|
|
PythonObject py_return(
|
|
|
|
|
PyRefType::Owned,
|
|
|
|
|
PyObject_CallMethod(implementor.get(), callee_name, param_format, tid));
|
2012-08-23 16:51:29 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// if it fails, print the error but otherwise go on
|
|
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
|
PyErr_Print();
|
|
|
|
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (py_return.get()) {
|
|
|
|
|
PythonBytes result(PyRefType::Borrowed, py_return.get());
|
|
|
|
|
return result.CreateStructuredString();
|
|
|
|
|
}
|
|
|
|
|
return StructuredData::StringSP();
|
<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
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread(
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid,
|
|
|
|
|
lldb::addr_t context) {
|
|
|
|
|
Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
static char callee_name[] = "create_thread";
|
|
|
|
|
std::string param_format;
|
|
|
|
|
param_format += GetPythonValueFormatString(tid);
|
|
|
|
|
param_format += GetPythonValueFormatString(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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!os_plugin_object_sp)
|
|
|
|
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric();
|
|
|
|
|
if (!generic)
|
|
|
|
|
return nullptr;
|
2012-08-23 16:51:29 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject implementor(PyRefType::Borrowed,
|
|
|
|
|
(PyObject *)generic->GetValue());
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!implementor.IsAllocated())
|
|
|
|
|
return StructuredData::DictionarySP();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject pmeth(PyRefType::Owned,
|
|
|
|
|
PyObject_GetAttrString(implementor.get(), callee_name));
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -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
|
|
|
|
2016-09-06 12:57:50 -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())
|
2016-09-06 12:57:50 -08:00
|
|
|
PyErr_Clear();
|
|
|
|
|
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
|
|
|
|
2016-09-06 12:57:50 -08: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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// right now we know this function exists and is callable..
|
|
|
|
|
PythonObject py_return(PyRefType::Owned,
|
|
|
|
|
PyObject_CallMethod(implementor.get(), callee_name,
|
|
|
|
|
¶m_format[0], tid, context));
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
// if it fails, print the error but otherwise go on
|
|
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
|
PyErr_Print();
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
}
|
2012-08-23 16:51:29 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (py_return.get()) {
|
|
|
|
|
PythonDictionary result_dict(PyRefType::Borrowed, py_return.get());
|
|
|
|
|
return result_dict.CreateStructuredDictionary();
|
|
|
|
|
}
|
|
|
|
|
return StructuredData::DictionarySP();
|
|
|
|
|
}
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan(
|
2016-09-06 12:57:50 -08:00
|
|
|
const char *class_name, lldb::ThreadPlanSP thread_plan_sp) {
|
|
|
|
|
if (class_name == nullptr || class_name[0] == '\0')
|
|
|
|
|
return StructuredData::ObjectSP();
|
2014-09-29 15:17:18 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!thread_plan_sp.get())
|
|
|
|
|
return StructuredData::ObjectSP();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger();
|
2019-04-26 14:43:16 -08:00
|
|
|
ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter();
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl *python_interpreter =
|
|
|
|
|
static_cast<ScriptInterpreterPythonImpl *>(script_interpreter);
|
2014-09-29 15:17:18 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!script_interpreter)
|
|
|
|
|
return StructuredData::ObjectSP();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
void *ret_val;
|
2014-09-29 15:17:18 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
{
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2014-09-29 15:17:18 -08:00
|
|
|
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSwigPythonCreateScriptedThreadPlan(
|
2016-09-06 12:57:50 -08:00
|
|
|
class_name, python_interpreter->m_dictionary_name.c_str(),
|
|
|
|
|
thread_plan_sp);
|
|
|
|
|
}
|
2014-09-29 15:17:18 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
return StructuredData::ObjectSP(new StructuredPythonObject(ret_val));
|
2016-08-05 14:06:12 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::ScriptedThreadPlanExplainsStop(
|
2016-09-06 12:57:50 -08:00
|
|
|
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);
|
2019-03-26 13:57:02 -08:00
|
|
|
explains_stop = LLDBSWIGPythonCallThreadPlan(
|
2016-09-06 12:57:50 -08:00
|
|
|
generic->GetValue(), "explains_stop", event, script_error);
|
|
|
|
|
if (script_error)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return explains_stop;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::ScriptedThreadPlanShouldStop(
|
2016-09-06 12:57:50 -08:00
|
|
|
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);
|
2019-03-26 13:57:02 -08:00
|
|
|
should_stop = LLDBSWIGPythonCallThreadPlan(
|
|
|
|
|
generic->GetValue(), "should_stop", event, script_error);
|
2016-09-06 12:57:50 -08:00
|
|
|
if (script_error)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return should_stop;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::ScriptedThreadPlanIsStale(
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::ObjectSP implementor_sp, bool &script_error) {
|
|
|
|
|
bool is_stale = true;
|
|
|
|
|
StructuredData::Generic *generic = nullptr;
|
|
|
|
|
if (implementor_sp)
|
|
|
|
|
generic = implementor_sp->GetAsGeneric();
|
|
|
|
|
if (generic) {
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
is_stale = LLDBSWIGPythonCallThreadPlan(generic->GetValue(), "is_stale",
|
|
|
|
|
nullptr, script_error);
|
2016-09-06 12:57:50 -08:00
|
|
|
if (script_error)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return is_stale;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
lldb::StateType ScriptInterpreterPythonImpl::ScriptedThreadPlanGetRunState(
|
2016-09-06 12:57:50 -08:00
|
|
|
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);
|
2019-03-26 13:57:02 -08:00
|
|
|
should_step = LLDBSWIGPythonCallThreadPlan(
|
[lldb] NFC modernize codebase with modernize-use-nullptr
Summary:
NFC = [[ https://llvm.org/docs/Lexicon.html#nfc | Non functional change ]]
This commit is the result of modernizing the LLDB codebase by using
`nullptr` instread of `0` or `NULL`. See
https://clang.llvm.org/extra/clang-tidy/checks/modernize-use-nullptr.html
for more information.
This is the command I ran and I to fix and format the code base:
```
run-clang-tidy.py \
-header-filter='.*' \
-checks='-*,modernize-use-nullptr' \
-fix ~/dev/llvm-project/lldb/.* \
-format \
-style LLVM \
-p ~/llvm-builds/debug-ninja-gcc
```
NOTE: There were also changes to `llvm/utils/unittest` but I did not
include them because I felt that maybe this library shall be updated in
isolation somehow.
NOTE: I know this is a rather large commit but it is a nobrainer in most
parts.
Reviewers: martong, espindola, shafik, #lldb, JDevlieghere
Reviewed By: JDevlieghere
Subscribers: arsenm, jvesely, nhaehnle, hiraditya, JDevlieghere, teemperor, rnkovacs, emaste, kubamracek, nemanjai, ki.stfu, javed.absar, arichardson, kbarton, jrtc27, MaskRay, atanasyan, dexonsmith, arphaman, jfb, jsji, jdoerfert, lldb-commits, llvm-commits
Tags: #lldb, #llvm
Differential Revision: https://reviews.llvm.org/D61847
llvm-svn: 361484
2019-05-23 03:14:47 -08:00
|
|
|
generic->GetValue(), "should_step", nullptr, script_error);
|
2016-09-06 12:57:50 -08:00
|
|
|
if (script_error)
|
|
|
|
|
should_step = true;
|
|
|
|
|
}
|
|
|
|
|
if (should_step)
|
|
|
|
|
return lldb::eStateStepping;
|
|
|
|
|
else
|
|
|
|
|
return lldb::eStateRunning;
|
2014-09-29 15:17:18 -08:00
|
|
|
}
|
|
|
|
|
|
2018-09-13 13:35:32 -08:00
|
|
|
StructuredData::GenericSP
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver(
|
|
|
|
|
const char *class_name, StructuredDataImpl *args_data,
|
2018-09-13 13:35:32 -08:00
|
|
|
lldb::BreakpointSP &bkpt_sp) {
|
2019-03-25 12:14:31 -08:00
|
|
|
|
2018-09-13 13:35:32 -08:00
|
|
|
if (class_name == nullptr || class_name[0] == '\0')
|
|
|
|
|
return StructuredData::GenericSP();
|
|
|
|
|
|
|
|
|
|
if (!bkpt_sp.get())
|
|
|
|
|
return StructuredData::GenericSP();
|
|
|
|
|
|
|
|
|
|
Debugger &debugger = bkpt_sp->GetTarget().GetDebugger();
|
2019-04-26 14:43:16 -08:00
|
|
|
ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter();
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl *python_interpreter =
|
|
|
|
|
static_cast<ScriptInterpreterPythonImpl *>(script_interpreter);
|
2018-09-13 13:35:32 -08:00
|
|
|
|
|
|
|
|
if (!script_interpreter)
|
|
|
|
|
return StructuredData::GenericSP();
|
|
|
|
|
|
|
|
|
|
void *ret_val;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
|
|
|
|
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSwigPythonCreateScriptedBreakpointResolver(
|
|
|
|
|
class_name, python_interpreter->m_dictionary_name.c_str(), args_data,
|
|
|
|
|
bkpt_sp);
|
2018-09-13 13:35:32 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchCallback(
|
|
|
|
|
StructuredData::GenericSP implementor_sp, SymbolContext *sym_ctx) {
|
2018-09-13 13:35:32 -08:00
|
|
|
bool should_continue = false;
|
2019-03-25 12:14:31 -08:00
|
|
|
|
2018-09-13 13:35:32 -08:00
|
|
|
if (implementor_sp) {
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
should_continue = LLDBSwigPythonCallBreakpointResolver(
|
|
|
|
|
implementor_sp->GetValue(), "__callback__", sym_ctx);
|
2018-09-13 13:35:32 -08:00
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
|
PyErr_Print();
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return should_continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lldb::SearchDepth
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchDepth(
|
2018-09-13 13:35:32 -08:00
|
|
|
StructuredData::GenericSP implementor_sp) {
|
|
|
|
|
int depth_as_int = lldb::eSearchDepthModule;
|
|
|
|
|
if (implementor_sp) {
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
depth_as_int = LLDBSwigPythonCallBreakpointResolver(
|
|
|
|
|
implementor_sp->GetValue(), "__get_depth__", nullptr);
|
2018-09-13 13:35:32 -08:00
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
|
PyErr_Print();
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (depth_as_int == lldb::eSearchDepthInvalid)
|
|
|
|
|
return lldb::eSearchDepthModule;
|
|
|
|
|
|
|
|
|
|
if (depth_as_int <= lldb::kLastSearchDepthKind)
|
2019-03-29 12:17:20 -08:00
|
|
|
return (lldb::SearchDepth)depth_as_int;
|
2018-09-13 13:35:32 -08:00
|
|
|
else
|
|
|
|
|
return lldb::eSearchDepthModule;
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-17 12:04:04 -08:00
|
|
|
StructuredData::ObjectSP
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec,
|
|
|
|
|
lldb_private::Status &error) {
|
2018-11-01 09:09:25 -08:00
|
|
|
if (!FileSystem::Instance().Exists(file_spec)) {
|
2016-09-06 12:57:50 -08:00
|
|
|
error.SetErrorString("no such file");
|
|
|
|
|
return StructuredData::ObjectSP();
|
|
|
|
|
}
|
2013-10-14 13:39:38 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::ObjectSP module_sp;
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (LoadScriptingModule(file_spec.GetPath().c_str(), true, true, error,
|
|
|
|
|
&module_sp))
|
|
|
|
|
return module_sp;
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
return StructuredData::ObjectSP();
|
2013-10-14 13:39:38 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
StructuredData::DictionarySP ScriptInterpreterPythonImpl::GetDynamicSettings(
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::ObjectSP plugin_module_sp, Target *target,
|
2017-05-11 20:51:55 -08:00
|
|
|
const char *setting_name, lldb_private::Status &error) {
|
2019-03-26 13:57:02 -08:00
|
|
|
if (!plugin_module_sp || !target || !setting_name || !setting_name[0])
|
2016-09-06 12:57:50 -08:00
|
|
|
return StructuredData::DictionarySP();
|
|
|
|
|
StructuredData::Generic *generic = plugin_module_sp->GetAsGeneric();
|
|
|
|
|
if (!generic)
|
|
|
|
|
return StructuredData::DictionarySP();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject reply_pyobj;
|
2017-07-09 15:32:15 -08:00
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
|
|
|
|
TargetSP target_sp(target->shared_from_this());
|
|
|
|
|
reply_pyobj.Reset(PyRefType::Owned,
|
2019-03-26 13:57:02 -08:00
|
|
|
(PyObject *)LLDBSWIGPython_GetDynamicSetting(
|
|
|
|
|
generic->GetValue(), setting_name, target_sp));
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonDictionary py_dict(PyRefType::Borrowed, reply_pyobj.get());
|
|
|
|
|
return py_dict.CreateStructuredDictionary();
|
2013-10-14 13:39:38 -08:00
|
|
|
}
|
|
|
|
|
|
2015-03-17 12:04:04 -08:00
|
|
|
StructuredData::ObjectSP
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::CreateSyntheticScriptedProvider(
|
2016-09-06 12:57:50 -08:00
|
|
|
const char *class_name, lldb::ValueObjectSP valobj) {
|
|
|
|
|
if (class_name == nullptr || class_name[0] == '\0')
|
|
|
|
|
return StructuredData::ObjectSP();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!valobj.get())
|
|
|
|
|
return StructuredData::ObjectSP();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
ExecutionContext exe_ctx(valobj->GetExecutionContextRef());
|
|
|
|
|
Target *target = exe_ctx.GetTargetPtr();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!target)
|
|
|
|
|
return StructuredData::ObjectSP();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
Debugger &debugger = target->GetDebugger();
|
2019-04-26 14:43:16 -08:00
|
|
|
ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter();
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl *python_interpreter =
|
|
|
|
|
(ScriptInterpreterPythonImpl *)script_interpreter;
|
2011-10-24 09:22:21 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!script_interpreter)
|
|
|
|
|
return StructuredData::ObjectSP();
|
|
|
|
|
|
|
|
|
|
void *ret_val = nullptr;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSwigPythonCreateSyntheticProvider(
|
2016-09-06 12:57:50 -08:00
|
|
|
class_name, python_interpreter->m_dictionary_name.c_str(), valobj);
|
|
|
|
|
}
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
return StructuredData::ObjectSP(new StructuredPythonObject(ret_val));
|
2011-07-23 16:14:56 -08:00
|
|
|
}
|
|
|
|
|
|
2015-03-17 12:04:04 -08:00
|
|
|
StructuredData::GenericSP
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::CreateScriptCommandObject(const char *class_name) {
|
2019-04-26 09:58:19 -08:00
|
|
|
DebuggerSP debugger_sp(m_debugger.shared_from_this());
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
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);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSwigPythonCreateCommandObject(
|
|
|
|
|
class_name, m_dictionary_name.c_str(), debugger_sp);
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return StructuredData::GenericSP(new StructuredPythonObject(ret_val));
|
2015-03-12 18:20:41 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction(
|
2016-09-06 12:57:50 -08:00
|
|
|
const char *oneliner, std::string &output, const void *name_token) {
|
|
|
|
|
StringList input;
|
|
|
|
|
input.SplitIntoLines(oneliner, strlen(oneliner));
|
|
|
|
|
return GenerateTypeScriptFunction(input, output, name_token);
|
2011-07-14 18:26:42 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass(
|
|
|
|
|
const char *oneliner, std::string &output, const void *name_token) {
|
2016-09-06 12:57:50 -08:00
|
|
|
StringList input;
|
|
|
|
|
input.SplitIntoLines(oneliner, strlen(oneliner));
|
|
|
|
|
return GenerateTypeSynthClass(input, output, name_token);
|
2012-02-14 17:34:21 -09:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData(
|
2016-09-06 12:57:50 -08:00
|
|
|
StringList &user_input, std::string &output) {
|
|
|
|
|
static uint32_t num_created_functions = 0;
|
|
|
|
|
user_input.RemoveBlankLines();
|
|
|
|
|
StreamString sstr;
|
2017-05-11 20:51:55 -08:00
|
|
|
Status error;
|
2016-09-06 12:57:50 -08:00
|
|
|
if (user_input.GetSize() == 0) {
|
|
|
|
|
error.SetErrorString("No input data.");
|
|
|
|
|
return error;
|
|
|
|
|
}
|
2012-02-14 17:34:21 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
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());
|
2010-11-19 11:47:54 -09:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
error = GenerateFunction(sstr.GetData(), user_input);
|
|
|
|
|
if (!error.Success())
|
2014-04-01 17:04:55 -08:00
|
|
|
return error;
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
// Store the name of the auto-generated function to be called.
|
|
|
|
|
output.assign(auto_generated_function_name);
|
|
|
|
|
return error;
|
2010-06-08 08:52:24 -08:00
|
|
|
}
|
2010-09-27 10:00:20 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::GenerateWatchpointCommandCallbackData(
|
2016-09-06 12:57:50 -08:00
|
|
|
StringList &user_input, std::string &output) {
|
|
|
|
|
static uint32_t num_created_functions = 0;
|
|
|
|
|
user_input.RemoveBlankLines();
|
|
|
|
|
StreamString sstr;
|
2012-08-09 15:09:42 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (user_input.GetSize() == 0)
|
|
|
|
|
return false;
|
2012-08-09 15:09:42 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
2012-08-09 15:09:42 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::GetScriptedSummary(
|
2016-09-06 12:57:50 -08:00
|
|
|
const char *python_function_name, lldb::ValueObjectSP valobj,
|
|
|
|
|
StructuredData::ObjectSP &callee_wrapper_sp,
|
|
|
|
|
const TypeSummaryOptions &options, std::string &retval) {
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2017-05-15 05:02:37 -08:00
|
|
|
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
|
|
|
|
|
Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
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));
|
|
|
|
|
|
2019-03-26 13:57:02 -08:00
|
|
|
static Timer::Category func_cat("LLDBSwigPythonCallTypeScript");
|
|
|
|
|
Timer scoped_timer(func_cat, "LLDBSwigPythonCallTypeScript");
|
|
|
|
|
ret_val = LLDBSwigPythonCallTypeScript(
|
2016-09-06 12:57:50 -08:00
|
|
|
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)
|
2019-02-11 14:13:08 -09:00
|
|
|
callee_wrapper_sp = std::make_shared<StructuredPythonObject>(new_callee);
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
return ret_val;
|
2011-07-14 18:26:42 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::Clear() {
|
2016-09-06 12:57:50 -08:00
|
|
|
// Release any global variables that might have strong references to
|
|
|
|
|
// LLDB objects when clearing the python script interpreter.
|
2019-03-29 12:17:20 -08:00
|
|
|
Locker locker(this, Locker::AcquireLock, Locker::FreeAcquiredLock);
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
// This may be called as part of Py_Finalize. In that case the modules are
|
2018-04-30 08:49:04 -08:00
|
|
|
// destroyed in random order and we can't guarantee that we can access these.
|
2016-09-06 12:57:50 -08:00
|
|
|
if (Py_IsInitialized())
|
|
|
|
|
PyRun_SimpleString("lldb.debugger = None; lldb.target = None; lldb.process "
|
|
|
|
|
"= None; lldb.thread = None; lldb.frame = None");
|
2010-10-07 09:14:24 -08:00
|
|
|
}
|
2010-11-10 10:18:14 -09:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction(
|
2016-09-06 12:57:50 -08:00
|
|
|
void *baton, StoppointCallbackContext *context, user_id_t break_id,
|
|
|
|
|
user_id_t break_loc_id) {
|
2016-09-26 11:47:37 -08:00
|
|
|
CommandDataPython *bp_option_data = (CommandDataPython *)baton;
|
2016-09-06 12:57:50 -08:00
|
|
|
const char *python_function_name = bp_option_data->script_source.c_str();
|
|
|
|
|
|
|
|
|
|
if (!context)
|
2012-08-09 15:09:42 -08:00
|
|
|
return true;
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
ExecutionContext exe_ctx(context->exe_ctx_ref);
|
|
|
|
|
Target *target = exe_ctx.GetTargetPtr();
|
2011-07-23 16:14:56 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!target)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
Debugger &debugger = target->GetDebugger();
|
2019-04-26 14:43:16 -08:00
|
|
|
ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter();
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl *python_interpreter =
|
|
|
|
|
(ScriptInterpreterPythonImpl *)script_interpreter;
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
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;
|
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
|
|
|
{
|
2016-09-06 12:57:50 -08:00
|
|
|
Locker py_lock(python_interpreter, Locker::AcquireLock |
|
|
|
|
|
Locker::InitSession |
|
|
|
|
|
Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSwigPythonBreakpointCallbackFunction(
|
2016-09-06 12:57:50 -08:00
|
|
|
python_function_name,
|
|
|
|
|
python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
|
|
|
|
|
bp_loc_sp);
|
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
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
return ret_val;
|
|
|
|
|
}
|
2011-07-23 16:14:56 -08:00
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
// We currently always true so we stop in case anything goes wrong when
|
|
|
|
|
// trying to call the script function
|
|
|
|
|
return true;
|
2011-07-23 16:14:56 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::WatchpointCallbackFunction(
|
2016-09-06 12:57:50 -08:00
|
|
|
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();
|
2011-07-23 16:14:56 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!context)
|
|
|
|
|
return true;
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
ExecutionContext exe_ctx(context->exe_ctx_ref);
|
|
|
|
|
Target *target = exe_ctx.GetTargetPtr();
|
|
|
|
|
|
|
|
|
|
if (!target)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
Debugger &debugger = target->GetDebugger();
|
2019-04-26 14:43:16 -08:00
|
|
|
ScriptInterpreter *script_interpreter = debugger.GetScriptInterpreter();
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl *python_interpreter =
|
|
|
|
|
(ScriptInterpreterPythonImpl *)script_interpreter;
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
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);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSwigPythonWatchpointCallbackFunction(
|
2016-09-06 12:57:50 -08:00
|
|
|
python_function_name,
|
|
|
|
|
python_interpreter->m_dictionary_name.c_str(), stop_frame_sp,
|
|
|
|
|
wp_sp);
|
|
|
|
|
}
|
2012-03-19 14:58:49 -08:00
|
|
|
return ret_val;
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
2011-07-29 11:53:35 -08:00
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
// We currently always true so we stop in case anything goes wrong when
|
|
|
|
|
// trying to call the script function
|
|
|
|
|
return true;
|
2011-07-29 11:53:35 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
size_t ScriptInterpreterPythonImpl::CalculateNumChildren(
|
2016-09-06 12:57:50 -08:00
|
|
|
const StructuredData::ObjectSP &implementor_sp, uint32_t max) {
|
|
|
|
|
if (!implementor_sp)
|
|
|
|
|
return 0;
|
|
|
|
|
StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
|
|
|
|
|
if (!generic)
|
|
|
|
|
return 0;
|
|
|
|
|
void *implementor = generic->GetValue();
|
|
|
|
|
if (!implementor)
|
|
|
|
|
return 0;
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
size_t ret_val = 0;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSwigPython_CalculateNumChildren(implementor, max);
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
2012-10-23 11:54:09 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetChildAtIndex(
|
2016-09-06 12:57:50 -08:00
|
|
|
const StructuredData::ObjectSP &implementor_sp, uint32_t idx) {
|
|
|
|
|
if (!implementor_sp)
|
|
|
|
|
return lldb::ValueObjectSP();
|
2015-03-17 12:04:04 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
|
|
|
|
|
if (!generic)
|
|
|
|
|
return lldb::ValueObjectSP();
|
|
|
|
|
void *implementor = generic->GetValue();
|
|
|
|
|
if (!implementor)
|
|
|
|
|
return lldb::ValueObjectSP();
|
|
|
|
|
|
|
|
|
|
lldb::ValueObjectSP ret_val;
|
|
|
|
|
{
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
void *child_ptr = LLDBSwigPython_GetChildAtIndex(implementor, idx);
|
2016-09-06 12:57:50 -08:00
|
|
|
if (child_ptr != nullptr && child_ptr != Py_None) {
|
|
|
|
|
lldb::SBValue *sb_value_ptr =
|
2019-03-26 13:57:02 -08:00
|
|
|
(lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(child_ptr);
|
2016-09-06 12:57:50 -08:00
|
|
|
if (sb_value_ptr == nullptr)
|
|
|
|
|
Py_XDECREF(child_ptr);
|
|
|
|
|
else
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr);
|
2016-09-06 12:57:50 -08:00
|
|
|
} else {
|
|
|
|
|
Py_XDECREF(child_ptr);
|
Extend synthetic children to produce synthetic values (as in, those that GetValueAsUnsigned(), GetValueAsCString() would return)
The way to do this is to write a synthetic child provider for your type, and have it vend the (optional) get_value function.
If get_value is defined, and it returns a valid SBValue, that SBValue's value (as in lldb_private::Value) will be used as the synthetic ValueObject's Value
The rationale for doing things this way is twofold:
- there are many possible ways to define a "value" (SBData, a Python number, ...) but SBValue seems general enough as a thing that stores a "value", so we just trade values that way and that keeps our currency trivial
- we could introduce a new level of layering (ValueObjectSyntheticValue), a new kind of formatter (synthetic value producer), but that would complicate the model (can I have a dynamic with no synthetic children but synthetic value? synthetic value with synthetic children but no dynamic?), and I really couldn't see much benefit to be reaped from this added complexity in the matrix
On the other hand, just defining a synthetic child provider with a get_value but returning no actual children is easy enough that it's not a significant road-block to adoption of this feature
Comes with a test case
llvm-svn: 219330
2014-10-08 10:27:36 -08:00
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
Extend synthetic children to produce synthetic values (as in, those that GetValueAsUnsigned(), GetValueAsCString() would return)
The way to do this is to write a synthetic child provider for your type, and have it vend the (optional) get_value function.
If get_value is defined, and it returns a valid SBValue, that SBValue's value (as in lldb_private::Value) will be used as the synthetic ValueObject's Value
The rationale for doing things this way is twofold:
- there are many possible ways to define a "value" (SBData, a Python number, ...) but SBValue seems general enough as a thing that stores a "value", so we just trade values that way and that keeps our currency trivial
- we could introduce a new level of layering (ValueObjectSyntheticValue), a new kind of formatter (synthetic value producer), but that would complicate the model (can I have a dynamic with no synthetic children but synthetic value? synthetic value with synthetic children but no dynamic?), and I really couldn't see much benefit to be reaped from this added complexity in the matrix
On the other hand, just defining a synthetic child provider with a get_value but returning no actual children is easy enough that it's not a significant road-block to adoption of this feature
Comes with a test case
llvm-svn: 219330
2014-10-08 10:27:36 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
int ScriptInterpreterPythonImpl::GetIndexOfChildWithName(
|
2016-09-06 12:57:50 -08:00
|
|
|
const StructuredData::ObjectSP &implementor_sp, const char *child_name) {
|
|
|
|
|
if (!implementor_sp)
|
|
|
|
|
return UINT32_MAX;
|
2016-05-01 16:41:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
|
|
|
|
|
if (!generic)
|
|
|
|
|
return UINT32_MAX;
|
|
|
|
|
void *implementor = generic->GetValue();
|
|
|
|
|
if (!implementor)
|
|
|
|
|
return UINT32_MAX;
|
2016-05-01 16:41:24 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
int ret_val = UINT32_MAX;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSwigPython_GetIndexOfChildWithName(implementor, child_name);
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
2016-05-01 16:41:24 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::UpdateSynthProviderInstance(
|
2016-09-06 12:57:50 -08:00
|
|
|
const StructuredData::ObjectSP &implementor_sp) {
|
|
|
|
|
bool ret_val = false;
|
|
|
|
|
|
|
|
|
|
if (!implementor_sp)
|
2013-06-20 15:40:21 -08:00
|
|
|
return ret_val;
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
|
|
|
|
|
if (!generic)
|
|
|
|
|
return ret_val;
|
|
|
|
|
void *implementor = generic->GetValue();
|
|
|
|
|
if (!implementor)
|
2013-06-20 15:40:21 -08:00
|
|
|
return ret_val;
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
{
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSwigPython_UpdateSynthProviderInstance(implementor);
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
2013-06-20 15:40:21 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::MightHaveChildrenSynthProviderInstance(
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val =
|
|
|
|
|
LLDBSwigPython_MightHaveChildrenSynthProviderInstance(implementor);
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
2013-06-20 15:40:21 -08:00
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetSyntheticValue(
|
2016-09-06 12:57:50 -08:00
|
|
|
const StructuredData::ObjectSP &implementor_sp) {
|
|
|
|
|
lldb::ValueObjectSP ret_val(nullptr);
|
|
|
|
|
|
|
|
|
|
if (!implementor_sp)
|
|
|
|
|
return ret_val;
|
|
|
|
|
|
|
|
|
|
StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
|
|
|
|
|
if (!generic)
|
2014-10-28 13:07:00 -08:00
|
|
|
return ret_val;
|
2016-09-06 12:57:50 -08:00
|
|
|
void *implementor = generic->GetValue();
|
|
|
|
|
if (!implementor)
|
|
|
|
|
return ret_val;
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
void *child_ptr = LLDBSwigPython_GetValueSynthProviderInstance(implementor);
|
2016-09-06 12:57:50 -08:00
|
|
|
if (child_ptr != nullptr && child_ptr != Py_None) {
|
|
|
|
|
lldb::SBValue *sb_value_ptr =
|
2019-03-26 13:57:02 -08:00
|
|
|
(lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(child_ptr);
|
2016-09-06 12:57:50 -08:00
|
|
|
if (sb_value_ptr == nullptr)
|
|
|
|
|
Py_XDECREF(child_ptr);
|
|
|
|
|
else
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr);
|
2016-09-06 12:57:50 -08:00
|
|
|
} else {
|
|
|
|
|
Py_XDECREF(child_ptr);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
2014-10-28 13:07:00 -08:00
|
|
|
}
|
2013-06-20 15:40:21 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
ConstString ScriptInterpreterPythonImpl::GetSyntheticTypeName(
|
2016-09-06 12:57:50 -08:00
|
|
|
const StructuredData::ObjectSP &implementor_sp) {
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
|
|
|
|
|
|
|
|
|
static char callee_name[] = "get_type_name";
|
|
|
|
|
|
|
|
|
|
ConstString ret_val;
|
|
|
|
|
bool got_string = false;
|
|
|
|
|
std::string buffer;
|
|
|
|
|
|
|
|
|
|
if (!implementor_sp)
|
|
|
|
|
return ret_val;
|
|
|
|
|
|
|
|
|
|
StructuredData::Generic *generic = implementor_sp->GetAsGeneric();
|
|
|
|
|
if (!generic)
|
|
|
|
|
return ret_val;
|
|
|
|
|
PythonObject implementor(PyRefType::Borrowed,
|
|
|
|
|
(PyObject *)generic->GetValue());
|
|
|
|
|
if (!implementor.IsAllocated())
|
|
|
|
|
return ret_val;
|
|
|
|
|
|
|
|
|
|
PythonObject pmeth(PyRefType::Owned,
|
|
|
|
|
PyObject_GetAttrString(implementor.get(), callee_name));
|
|
|
|
|
|
|
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
|
|
|
|
|
if (!pmeth.IsAllocated())
|
|
|
|
|
return ret_val;
|
|
|
|
|
|
|
|
|
|
if (PyCallable_Check(pmeth.get()) == 0) {
|
|
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
|
|
|
|
|
// right now we know this function exists and is callable..
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (py_return.IsAllocated() && PythonString::Check(py_return.get())) {
|
|
|
|
|
PythonString py_string(PyRefType::Borrowed, py_return.get());
|
|
|
|
|
llvm::StringRef return_data(py_string.GetString());
|
|
|
|
|
if (!return_data.empty()) {
|
|
|
|
|
buffer.assign(return_data.data(), return_data.size());
|
|
|
|
|
got_string = true;
|
2013-06-17 16:58:06 -08:00
|
|
|
}
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (got_string)
|
|
|
|
|
ret_val.SetCStringWithLength(buffer.c_str(), buffer.size());
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
2013-06-17 16:58:06 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
|
|
|
|
|
const char *impl_function, Process *process, std::string &output,
|
|
|
|
|
Status &error) {
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
|
|
|
|
}
|
2019-03-26 13:57:02 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
{
|
|
|
|
|
ProcessSP process_sp(process->shared_from_this());
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSWIGPythonRunScriptKeywordProcess(
|
2016-09-06 12:57:50 -08:00
|
|
|
impl_function, m_dictionary_name.c_str(), process_sp, output);
|
|
|
|
|
if (!ret_val)
|
|
|
|
|
error.SetErrorString("python script evaluation failed");
|
|
|
|
|
}
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
|
|
|
|
|
const char *impl_function, Thread *thread, std::string &output,
|
|
|
|
|
Status &error) {
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
|
|
|
|
}
|
2019-03-26 13:57:02 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
{
|
|
|
|
|
ThreadSP thread_sp(thread->shared_from_this());
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSWIGPythonRunScriptKeywordThread(
|
2016-09-06 12:57:50 -08:00
|
|
|
impl_function, m_dictionary_name.c_str(), thread_sp, output);
|
|
|
|
|
if (!ret_val)
|
|
|
|
|
error.SetErrorString("python script evaluation failed");
|
|
|
|
|
}
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
|
|
|
|
|
const char *impl_function, Target *target, std::string &output,
|
|
|
|
|
Status &error) {
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
|
|
|
|
}
|
2019-03-26 13:57:02 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
{
|
|
|
|
|
TargetSP target_sp(target->shared_from_this());
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSWIGPythonRunScriptKeywordTarget(
|
2016-09-06 12:57:50 -08:00
|
|
|
impl_function, m_dictionary_name.c_str(), target_sp, output);
|
|
|
|
|
if (!ret_val)
|
|
|
|
|
error.SetErrorString("python script evaluation failed");
|
|
|
|
|
}
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
|
|
|
|
|
const char *impl_function, StackFrame *frame, std::string &output,
|
|
|
|
|
Status &error) {
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
|
|
|
|
}
|
2019-03-26 13:57:02 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
{
|
|
|
|
|
StackFrameSP frame_sp(frame->shared_from_this());
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSWIGPythonRunScriptKeywordFrame(
|
2016-09-06 12:57:50 -08:00
|
|
|
impl_function, m_dictionary_name.c_str(), frame_sp, output);
|
|
|
|
|
if (!ret_val)
|
|
|
|
|
error.SetErrorString("python script evaluation failed");
|
|
|
|
|
}
|
|
|
|
|
return ret_val;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword(
|
|
|
|
|
const char *impl_function, ValueObject *value, std::string &output,
|
|
|
|
|
Status &error) {
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
|
|
|
|
}
|
2019-03-26 13:57:02 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
{
|
|
|
|
|
ValueObjectSP value_sp(value->GetSP());
|
|
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSWIGPythonRunScriptKeywordValue(
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::LoadScriptingModule(
|
2016-09-06 12:57:50 -08:00
|
|
|
const char *pathname, bool can_reload, bool init_session,
|
2017-05-11 20:51:55 -08:00
|
|
|
lldb_private::Status &error, StructuredData::ObjectSP *module_sp) {
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!pathname || !pathname[0]) {
|
|
|
|
|
error.SetErrorString("invalid pathname");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2019-04-26 09:58:19 -08:00
|
|
|
lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
{
|
2018-11-01 13:05:36 -08:00
|
|
|
FileSpec target_file(pathname);
|
|
|
|
|
FileSystem::Instance().Resolve(target_file);
|
2016-09-06 12:57:50 -08:00
|
|
|
std::string basename(target_file.GetFilename().GetCString());
|
|
|
|
|
|
|
|
|
|
StreamString command_stream;
|
|
|
|
|
|
|
|
|
|
// Before executing Python code, lock the GIL.
|
2019-03-29 12:17:20 -08:00
|
|
|
Locker py_lock(this,
|
|
|
|
|
Locker::AcquireLock |
|
|
|
|
|
(init_session ? Locker::InitSession : 0) |
|
|
|
|
|
Locker::NoSTDIN,
|
2016-09-06 12:57:50 -08:00
|
|
|
Locker::FreeAcquiredLock |
|
|
|
|
|
(init_session ? Locker::TearDownSession : 0));
|
2017-03-08 08:56:08 -09:00
|
|
|
namespace fs = llvm::sys::fs;
|
|
|
|
|
fs::file_status st;
|
|
|
|
|
std::error_code ec = status(target_file.GetPath(), st);
|
2016-09-06 12:57:50 -08:00
|
|
|
|
2017-03-08 08:56:08 -09:00
|
|
|
if (ec || st.type() == fs::file_type::status_error ||
|
|
|
|
|
st.type() == fs::file_type::type_unknown ||
|
|
|
|
|
st.type() == fs::file_type::file_not_found) {
|
2016-09-06 12:57:50 -08:00
|
|
|
// 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, '/')) {
|
2011-10-17 13:45:27 -08:00
|
|
|
error.SetErrorString("invalid pathname");
|
|
|
|
|
return false;
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
basename = pathname; // not a filename, probably a package of some sort,
|
|
|
|
|
// let it go through
|
2017-03-08 08:56:08 -09:00
|
|
|
} else if (is_directory(st) || is_regular_file(st)) {
|
2019-02-15 07:42:29 -09:00
|
|
|
if (target_file.GetDirectory().IsEmpty()) {
|
|
|
|
|
error.SetErrorString("invalid directory name");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
std::string directory = target_file.GetDirectory().GetCString();
|
|
|
|
|
replace_all(directory, "\\", "\\\\");
|
|
|
|
|
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");
|
2011-10-17 13:45:27 -08:00
|
|
|
return false;
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// strip .py or .pyc extension
|
|
|
|
|
ConstString extension = target_file.GetFileNameExtension();
|
|
|
|
|
if (extension) {
|
2018-06-13 08:23:21 -08:00
|
|
|
if (llvm::StringRef(extension.GetCString()) == ".py")
|
2016-09-06 12:57:50 -08:00
|
|
|
basename.resize(basename.length() - 3);
|
2018-06-13 08:23:21 -08:00
|
|
|
else if (llvm::StringRef(extension.GetCString()) == ".pyc")
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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
|
2016-09-06 12:57:50 -08:00
|
|
|
bool was_imported_globally =
|
|
|
|
|
(ExecuteOneLineWithReturn(
|
|
|
|
|
command_stream.GetData(),
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::eScriptReturnTypeBool, &does_contain,
|
2016-09-06 12:57:50 -08:00
|
|
|
ScriptInterpreter::ExecuteScriptOptions()
|
|
|
|
|
.SetEnableIO(false)
|
|
|
|
|
.SetSetLLDBGlobals(false)) &&
|
|
|
|
|
does_contain);
|
|
|
|
|
// this call will fail if the module was not imported in this Debugger
|
|
|
|
|
// before
|
|
|
|
|
command_stream.Clear();
|
|
|
|
|
command_stream.Printf("sys.getrefcount(%s)", basename.c_str());
|
|
|
|
|
bool was_imported_locally = GetSessionDictionary()
|
|
|
|
|
.GetItemForKey(PythonString(basename))
|
|
|
|
|
.IsAllocated();
|
|
|
|
|
|
|
|
|
|
bool was_imported = (was_imported_globally || was_imported_locally);
|
|
|
|
|
|
2018-12-14 15:15:33 -09:00
|
|
|
if (was_imported && !can_reload) {
|
2016-09-06 12:57:50 -08:00
|
|
|
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_module(%s)", basename.c_str(),
|
|
|
|
|
basename.c_str());
|
|
|
|
|
else
|
|
|
|
|
command_stream.Printf("reload_module(%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)
|
2019-03-26 13:57:02 -08:00
|
|
|
if (!LLDBSwigPythonCallModuleInit(basename.c_str(),
|
|
|
|
|
m_dictionary_name.c_str(), debugger_sp)) {
|
2016-09-06 12:57:50 -08:00
|
|
|
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)
|
2019-02-11 14:13:08 -09:00
|
|
|
*module_sp = std::make_shared<StructuredPythonObject>(module_pyobj);
|
2011-10-17 13:45:27 -08:00
|
|
|
}
|
2011-10-24 09:22:21 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-04-07 14:52:12 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::IsReservedWord(const char *word) {
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!word || !word[0])
|
|
|
|
|
return false;
|
2011-10-17 13:45:27 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
llvm::StringRef word_sr(word);
|
|
|
|
|
|
2018-04-30 08:49:04 -08:00
|
|
|
// filter out a few characters that would just confuse us and that are
|
|
|
|
|
// clearly not keyword material anyway
|
2019-04-24 12:40:24 -08:00
|
|
|
if (word_sr.find('"') != llvm::StringRef::npos ||
|
|
|
|
|
word_sr.find('\'') != llvm::StringRef::npos)
|
2016-09-06 12:57:50 -08:00
|
|
|
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;
|
2011-10-17 13:45:27 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::SynchronicityHandler::SynchronicityHandler(
|
2016-09-06 12:57:50 -08:00
|
|
|
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);
|
|
|
|
|
}
|
2015-06-15 15:12:29 -08:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::SynchronicityHandler::~SynchronicityHandler() {
|
2016-09-06 12:57:50 -08:00
|
|
|
if (m_synch_wanted != eScriptedCommandSynchronicityCurrentValue)
|
|
|
|
|
m_debugger_sp->SetAsyncExecution(m_old_asynch);
|
2015-02-25 16:37:26 -09:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::RunScriptBasedCommand(
|
2018-07-12 14:28:52 -08:00
|
|
|
const char *impl_function, llvm::StringRef args,
|
2016-09-06 12:57:50 -08:00
|
|
|
ScriptedCommandSynchronicity synchronicity,
|
2017-05-11 20:51:55 -08:00
|
|
|
lldb_private::CommandReturnObject &cmd_retobj, Status &error,
|
2016-09-06 12:57:50 -08:00
|
|
|
const lldb_private::ExecutionContext &exe_ctx) {
|
|
|
|
|
if (!impl_function) {
|
|
|
|
|
error.SetErrorString("no function to execute");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-07-18 13:06:51 -08:00
|
|
|
|
2019-04-26 09:58:19 -08:00
|
|
|
lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();
|
2016-09-06 12:57:50 -08:00
|
|
|
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);
|
|
|
|
|
|
2018-07-12 14:28:52 -08:00
|
|
|
std::string args_str = args.str();
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSwigPythonCallCommand(
|
|
|
|
|
impl_function, m_dictionary_name.c_str(), debugger_sp, args_str.c_str(),
|
|
|
|
|
cmd_retobj, exe_ctx_ref_sp);
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ret_val)
|
|
|
|
|
error.SetErrorString("unable to execute script function");
|
|
|
|
|
else
|
|
|
|
|
error.Clear();
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
2011-08-16 08:49:25 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::RunScriptBasedCommand(
|
2018-07-12 14:28:52 -08:00
|
|
|
StructuredData::GenericSP impl_obj_sp, llvm::StringRef args,
|
2016-09-06 12:57:50 -08:00
|
|
|
ScriptedCommandSynchronicity synchronicity,
|
2017-05-11 20:51:55 -08:00
|
|
|
lldb_private::CommandReturnObject &cmd_retobj, Status &error,
|
2016-09-06 12:57:50 -08:00
|
|
|
const lldb_private::ExecutionContext &exe_ctx) {
|
|
|
|
|
if (!impl_obj_sp || !impl_obj_sp->IsValid()) {
|
|
|
|
|
error.SetErrorString("no function to execute");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2015-03-12 18:20:41 -08:00
|
|
|
|
2019-04-26 09:58:19 -08:00
|
|
|
lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();
|
2016-09-06 12:57:50 -08:00
|
|
|
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);
|
|
|
|
|
|
2018-07-12 14:28:52 -08:00
|
|
|
std::string args_str = args.str();
|
2019-03-26 13:57:02 -08:00
|
|
|
ret_val = LLDBSwigPythonCallCommandObject(impl_obj_sp->GetValue(),
|
|
|
|
|
debugger_sp, args_str.c_str(),
|
|
|
|
|
cmd_retobj, exe_ctx_ref_sp);
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!ret_val)
|
|
|
|
|
error.SetErrorString("unable to execute script function");
|
|
|
|
|
else
|
|
|
|
|
error.Clear();
|
|
|
|
|
|
|
|
|
|
return ret_val;
|
2015-03-12 18:20:41 -08:00
|
|
|
}
|
|
|
|
|
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::GetDocumentationForItem(const char *item,
|
|
|
|
|
std::string &dest) {
|
2016-09-06 12:57:50 -08:00
|
|
|
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(), 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);
|
2016-11-16 12:15:24 -09:00
|
|
|
dest = str_stream.GetString();
|
2016-09-06 12:57:50 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
2011-08-16 17:30:04 -08:00
|
|
|
}
|
2010-11-10 10:18:14 -09:00
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::GetShortHelpForCommandObject(
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::GenericSP cmd_obj_sp, std::string &dest) {
|
|
|
|
|
bool got_string = false;
|
|
|
|
|
dest.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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
static char callee_name[] = "get_short_help";
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject implementor(PyRefType::Borrowed,
|
|
|
|
|
(PyObject *)cmd_obj_sp->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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!implementor.IsAllocated())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
PythonObject pmeth(PyRefType::Owned,
|
|
|
|
|
PyObject_GetAttrString(implementor.get(), callee_name));
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
|
|
|
|
|
if (!pmeth.IsAllocated())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (PyCallable_Check(pmeth.get()) == 0) {
|
2015-03-13 14:22:28 -08:00
|
|
|
if (PyErr_Occurred())
|
2016-09-06 12:57:50 -08:00
|
|
|
PyErr_Clear();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
Port native Python-API to 3.x
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x. This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes. Primarily, these are:
1) PyString doesn't exist in Python 3. Everything is a PyUnicode.
To account for this, PythonString now stores a PyBytes instead
of a PyString. In Python 2, this is equivalent to a PyUnicode,
and in Python 3, we do a conversion from PyUnicode to PyBytes
and store the PyBytes.
2) PyInt doesn't exist in Python 3. Everything is a PyLong. To
account for this, PythonInteger stores a PyLong instead of a
PyInt. In Python 2.x, this requires doing a conversion to
PyLong when creating a PythonInteger from a PyInt. In 3.x,
there is no PyInt anyway, so we can assume everything is a
PyLong.
3) PyFile_FromFile doesn't exist in Python 3. Instead there is a
PyFile_FromFd. This is not addressed in this patch because it
will require quite a large change to plumb fd's all the way
through the system into the ScriptInterpreter. This is the only
remaining piece of the puzzle to get LLDB supporting Python 3.x.
Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.
llvm-svn: 249886
2015-10-09 11:45:41 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
|
|
|
|
|
// right now we know this function exists and is callable..
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (py_return.IsAllocated() && PythonString::Check(py_return.get())) {
|
|
|
|
|
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;
|
2015-03-13 14:22:28 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
uint32_t ScriptInterpreterPythonImpl::GetFlagsForCommandObject(
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::GenericSP cmd_obj_sp) {
|
|
|
|
|
uint32_t result = 0;
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
static char callee_name[] = "get_flags";
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject implementor(PyRefType::Borrowed,
|
|
|
|
|
(PyObject *)cmd_obj_sp->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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject pmeth(PyRefType::Owned,
|
|
|
|
|
PyObject_GetAttrString(implementor.get(), callee_name));
|
Port native Python-API to 3.x
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x. This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes. Primarily, these are:
1) PyString doesn't exist in Python 3. Everything is a PyUnicode.
To account for this, PythonString now stores a PyBytes instead
of a PyString. In Python 2, this is equivalent to a PyUnicode,
and in Python 3, we do a conversion from PyUnicode to PyBytes
and store the PyBytes.
2) PyInt doesn't exist in Python 3. Everything is a PyLong. To
account for this, PythonInteger stores a PyLong instead of a
PyInt. In Python 2.x, this requires doing a conversion to
PyLong when creating a PythonInteger from a PyInt. In 3.x,
there is no PyInt anyway, so we can assume everything is a
PyLong.
3) PyFile_FromFile doesn't exist in Python 3. Instead there is a
PyFile_FromFd. This is not addressed in this patch because it
will require quite a large change to plumb fd's all the way
through the system into the ScriptInterpreter. This is the only
remaining piece of the puzzle to get LLDB supporting Python 3.x.
Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.
llvm-svn: 249886
2015-10-09 11:45:41 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
|
|
|
|
|
if (!pmeth.IsAllocated())
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
|
|
if (PyCallable_Check(pmeth.get()) == 0) {
|
|
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
2015-05-26 21:04:35 -08:00
|
|
|
return result;
|
2016-09-06 12:57:50 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
|
|
|
|
|
// right now we know this function exists and is callable..
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (py_return.IsAllocated() && PythonInteger::Check(py_return.get())) {
|
|
|
|
|
PythonInteger int_value(PyRefType::Borrowed, py_return.get());
|
|
|
|
|
result = int_value.GetInteger();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
2015-05-26 21:04:35 -08:00
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
bool ScriptInterpreterPythonImpl::GetLongHelpForCommandObject(
|
2016-09-06 12:57:50 -08:00
|
|
|
StructuredData::GenericSP cmd_obj_sp, std::string &dest) {
|
|
|
|
|
bool got_string = false;
|
|
|
|
|
dest.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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
static char callee_name[] = "get_long_help";
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
PythonObject implementor(PyRefType::Borrowed,
|
|
|
|
|
(PyObject *)cmd_obj_sp->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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (!implementor.IsAllocated())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
PythonObject pmeth(PyRefType::Owned,
|
|
|
|
|
PyObject_GetAttrString(implementor.get(), callee_name));
|
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
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
|
|
|
|
|
if (!pmeth.IsAllocated())
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (PyCallable_Check(pmeth.get()) == 0) {
|
2015-03-13 14:22:28 -08:00
|
|
|
if (PyErr_Occurred())
|
2016-09-06 12:57:50 -08:00
|
|
|
PyErr_Clear();
|
Port native Python-API to 3.x
With this change, liblldb is 95% of the way towards being able
to work under both Python 2.x and Python 3.x. This should
introduce no functional change for Python 2.x, but for Python
3.x there are some important changes. Primarily, these are:
1) PyString doesn't exist in Python 3. Everything is a PyUnicode.
To account for this, PythonString now stores a PyBytes instead
of a PyString. In Python 2, this is equivalent to a PyUnicode,
and in Python 3, we do a conversion from PyUnicode to PyBytes
and store the PyBytes.
2) PyInt doesn't exist in Python 3. Everything is a PyLong. To
account for this, PythonInteger stores a PyLong instead of a
PyInt. In Python 2.x, this requires doing a conversion to
PyLong when creating a PythonInteger from a PyInt. In 3.x,
there is no PyInt anyway, so we can assume everything is a
PyLong.
3) PyFile_FromFile doesn't exist in Python 3. Instead there is a
PyFile_FromFd. This is not addressed in this patch because it
will require quite a large change to plumb fd's all the way
through the system into the ScriptInterpreter. This is the only
remaining piece of the puzzle to get LLDB supporting Python 3.x.
Being able to run the test suite is not addressed in this patch.
After the extension module can compile and you can enter an embedded
3.x interpreter, the test suite will be addressed in a followup.
llvm-svn: 249886
2015-10-09 11:45:41 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
return false;
|
|
|
|
|
}
|
2015-03-13 14:22:28 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
if (PyErr_Occurred())
|
|
|
|
|
PyErr_Clear();
|
|
|
|
|
|
|
|
|
|
// right now we know this function exists and is callable..
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (py_return.IsAllocated() && PythonString::Check(py_return.get())) {
|
|
|
|
|
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;
|
2015-04-09 10:08:50 -08:00
|
|
|
}
|
|
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
std::unique_ptr<ScriptInterpreterLocker>
|
2019-03-29 12:17:20 -08:00
|
|
|
ScriptInterpreterPythonImpl::AcquireInterpreterLock() {
|
2016-09-06 12:57:50 -08:00
|
|
|
std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker(
|
|
|
|
|
this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN,
|
|
|
|
|
Locker::FreeLock | Locker::TearDownSession));
|
|
|
|
|
return py_lock;
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::InitializePrivate() {
|
2016-09-06 12:57:50 -08:00
|
|
|
if (g_initialized)
|
|
|
|
|
return;
|
2015-04-09 10:08:50 -08:00
|
|
|
|
2016-09-06 12:57:50 -08:00
|
|
|
g_initialized = true;
|
|
|
|
|
|
2017-05-15 05:02:37 -08:00
|
|
|
static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
|
|
|
|
|
Timer scoped_timer(func_cat, LLVM_PRETTY_FUNCTION);
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
// RAII-based initialization which correctly handles multiple-initialization,
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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.
|
2016-09-06 12:57:50 -08:00
|
|
|
InitializePythonRAII initialize_guard;
|
|
|
|
|
|
2019-03-26 13:57:02 -08:00
|
|
|
LLDBSwigPyInit();
|
2016-09-06 12:57:50 -08:00
|
|
|
|
|
|
|
|
// Update the path python uses to search for modules to include the current
|
|
|
|
|
// directory.
|
|
|
|
|
|
|
|
|
|
PyRun_SimpleString("import sys");
|
|
|
|
|
AddToSysPath(AddLocation::End, ".");
|
|
|
|
|
|
|
|
|
|
// Don't denormalize paths when calling file_spec.GetPath(). On platforms
|
2018-04-30 08:49:04 -08:00
|
|
|
// 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.
|
2018-06-20 00:35:45 -08:00
|
|
|
if (FileSpec file_spec = GetPythonDir())
|
2016-09-06 12:57:50 -08:00
|
|
|
AddToSysPath(AddLocation::Beginning, file_spec.GetPath(false));
|
2018-06-19 07:09:07 -08:00
|
|
|
if (FileSpec file_spec = HostInfo::GetShlibDir())
|
2016-09-06 12:57:50 -08:00
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-29 12:17:20 -08:00
|
|
|
void ScriptInterpreterPythonImpl::AddToSysPath(AddLocation location,
|
|
|
|
|
std::string path) {
|
2016-09-06 12:57:50 -08:00
|
|
|
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());
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-21 06:09:15 -08:00
|
|
|
// 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
|
2019-03-29 12:17:20 -08:00
|
|
|
// ScriptInterpreterPythonImpl::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
|
2018-06-21 06:09:15 -08:00
|
|
|
// should not cause any problems (everything should shut down/go away anyway
|
|
|
|
|
// when the process exits).
|
|
|
|
|
//
|
2019-03-29 12:17:20 -08:00
|
|
|
// void ScriptInterpreterPythonImpl::Terminate() { Py_Finalize (); }
|
2018-06-21 09:36:32 -08:00
|
|
|
|
|
|
|
|
#endif // LLDB_DISABLE_PYTHON
|