diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python')
15 files changed, 514 insertions, 406 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp index ae61736fbbb3..22918561692c 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -20,7 +20,6 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/Stream.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/Errno.h" @@ -923,7 +922,7 @@ const char *PythonException::toCString() const { PythonException::PythonException(const char *caller) { assert(PyErr_Occurred()); - m_exception_type = m_exception = m_traceback = m_repr_bytes = NULL; + m_exception_type = m_exception = m_traceback = m_repr_bytes = nullptr; PyErr_Fetch(&m_exception_type, &m_exception, &m_traceback); PyErr_NormalizeException(&m_exception_type, &m_exception, &m_traceback); PyErr_Clear(); @@ -951,7 +950,7 @@ void PythonException::Restore() { } else { PyErr_SetString(PyExc_Exception, toCString()); } - m_exception_type = m_exception = m_traceback = NULL; + m_exception_type = m_exception = m_traceback = nullptr; } PythonException::~PythonException() { diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h index 76ad47f2907e..365d499bead8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -185,22 +185,34 @@ inline const char *py2_const_cast(const char *s) { return s; } enum class PyInitialValue { Invalid, Empty }; +// DOC: https://docs.python.org/3/c-api/arg.html#building-values template <typename T, typename Enable = void> struct PythonFormat; -template <> struct PythonFormat<unsigned long long> { - static constexpr char format = 'K'; - static auto get(unsigned long long value) { return value; } +template <typename T, char F> struct PassthroughFormat { + static constexpr char format = F; + static constexpr T get(T t) { return t; } }; -template <> struct PythonFormat<long long> { - static constexpr char format = 'L'; - static auto get(long long value) { return value; } -}; - -template <> struct PythonFormat<PyObject *> { - static constexpr char format = 'O'; - static auto get(PyObject *value) { return value; } -}; +template <> struct PythonFormat<char *> : PassthroughFormat<char *, 's'> {}; +template <> struct PythonFormat<char> : PassthroughFormat<char, 'b'> {}; +template <> +struct PythonFormat<unsigned char> : PassthroughFormat<unsigned char, 'B'> {}; +template <> struct PythonFormat<short> : PassthroughFormat<short, 'h'> {}; +template <> +struct PythonFormat<unsigned short> : PassthroughFormat<unsigned short, 'H'> {}; +template <> struct PythonFormat<int> : PassthroughFormat<int, 'i'> {}; +template <> +struct PythonFormat<unsigned int> : PassthroughFormat<unsigned int, 'I'> {}; +template <> struct PythonFormat<long> : PassthroughFormat<long, 'l'> {}; +template <> +struct PythonFormat<unsigned long> : PassthroughFormat<unsigned long, 'k'> {}; +template <> +struct PythonFormat<long long> : PassthroughFormat<long long, 'L'> {}; +template <> +struct PythonFormat<unsigned long long> + : PassthroughFormat<unsigned long long, 'K'> {}; +template <> +struct PythonFormat<PyObject *> : PassthroughFormat<PyObject *, 'O'> {}; template <typename T> struct PythonFormat< diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp index 2753847f39f8..3cbd3b5efecc 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonReadline.cpp @@ -40,7 +40,7 @@ static char *simple_readline(FILE *stdin, FILE *stdout, const char *prompt) { char *line = readline(prompt); if (!line) { char *ret = (char *)PyMem_RawMalloc(1); - if (ret != NULL) + if (ret != nullptr) *ret = '\0'; return ret; } diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp deleted file mode 100644 index 7c7c5d73680a..000000000000 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.cpp +++ /dev/null @@ -1,48 +0,0 @@ -//===-- SWIGPythonBridge.cpp ----------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "lldb/Host/Config.h" -#include "lldb/lldb-enumerations.h" - -#if LLDB_ENABLE_PYTHON - -// LLDB Python header must be included first -#include "lldb-python.h" - -#include "SWIGPythonBridge.h" - -using namespace lldb; - -namespace lldb_private { - -template <typename T> const char *GetPythonValueFormatString(T t); -template <> const char *GetPythonValueFormatString(char *) { return "s"; } -template <> const char *GetPythonValueFormatString(char) { return "b"; } -template <> const char *GetPythonValueFormatString(unsigned char) { - return "B"; -} -template <> const char *GetPythonValueFormatString(short) { return "h"; } -template <> const char *GetPythonValueFormatString(unsigned short) { - return "H"; -} -template <> const char *GetPythonValueFormatString(int) { return "i"; } -template <> const char *GetPythonValueFormatString(unsigned int) { return "I"; } -template <> const char *GetPythonValueFormatString(long) { return "l"; } -template <> const char *GetPythonValueFormatString(unsigned long) { - return "k"; -} -template <> const char *GetPythonValueFormatString(long long) { return "L"; } -template <> const char *GetPythonValueFormatString(unsigned long long) { - return "K"; -} -template <> const char *GetPythonValueFormatString(float) { return "f"; } -template <> const char *GetPythonValueFormatString(double) { return "d"; } - -} // namespace lldb_private - -#endif // LLDB_ENABLE_PYTHON diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h index 4df235356737..3dc2864f8d42 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -9,6 +9,7 @@ #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SWIGPYTHONBRIDGE_H +#include <optional> #include <string> #include "lldb/Host/Config.h" @@ -23,28 +24,68 @@ #include "lldb/lldb-types.h" #include "llvm/Support/Error.h" -namespace lldb_private { +namespace lldb { +class SBEvent; +class SBCommandReturnObject; +class SBValue; +class SBStream; +class SBStructuredData; +} // namespace lldb -// GetPythonValueFormatString provides a system independent type safe way to -// convert a variable's type into a python value format. Python value formats -// are defined in terms of builtin C types and could change from system to as -// the underlying typedef for uint* types, size_t, off_t and other values -// change. - -template <typename T> const char *GetPythonValueFormatString(T t); -template <> const char *GetPythonValueFormatString(char *); -template <> const char *GetPythonValueFormatString(char); -template <> const char *GetPythonValueFormatString(unsigned char); -template <> const char *GetPythonValueFormatString(short); -template <> const char *GetPythonValueFormatString(unsigned short); -template <> const char *GetPythonValueFormatString(int); -template <> const char *GetPythonValueFormatString(unsigned int); -template <> const char *GetPythonValueFormatString(long); -template <> const char *GetPythonValueFormatString(unsigned long); -template <> const char *GetPythonValueFormatString(long long); -template <> const char *GetPythonValueFormatString(unsigned long long); -template <> const char *GetPythonValueFormatString(float t); -template <> const char *GetPythonValueFormatString(double t); +namespace lldb_private { +namespace python { + +typedef struct swig_type_info swig_type_info; + +python::PythonObject ToSWIGHelper(void *obj, swig_type_info *info); + +/// A class that automatically clears an SB object when it goes out of scope. +/// Use for cases where the SB object points to a temporary/unowned entity. +template <typename T> class ScopedPythonObject : PythonObject { +public: + ScopedPythonObject(T *sb, swig_type_info *info) + : PythonObject(ToSWIGHelper(sb, info)), m_sb(sb) {} + ~ScopedPythonObject() { + if (m_sb) + *m_sb = T(); + } + ScopedPythonObject(ScopedPythonObject &&rhs) + : PythonObject(std::move(rhs)), m_sb(std::exchange(rhs.m_sb, nullptr)) {} + ScopedPythonObject(const ScopedPythonObject &) = delete; + ScopedPythonObject &operator=(const ScopedPythonObject &) = delete; + ScopedPythonObject &operator=(ScopedPythonObject &&) = delete; + + const PythonObject &obj() const { return *this; } + +private: + T *m_sb; +}; + +PythonObject ToSWIGWrapper(lldb::ValueObjectSP value_sp); +PythonObject ToSWIGWrapper(lldb::TargetSP target_sp); +PythonObject ToSWIGWrapper(lldb::ProcessSP process_sp); +PythonObject ToSWIGWrapper(lldb::ThreadPlanSP thread_plan_sp); +PythonObject ToSWIGWrapper(lldb::BreakpointSP breakpoint_sp); +PythonObject ToSWIGWrapper(const Status &status); +PythonObject ToSWIGWrapper(const StructuredDataImpl &data_impl); +PythonObject ToSWIGWrapper(lldb::ThreadSP thread_sp); +PythonObject ToSWIGWrapper(lldb::StackFrameSP frame_sp); +PythonObject ToSWIGWrapper(lldb::DebuggerSP debugger_sp); +PythonObject ToSWIGWrapper(lldb::WatchpointSP watchpoint_sp); +PythonObject ToSWIGWrapper(lldb::BreakpointLocationSP bp_loc_sp); +PythonObject ToSWIGWrapper(lldb::ExecutionContextRefSP ctx_sp); +PythonObject ToSWIGWrapper(const TypeSummaryOptions &summary_options); +PythonObject ToSWIGWrapper(const SymbolContext &sym_ctx); + +PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBValue> value_sb); +PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBStream> stream_sb); +PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBStructuredData> data_sb); + +python::ScopedPythonObject<lldb::SBCommandReturnObject> +ToSWIGWrapper(CommandReturnObject &cmd_retobj); +python::ScopedPythonObject<lldb::SBEvent> ToSWIGWrapper(Event *event); + +} // namespace python void *LLDBSWIGPython_CastPyObjectToSBData(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data); @@ -55,14 +96,10 @@ void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data); // Although these are scripting-language specific, their definition depends on // the public API. -python::PythonObject LLDBSwigPythonCreateScriptedProcess( +python::PythonObject LLDBSwigPythonCreateScriptedObject( const char *python_class_name, const char *session_dictionary_name, - const lldb::TargetSP &target_sp, const StructuredDataImpl &args_impl, - std::string &error_string); - -python::PythonObject LLDBSwigPythonCreateScriptedThread( - const char *python_class_name, const char *session_dictionary_name, - const lldb::ProcessSP &process_sp, const StructuredDataImpl &args_impl, + lldb::ExecutionContextRefSP exe_ctx_sp, + const lldb_private::StructuredDataImpl &args_impl, std::string &error_string); llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction( @@ -75,6 +112,10 @@ bool LLDBSwigPythonWatchpointCallbackFunction( const char *python_function_name, const char *session_dictionary_name, const lldb::StackFrameSP &sb_frame, const lldb::WatchpointSP &sb_wp); +bool LLDBSwigPythonFormatterCallbackFunction( + const char *python_function_name, const char *session_dictionary_name, + lldb::TypeImplSP type_impl_sp); + bool LLDBSwigPythonCallTypeScript(const char *python_function_name, const void *session_dictionary, const lldb::ValueObjectSP &valobj_sp, @@ -167,7 +208,7 @@ bool LLDBSWIGPythonRunScriptKeywordProcess(const char *python_function_name, const lldb::ProcessSP &process, std::string &output); -llvm::Optional<std::string> +std::optional<std::string> LLDBSWIGPythonRunScriptKeywordThread(const char *python_function_name, const char *session_dictionary_name, lldb::ThreadSP thread); @@ -177,7 +218,7 @@ bool LLDBSWIGPythonRunScriptKeywordTarget(const char *python_function_name, const lldb::TargetSP &target, std::string &output); -llvm::Optional<std::string> +std::optional<std::string> LLDBSWIGPythonRunScriptKeywordFrame(const char *python_function_name, const char *session_dictionary_name, lldb::StackFrameSP frame); 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 a21adcfbdbd6..7026815e120d 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -18,6 +18,7 @@ #include "PythonReadline.h" #include "SWIGPythonBridge.h" #include "ScriptInterpreterPythonImpl.h" +#include "ScriptedPlatformPythonInterface.h" #include "ScriptedProcessPythonInterface.h" #include "lldb/API/SBError.h" @@ -25,9 +26,9 @@ #include "lldb/API/SBValue.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Breakpoint/WatchpointOptions.h" -#include "lldb/Core/Communication.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/ThreadedCommunication.h" #include "lldb/Core/ValueObject.h" #include "lldb/DataFormatters/TypeSummary.h" #include "lldb/Host/FileSystem.h" @@ -50,6 +51,7 @@ #include <cstdlib> #include <memory> #include <mutex> +#include <optional> #include <string> using namespace lldb; @@ -96,7 +98,7 @@ public: // 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 != NULL; p++) { + for (auto *p = PyImport_Inittab; p->name != nullptr; p++) { if (strcmp(p->name, "readline") == 0) { p->initfunc = initlldb_readline; break; @@ -241,7 +243,7 @@ void ScriptInterpreterPython::ComputePythonDir( llvm::sys::path::append(path, LLDB_PYTHON_RELATIVE_LIBDIR); #if defined(_WIN32) - // This will be injected directly through FileSpec.GetDirectory().SetString(), + // This will be injected directly through FileSpec.SetDirectory(), // so we need to normalize manually. std::replace(path.begin(), path.end(), '\\', '/'); #endif @@ -260,7 +262,7 @@ FileSpec ScriptInterpreterPython::GetPythonDir() { #else ComputePythonDir(path); #endif - spec.GetDirectory().SetString(path); + spec.SetDirectory(path); return spec; }(); return g_spec; @@ -412,6 +414,8 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) m_command_thread_state(nullptr) { m_scripted_process_interface_up = std::make_unique<ScriptedProcessPythonInterface>(*this); + m_scripted_platform_interface_up = + std::make_unique<ScriptedPlatformPythonInterface>(*this); m_dictionary_name.append("_dict"); StreamString run_string; @@ -429,7 +433,7 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) // Reloading modules requires a different syntax in Python 2 and Python 3. // This provides a consistent syntax no matter what version of Python. run_string.Clear(); - run_string.Printf("run_one_line (%s, 'from six.moves import reload_module')", + run_string.Printf("run_one_line (%s, 'from importlib import reload as reload_module')", m_dictionary_name.c_str()); PyRun_SimpleString(run_string.GetData()); @@ -1259,8 +1263,6 @@ void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback( wp_options->SetCallback( ScriptInterpreterPythonImpl::WatchpointCallbackFunction, baton_sp); } - - return; } Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter( @@ -1371,7 +1373,7 @@ bool ScriptInterpreterPythonImpl::GenerateScriptAliasFunction( std::string auto_generated_function_name(GenerateUniqueName( "lldb_autogen_python_cmd_alias_func", num_created_functions)); - sstr.Printf("def %s (debugger, args, result, internal_dict):", + sstr.Printf("def %s (debugger, args, exe_ctx, result, internal_dict):", auto_generated_function_name.c_str()); if (!GenerateFunction(sstr.GetData(), user_input).Success()) @@ -1503,50 +1505,29 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_RegisterInfo( StructuredData::ObjectSP os_plugin_object_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - static char callee_name[] = "get_register_info"; - if (!os_plugin_object_sp) - return StructuredData::DictionarySP(); + return {}; StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); if (!generic) - return nullptr; + return {}; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) - return StructuredData::DictionarySP(); - - PythonObject pmeth(PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), callee_name)); - - if (PyErr_Occurred()) - PyErr_Clear(); - - if (!pmeth.IsAllocated()) - return StructuredData::DictionarySP(); + return {}; - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("get_register_info"); - return StructuredData::DictionarySP(); + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); + return {}; } - 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)); + PythonObject py_return = std::move(expected_py_return.get()); - // 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(); @@ -1557,51 +1538,28 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_RegisterInfo( StructuredData::ArraySP ScriptInterpreterPythonImpl::OSPlugin_ThreadsInfo( StructuredData::ObjectSP os_plugin_object_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - - static char callee_name[] = "get_thread_info"; - if (!os_plugin_object_sp) - return StructuredData::ArraySP(); + return {}; StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); if (!generic) - return nullptr; + return {}; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) - return StructuredData::ArraySP(); - - PythonObject pmeth(PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), callee_name)); + return {}; - if (PyErr_Occurred()) - PyErr_Clear(); + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("get_thread_info"); - if (!pmeth.IsAllocated()) - return StructuredData::ArraySP(); - - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); - - return StructuredData::ArraySP(); + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); + return {}; } - 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(); - } + PythonObject py_return = std::move(expected_py_return.get()); if (py_return.get()) { PythonList result_list(PyRefType::Borrowed, py_return.get()); @@ -1615,56 +1573,33 @@ ScriptInterpreterPythonImpl::OSPlugin_RegisterContextData( StructuredData::ObjectSP os_plugin_object_sp, lldb::tid_t tid) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - static char callee_name[] = "get_register_data"; - static char *param_format = - const_cast<char *>(GetPythonValueFormatString(tid)); - if (!os_plugin_object_sp) - return StructuredData::StringSP(); + return {}; StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); if (!generic) - return nullptr; + return {}; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) - return StructuredData::StringSP(); - - PythonObject pmeth(PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), callee_name)); - - if (PyErr_Occurred()) - PyErr_Clear(); + return {}; - if (!pmeth.IsAllocated()) - return StructuredData::StringSP(); + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("get_register_data", tid); - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); - return StructuredData::StringSP(); + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); + return {}; } - 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, param_format, tid)); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + PythonObject py_return = std::move(expected_py_return.get()); if (py_return.get()) { PythonBytes result(PyRefType::Borrowed, py_return.get()); return result.CreateStructuredString(); } - return StructuredData::StringSP(); + return {}; } StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread( @@ -1672,52 +1607,28 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::OSPlugin_CreateThread( lldb::addr_t context) { Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - static char callee_name[] = "create_thread"; - std::string param_format; - param_format += GetPythonValueFormatString(tid); - param_format += GetPythonValueFormatString(context); - if (!os_plugin_object_sp) - return StructuredData::DictionarySP(); + return {}; StructuredData::Generic *generic = os_plugin_object_sp->GetAsGeneric(); if (!generic) - return nullptr; + return {}; PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) - return StructuredData::DictionarySP(); - - PythonObject pmeth(PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), callee_name)); - - if (PyErr_Occurred()) - PyErr_Clear(); + return {}; - if (!pmeth.IsAllocated()) - return StructuredData::DictionarySP(); + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("create_thread", tid, context); - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); - return StructuredData::DictionarySP(); + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); + return {}; } - 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, - ¶m_format[0], tid, context)); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } + PythonObject py_return = std::move(expected_py_return.get()); if (py_return.get()) { PythonDictionary result_dict(PyRefType::Borrowed, py_return.get()); @@ -2156,6 +2067,14 @@ bool ScriptInterpreterPythonImpl::GetScriptedSummary( return ret_val; } +bool ScriptInterpreterPythonImpl::FormatterCallbackFunction( + const char *python_function_name, TypeImplSP type_impl_sp) { + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + return LLDBSwigPythonFormatterCallbackFunction( + python_function_name, m_dictionary_name.c_str(), type_impl_sp); +} + bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction( void *baton, StoppointCallbackContext *context, user_id_t break_id, user_id_t break_loc_id) { @@ -2430,51 +2349,31 @@ ConstString ScriptInterpreterPythonImpl::GetSyntheticTypeName( 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; + return {}; StructuredData::Generic *generic = implementor_sp->GetAsGeneric(); if (!generic) - return ret_val; + return {}; + PythonObject implementor(PyRefType::Borrowed, (PyObject *)generic->GetValue()); if (!implementor.IsAllocated()) - return ret_val; - - PythonObject pmeth(PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), callee_name)); + return {}; - if (PyErr_Occurred()) - PyErr_Clear(); + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("get_type_name"); - if (!pmeth.IsAllocated()) - return ret_val; - - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); - return ret_val; + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); + return {}; } - if (PyErr_Occurred()) - PyErr_Clear(); + PythonObject py_return = std::move(expected_py_return.get()); - // 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(); - } + ConstString ret_val; + bool got_string = false; + std::string buffer; if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { PythonString py_string(PyRefType::Borrowed, py_return.get()); @@ -2530,7 +2429,7 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - if (llvm::Optional<std::string> result = LLDBSWIGPythonRunScriptKeywordThread( + if (std::optional<std::string> result = LLDBSWIGPythonRunScriptKeywordThread( impl_function, m_dictionary_name.c_str(), thread->shared_from_this())) { output = std::move(*result); @@ -2579,7 +2478,7 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - if (llvm::Optional<std::string> result = LLDBSWIGPythonRunScriptKeywordFrame( + if (std::optional<std::string> result = LLDBSWIGPythonRunScriptKeywordFrame( impl_function, m_dictionary_name.c_str(), frame->shared_from_this())) { output = std::move(*result); @@ -2888,9 +2787,10 @@ bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( if (!ret_val) error.SetErrorString("unable to execute script function"); - else - error.Clear(); + else if (cmd_retobj.GetStatus() == eReturnStatusFailed) + return false; + error.Clear(); return ret_val; } @@ -2932,9 +2832,10 @@ bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( if (!ret_val) error.SetErrorString("unable to execute script function"); - else - error.Clear(); + else if (cmd_retobj.GetStatus() == eReturnStatusFailed) + return false; + error.Clear(); return ret_val; } @@ -2978,8 +2879,6 @@ bool ScriptInterpreterPythonImpl::GetShortHelpForCommandObject( Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - static char callee_name[] = "get_short_help"; - if (!cmd_obj_sp) return false; @@ -2989,34 +2888,15 @@ bool ScriptInterpreterPythonImpl::GetShortHelpForCommandObject( 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; + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("get_short_help"); - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); return false; } - 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(); - } + PythonObject py_return = std::move(expected_py_return.get()); if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { PythonString py_string(PyRefType::Borrowed, py_return.get()); @@ -3079,13 +2959,10 @@ uint32_t ScriptInterpreterPythonImpl::GetFlagsForCommandObject( bool ScriptInterpreterPythonImpl::GetLongHelpForCommandObject( StructuredData::GenericSP cmd_obj_sp, std::string &dest) { - bool got_string = false; dest.clear(); Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - static char callee_name[] = "get_long_help"; - if (!cmd_obj_sp) return false; @@ -3095,36 +2972,17 @@ bool ScriptInterpreterPythonImpl::GetLongHelpForCommandObject( 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(); + llvm::Expected<PythonObject> expected_py_return = + implementor.CallMethod("get_long_help"); + if (!expected_py_return) { + llvm::consumeError(expected_py_return.takeError()); return false; } - 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(); - } + PythonObject py_return = std::move(expected_py_return.get()); + bool got_string = false; if (py_return.IsAllocated() && PythonString::Check(py_return.get())) { PythonString str(PyRefType::Borrowed, py_return.get()); llvm::StringRef str_data(str.GetString()); diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index 3b80c67d201a..f4875bfb8d18 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -202,6 +202,9 @@ public: const TypeSummaryOptions &options, std::string &retval) override; + bool FormatterCallbackFunction(const char *function_name, + lldb::TypeImplSP type_impl_sp) override; + bool GetDocumentationForItem(const char *item, std::string &dest) override; bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp new file mode 100644 index 000000000000..9fbf50114694 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp @@ -0,0 +1,108 @@ +//===-- ScriptedPlatformPythonInterface.cpp -------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#include "lldb/Host/Config.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Status.h" +#include "lldb/lldb-enumerations.h" + +#if LLDB_ENABLE_PYTHON + +// LLDB Python header must be included first +#include "lldb-python.h" + +#include "SWIGPythonBridge.h" +#include "ScriptInterpreterPythonImpl.h" +#include "ScriptedPlatformPythonInterface.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; +using Locker = ScriptInterpreterPythonImpl::Locker; + +ScriptedPlatformPythonInterface::ScriptedPlatformPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedPlatformInterface(), ScriptedPythonInterface(interpreter) {} + +StructuredData::GenericSP ScriptedPlatformPythonInterface::CreatePluginObject( + llvm::StringRef class_name, ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj) { + if (class_name.empty()) + return {}; + + StructuredDataImpl args_impl(args_sp); + std::string error_string; + + Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + lldb::ExecutionContextRefSP exe_ctx_ref_sp = + std::make_shared<ExecutionContextRef>(exe_ctx); + + PythonObject ret_val = LLDBSwigPythonCreateScriptedObject( + class_name.str().c_str(), m_interpreter.GetDictionaryName(), + exe_ctx_ref_sp, args_impl, error_string); + + m_object_instance_sp = + StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val))); + + return m_object_instance_sp; +} + +StructuredData::DictionarySP ScriptedPlatformPythonInterface::ListProcesses() { + Status error; + StructuredData::DictionarySP dict_sp = + Dispatch<StructuredData::DictionarySP>("list_processes", error); + + if (!dict_sp || !dict_sp->IsValid() || error.Fail()) { + return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>( + LLVM_PRETTY_FUNCTION, + llvm::Twine("Null or invalid object (" + + llvm::Twine(error.AsCString()) + llvm::Twine(").")) + .str(), + error); + } + + return dict_sp; +} + +StructuredData::DictionarySP +ScriptedPlatformPythonInterface::GetProcessInfo(lldb::pid_t pid) { + Status error; + StructuredData::DictionarySP dict_sp = + Dispatch<StructuredData::DictionarySP>("get_process_info", error, pid); + + if (!dict_sp || !dict_sp->IsValid() || error.Fail()) { + return ScriptedInterface::ErrorWithMessage<StructuredData::DictionarySP>( + LLVM_PRETTY_FUNCTION, + llvm::Twine("Null or invalid object (" + + llvm::Twine(error.AsCString()) + llvm::Twine(").")) + .str(), + error); + } + + return dict_sp; +} + +Status ScriptedPlatformPythonInterface::AttachToProcess( + ProcessAttachInfoSP attach_info) { + // FIXME: Pass `attach_info` to method call + return GetStatusFromMethod("attach_to_process"); +} + +Status ScriptedPlatformPythonInterface::LaunchProcess( + ProcessLaunchInfoSP launch_info) { + // FIXME: Pass `launch_info` to method call + return GetStatusFromMethod("launch_process"); +} + +Status ScriptedPlatformPythonInterface::KillProcess(lldb::pid_t pid) { + return GetStatusFromMethod("kill_process", pid); +} + +#endif // LLDB_ENABLE_PYTHON diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h new file mode 100644 index 000000000000..1e3ad9962325 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.h @@ -0,0 +1,44 @@ +//===-- ScriptedPlatformPythonInterface.h -----------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H +#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H + +#include "lldb/Host/Config.h" + +#if LLDB_ENABLE_PYTHON + +#include "ScriptedPythonInterface.h" +#include "lldb/Interpreter/ScriptedPlatformInterface.h" + +namespace lldb_private { +class ScriptedPlatformPythonInterface : public ScriptedPlatformInterface, + public ScriptedPythonInterface { +public: + ScriptedPlatformPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + StructuredData::GenericSP + CreatePluginObject(const llvm::StringRef class_name, + ExecutionContext &exe_ctx, + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override; + + StructuredData::DictionarySP ListProcesses() override; + + StructuredData::DictionarySP GetProcessInfo(lldb::pid_t) override; + + Status AttachToProcess(lldb::ProcessAttachInfoSP attach_info) override; + + Status LaunchProcess(lldb::ProcessLaunchInfoSP launch_info) override; + + Status KillProcess(lldb::pid_t pid) override; +}; +} // namespace lldb_private + +#endif // LLDB_ENABLE_PYTHON +#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPLATFORMPYTHONINTERFACE_H diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp index 576bf69c9258..6f087e8390ce 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp @@ -8,6 +8,7 @@ #include "lldb/Host/Config.h" #include "lldb/Utility/Log.h" +#include "lldb/Utility/Status.h" #include "lldb/lldb-enumerations.h" #if LLDB_ENABLE_PYTHON @@ -19,6 +20,7 @@ #include "ScriptInterpreterPythonImpl.h" #include "ScriptedProcessPythonInterface.h" #include "ScriptedThreadPythonInterface.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -35,16 +37,18 @@ StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject( if (class_name.empty()) return {}; - TargetSP target_sp = exe_ctx.GetTargetSP(); StructuredDataImpl args_impl(args_sp); std::string error_string; Locker py_lock(&m_interpreter, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - PythonObject ret_val = LLDBSwigPythonCreateScriptedProcess( - class_name.str().c_str(), m_interpreter.GetDictionaryName(), target_sp, - args_impl, error_string); + lldb::ExecutionContextRefSP exe_ctx_ref_sp = + std::make_shared<ExecutionContextRef>(exe_ctx); + + PythonObject ret_val = LLDBSwigPythonCreateScriptedObject( + class_name.str().c_str(), m_interpreter.GetDictionaryName(), + exe_ctx_ref_sp, args_impl, error_string); m_object_instance_sp = StructuredData::GenericSP(new StructuredPythonObject(std::move(ret_val))); @@ -74,10 +78,10 @@ Status ScriptedProcessPythonInterface::Stop() { return GetStatusFromMethod("stop"); } -llvm::Optional<MemoryRegionInfo> +std::optional<MemoryRegionInfo> ScriptedProcessPythonInterface::GetMemoryRegionContainingAddress( lldb::addr_t address, Status &error) { - auto mem_region = Dispatch<llvm::Optional<MemoryRegionInfo>>( + auto mem_region = Dispatch<std::optional<MemoryRegionInfo>>( "get_memory_region_containing_address", error, address); if (error.Fail()) { @@ -120,8 +124,15 @@ ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) { lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( lldb::addr_t address, size_t size, Status &error) { - return Dispatch<lldb::DataExtractorSP>("read_memory_at_address", error, - address, size); + Status py_error; + lldb::DataExtractorSP data_sp = Dispatch<lldb::DataExtractorSP>( + "read_memory_at_address", py_error, address, size, error); + + // If there was an error on the python call, surface it to the user. + if (py_error.Fail()) + error = py_error; + + return data_sp; } StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() { @@ -161,7 +172,7 @@ bool ScriptedProcessPythonInterface::IsAlive() { return obj->GetBooleanValue(); } -llvm::Optional<std::string> +std::optional<std::string> ScriptedProcessPythonInterface::GetScriptedThreadPluginName() { Status error; StructuredData::ObjectSP obj = Dispatch("get_scripted_thread_plugin", error); @@ -177,4 +188,15 @@ ScriptedProcessPythonInterface::CreateScriptedThreadInterface() { return std::make_shared<ScriptedThreadPythonInterface>(m_interpreter); } +StructuredData::DictionarySP ScriptedProcessPythonInterface::GetMetadata() { + Status error; + StructuredData::DictionarySP dict = + Dispatch<StructuredData::DictionarySP>("get_process_metadata", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) + return {}; + + return dict; +} + #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h index 7f458b1dd9bd..6b4ee3021cfa 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h @@ -15,6 +15,7 @@ #include "ScriptedPythonInterface.h" #include "lldb/Interpreter/ScriptedProcessInterface.h" +#include <optional> namespace lldb_private { class ScriptedProcessPythonInterface : public ScriptedProcessInterface, @@ -36,7 +37,7 @@ public: Status Stop() override; - llvm::Optional<MemoryRegionInfo> + std::optional<MemoryRegionInfo> GetMemoryRegionContainingAddress(lldb::addr_t address, Status &error) override; @@ -55,7 +56,9 @@ public: bool IsAlive() override; - llvm::Optional<std::string> GetScriptedThreadPluginName() override; + std::optional<std::string> GetScriptedThreadPluginName() override; + + StructuredData::DictionarySP GetMetadata() override; private: lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp index d5c527c61a5c..789b39abf587 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp @@ -18,6 +18,7 @@ #include "SWIGPythonBridge.h" #include "ScriptInterpreterPythonImpl.h" #include "ScriptedPythonInterface.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -26,14 +27,6 @@ ScriptedPythonInterface::ScriptedPythonInterface( ScriptInterpreterPythonImpl &interpreter) : ScriptedInterface(), m_interpreter(interpreter) {} -Status -ScriptedPythonInterface::GetStatusFromMethod(llvm::StringRef method_name) { - Status error; - Dispatch<Status>(method_name, error); - - return error; -} - template <> StructuredData::ArraySP ScriptedPythonInterface::ExtractValueFromPythonObject<StructuredData::ArraySP>( @@ -55,11 +48,11 @@ Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>( python::PythonObject &p, Status &error) { if (lldb::SBError *sb_error = reinterpret_cast<lldb::SBError *>( LLDBSWIGPython_CastPyObjectToSBError(p.get()))) - error = m_interpreter.GetStatusFromSBError(*sb_error); + return m_interpreter.GetStatusFromSBError(*sb_error); else error.SetErrorString("Couldn't cast lldb::SBError to lldb::Status."); - return error; + return {}; } template <> @@ -79,9 +72,9 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( } template <> -llvm::Optional<MemoryRegionInfo> +std::optional<MemoryRegionInfo> ScriptedPythonInterface::ExtractValueFromPythonObject< - llvm::Optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error) { + std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error) { lldb::SBMemoryRegionInfo *sb_mem_reg_info = reinterpret_cast<lldb::SBMemoryRegionInfo *>( diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h index 7c2fadc21d42..01dc07b49737 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h @@ -9,10 +9,15 @@ #ifndef LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H #define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_SCRIPTEDPYTHONINTERFACE_H -#include "lldb/Host/Config.h" - #if LLDB_ENABLE_PYTHON +#include <optional> +#include <sstream> +#include <tuple> +#include <type_traits> +#include <utility> + +#include "lldb/Host/Config.h" #include "lldb/Interpreter/ScriptedInterface.h" #include "lldb/Utility/DataBufferHeap.h" @@ -34,7 +39,7 @@ protected: } template <typename T = StructuredData::ObjectSP, typename... Args> - T Dispatch(llvm::StringRef method_name, Status &error, Args... args) { + T Dispatch(llvm::StringRef method_name, Status &error, Args &&...args) { using namespace python; using Locker = ScriptInterpreterPythonImpl::Locker; @@ -56,59 +61,112 @@ protected: return ErrorWithMessage<T>(caller_signature, "Python implementor not allocated.", error); - PythonObject pmeth( - PyRefType::Owned, - PyObject_GetAttrString(implementor.get(), method_name.str().c_str())); + std::tuple<Args...> original_args = std::forward_as_tuple(args...); + auto transformed_args = TransformArgs(original_args); + + llvm::Expected<PythonObject> expected_return_object = + llvm::make_error<llvm::StringError>("Not initialized.", + llvm::inconvertibleErrorCode()); + std::apply( + [&implementor, &method_name, &expected_return_object](auto &&...args) { + llvm::consumeError(expected_return_object.takeError()); + expected_return_object = + implementor.CallMethod(method_name.data(), args...); + }, + transformed_args); + + if (llvm::Error e = expected_return_object.takeError()) { + error.SetErrorString(llvm::toString(std::move(e)).c_str()); + return ErrorWithMessage<T>(caller_signature, + "Python method could not be called.", error); + } - if (PyErr_Occurred()) - PyErr_Clear(); + PythonObject py_return = std::move(expected_return_object.get()); - if (!pmeth.IsAllocated()) - return ErrorWithMessage<T>(caller_signature, - "Python method not allocated.", error); + if (!py_return.IsAllocated()) + return ErrorWithMessage<T>(caller_signature, "Returned object is null.", + error); - if (PyCallable_Check(pmeth.get()) == 0) { - if (PyErr_Occurred()) - PyErr_Clear(); - return ErrorWithMessage<T>(caller_signature, - "Python method not callable.", error); - } + // Now that we called the python method with the transformed arguments, + // we need to interate again over both the original and transformed + // parameter pack, and transform back the parameter that were passed in + // the original parameter pack as references or pointers. + if (sizeof...(Args) > 0) + if (!ReassignPtrsOrRefsArgs(original_args, transformed_args)) + return ErrorWithMessage<T>( + caller_signature, + "Couldn't re-assign reference and pointer arguments.", error); - if (PyErr_Occurred()) - PyErr_Clear(); + return ExtractValueFromPythonObject<T>(py_return, error); + } - // TODO: make `const char *` when removing support for Python 2. - char *format = nullptr; - std::string format_buffer; + template <typename... Args> + Status GetStatusFromMethod(llvm::StringRef method_name, Args &&...args) { + Status error; + Dispatch<Status>(method_name, error, std::forward<Args>(args)...); - if (sizeof...(Args) > 0) { - FormatArgs(format_buffer, args...); - // TODO: make `const char *` when removing support for Python 2. - format = const_cast<char *>(format_buffer.c_str()); - } + return error; + } - // TODO: make `const char *` when removing support for Python 2. - PythonObject py_return( - PyRefType::Owned, - PyObject_CallMethod(implementor.get(), - const_cast<char *>(method_name.data()), format, - args...)); + template <typename T> T Transform(T object) { + // No Transformation for generic usage + return {object}; + } - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - return ErrorWithMessage<T>(caller_signature, - "Python method could not be called.", error); - } + python::PythonObject Transform(Status arg) { + return python::ToSWIGWrapper(arg); + } - if (!py_return.IsAllocated()) - return ErrorWithMessage<T>(caller_signature, "Returned object is null.", - error); + template <typename T, typename U> + void ReverseTransform(T &original_arg, U transformed_arg, Status &error) { + // If U is not a PythonObject, don't touch it! + return; + } - return ExtractValueFromPythonObject<T>(py_return, error); + template <typename T> + void ReverseTransform(T &original_arg, python::PythonObject transformed_arg, + Status &error) { + original_arg = ExtractValueFromPythonObject<T>(transformed_arg, error); + } + + template <std::size_t... I, typename... Args> + auto TransformTuple(const std::tuple<Args...> &args, + std::index_sequence<I...>) { + return std::make_tuple(Transform(std::get<I>(args))...); + } + + // This will iterate over the Dispatch parameter pack and replace in-place + // every `lldb_private` argument that has a SB counterpart. + template <typename... Args> + auto TransformArgs(const std::tuple<Args...> &args) { + return TransformTuple(args, std::make_index_sequence<sizeof...(Args)>()); + } + + template <typename T, typename U> + void TransformBack(T &original_arg, U transformed_arg, Status &error) { + ReverseTransform(original_arg, transformed_arg, error); } - Status GetStatusFromMethod(llvm::StringRef method_name); + template <std::size_t... I, typename... Ts, typename... Us> + bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, + std::tuple<Us...> &transformed_args, + std::index_sequence<I...>) { + Status error; + (TransformBack(std::get<I>(original_args), std::get<I>(transformed_args), + error), + ...); + return error.Success(); + } + + template <typename... Ts, typename... Us> + bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, + std::tuple<Us...> &transformed_args) { + if (sizeof...(Ts) != sizeof...(Us)) + return false; + + return ReassignPtrsOrRefsArgs(original_args, transformed_args, + std::make_index_sequence<sizeof...(Ts)>()); + } template <typename T, typename... Args> void FormatArgs(std::string &fmt, T arg, Args... args) const { @@ -117,7 +175,7 @@ protected: } template <typename T> void FormatArgs(std::string &fmt, T arg) const { - fmt += GetPythonValueFormatString(arg); + fmt += python::PythonFormat<T>::format; } void FormatArgs(std::string &fmt) const {} @@ -146,9 +204,9 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( python::PythonObject &p, Status &error); template <> -llvm::Optional<MemoryRegionInfo> +std::optional<MemoryRegionInfo> ScriptedPythonInterface::ExtractValueFromPythonObject< - llvm::Optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error); + std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error); } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp index 3ff592fb83cd..1b31ed2e5881 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp @@ -18,6 +18,7 @@ #include "SWIGPythonBridge.h" #include "ScriptInterpreterPythonImpl.h" #include "ScriptedThreadPythonInterface.h" +#include <optional> using namespace lldb; using namespace lldb_private; @@ -34,7 +35,6 @@ StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject( if (class_name.empty() && !script_obj) return {}; - ProcessSP process_sp = exe_ctx.GetProcessSP(); StructuredDataImpl args_impl(args_sp); std::string error_string; @@ -43,11 +43,13 @@ StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject( PythonObject ret_val; - if (!script_obj) - ret_val = LLDBSwigPythonCreateScriptedThread( - class_name.str().c_str(), m_interpreter.GetDictionaryName(), process_sp, - args_impl, error_string); - else + if (!script_obj) { + lldb::ExecutionContextRefSP exe_ctx_ref_sp = + std::make_shared<ExecutionContextRef>(exe_ctx); + ret_val = LLDBSwigPythonCreateScriptedObject( + class_name.str().c_str(), m_interpreter.GetDictionaryName(), + exe_ctx_ref_sp, args_impl, error_string); + } else ret_val = PythonObject(PyRefType::Borrowed, static_cast<PyObject *>(script_obj->GetValue())); @@ -70,7 +72,7 @@ lldb::tid_t ScriptedThreadPythonInterface::GetThreadID() { return obj->GetIntegerValue(LLDB_INVALID_THREAD_ID); } -llvm::Optional<std::string> ScriptedThreadPythonInterface::GetName() { +std::optional<std::string> ScriptedThreadPythonInterface::GetName() { Status error; StructuredData::ObjectSP obj = Dispatch("get_name", error); @@ -90,7 +92,7 @@ lldb::StateType ScriptedThreadPythonInterface::GetState() { return static_cast<StateType>(obj->GetIntegerValue(eStateInvalid)); } -llvm::Optional<std::string> ScriptedThreadPythonInterface::GetQueue() { +std::optional<std::string> ScriptedThreadPythonInterface::GetQueue() { Status error; StructuredData::ObjectSP obj = Dispatch("get_queue", error); @@ -133,8 +135,7 @@ StructuredData::DictionarySP ScriptedThreadPythonInterface::GetRegisterInfo() { return dict; } -llvm::Optional<std::string> -ScriptedThreadPythonInterface::GetRegisterContext() { +std::optional<std::string> ScriptedThreadPythonInterface::GetRegisterContext() { Status error; StructuredData::ObjectSP obj = Dispatch("get_register_context", error); @@ -144,4 +145,15 @@ ScriptedThreadPythonInterface::GetRegisterContext() { return obj->GetAsString()->GetValue().str(); } +StructuredData::ArraySP ScriptedThreadPythonInterface::GetExtendedInfo() { + Status error; + StructuredData::ArraySP arr = + Dispatch<StructuredData::ArraySP>("get_extended_info", error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, arr, error)) + return {}; + + return arr; +} + #endif diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h index 59bb182ae3f3..eac4941f8814 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.h @@ -15,6 +15,7 @@ #include "ScriptedPythonInterface.h" #include "lldb/Interpreter/ScriptedProcessInterface.h" +#include <optional> namespace lldb_private { class ScriptedThreadPythonInterface : public ScriptedThreadInterface, @@ -29,11 +30,11 @@ public: lldb::tid_t GetThreadID() override; - llvm::Optional<std::string> GetName() override; + std::optional<std::string> GetName() override; lldb::StateType GetState() override; - llvm::Optional<std::string> GetQueue() override; + std::optional<std::string> GetQueue() override; StructuredData::DictionarySP GetStopReason() override; @@ -41,7 +42,9 @@ public: StructuredData::DictionarySP GetRegisterInfo() override; - llvm::Optional<std::string> GetRegisterContext() override; + std::optional<std::string> GetRegisterContext() override; + + StructuredData::ArraySP GetExtendedInfo() override; }; } // namespace lldb_private |