https://github.com/medismailben updated https://github.com/llvm/llvm-project/pull/210430
>From 445cc9fd587c5f0ae99c55f637a8661ea82a52a3 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani <[email protected]> Date: Fri, 17 Jul 2026 16:38:42 -0700 Subject: [PATCH] [lldb/script] Migrate ParsedCommand & raw commands onto ScriptedPythonInterface Give both `command script add -c` (raw class) and `-P` (ParsedCommand) a single, shared `ScriptedCommandInterface`/`ScriptedCommandPythonInterface`, built on the existing `ScriptedPythonInterface` machinery: `CreatePluginObject` delegates to the base template, and every other method goes through `Dispatch()`. Add a lighter `ScriptedCommand` ABC template (`scripted_command.py`) for raw mode; the existing `ParsedCommand`/`LLDBOptionValueParser` classes are kept as-is. Extend `ScriptedPythonInterface` with a few `Transform` overloads (`DebuggerSP`, `std::vector<StringRef>`, `CommandReturnObject &`) so those argument types route through `Dispatch` without extra plumbing. Delete the standalone SWIG bridge functions this plugin was the sole caller of. `CommandObjectScriptingObjectRaw` and `CommandObjectScriptingObjectParsed` now hold a `ScriptedCommandInterfaceSP` instead of a raw `StructuredData::GenericSP`; `command script add`'s `DoExecute` constructs the interface once via `CreateScriptedCommandInterface()->CreatePluginObject` for either flag. Signed-off-by: Med Ismail Bennani <[email protected]> --- lldb/bindings/python/CMakeLists.txt | 1 + lldb/bindings/python/python-wrapper.swig | 184 +------ lldb/docs/CMakeLists.txt | 1 + .../python/templates/scripted_command.py | 86 +++ lldb/include/lldb/API/SBCommandReturnObject.h | 18 +- lldb/include/lldb/API/SBDebugger.h | 1 + .../Interfaces/ScriptedCommandInterface.h | 83 +++ .../lldb/Interpreter/ScriptInterpreter.h | 88 +-- lldb/include/lldb/lldb-enumerations.h | 4 +- lldb/include/lldb/lldb-forward.h | 3 + lldb/source/API/SBCommandReturnObject.cpp | 49 +- .../source/Commands/CommandObjectCommands.cpp | 199 +++---- lldb/source/Interpreter/ScriptInterpreter.cpp | 18 + .../ScriptInterpreter/Python/CMakeLists.txt | 1 + .../ScriptInterpreterPythonInterfaces.cpp | 2 + .../ScriptInterpreterPythonInterfaces.h | 1 + .../ScriptedCommandPythonInterface.cpp | 247 +++++++++ .../ScriptedCommandPythonInterface.h | 81 +++ .../Interfaces/ScriptedPythonInterface.cpp | 55 ++ .../Interfaces/ScriptedPythonInterface.h | 36 ++ .../Python/SWIGPythonBridge.h | 33 +- .../Python/ScriptInterpreterPython.cpp | 506 +----------------- .../Python/ScriptInterpreterPythonImpl.h | 52 +- .../Python/PythonTestSuite.cpp | 51 +- 24 files changed, 806 insertions(+), 994 deletions(-) create mode 100644 lldb/examples/python/templates/scripted_command.py create mode 100644 lldb/include/lldb/Interpreter/Interfaces/ScriptedCommandInterface.h create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedCommandPythonInterface.cpp create mode 100644 lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedCommandPythonInterface.h diff --git a/lldb/bindings/python/CMakeLists.txt b/lldb/bindings/python/CMakeLists.txt index d29b143c1408c..6ffdf9ccafabc 100644 --- a/lldb/bindings/python/CMakeLists.txt +++ b/lldb/bindings/python/CMakeLists.txt @@ -120,6 +120,7 @@ function(finish_swig_python swig_target lldb_python_bindings_dir lldb_python_tar "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_breakpoint.py" "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_hook.py" "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_stackframe_recognizer.py" + "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_command.py" ) if(APPLE) diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig index 2392737402e20..c4071b3f7b5b1 100644 --- a/lldb/bindings/python/python-wrapper.swig +++ b/lldb/bindings/python/python-wrapper.swig @@ -213,25 +213,6 @@ PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateSyntheticProv return PythonObject(); } -PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateCommandObject( - const char *python_class_name, const char *session_dictionary_name, - lldb::DebuggerSP debugger_sp) { - if (python_class_name == NULL || python_class_name[0] == '\0' || - !session_dictionary_name) - return PythonObject(); - - PyErr_Cleaner py_err_cleaner(true); - auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>( - session_dictionary_name); - auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>( - python_class_name, dict); - - if (!pfunc.IsAllocated()) - return PythonObject(); - - return pfunc(SWIGBridge::ToSWIGWrapper(std::move(debugger_sp)), dict); -} - // wrapper that calls an optional instance member of an object taking no // arguments static PyObject *LLDBSwigPython_CallOptionalMember( @@ -497,6 +478,32 @@ void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBError(PyObject * data return sb_ptr; } +void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBCommandReturnObject( + PyObject *data) { + lldb::SBCommandReturnObject *sb_ptr = nullptr; + + int valid_cast = SWIG_ConvertPtr( + data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBCommandReturnObject, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + +void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBDebugger( + PyObject *data) { + lldb::SBDebugger *sb_ptr = nullptr; + + int valid_cast = + SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBDebugger, 0); + + if (valid_cast == -1) + return NULL; + + return sb_ptr; +} + void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBEvent(PyObject * data) { lldb::SBEvent *sb_ptr = nullptr; @@ -639,145 +646,6 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallCommand( return true; } -bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallCommandObject( - PyObject *implementor, lldb::DebuggerSP debugger, const char *args, - lldb_private::CommandReturnObject &cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp) { - - PyErr_Cleaner py_err_cleaner(true); - - PythonObject self(PyRefType::Borrowed, implementor); - auto pfunc = self.ResolveName<PythonCallable>("__call__"); - - if (!pfunc.IsAllocated()) - return false; - - auto cmd_retobj_arg = SWIGBridge::ToSWIGWrapper(cmd_retobj); - - pfunc(SWIGBridge::ToSWIGWrapper(std::move(debugger)), PythonString(args), - SWIGBridge::ToSWIGWrapper(exe_ctx_ref_sp), cmd_retobj_arg.obj()); - - return true; -} - -std::optional<std::string> -lldb_private::python::SWIGBridge::LLDBSwigPythonGetRepeatCommandForScriptedCommand(PyObject *implementor, - std::string &command) { - PyErr_Cleaner py_err_cleaner(true); - - PythonObject self(PyRefType::Borrowed, implementor); - auto pfunc = self.ResolveName<PythonCallable>("get_repeat_command"); - // If not implemented, repeat the exact command. - if (!pfunc.IsAllocated()) - return std::nullopt; - - PythonString command_str(command); - PythonObject result = pfunc(command_str); - - // A return of None is the equivalent of nullopt - means repeat - // the command as is: - if (result.IsNone()) - return std::nullopt; - - return result.Str().GetString().str(); -} - -StructuredData::DictionarySP -lldb_private::python::SWIGBridge::LLDBSwigPythonHandleArgumentCompletionForScriptedCommand(PyObject *implementor, - std::vector<llvm::StringRef> &args_vec, size_t args_pos, size_t pos_in_arg) { - - PyErr_Cleaner py_err_cleaner(true); - - PythonObject self(PyRefType::Borrowed, implementor); - auto pfunc = self.ResolveName<PythonCallable>("handle_argument_completion"); - // If this isn't implemented, return an empty dict to signal falling back to default completion: - if (!pfunc.IsAllocated()) - return {}; - - PythonList args_list(PyInitialValue::Empty); - for (auto elem : args_vec) - args_list.AppendItem(PythonString(elem)); - - PythonObject result = pfunc(args_list, PythonInteger(args_pos), PythonInteger(pos_in_arg)); - // Returning None means do the ordinary completion - if (result.IsNone()) - return {}; - - // Convert the return dictionary to a DictionarySP. - StructuredData::ObjectSP result_obj_sp = result.CreateStructuredObject(); - if (!result_obj_sp) - return {}; - - StructuredData::DictionarySP dict_sp(new StructuredData::Dictionary(result_obj_sp)); - if (dict_sp->GetType() == lldb::eStructuredDataTypeInvalid) - return {}; - return dict_sp; -} - -StructuredData::DictionarySP -lldb_private::python::SWIGBridge::LLDBSwigPythonHandleOptionArgumentCompletionForScriptedCommand(PyObject *implementor, - llvm::StringRef &long_option, size_t pos_in_arg) { - - PyErr_Cleaner py_err_cleaner(true); - - PythonObject self(PyRefType::Borrowed, implementor); - auto pfunc = self.ResolveName<PythonCallable>("handle_option_argument_completion"); - // If this isn't implemented, return an empty dict to signal falling back to default completion: - if (!pfunc.IsAllocated()) - return {}; - - PythonObject result = pfunc(PythonString(long_option), PythonInteger(pos_in_arg)); - // Returning None means do the ordinary completion - if (result.IsNone()) - return {}; - - // Returning a boolean: - // True means the completion was handled, but there were no completions - // False means that the completion was not handled, again, do the ordinary completion: - if (result.GetObjectType() == PyObjectType::Boolean) { - if (!result.IsTrue()) - return {}; - // Make up a completion dictionary with the right element: - StructuredData::DictionarySP dict_sp(new StructuredData::Dictionary()); - dict_sp->AddBooleanItem("no-completion", true); - return dict_sp; - } - - - // Convert the return dictionary to a DictionarySP. - StructuredData::ObjectSP result_obj_sp = result.CreateStructuredObject(); - if (!result_obj_sp) - return {}; - - StructuredData::DictionarySP dict_sp(new StructuredData::Dictionary(result_obj_sp)); - if (dict_sp->GetType() == lldb::eStructuredDataTypeInvalid) - return {}; - return dict_sp; -} - -#include "lldb/Interpreter/CommandReturnObject.h" - -bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallParsedCommandObject( - PyObject *implementor, lldb::DebuggerSP debugger, lldb_private::StructuredDataImpl &args_impl, - lldb_private::CommandReturnObject &cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp) { - - PyErr_Cleaner py_err_cleaner(true); - - PythonObject self(PyRefType::Borrowed, implementor); - auto pfunc = self.ResolveName<PythonCallable>("__call__"); - - if (!pfunc.IsAllocated()) { - cmd_retobj.AppendError("Could not find '__call__' method in implementation class"); - return false; - } - - pfunc(SWIGBridge::ToSWIGWrapper(std::move(debugger)), SWIGBridge::ToSWIGWrapper(args_impl), - SWIGBridge::ToSWIGWrapper(exe_ctx_ref_sp), SWIGBridge::ToSWIGWrapper(cmd_retobj).obj()); - - return true; -} - PythonObject lldb_private::python::SWIGBridge::LLDBSWIGPythonCreateOSPlugin( const char *python_class_name, const char *session_dictionary_name, const lldb::ProcessSP &process_sp) { diff --git a/lldb/docs/CMakeLists.txt b/lldb/docs/CMakeLists.txt index dd091836dc1aa..53647990f7842 100644 --- a/lldb/docs/CMakeLists.txt +++ b/lldb/docs/CMakeLists.txt @@ -33,6 +33,7 @@ if (LLDB_ENABLE_PYTHON AND SPHINX_FOUND) COMMAND "${CMAKE_COMMAND}" -E copy "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_breakpoint.py" "${CMAKE_CURRENT_BINARY_DIR}/lldb/plugins/" COMMAND "${CMAKE_COMMAND}" -E copy "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_hook.py" "${CMAKE_CURRENT_BINARY_DIR}/lldb/plugins/" COMMAND "${CMAKE_COMMAND}" -E copy "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_stackframe_recognizer.py" "${CMAKE_CURRENT_BINARY_DIR}/lldb/plugins/" + COMMAND "${CMAKE_COMMAND}" -E copy "${LLDB_SOURCE_DIR}/examples/python/templates/scripted_command.py" "${CMAKE_CURRENT_BINARY_DIR}/lldb/plugins/" COMMENT "Copying lldb.py to pretend its a Python package.") add_dependencies(lldb-python-doc-package swig_wrapper_python) diff --git a/lldb/examples/python/templates/scripted_command.py b/lldb/examples/python/templates/scripted_command.py new file mode 100644 index 0000000000000..d9b18ea4376aa --- /dev/null +++ b/lldb/examples/python/templates/scripted_command.py @@ -0,0 +1,86 @@ +from abc import ABCMeta, abstractmethod +from typing import Optional + +import lldb + + +class ScriptedCommand(metaclass=ABCMeta): + """ + The base class for a scripted (raw) command. + + A raw command receives the unparsed argument string exactly as the user + typed it, and is responsible for any parsing it needs. For a command + with a table-driven option/argument parser, see `ParsedCommand` instead. + Register it with `command script add -c <ClassName> ...`. + + Most of the base class methods are `@abstractmethod` that need to be + overwritten by the inheriting class. + """ + + def __init__(self, debugger: lldb.SBDebugger): + """Construct a scripted command. + + Args: + debugger (lldb.SBDebugger): The debugger this command is being + added to. + """ + pass + + @abstractmethod + def __call__( + self, + debugger: lldb.SBDebugger, + args: str, + exe_ctx: lldb.SBExecutionContext, + result: lldb.SBCommandReturnObject, + ) -> None: + """Execute the command. + + Args: + debugger (lldb.SBDebugger): The debugger the command runs + against. + args (str): The raw, unparsed argument string. + exe_ctx (lldb.SBExecutionContext): The execution context. + result (lldb.SBCommandReturnObject): Write command output/errors + here. + """ + pass + + def get_short_help(self) -> Optional[str]: + """A one-line description shown by `help`. + + Returns: + str: The short help string. + """ + pass + + def get_long_help(self) -> Optional[str]: + """The full help text shown by `help <command>`. + + Returns: + str: The long help string. + """ + pass + + def get_flags(self) -> int: + """Command flags (a bitmask of `lldb.eCommandRequires*`/ + `lldb.eCommandProcessMustBe*` etc.) controlling when this command is + available. + + Returns: + int: The flags bitmask. Defaults to 0 (no restrictions). + """ + return 0 + + def get_repeat_command(self, command: str) -> Optional[str]: + """Customize what runs when the user presses Enter to repeat this + command. + + Args: + command (str): The command line that was run. + + Returns: + str: The command line to run on repeat. Defaults to `None`, + meaning repeat the original command unmodified. + """ + pass diff --git a/lldb/include/lldb/API/SBCommandReturnObject.h b/lldb/include/lldb/API/SBCommandReturnObject.h index 6386bd250afa5..ca7debfc4e575 100644 --- a/lldb/include/lldb/API/SBCommandReturnObject.h +++ b/lldb/include/lldb/API/SBCommandReturnObject.h @@ -17,10 +17,25 @@ namespace lldb_private { class CommandPluginInterfaceImplementation; -class SBCommandReturnObjectImpl; +class CommandReturnObject; namespace python { class SWIGBridge; } + +class SBCommandReturnObjectImpl { +public: + SBCommandReturnObjectImpl(); + SBCommandReturnObjectImpl(CommandReturnObject &ref); + SBCommandReturnObjectImpl(const SBCommandReturnObjectImpl &rhs); + SBCommandReturnObjectImpl &operator=(const SBCommandReturnObjectImpl &rhs); + ~SBCommandReturnObjectImpl(); + + CommandReturnObject *get() const { return m_ptr; } + +private: + CommandReturnObject *m_ptr; + bool m_owned = true; +}; } // namespace lldb_private namespace lldb { @@ -144,6 +159,7 @@ class LLDB_API SBCommandReturnObject { friend class lldb_private::CommandPluginInterfaceImplementation; friend class lldb_private::python::SWIGBridge; + friend class lldb_private::ScriptInterpreter; SBCommandReturnObject(lldb_private::CommandReturnObject &ref); diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h index 14b8350902811..3e302f121f5ec 100644 --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -678,6 +678,7 @@ class LLDB_API SBDebugger { protected: friend class lldb_private::CommandPluginInterfaceImplementation; friend class lldb_private::python::SWIGBridge; + friend class lldb_private::ScriptInterpreter; friend class lldb_private::SystemInitializerFull; SBDebugger(const lldb::DebuggerSP &debugger_sp); diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedCommandInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedCommandInterface.h new file mode 100644 index 0000000000000..a302c8d766eb9 --- /dev/null +++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedCommandInterface.h @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// 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_INTERPRETER_INTERFACES_SCRIPTEDCOMMANDINTERFACE_H +#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDCOMMANDINTERFACE_H + +#include "ScriptedInterface.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { +/// Interface for a scripted command, covering both the raw (`command script +/// add -c`, `__call__(debugger, args, exe_ctx, result)`) and parsed +/// (`command script add -P`, option/argument table driven) calling +/// conventions. Both are instantiated through the same Python class lookup, +/// and differ only in which of RunRawCommand/RunParsedCommand gets called. +class ScriptedCommandInterface : virtual public ScriptedInterface { +public: + virtual llvm::Expected<StructuredData::GenericSP> + CreatePluginObject(llvm::StringRef class_name, + lldb::DebuggerSP debugger_sp) = 0; + + virtual bool RunRawCommand(llvm::StringRef args, + ScriptedCommandSynchronicity synchronicity, + CommandReturnObject &cmd_retobj, Status &error, + const ExecutionContext &exe_ctx) { + return false; + } + + virtual bool RunParsedCommand(Args &args, + ScriptedCommandSynchronicity synchronicity, + CommandReturnObject &cmd_retobj, Status &error, + const ExecutionContext &exe_ctx) { + return false; + } + + virtual std::optional<std::string> GetRepeatCommand(Args &args) { + return std::nullopt; + } + + virtual StructuredData::DictionarySP + HandleArgumentCompletion(std::vector<llvm::StringRef> &args, size_t args_pos, + size_t char_in_arg) { + return {}; + } + + virtual StructuredData::DictionarySP + HandleOptionArgumentCompletion(llvm::StringRef &long_option, + size_t char_in_arg) { + return {}; + } + + virtual bool GetShortHelp(std::string &dest) { + dest.clear(); + return false; + } + + virtual bool GetLongHelp(std::string &dest) { + dest.clear(); + return false; + } + + virtual uint32_t GetFlags() { return 0; } + + virtual StructuredData::ObjectSP GetOptionsDefinition() { return {}; } + + virtual StructuredData::ObjectSP GetArgumentsDefinition() { return {}; } + + virtual void OptionParsingStarted() {} + + virtual bool SetOptionValue(ExecutionContext *exe_ctx, + llvm::StringRef long_option, + llvm::StringRef value) { + return false; + } +}; +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDCOMMANDINTERFACE_H diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h index 0e65cb4b8ac4a..9d3e7e6f32ff5 100644 --- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h +++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h @@ -263,11 +263,6 @@ class ScriptInterpreter : public PluginInterface { return StructuredData::ObjectSP(); } - virtual StructuredData::GenericSP - CreateScriptCommandObject(const char *class_name) { - return StructuredData::GenericSP(); - } - virtual StructuredData::ObjectSP LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) { return StructuredData::ObjectSP(); @@ -394,42 +389,6 @@ class ScriptInterpreter : public PluginInterface { return false; } - virtual bool RunScriptBasedCommand( - StructuredData::GenericSP impl_obj_sp, llvm::StringRef args, - ScriptedCommandSynchronicity synchronicity, - lldb_private::CommandReturnObject &cmd_retobj, Status &error, - const lldb_private::ExecutionContext &exe_ctx) { - return false; - } - - virtual bool RunScriptBasedParsedCommand( - StructuredData::GenericSP impl_obj_sp, Args& args, - ScriptedCommandSynchronicity synchronicity, - lldb_private::CommandReturnObject &cmd_retobj, Status &error, - const lldb_private::ExecutionContext &exe_ctx) { - return false; - } - - virtual std::optional<std::string> - GetRepeatCommandForScriptedCommand(StructuredData::GenericSP impl_obj_sp, - Args &args) { - return std::nullopt; - } - - virtual StructuredData::DictionarySP - HandleArgumentCompletionForScriptedCommand( - StructuredData::GenericSP impl_obj_sp, std::vector<llvm::StringRef> &args, - size_t args_pos, size_t char_in_arg) { - return {}; - } - - virtual StructuredData::DictionarySP - HandleOptionArgumentCompletionForScriptedCommand( - StructuredData::GenericSP impl_obj_sp, llvm::StringRef &long_name, - size_t char_in_arg) { - return {}; - } - virtual bool RunScriptFormatKeyword(const char *impl_function, Process *process, std::string &output, Status &error) { @@ -468,43 +427,6 @@ class ScriptInterpreter : public PluginInterface { return false; } - virtual bool - GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, - std::string &dest) { - dest.clear(); - return false; - } - - virtual StructuredData::ObjectSP - GetOptionsForCommandObject(StructuredData::GenericSP cmd_obj_sp) { - return {}; - } - - virtual StructuredData::ObjectSP - GetArgumentsForCommandObject(StructuredData::GenericSP cmd_obj_sp) { - return {}; - } - - virtual bool SetOptionValueForCommandObject( - StructuredData::GenericSP cmd_obj_sp, ExecutionContext *exe_ctx, - llvm::StringRef long_option, llvm::StringRef value) { - return false; - } - - virtual void - OptionParsingStartedForCommandObject(StructuredData::GenericSP cmd_obj_sp) {} - - virtual uint32_t - GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) { - return 0; - } - - virtual bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, - std::string &dest) { - dest.clear(); - return false; - } - virtual bool CheckObjectExists(const char *name) { return false; } virtual bool @@ -586,6 +508,10 @@ class ScriptInterpreter : public PluginInterface { return {}; } + virtual lldb::ScriptedCommandInterfaceSP CreateScriptedCommandInterface() { + return {}; + } + virtual StructuredData::ObjectSP CreateStructuredDataFromScriptObject(ScriptObject obj) { return {}; @@ -658,6 +584,12 @@ class ScriptInterpreter : public PluginInterface { lldb::BreakpointLocationSP GetOpaqueTypeFromSBBreakpointLocation( const lldb::SBBreakpointLocation &break_loc) const; + CommandReturnObject *GetOpaqueTypeFromSBCommandReturnObject( + const lldb::SBCommandReturnObject &cmd_retobj) const; + + lldb::DebuggerSP + GetOpaqueTypeFromSBDebugger(const lldb::SBDebugger &debugger) const; + lldb::ProcessAttachInfoSP GetOpaqueTypeFromSBAttachInfo(const lldb::SBAttachInfo &attach_info) const; diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index 93c252b55de99..f73d0085f2320 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -268,7 +268,9 @@ enum ScriptedExtension { eScriptedExtensionScriptedThread, eScriptedExtensionScriptedFrame, eScriptedExtensionScriptedStackFrameRecognizer, - kLastScriptedExtension = eScriptedExtensionScriptedStackFrameRecognizer + eScriptedExtensionScriptedCommand, + eScriptedExtensionParsedCommand, + kLastScriptedExtension = eScriptedExtensionParsedCommand }; /// Register numbering types. diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 157aa5743f016..2572aa0dc344b 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -193,6 +193,7 @@ class ScriptedFrameInterface; class ScriptedFrameProviderInterface; class ScriptedMetadata; class ScriptedBreakpointInterface; +class ScriptedCommandInterface; class ScriptedHookInterface; class ScriptedPlatformInterface; class ScriptedProcessInterface; @@ -438,6 +439,8 @@ typedef std::shared_ptr<lldb_private::ScriptedBreakpointInterface> ScriptedBreakpointInterfaceSP; typedef std::shared_ptr<lldb_private::ScriptedStackFrameRecognizerInterface> ScriptedStackFrameRecognizerInterfaceSP; +typedef std::shared_ptr<lldb_private::ScriptedCommandInterface> + ScriptedCommandInterfaceSP; typedef std::shared_ptr<lldb_private::Section> SectionSP; typedef std::unique_ptr<lldb_private::SectionList> SectionListUP; typedef std::weak_ptr<lldb_private::Section> SectionWP; diff --git a/lldb/source/API/SBCommandReturnObject.cpp b/lldb/source/API/SBCommandReturnObject.cpp index 62cc7a1f05573..7c71d9da8374d 100644 --- a/lldb/source/API/SBCommandReturnObject.cpp +++ b/lldb/source/API/SBCommandReturnObject.cpp @@ -25,30 +25,27 @@ using namespace lldb; using namespace lldb_private; -class lldb_private::SBCommandReturnObjectImpl { -public: - SBCommandReturnObjectImpl() : m_ptr(new CommandReturnObject(false)) {} - SBCommandReturnObjectImpl(CommandReturnObject &ref) - : m_ptr(&ref), m_owned(false) {} - SBCommandReturnObjectImpl(const SBCommandReturnObjectImpl &rhs) - : m_ptr(new CommandReturnObject(*rhs.m_ptr)), m_owned(rhs.m_owned) {} - SBCommandReturnObjectImpl &operator=(const SBCommandReturnObjectImpl &rhs) { - SBCommandReturnObjectImpl copy(rhs); - std::swap(*this, copy); - return *this; - } - // rvalue ctor+assignment are not used by SBCommandReturnObject. - ~SBCommandReturnObjectImpl() { - if (m_owned) - delete m_ptr; - } +SBCommandReturnObjectImpl::SBCommandReturnObjectImpl() + : m_ptr(new CommandReturnObject(false)) {} - CommandReturnObject &operator*() const { return *m_ptr; } +SBCommandReturnObjectImpl::SBCommandReturnObjectImpl(CommandReturnObject &ref) + : m_ptr(&ref), m_owned(false) {} -private: - CommandReturnObject *m_ptr; - bool m_owned = true; -}; +SBCommandReturnObjectImpl::SBCommandReturnObjectImpl( + const SBCommandReturnObjectImpl &rhs) + : m_ptr(new CommandReturnObject(*rhs.m_ptr)), m_owned(rhs.m_owned) {} + +SBCommandReturnObjectImpl & +SBCommandReturnObjectImpl::operator=(const SBCommandReturnObjectImpl &rhs) { + SBCommandReturnObjectImpl copy(rhs); + std::swap(*this, copy); + return *this; +} + +SBCommandReturnObjectImpl::~SBCommandReturnObjectImpl() { + if (m_owned) + delete m_ptr; +} SBCommandReturnObject::SBCommandReturnObject() : m_opaque_up(new SBCommandReturnObjectImpl()) { @@ -221,19 +218,19 @@ void SBCommandReturnObject::AppendWarning(const char *message) { } CommandReturnObject *SBCommandReturnObject::operator->() const { - return &**m_opaque_up; + return m_opaque_up->get(); } CommandReturnObject *SBCommandReturnObject::get() const { - return &**m_opaque_up; + return m_opaque_up->get(); } CommandReturnObject &SBCommandReturnObject::operator*() const { - return **m_opaque_up; + return *m_opaque_up->get(); } CommandReturnObject &SBCommandReturnObject::ref() const { - return **m_opaque_up; + return *m_opaque_up->get(); } bool SBCommandReturnObject::GetDescription(SBStream &description) { diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 8f006768ecc9a..b29059bd3cf22 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -16,6 +16,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Interpreter/Interfaces/ScriptedCommandInterface.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionValueBoolean.h" #include "lldb/Interpreter/OptionValueString.h" @@ -1119,19 +1120,19 @@ class CommandObjectPythonFunction : public CommandObjectRaw { /// substitution). class CommandObjectScriptingObjectRaw : public CommandObjectRaw { public: - CommandObjectScriptingObjectRaw(CommandInterpreter &interpreter, - std::string name, - StructuredData::GenericSP cmd_obj_sp, - ScriptedCommandSynchronicity synch, - CompletionType completion_type) - : CommandObjectRaw(interpreter, name), m_cmd_obj_sp(cmd_obj_sp), - m_synchro(synch), m_fetched_help_short(false), - m_fetched_help_long(false), m_completion_type(completion_type) { + CommandObjectScriptingObjectRaw( + CommandInterpreter &interpreter, std::string name, + lldb::ScriptedCommandInterfaceSP cmd_interface_sp, + ScriptedCommandSynchronicity synch, CompletionType completion_type) + : CommandObjectRaw(interpreter, name), + m_cmd_interface_sp(cmd_interface_sp), m_synchro(synch), + m_fetched_help_short(false), m_fetched_help_long(false), + m_completion_type(completion_type) { StreamString stream; stream.Printf("For more information run 'help %s'", name.c_str()); SetHelp(stream.GetString()); - if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter()) - GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); + if (m_cmd_interface_sp) + GetFlags().Set(m_cmd_interface_sp->GetFlags()); } ~CommandObjectScriptingObjectRaw() override = default; @@ -1151,22 +1152,19 @@ class CommandObjectScriptingObjectRaw : public CommandObjectRaw { std::optional<std::string> GetRepeatCommand(Args &args, uint32_t index) override { - ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); - if (!scripter) + if (!m_cmd_interface_sp) return std::nullopt; - return scripter->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp, args); + return m_cmd_interface_sp->GetRepeatCommand(args); } llvm::StringRef GetHelp() override { if (m_fetched_help_short) return CommandObjectRaw::GetHelp(); - ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); - if (!scripter) + if (!m_cmd_interface_sp) return CommandObjectRaw::GetHelp(); std::string docstring; - m_fetched_help_short = - scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring); + m_fetched_help_short = m_cmd_interface_sp->GetShortHelp(docstring); if (!docstring.empty()) SetHelp(docstring); @@ -1177,13 +1175,11 @@ class CommandObjectScriptingObjectRaw : public CommandObjectRaw { if (m_fetched_help_long) return CommandObjectRaw::GetHelpLong(); - ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); - if (!scripter) + if (!m_cmd_interface_sp) return CommandObjectRaw::GetHelpLong(); std::string docstring; - m_fetched_help_long = - scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring); + m_fetched_help_long = m_cmd_interface_sp->GetLongHelp(docstring); if (!docstring.empty()) SetHelpLong(docstring); return CommandObjectRaw::GetHelpLong(); @@ -1192,15 +1188,13 @@ class CommandObjectScriptingObjectRaw : public CommandObjectRaw { protected: void DoExecute(llvm::StringRef raw_command_line, CommandReturnObject &result) override { - ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); - Status error; result.SetStatus(eReturnStatusInvalid); - if (!scripter || - !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line, - m_synchro, result, error, m_exe_ctx)) { + if (!m_cmd_interface_sp || + !m_cmd_interface_sp->RunRawCommand(raw_command_line, m_synchro, result, + error, m_exe_ctx)) { result.AppendError(error.AsCString()); } else { // Don't change the status if the command already set it... @@ -1214,7 +1208,7 @@ class CommandObjectScriptingObjectRaw : public CommandObjectRaw { } private: - StructuredData::GenericSP m_cmd_obj_sp; + lldb::ScriptedCommandInterfaceSP m_cmd_interface_sp; ScriptedCommandSynchronicity m_synchro; bool m_fetched_help_short : 1; bool m_fetched_help_long : 1; @@ -1238,23 +1232,16 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { private: class CommandOptions : public Options { public: - CommandOptions(CommandInterpreter &interpreter, - StructuredData::GenericSP cmd_obj_sp) : m_interpreter(interpreter), - m_cmd_obj_sp(cmd_obj_sp) {} + CommandOptions(CommandInterpreter &interpreter, + lldb::ScriptedCommandInterfaceSP cmd_interface_sp) + : m_cmd_interface_sp(cmd_interface_sp) {} ~CommandOptions() override = default; Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override { Status error; - ScriptInterpreter *scripter = - m_interpreter.GetDebugger().GetScriptInterpreter(); - if (!scripter) { - return Status::FromErrorString( - "No script interpreter for SetOptionValue."); - return error; - } - if (!m_cmd_obj_sp) { + if (!m_cmd_interface_sp) { return Status::FromErrorString( "SetOptionValue called with empty cmd_obj."); return error; @@ -1268,10 +1255,10 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { // Pass the long option, since you aren't actually required to have a // short_option, and for those options the index or short option character // aren't meaningful on the python side. - const char * long_option = - m_options_definition_up.get()[option_idx].long_option; - bool success = scripter->SetOptionValueForCommandObject(m_cmd_obj_sp, - execution_context, long_option, option_arg); + const char *long_option = + m_options_definition_up.get()[option_idx].long_option; + bool success = m_cmd_interface_sp->SetOptionValue( + execution_context, long_option, option_arg); if (!success) return Status::FromErrorStringWithFormatv( "Error setting option: {0} to {1}", long_option, option_arg); @@ -1279,12 +1266,10 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { } void OptionParsingStarting(ExecutionContext *execution_context) override { - ScriptInterpreter *scripter = - m_interpreter.GetDebugger().GetScriptInterpreter(); - if (!scripter || !m_cmd_obj_sp) + if (!m_cmd_interface_sp) return; - scripter->OptionParsingStartedForCommandObject(m_cmd_obj_sp); + m_cmd_interface_sp->OptionParsingStarted(); } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { @@ -1292,7 +1277,7 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { return {}; return llvm::ArrayRef(m_options_definition_up.get(), m_num_options); } - + static Status ParseUsageMaskFromArray(StructuredData::ObjectSP obj_sp, size_t counter, uint32_t &usage_mask) { // If the usage entry is not provided, we use LLDB_OPT_SET_ALL. @@ -1726,10 +1711,7 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { OptionElementVector &option_vec, int opt_element_index, CommandInterpreter &interpreter) override { - ScriptInterpreter *scripter = - interpreter.GetDebugger().GetScriptInterpreter(); - - if (!scripter) + if (!m_cmd_interface_sp) return; ExecutionContext exe_ctx = interpreter.GetExecutionContext(); @@ -1746,9 +1728,8 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { // regular option completer handle that: StructuredData::DictionarySP completion_dict_sp; if (!is_enum) - completion_dict_sp = - scripter->HandleOptionArgumentCompletionForScriptedCommand( - m_cmd_obj_sp, option_name, request.GetCursorCharPos()); + completion_dict_sp = m_cmd_interface_sp->HandleOptionArgumentCompletion( + option_name, request.GetCursorCharPos()); if (!completion_dict_sp) { Options::HandleOptionArgumentCompletion(request, option_vec, @@ -1809,19 +1790,17 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { std::vector<std::vector<EnumValueStorage>> m_enum_storage; std::vector<std::vector<OptionEnumValueElement>> m_enum_vector; std::vector<std::string> m_usage_container; - CommandInterpreter &m_interpreter; - StructuredData::GenericSP m_cmd_obj_sp; + lldb::ScriptedCommandInterfaceSP m_cmd_interface_sp; static std::unordered_set<std::string> g_string_storer; }; public: - static CommandObjectSP Create(CommandInterpreter &interpreter, - std::string name, - StructuredData::GenericSP cmd_obj_sp, - ScriptedCommandSynchronicity synch, - CommandReturnObject &result) { + static CommandObjectSP + Create(CommandInterpreter &interpreter, std::string name, + lldb::ScriptedCommandInterfaceSP cmd_interface_sp, + ScriptedCommandSynchronicity synch, CommandReturnObject &result) { CommandObjectSP new_cmd_sp(new CommandObjectScriptingObjectParsed( - interpreter, name, cmd_obj_sp, synch)); + interpreter, name, cmd_interface_sp, synch)); CommandObjectScriptingObjectParsed *parsed_cmd = static_cast<CommandObjectScriptingObjectParsed *>(new_cmd_sp.get()); @@ -1843,34 +1822,33 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { return new_cmd_sp; } - CommandObjectScriptingObjectParsed(CommandInterpreter &interpreter, - std::string name, - StructuredData::GenericSP cmd_obj_sp, - ScriptedCommandSynchronicity synch) - : CommandObjectParsed(interpreter, name.c_str()), - m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), - m_options(interpreter, cmd_obj_sp), m_fetched_help_short(false), + CommandObjectScriptingObjectParsed( + CommandInterpreter &interpreter, std::string name, + lldb::ScriptedCommandInterfaceSP cmd_interface_sp, + ScriptedCommandSynchronicity synch) + : CommandObjectParsed(interpreter, name.c_str()), + m_cmd_interface_sp(cmd_interface_sp), m_synchro(synch), + m_options(interpreter, cmd_interface_sp), m_fetched_help_short(false), m_fetched_help_long(false) { StreamString stream; - ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); - if (!scripter) { + if (!m_cmd_interface_sp) { m_options_error = Status::FromErrorString("No script interpreter"); return; } // Set the flags: - GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); + GetFlags().Set(m_cmd_interface_sp->GetFlags()); // Now set up the options definitions from the options: - StructuredData::ObjectSP options_object_sp - = scripter->GetOptionsForCommandObject(cmd_obj_sp); + StructuredData::ObjectSP options_object_sp = + m_cmd_interface_sp->GetOptionsDefinition(); // It's okay not to have an options dict. if (options_object_sp) { // The options come as a dictionary of dictionaries. The key of the // outer dict is the long option name (since that's required). The // value holds all the other option specification bits. - StructuredData::Dictionary *options_dict - = options_object_sp->GetAsDictionary(); + StructuredData::Dictionary *options_dict = + options_object_sp->GetAsDictionary(); // but if it exists, it has to be an array. if (options_dict) { m_options_error = m_options.SetOptionsFromArray(*(options_dict)); @@ -1884,8 +1862,8 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { } // Then fetch the args. Since the arguments can have usage masks you need // an array of arrays. - StructuredData::ObjectSP args_object_sp - = scripter->GetArgumentsForCommandObject(cmd_obj_sp); + StructuredData::ObjectSP args_object_sp = + m_cmd_interface_sp->GetArgumentsDefinition(); if (args_object_sp) { StructuredData::Array *args_array = args_object_sp->GetAsArray(); if (!args_array) { @@ -2017,9 +1995,7 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { public: void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &option_vec) override { - ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); - - if (!scripter) + if (!m_cmd_interface_sp) return; // Set up the options values on the scripted side: @@ -2057,8 +2033,8 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { args_elem_pos--; } StructuredData::DictionarySP completion_dict_sp = - scripter->HandleArgumentCompletionForScriptedCommand( - m_cmd_obj_sp, args_vec, args_elem_pos, request.GetCursorCharPos()); + m_cmd_interface_sp->HandleArgumentCompletion( + args_vec, args_elem_pos, request.GetCursorCharPos()); if (!completion_dict_sp) { CommandObject::HandleArgumentCompletion(request, option_vec); @@ -2074,22 +2050,19 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { std::optional<std::string> GetRepeatCommand(Args &args, uint32_t index) override { - ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); - if (!scripter) + if (!m_cmd_interface_sp) return std::nullopt; - return scripter->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp, args); + return m_cmd_interface_sp->GetRepeatCommand(args); } llvm::StringRef GetHelp() override { if (m_fetched_help_short) return CommandObjectParsed::GetHelp(); - ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); - if (!scripter) + if (!m_cmd_interface_sp) return CommandObjectParsed::GetHelp(); std::string docstring; - m_fetched_help_short = - scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring); + m_fetched_help_short = m_cmd_interface_sp->GetShortHelp(docstring); if (!docstring.empty()) SetHelp(docstring); @@ -2100,13 +2073,11 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { if (m_fetched_help_long) return CommandObjectParsed::GetHelpLong(); - ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); - if (!scripter) + if (!m_cmd_interface_sp) return CommandObjectParsed::GetHelpLong(); std::string docstring; - m_fetched_help_long = - scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring); + m_fetched_help_long = m_cmd_interface_sp->GetLongHelp(docstring); if (!docstring.empty()) SetHelpLong(docstring); return CommandObjectParsed::GetHelpLong(); @@ -2121,17 +2092,13 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { } protected: - void DoExecute(Args &args, - CommandReturnObject &result) override { - ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); - + void DoExecute(Args &args, CommandReturnObject &result) override { Status error; result.SetStatus(eReturnStatusInvalid); - - if (!scripter || - !scripter->RunScriptBasedParsedCommand(m_cmd_obj_sp, args, - m_synchro, result, error, m_exe_ctx)) { + + if (!m_cmd_interface_sp || !m_cmd_interface_sp->RunParsedCommand( + args, m_synchro, result, error, m_exe_ctx)) { result.AppendError(error.AsCString()); } else { // Don't change the status if the command already set it... @@ -2145,7 +2112,7 @@ class CommandObjectScriptingObjectParsed : public CommandObjectParsed { } private: - StructuredData::GenericSP m_cmd_obj_sp; + lldb::ScriptedCommandInterfaceSP m_cmd_interface_sp; ScriptedCommandSynchronicity m_synchro; CommandOptions m_options; Status m_options_error; @@ -2513,22 +2480,32 @@ class CommandObjectCommandsScriptAdd : public CommandObjectParsed, return; } - auto cmd_obj_sp = interpreter->CreateScriptCommandObject( - m_options.m_class_name.c_str()); - if (!cmd_obj_sp) { + lldb::ScriptedCommandInterfaceSP cmd_interface_sp = + interpreter->CreateScriptedCommandInterface(); + if (!cmd_interface_sp) { + result.AppendError("cannot create ScriptedCommandInterface"); + return; + } + + auto obj_or_err = cmd_interface_sp->CreatePluginObject( + m_options.m_class_name, GetDebugger().shared_from_this()); + if (!obj_or_err) { result.AppendErrorWithFormatv("cannot create helper object for: " - "'{0}'", m_options.m_class_name); + "'{0}': {1}", + m_options.m_class_name, + llvm::toString(obj_or_err.takeError())); return; } - + if (m_options.m_parsed_command) { - new_cmd_sp = CommandObjectScriptingObjectParsed::Create(m_interpreter, - m_cmd_name, cmd_obj_sp, m_synchronicity, result); + new_cmd_sp = CommandObjectScriptingObjectParsed::Create( + m_interpreter, m_cmd_name, cmd_interface_sp, m_synchronicity, + result); if (!result.Succeeded()) return; } else new_cmd_sp = std::make_shared<CommandObjectScriptingObjectRaw>( - m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity, + m_interpreter, m_cmd_name, cmd_interface_sp, m_synchronicity, m_completion_type); } diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp index 4f6095d097d10..44cae7a76ff10 100644 --- a/lldb/source/Interpreter/ScriptInterpreter.cpp +++ b/lldb/source/Interpreter/ScriptInterpreter.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// #include "lldb/Interpreter/ScriptInterpreter.h" +#include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBDebugger.h" #include "lldb/Core/Debugger.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Pipe.h" @@ -96,6 +98,16 @@ ScriptInterpreter::GetOpaqueTypeFromSBBreakpointLocation( return break_loc.m_opaque_wp.lock(); } +CommandReturnObject *ScriptInterpreter::GetOpaqueTypeFromSBCommandReturnObject( + const lldb::SBCommandReturnObject &cmd_retobj) const { + return cmd_retobj.m_opaque_up->get(); +} + +lldb::DebuggerSP ScriptInterpreter::GetOpaqueTypeFromSBDebugger( + const lldb::SBDebugger &debugger) const { + return debugger.m_opaque_sp; +} + lldb::ProcessAttachInfoSP ScriptInterpreter::GetOpaqueTypeFromSBAttachInfo( const lldb::SBAttachInfo &attach_info) const { return attach_info.m_opaque_sp; @@ -221,6 +233,10 @@ ScriptInterpreter::ExtensionToString(lldb::ScriptedExtension extension) { return "ScriptedFrame"; case eScriptedExtensionScriptedStackFrameRecognizer: return "ScriptedStackFrameRecognizer"; + case eScriptedExtensionScriptedCommand: + return "ScriptedCommand"; + case eScriptedExtensionParsedCommand: + return "ParsedCommand"; } llvm_unreachable("unhandled ScriptedExtension"); } @@ -241,6 +257,8 @@ ScriptInterpreter::StringToExtension(llvm::StringRef string) { .CaseLower("ScriptedFrame", eScriptedExtensionScriptedFrame) .CaseLower("ScriptedStackFrameRecognizer", eScriptedExtensionScriptedStackFrameRecognizer) + .CaseLower("ScriptedCommand", eScriptedExtensionScriptedCommand) + .CaseLower("ParsedCommand", eScriptedExtensionParsedCommand) .Default(eScriptedExtensionInvalid); } diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt index 201574da72a19..d3dc5773eb0af 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt +++ b/lldb/source/Plugins/ScriptInterpreter/Python/CMakeLists.txt @@ -32,6 +32,7 @@ set(python_plugin_sources Interfaces/ScriptedPythonInterface.cpp Interfaces/ScriptedHookPythonInterface.cpp Interfaces/ScriptedBreakpointPythonInterface.cpp + Interfaces/ScriptedCommandPythonInterface.cpp Interfaces/ScriptedStackFrameRecognizerPythonInterface.cpp Interfaces/ScriptedThreadPlanPythonInterface.cpp Interfaces/ScriptedThreadPythonInterface.cpp diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp index 8914f6b239023..2c8e0ef8bbeb0 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp @@ -30,6 +30,7 @@ void ScriptInterpreterPythonInterfaces::Initialize() { ScriptedThreadPythonInterface::Initialize(); ScriptedFramePythonInterface::Initialize(); ScriptedStackFrameRecognizerPythonInterface::Initialize(); + ScriptedCommandPythonInterface::Initialize(); } void ScriptInterpreterPythonInterfaces::Terminate() { @@ -43,4 +44,5 @@ void ScriptInterpreterPythonInterfaces::Terminate() { ScriptedThreadPythonInterface::Terminate(); ScriptedFramePythonInterface::Terminate(); ScriptedStackFrameRecognizerPythonInterface::Terminate(); + ScriptedCommandPythonInterface::Terminate(); } diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h index 03d747e63a592..7ddf7ec0e5ae5 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h @@ -14,6 +14,7 @@ #include "OperatingSystemPythonInterface.h" #include "ScriptedBreakpointPythonInterface.h" +#include "ScriptedCommandPythonInterface.h" #include "ScriptedFrameProviderPythonInterface.h" #include "ScriptedFramePythonInterface.h" #include "ScriptedHookPythonInterface.h" diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedCommandPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedCommandPythonInterface.cpp new file mode 100644 index 0000000000000..d73ddb9f39327 --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedCommandPythonInterface.cpp @@ -0,0 +1,247 @@ +//===----------------------------------------------------------------------===// +// +// 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-python.h" + +#include "lldb/API/SBCommandReturnObject.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Utility/Args.h" +#include "lldb/Utility/ScriptedMetadata.h" +#include "lldb/lldb-enumerations.h" + +#include "../SWIGPythonBridge.h" +#include "../ScriptInterpreterPythonImpl.h" +#include "ScriptedCommandPythonInterface.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::python; +using Locker = ScriptInterpreterPythonImpl::Locker; + +ScriptedCommandPythonInterface::ScriptedCommandPythonInterface( + ScriptInterpreterPythonImpl &interpreter) + : ScriptedCommandInterface(), ScriptedPythonInterface(interpreter) {} + +llvm::Expected<StructuredData::GenericSP> +ScriptedCommandPythonInterface::CreatePluginObject( + llvm::StringRef class_name, lldb::DebuggerSP debugger_sp) { + if (class_name.empty()) + return llvm::createStringError("empty class name"); + + if (!debugger_sp) + return llvm::createStringError("invalid Debugger pointer"); + + m_debugger_sp = debugger_sp; + ScriptedMetadata scripted_metadata(class_name, + StructuredData::DictionarySP()); + return ScriptedPythonInterface::CreatePluginObject( + scripted_metadata, /*script_obj=*/nullptr, debugger_sp); +} + +bool ScriptedCommandPythonInterface::RunRawCommand( + llvm::StringRef args, ScriptedCommandSynchronicity synchronicity, + CommandReturnObject &cmd_retobj, Status &error, + const ExecutionContext &exe_ctx) { + lldb::DebuggerSP debugger_sp = m_debugger_sp; + if (!debugger_sp) { + error = Status::FromErrorString("invalid Debugger pointer"); + return false; + } + lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); + + // Outer Locker sets up the session (with conditional NoSTDIN for + // interactive commands and TearDownSession on exit) that Dispatch's inner + // Locker doesn't provide. Nested locks are safe. + Locker py_lock(&m_interpreter, + Locker::AcquireLock | Locker::InitSession | + (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), + Locker::FreeLock | Locker::TearDownSession); + ScriptInterpreterPythonImpl::SynchronicityHandler synch_handler( + debugger_sp, synchronicity); + + std::string args_str = args.str(); + Dispatch("__call__", error, debugger_sp, args_str.c_str(), exe_ctx_ref_sp, + &cmd_retobj); + + if (!error.Success() || cmd_retobj.GetStatus() == eReturnStatusFailed) + return false; + + return true; +} + +bool ScriptedCommandPythonInterface::RunParsedCommand( + Args &args, ScriptedCommandSynchronicity synchronicity, + CommandReturnObject &cmd_retobj, Status &error, + const ExecutionContext &exe_ctx) { + lldb::DebuggerSP debugger_sp = m_debugger_sp; + if (!debugger_sp) { + error = Status::FromErrorString("invalid Debugger pointer"); + return false; + } + lldb::ExecutionContextRefSP exe_ctx_ref_sp(new ExecutionContextRef(exe_ctx)); + + Locker py_lock(&m_interpreter, + Locker::AcquireLock | Locker::InitSession | + (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), + Locker::FreeLock | Locker::TearDownSession); + ScriptInterpreterPythonImpl::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); + + Dispatch("__call__", error, debugger_sp, args_impl, exe_ctx_ref_sp, + &cmd_retobj); + + if (!error.Success() || cmd_retobj.GetStatus() == eReturnStatusFailed) + return false; + + return true; +} + +std::optional<std::string> +ScriptedCommandPythonInterface::GetRepeatCommand(Args &args) { + std::string command; + args.GetQuotedCommandString(command); + Status error; + StructuredData::ObjectSP obj = + Dispatch("get_repeat_command", error, command.c_str()); + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return {}; + return obj->GetStringValue().str(); +} + +StructuredData::DictionarySP +ScriptedCommandPythonInterface::HandleArgumentCompletion( + std::vector<llvm::StringRef> &args, size_t args_pos, size_t char_in_arg) { + Status error; + StructuredData::ObjectSP obj = Dispatch("handle_argument_completion", error, + args, args_pos, char_in_arg); + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return {}; + StructuredData::DictionarySP dict_sp(new StructuredData::Dictionary(obj)); + if (dict_sp->GetType() == lldb::eStructuredDataTypeInvalid) + return {}; + return dict_sp; +} + +StructuredData::DictionarySP +ScriptedCommandPythonInterface::HandleOptionArgumentCompletion( + llvm::StringRef &long_option, size_t char_in_arg) { + Status error; + std::string long_option_str = long_option.str(); + StructuredData::ObjectSP obj = + Dispatch("handle_option_argument_completion", error, + long_option_str.c_str(), char_in_arg); + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return {}; + + // A boolean return means: True means completion handled but no + // completions; False means completion not handled (fall back to default). + if (obj->GetType() == lldb::eStructuredDataTypeBoolean) { + if (!obj->GetBooleanValue()) + return {}; + StructuredData::DictionarySP dict_sp(new StructuredData::Dictionary()); + dict_sp->AddBooleanItem("no-completion", true); + return dict_sp; + } + + StructuredData::DictionarySP dict_sp(new StructuredData::Dictionary(obj)); + if (dict_sp->GetType() == lldb::eStructuredDataTypeInvalid) + return {}; + return dict_sp; +} + +bool ScriptedCommandPythonInterface::GetShortHelp(std::string &dest) { + dest.clear(); + Status error; + StructuredData::ObjectSP obj = Dispatch("get_short_help", error); + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return false; + dest = obj->GetStringValue().str(); + return !dest.empty(); +} + +bool ScriptedCommandPythonInterface::GetLongHelp(std::string &dest) { + dest.clear(); + Status error; + StructuredData::ObjectSP obj = Dispatch("get_long_help", error); + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return false; + dest = obj->GetStringValue().str(); + return !dest.empty(); +} + +uint32_t ScriptedCommandPythonInterface::GetFlags() { + Status error; + StructuredData::ObjectSP obj = Dispatch("get_flags", error); + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return 0; + return static_cast<uint32_t>(obj->GetUnsignedIntegerValue()); +} + +StructuredData::ObjectSP +ScriptedCommandPythonInterface::GetOptionsDefinition() { + Status error; + return Dispatch("get_options_definition", error); +} + +StructuredData::ObjectSP +ScriptedCommandPythonInterface::GetArgumentsDefinition() { + Status error; + return Dispatch("get_args_definition", error); +} + +void ScriptedCommandPythonInterface::OptionParsingStarted() { + Status error; + Dispatch("option_parsing_started", error); +} + +bool ScriptedCommandPythonInterface::SetOptionValue(ExecutionContext *exe_ctx, + llvm::StringRef long_option, + llvm::StringRef value) { + lldb::ExecutionContextRefSP exe_ctx_ref_sp; + if (exe_ctx) + exe_ctx_ref_sp = std::make_shared<ExecutionContextRef>(exe_ctx); + Status error; + std::string long_option_str = long_option.str(); + std::string value_str = value.str(); + StructuredData::ObjectSP obj = + Dispatch("set_option_value", error, exe_ctx_ref_sp, + long_option_str.c_str(), value_str.c_str()); + if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, + error)) + return false; + return obj->GetBooleanValue(); +} + +void ScriptedCommandPythonInterface::Initialize() { + const std::vector<llvm::StringRef> ci_usages = { + "command script add -c <ClassName> <cmd>", + "command script add -p <ClassName> <cmd>"}; + const std::vector<llvm::StringRef> api_usages = {}; + PluginManager::RegisterPlugin( + GetPluginNameStatic(), + "Implement a raw or parsed custom command backed by a Python class.", + CreateInstance, eScriptedExtensionScriptedCommand, eScriptLanguagePython, + ScriptedInterfaceUsages(ci_usages, api_usages)); +} + +void ScriptedCommandPythonInterface::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedCommandPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedCommandPythonInterface.h new file mode 100644 index 0000000000000..d2bb5386a69ab --- /dev/null +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedCommandPythonInterface.h @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// 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_SOURCE_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDCOMMANDPYTHONINTERFACE_H +#define LLDB_SOURCE_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDCOMMANDPYTHONINTERFACE_H + +#include "lldb/Interpreter/Interfaces/ScriptedCommandInterface.h" + +#include "ScriptedPythonInterface.h" +namespace lldb_private { + +class ScriptedCommandPythonInterface : public ScriptedCommandInterface, + public ScriptedPythonInterface, + public PluginInterface { +public: + ScriptedCommandPythonInterface(ScriptInterpreterPythonImpl &interpreter); + + llvm::Expected<StructuredData::GenericSP> + CreatePluginObject(llvm::StringRef class_name, + lldb::DebuggerSP debugger_sp) override; + + llvm::SmallVector<AbstractMethodRequirement> + GetAbstractMethodRequirements() const override { + return llvm::SmallVector<AbstractMethodRequirement>(); + } + + bool RunRawCommand(llvm::StringRef args, + ScriptedCommandSynchronicity synchronicity, + CommandReturnObject &cmd_retobj, Status &error, + const ExecutionContext &exe_ctx) override; + + bool RunParsedCommand(Args &args, ScriptedCommandSynchronicity synchronicity, + CommandReturnObject &cmd_retobj, Status &error, + const ExecutionContext &exe_ctx) override; + + std::optional<std::string> GetRepeatCommand(Args &args) override; + + StructuredData::DictionarySP + HandleArgumentCompletion(std::vector<llvm::StringRef> &args, size_t args_pos, + size_t char_in_arg) override; + + StructuredData::DictionarySP + HandleOptionArgumentCompletion(llvm::StringRef &long_option, + size_t char_in_arg) override; + + bool GetShortHelp(std::string &dest) override; + + bool GetLongHelp(std::string &dest) override; + + uint32_t GetFlags() override; + + StructuredData::ObjectSP GetOptionsDefinition() override; + + StructuredData::ObjectSP GetArgumentsDefinition() override; + + void OptionParsingStarted() override; + + bool SetOptionValue(ExecutionContext *exe_ctx, llvm::StringRef long_option, + llvm::StringRef value) override; + + static void Initialize(); + + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { + return "ScriptedCommandPythonInterface"; + } + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + +private: + lldb::DebuggerSP m_debugger_sp; +}; +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDCOMMANDPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp index 61ceb40dd9d32..4658fc948cb1a 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp @@ -8,7 +8,9 @@ #include "../lldb-python.h" +#include "lldb/API/SBDebugger.h" #include "lldb/Host/Config.h" +#include "lldb/Utility/ConstString.h" #include "lldb/Utility/Log.h" #include "lldb/lldb-enumerations.h" @@ -65,6 +67,21 @@ Event *ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>( return nullptr; } +template <> +CommandReturnObject * +ScriptedPythonInterface::ExtractValueFromPythonObject<CommandReturnObject *>( + python::PythonObject &p, Status &error) { + if (lldb::SBCommandReturnObject *sb_cmd_retobj = + reinterpret_cast<lldb::SBCommandReturnObject *>( + python::LLDBSWIGPython_CastPyObjectToSBCommandReturnObject( + p.get()))) + return m_interpreter.GetOpaqueTypeFromSBCommandReturnObject(*sb_cmd_retobj); + error = + Status::FromErrorString("Couldn't cast lldb::SBCommandReturnObject to " + "lldb_private::CommandReturnObject."); + return nullptr; +} + template <> lldb::StreamSP ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>( @@ -380,3 +397,41 @@ ScriptedPythonInterface::ExtractValueFromPythonObject< return static_cast<ValueType>(unmasked | flags); } + +template <> +lldb::DebuggerSP +ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DebuggerSP>( + python::PythonObject &p, Status &error) { + if (lldb::SBDebugger *sb_dbg = reinterpret_cast<lldb::SBDebugger *>( + python::LLDBSWIGPython_CastPyObjectToSBDebugger(p.get()))) + return m_interpreter.GetOpaqueTypeFromSBDebugger(*sb_dbg); + error = Status::FromErrorString( + "Couldn't cast lldb::SBDebugger to lldb::DebuggerSP."); + return {}; +} + +template <> +std::vector<llvm::StringRef> +ScriptedPythonInterface::ExtractValueFromPythonObject< + std::vector<llvm::StringRef>>(python::PythonObject &p, Status &error) { + std::vector<llvm::StringRef> result; + python::PythonList list(python::PyRefType::Borrowed, p.get()); + if (!list.IsValid()) { + error = Status::FromErrorString( + "Couldn't extract std::vector<llvm::StringRef>: not a Python list."); + return result; + } + + const uint32_t size = list.GetSize(); + result.reserve(size); + for (uint32_t i = 0; i < size; ++i) { + python::PythonString item(python::PyRefType::Borrowed, + list.GetItemAtIndex(i).get()); + if (!item.IsValid()) + continue; + // Persist the backing storage in ConstString's static pool so the + // returned StringRefs outlive the Python list. + result.push_back(ConstString(item.GetString()).GetStringRef()); + } + return result; +} diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h index aaa0b6a0f7a59..eee13783c74bf 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h @@ -15,6 +15,7 @@ #include <type_traits> #include <utility> +#include "lldb/API/SBCommandReturnObject.h" #include "lldb/Interpreter/Interfaces/ScriptedInterface.h" #include "lldb/Utility/DataBufferHeap.h" @@ -668,6 +669,22 @@ class ScriptedPythonInterface : virtual public ScriptedInterface { return python::SWIGBridge::ToSWIGWrapper(arg); } + python::PythonObject Transform(lldb::DebuggerSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(const std::vector<llvm::StringRef> &arg) { + python::PythonList list(python::PyInitialValue::Empty); + for (llvm::StringRef s : arg) + list.AppendItem(python::PythonString(s)); + return list; + } + + python::ScopedPythonObject<lldb::SBCommandReturnObject> + Transform(CommandReturnObject *arg) { + return python::SWIGBridge::ToSWIGWrapper(*arg); + } + 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! @@ -708,6 +725,15 @@ class ScriptedPythonInterface : virtual public ScriptedInterface { ReverseTransform(original_arg, transformed_arg, error); } + // ScopedPythonObject is non-copyable — passing it through the generic + // TransformBack would trigger the deleted copy ctor. It manages its own + // cleanup via the destructor when the transformed-args tuple destructs, so + // there is nothing to reverse-transform back into the original arg. + template <typename T, typename SB> + void TransformBack(T &original_arg, + python::ScopedPythonObject<SB> &transformed_arg, + Status &error) {} + template <std::size_t... I, typename... Ts, typename... Us> bool ReassignPtrsOrRefsArgs(std::tuple<Ts...> &original_args, std::tuple<Us...> &transformed_args, @@ -846,6 +872,16 @@ std::optional<lldb::ValueType> ScriptedPythonInterface::ExtractValueFromPythonObject< std::optional<lldb::ValueType>>(python::PythonObject &p, Status &error); +template <> +lldb::DebuggerSP +ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DebuggerSP>( + python::PythonObject &p, Status &error); + +template <> +std::vector<llvm::StringRef> +ScriptedPythonInterface::ExtractValueFromPythonObject< + std::vector<llvm::StringRef>>(python::PythonObject &p, Status &error); + } // namespace lldb_private #endif // LLDB_SOURCE_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDPYTHONINTERFACE_H diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h index 07e0da1dcf70d..9c5391e754396 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -39,7 +39,7 @@ 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 { +template <typename T> class ScopedPythonObject : public PythonObject { public: ScopedPythonObject(T *sb, swig_type_info *info) : PythonObject(ToSWIGHelper(sb, info)), m_sb(sb) {} @@ -143,11 +143,6 @@ class SWIGBridge { const char *session_dictionary_name, const lldb::ValueObjectSP &valobj_sp); - static python::PythonObject - LLDBSwigPythonCreateCommandObject(const char *python_class_name, - const char *session_dictionary_name, - lldb::DebuggerSP debugger_sp); - static size_t LLDBSwigPython_CalculateNumChildren(PyObject *implementor, uint32_t max); @@ -176,30 +171,6 @@ class SWIGBridge { lldb_private::CommandReturnObject &cmd_retobj, lldb::ExecutionContextRefSP exe_ctx_ref_sp); - static bool - LLDBSwigPythonCallCommandObject(PyObject *implementor, - lldb::DebuggerSP debugger, const char *args, - lldb_private::CommandReturnObject &cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp); - static bool LLDBSwigPythonCallParsedCommandObject( - PyObject *implementor, lldb::DebuggerSP debugger, - StructuredDataImpl &args_impl, - lldb_private::CommandReturnObject &cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp); - - static std::optional<std::string> - LLDBSwigPythonGetRepeatCommandForScriptedCommand(PyObject *implementor, - std::string &command); - - static StructuredData::DictionarySP - LLDBSwigPythonHandleArgumentCompletionForScriptedCommand( - PyObject *implementor, std::vector<llvm::StringRef> &args_impl, - size_t args_pos, size_t pos_in_arg); - - static StructuredData::DictionarySP - LLDBSwigPythonHandleOptionArgumentCompletionForScriptedCommand( - PyObject *implementor, llvm::StringRef &long_option, size_t pos_in_arg); - static bool LLDBSwigPythonCallModuleInit(const char *python_module_name, const char *session_dictionary_name, lldb::DebuggerSP debugger); @@ -247,6 +218,8 @@ void *LLDBSWIGPython_CastPyObjectToSBBreakpointLocation(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBCommandReturnObject(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBDebugger(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBEvent(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data); void *LLDBSWIGPython_CastPyObjectToSBThread(PyObject *data); diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 7b1bd9d8411c5..bb8871e234bc1 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -289,6 +289,9 @@ llvm::Expected<std::string> ScriptInterpreterPython::ExtensionToImportPath( return "lldb.plugins.scripted_process"; case eScriptedExtensionScriptedStackFrameRecognizer: return "lldb.plugins.scripted_stackframe_recognizer"; + case eScriptedExtensionScriptedCommand: + case eScriptedExtensionParsedCommand: + return "lldb.plugins.scripted_command"; case eScriptedExtensionInvalid: return llvm::createStringError("invalid extension name"); } @@ -2003,6 +2006,11 @@ ScriptInterpreterPythonImpl::CreateScriptedStackFrameRecognizerInterface() { return std::make_shared<ScriptedStackFrameRecognizerPythonInterface>(*this); } +ScriptedCommandInterfaceSP +ScriptInterpreterPythonImpl::CreateScriptedCommandInterface() { + return std::make_shared<ScriptedCommandPythonInterface>(*this); +} + ScriptedThreadInterfaceSP ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() { return std::make_shared<ScriptedThreadPythonInterface>(*this); @@ -2117,28 +2125,6 @@ ScriptInterpreterPythonImpl::CreateSyntheticScriptedProvider( new StructuredPythonObject(std::move(ret_val))); } -StructuredData::GenericSP -ScriptInterpreterPythonImpl::CreateScriptCommandObject(const char *class_name) { - DebuggerSP debugger_sp(m_debugger.shared_from_this()); - - if (class_name == nullptr || class_name[0] == '\0') - return StructuredData::GenericSP(); - - if (!debugger_sp.get()) - return StructuredData::GenericSP(); - - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateCommandObject( - class_name, m_dictionary_name.c_str(), debugger_sp); - - if (ret_val.IsValid()) - return StructuredData::GenericSP( - new StructuredPythonObject(std::move(ret_val))); - else - return {}; -} - bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction( const char *oneliner, std::string &output, const void *name_token) { StringList input; @@ -2987,166 +2973,6 @@ bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( return ret_val; } -bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( - StructuredData::GenericSP impl_obj_sp, llvm::StringRef 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 = Status::FromErrorString("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 = Status::FromErrorString("invalid Debugger pointer"); - return false; - } - - bool ret_val = false; - - { - Locker py_lock(this, - Locker::AcquireLock | Locker::InitSession | - (cmd_retobj.GetInteractive() ? 0 : Locker::NoSTDIN), - Locker::FreeLock | Locker::TearDownSession); - - SynchronicityHandler synch_handler(debugger_sp, synchronicity); - - std::string args_str = args.str(); - ret_val = SWIGBridge::LLDBSwigPythonCallCommandObject( - static_cast<PyObject *>(impl_obj_sp->GetValue()), debugger_sp, - args_str.c_str(), cmd_retobj, exe_ctx_ref_sp); - } - - if (!ret_val) - error = Status::FromErrorString("unable to execute script function"); - else if (cmd_retobj.GetStatus() == eReturnStatusFailed) - return false; - - error.Clear(); - 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 = Status::FromErrorString("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 = Status::FromErrorString("invalid Debugger pointer"); - return false; - } - - bool ret_val = false; - - { - 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 = Status::FromErrorString("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; -} - -StructuredData::DictionarySP -ScriptInterpreterPythonImpl::HandleArgumentCompletionForScriptedCommand( - StructuredData::GenericSP impl_obj_sp, std::vector<llvm::StringRef> &args, - size_t args_pos, size_t char_in_arg) { - StructuredData::DictionarySP completion_dict_sp; - if (!impl_obj_sp || !impl_obj_sp->IsValid()) - return completion_dict_sp; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - completion_dict_sp = - SWIGBridge::LLDBSwigPythonHandleArgumentCompletionForScriptedCommand( - static_cast<PyObject *>(impl_obj_sp->GetValue()), args, args_pos, - char_in_arg); - } - return completion_dict_sp; -} - -StructuredData::DictionarySP -ScriptInterpreterPythonImpl::HandleOptionArgumentCompletionForScriptedCommand( - StructuredData::GenericSP impl_obj_sp, llvm::StringRef &long_option, - size_t char_in_arg) { - StructuredData::DictionarySP completion_dict_sp; - if (!impl_obj_sp || !impl_obj_sp->IsValid()) - return completion_dict_sp; - - { - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, - Locker::FreeLock); - - completion_dict_sp = SWIGBridge:: - LLDBSwigPythonHandleOptionArgumentCompletionForScriptedCommand( - static_cast<PyObject *>(impl_obj_sp->GetValue()), long_option, - char_in_arg); - } - return completion_dict_sp; -} - /// 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. @@ -3180,322 +3006,6 @@ bool ScriptInterpreterPythonImpl::GetDocumentationForItem(const char *item, return false; } -bool ScriptInterpreterPythonImpl::GetShortHelpForCommandObject( - StructuredData::GenericSP cmd_obj_sp, std::string &dest) { - dest.clear(); - - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - - if (!cmd_obj_sp) - return false; - - PythonObject implementor(PyRefType::Borrowed, - (PyObject *)cmd_obj_sp->GetValue()); - - if (!implementor.IsAllocated()) - return false; - - llvm::Expected<PythonObject> expected_py_return = - implementor.CallMethod("get_short_help"); - - if (!expected_py_return) { - llvm::consumeError(expected_py_return.takeError()); - return false; - } - - 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()); - llvm::StringRef return_data(py_string.GetString()); - dest.assign(return_data.data(), return_data.size()); - return true; - } - - return false; -} - -uint32_t ScriptInterpreterPythonImpl::GetFlagsForCommandObject( - StructuredData::GenericSP cmd_obj_sp) { - uint32_t result = 0; - - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - - static char callee_name[] = "get_flags"; - - if (!cmd_obj_sp) - return result; - - 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(); - - long long py_return = unwrapOrSetPythonException( - As<long long>(implementor.CallMethod(callee_name))); - - // if it fails, print the error but otherwise go on - if (PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } else { - result = py_return; - } - - 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 = std::make_shared<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(); - - Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - - if (!cmd_obj_sp) - return false; - - PythonObject implementor(PyRefType::Borrowed, - (PyObject *)cmd_obj_sp->GetValue()); - - if (!implementor.IsAllocated()) - return false; - - llvm::Expected<PythonObject> expected_py_return = - implementor.CallMethod("get_long_help"); - - if (!expected_py_return) { - llvm::consumeError(expected_py_return.takeError()); - return false; - } - - 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()); - dest.assign(str_data.data(), str_data.size()); - got_string = true; - } - - return got_string; -} - std::unique_ptr<ScriptInterpreterLocker> ScriptInterpreterPythonImpl::AcquireInterpreterLock() { std::unique_ptr<ScriptInterpreterLocker> py_lock(new Locker( diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index d8a817198253f..51b373afbb9f4 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -70,9 +70,6 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { CreateSyntheticScriptedProvider(const char *class_name, lldb::ValueObjectSP valobj) override; - StructuredData::GenericSP - CreateScriptCommandObject(const char *class_name) override; - StructuredData::ObjectSP CreateStructuredDataFromScriptObject(ScriptObject obj) override; @@ -86,6 +83,8 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { lldb::ScriptedStackFrameRecognizerInterfaceSP CreateScriptedStackFrameRecognizerInterface() override; + lldb::ScriptedCommandInterfaceSP CreateScriptedCommandInterface() override; + lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override; lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() override; @@ -137,30 +136,6 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { Status &error, const lldb_private::ExecutionContext &exe_ctx) override; - bool RunScriptBasedCommand( - StructuredData::GenericSP impl_obj_sp, llvm::StringRef args, - ScriptedCommandSynchronicity synchronicity, - lldb_private::CommandReturnObject &cmd_retobj, Status &error, - const lldb_private::ExecutionContext &exe_ctx) override; - - bool RunScriptBasedParsedCommand( - StructuredData::GenericSP impl_obj_sp, Args &args, - ScriptedCommandSynchronicity synchronicity, - lldb_private::CommandReturnObject &cmd_retobj, Status &error, - const lldb_private::ExecutionContext &exe_ctx) override; - - std::optional<std::string> - GetRepeatCommandForScriptedCommand(StructuredData::GenericSP impl_obj_sp, - Args &args) override; - - StructuredData::DictionarySP HandleArgumentCompletionForScriptedCommand( - StructuredData::GenericSP impl_obj_sp, std::vector<llvm::StringRef> &args, - size_t args_pos, size_t char_in_arg) override; - - StructuredData::DictionarySP HandleOptionArgumentCompletionForScriptedCommand( - StructuredData::GenericSP impl_obj_sp, llvm::StringRef &long_options, - size_t char_in_arg) override; - Status GenerateFunction(const char *signature, const StringList &input, bool is_callback) override; @@ -183,29 +158,6 @@ class ScriptInterpreterPythonImpl : public ScriptInterpreterPython { bool GetDocumentationForItem(const char *item, std::string &dest) override; - bool GetShortHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, - std::string &dest) override; - - uint32_t - GetFlagsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override; - - bool GetLongHelpForCommandObject(StructuredData::GenericSP cmd_obj_sp, - std::string &dest) override; - - StructuredData::ObjectSP - GetOptionsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override; - - StructuredData::ObjectSP - GetArgumentsForCommandObject(StructuredData::GenericSP cmd_obj_sp) override; - - bool SetOptionValueForCommandObject(StructuredData::GenericSP cmd_obj_sp, - ExecutionContext *exe_ctx, - llvm::StringRef long_option, - llvm::StringRef value) override; - - void OptionParsingStartedForCommandObject( - StructuredData::GenericSP cmd_obj_sp) override; - bool CheckObjectExists(const char *name) override { if (!name || !name[0]) return false; diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp index c9298191ec3c1..808bb6157e5b8 100644 --- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp +++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp @@ -73,13 +73,6 @@ lldb_private::python::SWIGBridge::LLDBSwigPythonCreateSyntheticProvider( return python::PythonObject(); } -python::PythonObject -lldb_private::python::SWIGBridge::LLDBSwigPythonCreateCommandObject( - const char *python_class_name, const char *session_dictionary_name, - lldb::DebuggerSP debugger_sp) { - return python::PythonObject(); -} - size_t lldb_private::python::SWIGBridge::LLDBSwigPython_CalculateNumChildren( PyObject *implementor, uint32_t max) { return 0; @@ -126,6 +119,16 @@ lldb_private::python::LLDBSWIGPython_CastPyObjectToSBError(PyObject *data) { return nullptr; } +void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBCommandReturnObject( + PyObject *data) { + return nullptr; +} + +void * +lldb_private::python::LLDBSWIGPython_CastPyObjectToSBDebugger(PyObject *data) { + return nullptr; +} + void * lldb_private::python::LLDBSWIGPython_CastPyObjectToSBEvent(PyObject *data) { return nullptr; @@ -207,40 +210,6 @@ bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallCommand( return false; } -bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallCommandObject( - PyObject *implementor, lldb::DebuggerSP debugger, const char *args, - lldb_private::CommandReturnObject &cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp) { - return false; -} - -bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallParsedCommandObject( - PyObject *implementor, lldb::DebuggerSP debugger, - StructuredDataImpl &args_impl, - lldb_private::CommandReturnObject &cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp) { - return false; -} - -std::optional<std::string> -LLDBSwigPythonGetRepeatCommandForScriptedCommand(PyObject *implementor, - std::string &command) { - return std::nullopt; -} - -StructuredData::DictionarySP -LLDBSwigPythonHandleArgumentCompletionForScriptedCommand( - PyObject *implementor, std::vector<llvm::StringRef> &args, size_t args_pos, - size_t pos_in_arg) { - return {}; -} - -StructuredData::DictionarySP -LLDBSwigPythonHandleOptionArgumentCompletionForScriptedCommand( - PyObject *implementor, llvm::StringRef &long_options, size_t char_in_arg) { - return {}; -} - bool lldb_private::python::SWIGBridge::LLDBSwigPythonCallModuleInit( const char *python_module_name, const char *session_dictionary_name, lldb::DebuggerSP debugger) { _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
