aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp445
1 files changed, 307 insertions, 138 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index ef7a2c128a22..70fa6d83e306 100644
--- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -17,6 +17,7 @@
#include "Interfaces/OperatingSystemPythonInterface.h"
#include "Interfaces/ScriptedPlatformPythonInterface.h"
#include "Interfaces/ScriptedProcessPythonInterface.h"
+#include "Interfaces/ScriptedThreadPlanPythonInterface.h"
#include "Interfaces/ScriptedThreadPythonInterface.h"
#include "PythonDataObjects.h"
#include "PythonReadline.h"
@@ -24,6 +25,7 @@
#include "ScriptInterpreterPythonImpl.h"
#include "lldb/API/SBError.h"
+#include "lldb/API/SBExecutionContext.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBValue.h"
#include "lldb/Breakpoint/StoppointCallbackContext.h"
@@ -96,24 +98,28 @@ public:
InitializePythonRAII() {
InitializePythonHome();
+ // The table of built-in modules can only be extended before Python is
+ // initialized.
+ if (!Py_IsInitialized()) {
#ifdef LLDB_USE_LIBEDIT_READLINE_COMPAT_MODULE
- // Python's readline is incompatible with libedit being linked into lldb.
- // Provide a patched version local to the embedded interpreter.
- bool ReadlinePatched = false;
- for (auto *p = PyImport_Inittab; p->name != nullptr; p++) {
- if (strcmp(p->name, "readline") == 0) {
- p->initfunc = initlldb_readline;
- break;
+ // Python's readline is incompatible with libedit being linked into lldb.
+ // Provide a patched version local to the embedded interpreter.
+ bool ReadlinePatched = false;
+ for (auto *p = PyImport_Inittab; p->name != nullptr; p++) {
+ if (strcmp(p->name, "readline") == 0) {
+ p->initfunc = initlldb_readline;
+ break;
+ }
+ }
+ if (!ReadlinePatched) {
+ PyImport_AppendInittab("readline", initlldb_readline);
+ ReadlinePatched = true;
}
- }
- if (!ReadlinePatched) {
- PyImport_AppendInittab("readline", initlldb_readline);
- ReadlinePatched = true;
- }
#endif
- // Register _lldb as a built-in module.
- PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
+ // Register _lldb as a built-in module.
+ PyImport_AppendInittab("_lldb", LLDBSwigPyInit);
+ }
// Python < 3.2 and Python >= 3.2 reversed the ordering requirements for
// calling `Py_Initialize` and `PyEval_InitThreads`. < 3.2 requires that you
@@ -531,7 +537,6 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler,
break;
data_up->user_source.SplitIntoLines(data);
- StructuredData::ObjectSP empty_args_sp;
if (GenerateBreakpointCommandCallbackData(data_up->user_source,
data_up->script_source,
/*has_extra_args=*/false,
@@ -1413,7 +1418,7 @@ bool ScriptInterpreterPythonImpl::GenerateScriptAliasFunction(
sstr.Printf("def %s (debugger, args, exe_ctx, result, internal_dict):",
auto_generated_function_name.c_str());
- if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/true)
+ if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false)
.Success())
return false;
@@ -1533,6 +1538,11 @@ ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() {
return std::make_shared<ScriptedThreadPythonInterface>(*this);
}
+ScriptedThreadPlanInterfaceSP
+ScriptInterpreterPythonImpl::CreateScriptedThreadPlanInterface() {
+ return std::make_shared<ScriptedThreadPlanPythonInterface>(*this);
+}
+
OperatingSystemInterfaceSP
ScriptInterpreterPythonImpl::CreateOperatingSystemInterface() {
return std::make_shared<OperatingSystemPythonInterface>(*this);
@@ -1549,122 +1559,6 @@ ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject(
return py_obj.CreateStructuredObject();
}
-StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan(
- const char *class_name, const StructuredDataImpl &args_data,
- std::string &error_str, lldb::ThreadPlanSP thread_plan_sp) {
- if (class_name == nullptr || class_name[0] == '\0')
- return StructuredData::ObjectSP();
-
- if (!thread_plan_sp.get())
- return {};
-
- Debugger &debugger = thread_plan_sp->GetTarget().GetDebugger();
- ScriptInterpreterPythonImpl *python_interpreter =
- GetPythonInterpreter(debugger);
-
- if (!python_interpreter)
- return {};
-
- Locker py_lock(this,
- Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedThreadPlan(
- class_name, python_interpreter->m_dictionary_name.c_str(), args_data,
- error_str, thread_plan_sp);
- if (!ret_val)
- return {};
-
- return StructuredData::ObjectSP(
- new StructuredPythonObject(std::move(ret_val)));
-}
-
-bool ScriptInterpreterPythonImpl::ScriptedThreadPlanExplainsStop(
- StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) {
- bool explains_stop = true;
- StructuredData::Generic *generic = nullptr;
- if (implementor_sp)
- generic = implementor_sp->GetAsGeneric();
- if (generic) {
- Locker py_lock(this,
- Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- explains_stop = SWIGBridge::LLDBSWIGPythonCallThreadPlan(
- generic->GetValue(), "explains_stop", event, script_error);
- if (script_error)
- return true;
- }
- return explains_stop;
-}
-
-bool ScriptInterpreterPythonImpl::ScriptedThreadPlanShouldStop(
- StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) {
- bool should_stop = true;
- StructuredData::Generic *generic = nullptr;
- if (implementor_sp)
- generic = implementor_sp->GetAsGeneric();
- if (generic) {
- Locker py_lock(this,
- Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- should_stop = SWIGBridge::LLDBSWIGPythonCallThreadPlan(
- generic->GetValue(), "should_stop", event, script_error);
- if (script_error)
- return true;
- }
- return should_stop;
-}
-
-bool ScriptInterpreterPythonImpl::ScriptedThreadPlanIsStale(
- 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);
- is_stale = SWIGBridge::LLDBSWIGPythonCallThreadPlan(
- generic->GetValue(), "is_stale", (Event *)nullptr, script_error);
- if (script_error)
- return true;
- }
- return is_stale;
-}
-
-lldb::StateType ScriptInterpreterPythonImpl::ScriptedThreadPlanGetRunState(
- StructuredData::ObjectSP implementor_sp, bool &script_error) {
- bool should_step = false;
- StructuredData::Generic *generic = nullptr;
- if (implementor_sp)
- generic = implementor_sp->GetAsGeneric();
- if (generic) {
- Locker py_lock(this,
- Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- should_step = SWIGBridge::LLDBSWIGPythonCallThreadPlan(
- generic->GetValue(), "should_step", (Event *)nullptr, script_error);
- if (script_error)
- should_step = true;
- }
- if (should_step)
- return lldb::eStateStepping;
- return lldb::eStateRunning;
-}
-
-bool
-ScriptInterpreterPythonImpl::ScriptedThreadPlanGetStopDescription(
- StructuredData::ObjectSP implementor_sp, lldb_private::Stream *stream,
- bool &script_error) {
- StructuredData::Generic *generic = nullptr;
- if (implementor_sp)
- generic = implementor_sp->GetAsGeneric();
- if (!generic) {
- script_error = true;
- return false;
- }
- Locker py_lock(this,
- Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- return SWIGBridge::LLDBSWIGPythonCallThreadPlan(
- generic->GetValue(), "stop_description", stream, script_error);
-}
-
-
StructuredData::GenericSP
ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver(
const char *class_name, const StructuredDataImpl &args_data,
@@ -2490,8 +2384,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(
auto ExtendSysPath = [&](std::string directory) -> llvm::Error {
if (directory.empty()) {
- return llvm::make_error<llvm::StringError>(
- "invalid directory name", llvm::inconvertibleErrorCode());
+ return llvm::createStringError("invalid directory name");
}
replace_all(directory, "\\", "\\\\");
@@ -2504,10 +2397,8 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule(
directory.c_str(), directory.c_str());
bool syspath_retval =
ExecuteMultipleLines(command_stream.GetData(), exc_options).Success();
- if (!syspath_retval) {
- return llvm::make_error<llvm::StringError>(
- "Python sys.path handling failed", llvm::inconvertibleErrorCode());
- }
+ if (!syspath_retval)
+ return llvm::createStringError("Python sys.path handling failed");
return llvm::Error::success();
};
@@ -2766,6 +2657,85 @@ bool ScriptInterpreterPythonImpl::RunScriptBasedCommand(
return ret_val;
}
+bool ScriptInterpreterPythonImpl::RunScriptBasedParsedCommand(
+ StructuredData::GenericSP impl_obj_sp, Args &args,
+ ScriptedCommandSynchronicity synchronicity,
+ lldb_private::CommandReturnObject &cmd_retobj, Status &error,
+ const lldb_private::ExecutionContext &exe_ctx) {
+ if (!impl_obj_sp || !impl_obj_sp->IsValid()) {
+ error.SetErrorString("no function to execute");
+ return false;
+ }
+
+ lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();
+ lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx));
+
+ if (!debugger_sp.get()) {
+ error.SetErrorString("invalid Debugger pointer");
+ return false;
+ }
+
+ bool ret_val = false;
+
+ std::string err_msg;
+
+ {
+ Locker py_lock(this,
+ Locker::AcquireLock | Locker::InitSession |
+ (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN),
+ Locker::FreeLock | Locker::TearDownSession);
+
+ SynchronicityHandler synch_handler(debugger_sp, synchronicity);
+
+ StructuredData::ArraySP args_arr_sp(new StructuredData::Array());
+
+ for (const Args::ArgEntry &entry : args) {
+ args_arr_sp->AddStringItem(entry.ref());
+ }
+ StructuredDataImpl args_impl(args_arr_sp);
+
+ ret_val = SWIGBridge::LLDBSwigPythonCallParsedCommandObject(
+ static_cast<PyObject *>(impl_obj_sp->GetValue()), debugger_sp,
+ args_impl, cmd_retobj, exe_ctx_ref_sp);
+ }
+
+ if (!ret_val)
+ error.SetErrorString("unable to execute script function");
+ else if (cmd_retobj.GetStatus() == eReturnStatusFailed)
+ return false;
+
+ error.Clear();
+ return ret_val;
+}
+
+std::optional<std::string>
+ScriptInterpreterPythonImpl::GetRepeatCommandForScriptedCommand(
+ StructuredData::GenericSP impl_obj_sp, Args &args) {
+ if (!impl_obj_sp || !impl_obj_sp->IsValid())
+ return std::nullopt;
+
+ lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this();
+
+ if (!debugger_sp.get())
+ return std::nullopt;
+
+ std::optional<std::string> ret_val;
+
+ {
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN,
+ Locker::FreeLock);
+
+ StructuredData::ArraySP args_arr_sp(new StructuredData::Array());
+
+ // For scripting commands, we send the command string:
+ std::string command;
+ args.GetQuotedCommandString(command);
+ ret_val = SWIGBridge::LLDBSwigPythonGetRepeatCommandForScriptedCommand(
+ static_cast<PyObject *>(impl_obj_sp->GetValue()), command);
+ }
+ return ret_val;
+}
+
/// In Python, a special attribute __doc__ contains the docstring for an object
/// (function, method, class, ...) if any is defined Otherwise, the attribute's
/// value is None.
@@ -2884,6 +2854,205 @@ uint32_t ScriptInterpreterPythonImpl::GetFlagsForCommandObject(
return result;
}
+StructuredData::ObjectSP
+ScriptInterpreterPythonImpl::GetOptionsForCommandObject(
+ StructuredData::GenericSP cmd_obj_sp) {
+ StructuredData::ObjectSP result = {};
+
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
+
+ static char callee_name[] = "get_options_definition";
+
+ if (!cmd_obj_sp)
+ return result;
+
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)cmd_obj_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return result;
+
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return result;
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return result;
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ PythonDictionary py_return = unwrapOrSetPythonException(
+ As<PythonDictionary>(implementor.CallMethod(callee_name)));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ return {};
+ }
+ return py_return.CreateStructuredObject();
+}
+
+StructuredData::ObjectSP
+ScriptInterpreterPythonImpl::GetArgumentsForCommandObject(
+ StructuredData::GenericSP cmd_obj_sp) {
+ StructuredData::ObjectSP result = {};
+
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
+
+ static char callee_name[] = "get_args_definition";
+
+ if (!cmd_obj_sp)
+ return result;
+
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)cmd_obj_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return result;
+
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return result;
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return result;
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ PythonList py_return = unwrapOrSetPythonException(
+ As<PythonList>(implementor.CallMethod(callee_name)));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ return {};
+ }
+ return py_return.CreateStructuredObject();
+}
+
+void
+ScriptInterpreterPythonImpl::OptionParsingStartedForCommandObject(
+ StructuredData::GenericSP cmd_obj_sp) {
+
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
+
+ static char callee_name[] = "option_parsing_started";
+
+ if (!cmd_obj_sp)
+ return ;
+
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)cmd_obj_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return;
+
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return;
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return;
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ // option_parsing_starting doesn't return anything, ignore anything but
+ // python errors.
+ unwrapOrSetPythonException(
+ As<bool>(implementor.CallMethod(callee_name)));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ return;
+ }
+}
+
+bool
+ScriptInterpreterPythonImpl::SetOptionValueForCommandObject(
+ StructuredData::GenericSP cmd_obj_sp, ExecutionContext *exe_ctx,
+ llvm::StringRef long_option, llvm::StringRef value) {
+ StructuredData::ObjectSP result = {};
+
+ Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock);
+
+ static char callee_name[] = "set_option_value";
+
+ if (!cmd_obj_sp)
+ return false;
+
+ PythonObject implementor(PyRefType::Borrowed,
+ (PyObject *)cmd_obj_sp->GetValue());
+
+ if (!implementor.IsAllocated())
+ return false;
+
+ PythonObject pmeth(PyRefType::Owned,
+ PyObject_GetAttrString(implementor.get(), callee_name));
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ if (!pmeth.IsAllocated())
+ return false;
+
+ if (PyCallable_Check(pmeth.get()) == 0) {
+ if (PyErr_Occurred())
+ PyErr_Clear();
+ return false;
+ }
+
+ if (PyErr_Occurred())
+ PyErr_Clear();
+
+ lldb::ExecutionContextRefSP exe_ctx_ref_sp;
+ if (exe_ctx)
+ exe_ctx_ref_sp.reset(new ExecutionContextRef(exe_ctx));
+ PythonObject ctx_ref_obj = SWIGBridge::ToSWIGWrapper(exe_ctx_ref_sp);
+
+ bool py_return = unwrapOrSetPythonException(
+ As<bool>(implementor.CallMethod(callee_name, ctx_ref_obj, long_option.str().c_str(),
+ value.str().c_str())));
+
+ // if it fails, print the error but otherwise go on
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ return false;
+ }
+ return py_return;
+}
+
bool ScriptInterpreterPythonImpl::GetLongHelpForCommandObject(
StructuredData::GenericSP cmd_obj_sp, std::string &dest) {
dest.clear();