diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter')
15 files changed, 645 insertions, 355 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp index b82a2647e9a0..8dad22d077be 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/Lua.cpp @@ -83,8 +83,8 @@ Lua::CallBreakpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp, lua_pushlightuserdata(m_lua_state, baton); lua_gettable(m_lua_state, LUA_REGISTRYINDEX); StructuredDataImpl extra_args_impl(std::move(extra_args_sp)); - return LLDBSwigLuaBreakpointCallbackFunction(m_lua_state, stop_frame_sp, - bp_loc_sp, extra_args_impl); + return lua::SWIGBridge::LLDBSwigLuaBreakpointCallbackFunction( + m_lua_state, stop_frame_sp, bp_loc_sp, extra_args_impl); } llvm::Error Lua::RegisterWatchpointCallback(void *baton, const char *body) { @@ -109,8 +109,8 @@ Lua::CallWatchpointCallback(void *baton, lldb::StackFrameSP stop_frame_sp, lua_pushlightuserdata(m_lua_state, baton); lua_gettable(m_lua_state, LUA_REGISTRYINDEX); - return LLDBSwigLuaWatchpointCallbackFunction(m_lua_state, stop_frame_sp, - wp_sp); + return lua::SWIGBridge::LLDBSwigLuaWatchpointCallbackFunction( + m_lua_state, stop_frame_sp, wp_sp); } llvm::Error Lua::CheckSyntax(llvm::StringRef buffer) { @@ -131,14 +131,13 @@ llvm::Error Lua::CheckSyntax(llvm::StringRef buffer) { } llvm::Error Lua::LoadModule(llvm::StringRef filename) { - FileSpec file(filename); + const FileSpec file(filename); if (!FileSystem::Instance().Exists(file)) { return llvm::make_error<llvm::StringError>("invalid path", llvm::inconvertibleErrorCode()); } - ConstString module_extension = file.GetFileNameExtension(); - if (module_extension != ".lua") { + if (file.GetFileNameExtension() != ".lua") { return llvm::make_error<llvm::StringError>("invalid extension", llvm::inconvertibleErrorCode()); } diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/SWIGLuaBridge.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/SWIGLuaBridge.h index 5fca18f2dd6d..27263c3b634b 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/SWIGLuaBridge.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/SWIGLuaBridge.h @@ -15,13 +15,20 @@ namespace lldb_private { -llvm::Expected<bool> LLDBSwigLuaBreakpointCallbackFunction( - lua_State *L, lldb::StackFrameSP stop_frame_sp, - lldb::BreakpointLocationSP bp_loc_sp, - const StructuredDataImpl &extra_args_impl); +namespace lua { -llvm::Expected<bool> LLDBSwigLuaWatchpointCallbackFunction( - lua_State *L, lldb::StackFrameSP stop_frame_sp, lldb::WatchpointSP wp_sp); +class SWIGBridge { +public: + static llvm::Expected<bool> LLDBSwigLuaBreakpointCallbackFunction( + lua_State *L, lldb::StackFrameSP stop_frame_sp, + lldb::BreakpointLocationSP bp_loc_sp, + const StructuredDataImpl &extra_args_impl); + + static llvm::Expected<bool> LLDBSwigLuaWatchpointCallbackFunction( + lua_State *L, lldb::StackFrameSP stop_frame_sp, lldb::WatchpointSP wp_sp); +}; + +} // namespace lua } // namespace lldb_private diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp index ec0992583145..be573cfba610 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.cpp @@ -111,7 +111,7 @@ public: io_handler.GetUserData()); for (BreakpointOptions &bp_options : *bp_options_vec) { Status error = m_script_interpreter.SetBreakpointCommandCallback( - bp_options, data.c_str()); + bp_options, data.c_str(), /*is_callback=*/false); if (error.Fail()) *io_handler.GetErrorStreamFileSP() << error.AsCString() << '\n'; } @@ -121,7 +121,8 @@ public: auto *wp_options = static_cast<WatchpointOptions *>(io_handler.GetUserData()); m_script_interpreter.SetWatchpointCommandCallback(wp_options, - data.c_str()); + data.c_str(), + /*is_callback=*/false); io_handler.SetIsDone(true); } break; case eIOHandlerNone: @@ -348,7 +349,8 @@ Status ScriptInterpreterLua::SetBreakpointCommandCallbackFunction( } Status ScriptInterpreterLua::SetBreakpointCommandCallback( - BreakpointOptions &bp_options, const char *command_body_text) { + BreakpointOptions &bp_options, const char *command_body_text, + bool is_callback) { return RegisterBreakpointCallback(bp_options, command_body_text, {}); } @@ -368,7 +370,8 @@ Status ScriptInterpreterLua::RegisterBreakpointCallback( } void ScriptInterpreterLua::SetWatchpointCommandCallback( - WatchpointOptions *wp_options, const char *command_body_text) { + WatchpointOptions *wp_options, const char *command_body_text, + bool is_callback) { RegisterWatchpointCallback(wp_options, command_body_text, {}); } diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h index b601779ff301..ca14e189acd8 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Lua/ScriptInterpreterLua.h @@ -88,10 +88,12 @@ public: CommandReturnObject &result) override; Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, - const char *command_body_text) override; + const char *command_body_text, + bool is_callback) override; void SetWatchpointCommandCallback(WatchpointOptions *wp_options, - const char *command_body_text) override; + const char *command_body_text, + bool is_callback) override; Status SetBreakpointCommandCallbackFunction( BreakpointOptions &bp_options, const char *function_name, 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 22918561692c..eee2f6f5d43f 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/Errno.h" #include <cstdio> +#include <variant> using namespace lldb_private; using namespace lldb; @@ -101,7 +102,7 @@ Expected<long long> PythonObject::AsLongLong() const { return r; } -Expected<long long> PythonObject::AsUnsignedLongLong() const { +Expected<unsigned long long> PythonObject::AsUnsignedLongLong() const { if (!m_py_obj) return nullDeref(); assert(!PyErr_Occurred()); @@ -117,6 +118,7 @@ Expected<unsigned long long> PythonObject::AsModuloUnsignedLongLong() const { return nullDeref(); assert(!PyErr_Occurred()); unsigned long long r = PyLong_AsUnsignedLongLongMask(m_py_obj); + // FIXME: We should fetch the exception message and hoist it. if (PyErr_Occurred()) return exception(); return r; @@ -267,9 +269,15 @@ StructuredData::ObjectSP PythonObject::CreateStructuredObject() const { case PyObjectType::Boolean: return PythonBoolean(PyRefType::Borrowed, m_py_obj) .CreateStructuredBoolean(); - case PyObjectType::Integer: - return PythonInteger(PyRefType::Borrowed, m_py_obj) - .CreateStructuredInteger(); + case PyObjectType::Integer: { + StructuredData::IntegerSP int_sp = + PythonInteger(PyRefType::Borrowed, m_py_obj).CreateStructuredInteger(); + if (std::holds_alternative<StructuredData::UnsignedIntegerSP>(int_sp)) + return std::get<StructuredData::UnsignedIntegerSP>(int_sp); + if (std::holds_alternative<StructuredData::SignedIntegerSP>(int_sp)) + return std::get<StructuredData::SignedIntegerSP>(int_sp); + return nullptr; + }; case PyObjectType::List: return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray(); case PyObjectType::String: @@ -459,17 +467,32 @@ void PythonInteger::SetInteger(int64_t value) { } StructuredData::IntegerSP PythonInteger::CreateStructuredInteger() const { - StructuredData::IntegerSP result(new StructuredData::Integer); - // FIXME this is really not ideal. Errors are silently converted to 0 - // and overflows are silently wrapped. But we'd need larger changes - // to StructuredData to fix it, so that's how it is for now. - llvm::Expected<unsigned long long> value = AsModuloUnsignedLongLong(); - if (!value) { + StructuredData::UnsignedIntegerSP uint_sp = CreateStructuredUnsignedInteger(); + return uint_sp ? StructuredData::IntegerSP(uint_sp) + : CreateStructuredSignedInteger(); +} + +StructuredData::UnsignedIntegerSP +PythonInteger::CreateStructuredUnsignedInteger() const { + StructuredData::UnsignedIntegerSP result = nullptr; + llvm::Expected<unsigned long long> value = AsUnsignedLongLong(); + if (!value) llvm::consumeError(value.takeError()); - result->SetValue(0); - } else { - result->SetValue(value.get()); - } + else + result = std::make_shared<StructuredData::UnsignedInteger>(value.get()); + + return result; +} + +StructuredData::SignedIntegerSP +PythonInteger::CreateStructuredSignedInteger() const { + StructuredData::SignedIntegerSP result = nullptr; + llvm::Expected<long long> value = AsLongLong(); + if (!value) + llvm::consumeError(value.takeError()); + else + result = std::make_shared<StructuredData::SignedInteger>(value.get()); + return result; } 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 365d499bead8..012f16e95e77 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h @@ -201,6 +201,7 @@ 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<bool> : PassthroughFormat<bool, 'p'> {}; template <> struct PythonFormat<unsigned int> : PassthroughFormat<unsigned int, 'I'> {}; template <> struct PythonFormat<long> : PassthroughFormat<long, 'l'> {}; @@ -342,6 +343,15 @@ public: return python::Take<PythonObject>(obj); } + llvm::Expected<PythonObject> GetType() const { + if (!m_py_obj) + return nullDeref(); + PyObject *obj = PyObject_Type(m_py_obj); + if (!obj) + return exception(); + return python::Take<PythonObject>(obj); + } + llvm::Expected<bool> IsTrue() { if (!m_py_obj) return nullDeref(); @@ -353,7 +363,7 @@ public: llvm::Expected<long long> AsLongLong() const; - llvm::Expected<long long> AsUnsignedLongLong() const; + llvm::Expected<unsigned long long> AsUnsignedLongLong() const; // wraps on overflow, instead of raising an error. llvm::Expected<unsigned long long> AsModuloUnsignedLongLong() const; @@ -479,6 +489,10 @@ public: void SetInteger(int64_t value); StructuredData::IntegerSP CreateStructuredInteger() const; + + StructuredData::UnsignedIntegerSP CreateStructuredUnsignedInteger() const; + + StructuredData::SignedIntegerSP CreateStructuredSignedInteger() const; }; class PythonBoolean : public TypedPythonObject<PythonBoolean> { 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 3dc2864f8d42..630ab293cf93 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -30,6 +30,8 @@ class SBCommandReturnObject; class SBValue; class SBStream; class SBStructuredData; +class SBFileSpec; +class SBModuleSpec; } // namespace lldb namespace lldb_private { @@ -61,175 +63,214 @@ 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); +// TODO: We may want to support other languages in the future w/ SWIG (we +// already support Lua right now, for example). We could create a generic +// SWIGBridge class and have this one specialize it, something like this: +// +// <typename T> +// class SWIGBridge { +// static T ToSWIGWrapper(...); +// }; +// +// class SWIGPythonBridge : public SWIGBridge<PythonObject> { +// template<> static PythonObject ToSWIGWrapper(...); +// }; +// +// And we should be able to more easily support things like Lua +class SWIGBridge { +public: + static PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBValue> value_sb); + static PythonObject ToSWIGWrapper(lldb::ValueObjectSP value_sp); + static PythonObject ToSWIGWrapper(lldb::TargetSP target_sp); + static PythonObject ToSWIGWrapper(lldb::ProcessSP process_sp); + static PythonObject ToSWIGWrapper(lldb::ThreadPlanSP thread_plan_sp); + static PythonObject ToSWIGWrapper(lldb::BreakpointSP breakpoint_sp); + static PythonObject ToSWIGWrapper(const Status &status); + static PythonObject ToSWIGWrapper(const StructuredDataImpl &data_impl); + static PythonObject ToSWIGWrapper(lldb::ThreadSP thread_sp); + static PythonObject ToSWIGWrapper(lldb::StackFrameSP frame_sp); + static PythonObject ToSWIGWrapper(lldb::DebuggerSP debugger_sp); + static PythonObject ToSWIGWrapper(lldb::WatchpointSP watchpoint_sp); + static PythonObject ToSWIGWrapper(lldb::BreakpointLocationSP bp_loc_sp); + static PythonObject ToSWIGWrapper(lldb::TypeImplSP type_impl_sp); + static PythonObject ToSWIGWrapper(lldb::ExecutionContextRefSP ctx_sp); + static PythonObject ToSWIGWrapper(const TypeSummaryOptions &summary_options); + static PythonObject ToSWIGWrapper(const SymbolContext &sym_ctx); + + static PythonObject ToSWIGWrapper(lldb::ProcessAttachInfoSP attach_info_sp); + static PythonObject ToSWIGWrapper(lldb::ProcessLaunchInfoSP launch_info_sp); + static PythonObject ToSWIGWrapper(lldb::DataExtractorSP data_extractor_sp); + + static PythonObject ToSWIGWrapper(std::unique_ptr<lldb::SBStream> stream_sb); + static PythonObject + ToSWIGWrapper(std::unique_ptr<lldb::SBStructuredData> data_sb); + static PythonObject + ToSWIGWrapper(std::unique_ptr<lldb::SBFileSpec> file_spec_sb); + static PythonObject + ToSWIGWrapper(std::unique_ptr<lldb::SBModuleSpec> module_spec_sb); + + static python::ScopedPythonObject<lldb::SBCommandReturnObject> + ToSWIGWrapper(CommandReturnObject &cmd_retobj); + static python::ScopedPythonObject<lldb::SBEvent> ToSWIGWrapper(Event *event); + // These prototypes are the Pythonic implementations of the required + // callbacks. Although these are scripting-language specific, their definition + // depends on the public API. + + static python::PythonObject LLDBSwigPythonCreateScriptedObject( + const char *python_class_name, const char *session_dictionary_name, + lldb::ExecutionContextRefSP exe_ctx_sp, + const lldb_private::StructuredDataImpl &args_impl, + std::string &error_string); + + static llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction( + const char *python_function_name, const char *session_dictionary_name, + const lldb::StackFrameSP &sb_frame, + const lldb::BreakpointLocationSP &sb_bp_loc, + const lldb_private::StructuredDataImpl &args_impl); + + static bool LLDBSwigPythonWatchpointCallbackFunction( + const char *python_function_name, const char *session_dictionary_name, + const lldb::StackFrameSP &sb_frame, const lldb::WatchpointSP &sb_wp); + + static bool + LLDBSwigPythonFormatterCallbackFunction(const char *python_function_name, + const char *session_dictionary_name, + lldb::TypeImplSP type_impl_sp); -} // namespace python + static bool LLDBSwigPythonCallTypeScript( + const char *python_function_name, const void *session_dictionary, + const lldb::ValueObjectSP &valobj_sp, void **pyfunct_wrapper, + const lldb::TypeSummaryOptionsSP &options_sp, std::string &retval); -void *LLDBSWIGPython_CastPyObjectToSBData(PyObject *data); -void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data); -void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data); -void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data); + static python::PythonObject + LLDBSwigPythonCreateSyntheticProvider(const char *python_class_name, + const char *session_dictionary_name, + const lldb::ValueObjectSP &valobj_sp); -// These prototypes are the Pythonic implementations of the required callbacks. -// Although these are scripting-language specific, their definition depends on -// the public API. - -python::PythonObject LLDBSwigPythonCreateScriptedObject( - const char *python_class_name, const char *session_dictionary_name, - lldb::ExecutionContextRefSP exe_ctx_sp, - const lldb_private::StructuredDataImpl &args_impl, - std::string &error_string); - -llvm::Expected<bool> LLDBSwigPythonBreakpointCallbackFunction( - const char *python_function_name, const char *session_dictionary_name, - const lldb::StackFrameSP &sb_frame, - const lldb::BreakpointLocationSP &sb_bp_loc, - const lldb_private::StructuredDataImpl &args_impl); - -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, - void **pyfunct_wrapper, - const lldb::TypeSummaryOptionsSP &options_sp, - std::string &retval); - -python::PythonObject -LLDBSwigPythonCreateSyntheticProvider(const char *python_class_name, - 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); -python::PythonObject -LLDBSwigPythonCreateCommandObject(const char *python_class_name, - const char *session_dictionary_name, - lldb::DebuggerSP debugger_sp); + static python::PythonObject LLDBSwigPythonCreateScriptedThreadPlan( + const char *python_class_name, const char *session_dictionary_name, + const StructuredDataImpl &args_data, std::string &error_string, + const lldb::ThreadPlanSP &thread_plan_sp); -python::PythonObject LLDBSwigPythonCreateScriptedThreadPlan( - const char *python_class_name, const char *session_dictionary_name, - const StructuredDataImpl &args_data, std::string &error_string, - const lldb::ThreadPlanSP &thread_plan_sp); + static bool LLDBSWIGPythonCallThreadPlan(void *implementor, + const char *method_name, + lldb_private::Event *event_sp, + bool &got_error); -bool LLDBSWIGPythonCallThreadPlan(void *implementor, const char *method_name, - lldb_private::Event *event_sp, - bool &got_error); + static bool LLDBSWIGPythonCallThreadPlan(void *implementor, + const char *method_name, + lldb_private::Stream *stream, + bool &got_error); -python::PythonObject LLDBSwigPythonCreateScriptedBreakpointResolver( - const char *python_class_name, const char *session_dictionary_name, - const StructuredDataImpl &args, const lldb::BreakpointSP &bkpt_sp); + static python::PythonObject LLDBSwigPythonCreateScriptedBreakpointResolver( + const char *python_class_name, const char *session_dictionary_name, + const StructuredDataImpl &args, const lldb::BreakpointSP &bkpt_sp); -unsigned int -LLDBSwigPythonCallBreakpointResolver(void *implementor, const char *method_name, - lldb_private::SymbolContext *sym_ctx); + static unsigned int + LLDBSwigPythonCallBreakpointResolver(void *implementor, + const char *method_name, + lldb_private::SymbolContext *sym_ctx); -python::PythonObject LLDBSwigPythonCreateScriptedStopHook( - lldb::TargetSP target_sp, const char *python_class_name, - const char *session_dictionary_name, const StructuredDataImpl &args, - lldb_private::Status &error); + static python::PythonObject LLDBSwigPythonCreateScriptedStopHook( + lldb::TargetSP target_sp, const char *python_class_name, + const char *session_dictionary_name, const StructuredDataImpl &args, + lldb_private::Status &error); -bool LLDBSwigPythonStopHookCallHandleStop(void *implementor, - lldb::ExecutionContextRefSP exc_ctx, - lldb::StreamSP stream); + static bool + LLDBSwigPythonStopHookCallHandleStop(void *implementor, + lldb::ExecutionContextRefSP exc_ctx, + lldb::StreamSP stream); -size_t LLDBSwigPython_CalculateNumChildren(PyObject *implementor, uint32_t max); + static size_t LLDBSwigPython_CalculateNumChildren(PyObject *implementor, + uint32_t max); -PyObject *LLDBSwigPython_GetChildAtIndex(PyObject *implementor, uint32_t idx); + static PyObject *LLDBSwigPython_GetChildAtIndex(PyObject *implementor, + uint32_t idx); -int LLDBSwigPython_GetIndexOfChildWithName(PyObject *implementor, - const char *child_name); + static int LLDBSwigPython_GetIndexOfChildWithName(PyObject *implementor, + const char *child_name); -lldb::ValueObjectSP LLDBSWIGPython_GetValueObjectSPFromSBValue(void *data); + static lldb::ValueObjectSP + LLDBSWIGPython_GetValueObjectSPFromSBValue(void *data); -bool LLDBSwigPython_UpdateSynthProviderInstance(PyObject *implementor); + static bool LLDBSwigPython_UpdateSynthProviderInstance(PyObject *implementor); -bool LLDBSwigPython_MightHaveChildrenSynthProviderInstance( - PyObject *implementor); + static bool + LLDBSwigPython_MightHaveChildrenSynthProviderInstance(PyObject *implementor); -PyObject *LLDBSwigPython_GetValueSynthProviderInstance(PyObject *implementor); + static PyObject * + LLDBSwigPython_GetValueSynthProviderInstance(PyObject *implementor); -bool LLDBSwigPythonCallCommand(const char *python_function_name, - const char *session_dictionary_name, - lldb::DebuggerSP debugger, const char *args, - lldb_private::CommandReturnObject &cmd_retobj, - lldb::ExecutionContextRefSP exe_ctx_ref_sp); + static bool + LLDBSwigPythonCallCommand(const char *python_function_name, + const char *session_dictionary_name, + lldb::DebuggerSP debugger, const char *args, + lldb_private::CommandReturnObject &cmd_retobj, + lldb::ExecutionContextRefSP exe_ctx_ref_sp); -bool LLDBSwigPythonCallCommandObject( - PyObject *implementor, lldb::DebuggerSP debugger, const char *args, - 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); -bool LLDBSwigPythonCallModuleInit(const char *python_module_name, - const char *session_dictionary_name, - lldb::DebuggerSP debugger); + static bool LLDBSwigPythonCallModuleInit(const char *python_module_name, + const char *session_dictionary_name, + lldb::DebuggerSP debugger); -python::PythonObject -LLDBSWIGPythonCreateOSPlugin(const char *python_class_name, - const char *session_dictionary_name, - const lldb::ProcessSP &process_sp); + static python::PythonObject + LLDBSWIGPythonCreateOSPlugin(const char *python_class_name, + const char *session_dictionary_name, + const lldb::ProcessSP &process_sp); -python::PythonObject -LLDBSWIGPython_CreateFrameRecognizer(const char *python_class_name, - const char *session_dictionary_name); + static python::PythonObject + LLDBSWIGPython_CreateFrameRecognizer(const char *python_class_name, + const char *session_dictionary_name); -PyObject * -LLDBSwigPython_GetRecognizedArguments(PyObject *implementor, - const lldb::StackFrameSP &frame_sp); + static PyObject * + LLDBSwigPython_GetRecognizedArguments(PyObject *implementor, + const lldb::StackFrameSP &frame_sp); -bool LLDBSWIGPythonRunScriptKeywordProcess(const char *python_function_name, - const char *session_dictionary_name, - const lldb::ProcessSP &process, - std::string &output); + static bool LLDBSWIGPythonRunScriptKeywordProcess( + const char *python_function_name, const char *session_dictionary_name, + const lldb::ProcessSP &process, std::string &output); -std::optional<std::string> -LLDBSWIGPythonRunScriptKeywordThread(const char *python_function_name, - const char *session_dictionary_name, - lldb::ThreadSP thread); + static std::optional<std::string> + LLDBSWIGPythonRunScriptKeywordThread(const char *python_function_name, + const char *session_dictionary_name, + lldb::ThreadSP thread); -bool LLDBSWIGPythonRunScriptKeywordTarget(const char *python_function_name, - const char *session_dictionary_name, - const lldb::TargetSP &target, - std::string &output); + static bool LLDBSWIGPythonRunScriptKeywordTarget( + const char *python_function_name, const char *session_dictionary_name, + const lldb::TargetSP &target, std::string &output); -std::optional<std::string> -LLDBSWIGPythonRunScriptKeywordFrame(const char *python_function_name, - const char *session_dictionary_name, - lldb::StackFrameSP frame); + static std::optional<std::string> + LLDBSWIGPythonRunScriptKeywordFrame(const char *python_function_name, + const char *session_dictionary_name, + lldb::StackFrameSP frame); -bool LLDBSWIGPythonRunScriptKeywordValue(const char *python_function_name, - const char *session_dictionary_name, - const lldb::ValueObjectSP &value, - std::string &output); + static bool LLDBSWIGPythonRunScriptKeywordValue( + const char *python_function_name, const char *session_dictionary_name, + const lldb::ValueObjectSP &value, std::string &output); -void *LLDBSWIGPython_GetDynamicSetting(void *module, const char *setting, - const lldb::TargetSP &target_sp); + static void * + LLDBSWIGPython_GetDynamicSetting(void *module, const char *setting, + const lldb::TargetSP &target_sp); +}; + +void *LLDBSWIGPython_CastPyObjectToSBData(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBBreakpoint(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBAttachInfo(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data); +void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data); +} // namespace python } // namespace lldb_private 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 7026815e120d..55b7a73712c4 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -306,7 +306,7 @@ void ScriptInterpreterPython::SharedLibraryDirectoryHelper( // On windows, we need to manually back out of the python tree, and go into // the bin directory. This is pretty much the inverse of what ComputePythonDir // does. - if (this_file.GetFileNameExtension() == ConstString(".pyd")) { + if (this_file.GetFileNameExtension() == ".pyd") { this_file.RemoveLastPathComponent(); // _lldb.pyd or _lldb_d.pyd this_file.RemoveLastPathComponent(); // lldb llvm::StringRef libdir = LLDB_PYTHON_RELATIVE_LIBDIR; @@ -408,12 +408,10 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) m_session_dict(PyInitialValue::Invalid), m_sys_module_dict(PyInitialValue::Invalid), m_run_one_line_function(), m_run_one_line_str_global(), - m_dictionary_name(m_debugger.GetInstanceName().AsCString()), + m_dictionary_name(m_debugger.GetInstanceName()), m_active_io_handler(eIOHandlerNone), m_session_is_active(false), m_pty_secondary_is_open(false), m_valid_session(true), m_lock_count(0), 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); @@ -443,7 +441,7 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) // do their task run_string.Clear(); run_string.Printf( - "run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp, pydoc')", + "run_one_line (%s, 'import lldb.formatters, lldb.formatters.cpp')", m_dictionary_name.c_str()); PyRun_SimpleString(run_string.GetData()); run_string.Clear(); @@ -456,7 +454,7 @@ ScriptInterpreterPythonImpl::ScriptInterpreterPythonImpl(Debugger &debugger) run_string.Clear(); run_string.Printf("run_one_line (%s, 'lldb.debugger_unique_id = %" PRIu64 - "; pydoc.pager = pydoc.plainpager')", + "')", m_dictionary_name.c_str(), m_debugger.GetID()); PyRun_SimpleString(run_string.GetData()); } @@ -523,7 +521,8 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, StructuredData::ObjectSP empty_args_sp; if (GenerateBreakpointCommandCallbackData(data_up->user_source, data_up->script_source, - false) + /*has_extra_args=*/false, + /*is_callback=*/false) .Success()) { auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>( std::move(data_up)); @@ -546,7 +545,8 @@ void ScriptInterpreterPythonImpl::IOHandlerInputComplete(IOHandler &io_handler, data_up->user_source.SplitIntoLines(data); if (GenerateWatchpointCommandCallbackData(data_up->user_source, - data_up->script_source)) { + data_up->script_source, + /*is_callback=*/false)) { auto baton_sp = std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up)); wp_options->SetCallback( @@ -1160,8 +1160,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction( StructuredData::ObjectSP extra_args_sp) { Status error; // For now just cons up a oneliner that calls the provided function. - std::string oneliner("return "); - oneliner += function_name; + std::string function_signature = function_name; llvm::Expected<unsigned> maybe_args = GetMaxPositionalArgumentsForCallable(function_name); @@ -1176,7 +1175,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction( bool uses_extra_args = false; if (max_args >= 4) { uses_extra_args = true; - oneliner += "(frame, bp_loc, extra_args, internal_dict)"; + function_signature += "(frame, bp_loc, extra_args, internal_dict)"; } else if (max_args >= 3) { if (extra_args_sp) { error.SetErrorString("cannot pass extra_args to a three argument callback" @@ -1184,7 +1183,7 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction( return error; } uses_extra_args = false; - oneliner += "(frame, bp_loc, internal_dict)"; + function_signature += "(frame, bp_loc, internal_dict)"; } else { error.SetErrorStringWithFormat("expected 3 or 4 argument " "function, %s can only take %zu", @@ -1192,8 +1191,9 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallbackFunction( return error; } - SetBreakpointCommandCallback(bp_options, oneliner.c_str(), extra_args_sp, - uses_extra_args); + SetBreakpointCommandCallback(bp_options, function_signature.c_str(), + extra_args_sp, uses_extra_args, + /*is_callback=*/true); return error; } @@ -1203,7 +1203,8 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( Status error; error = GenerateBreakpointCommandCallbackData(cmd_data_up->user_source, cmd_data_up->script_source, - false); + /*has_extra_args=*/false, + /*is_callback=*/false); if (error.Fail()) { return error; } @@ -1215,14 +1216,17 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( } Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( - BreakpointOptions &bp_options, const char *command_body_text) { - return SetBreakpointCommandCallback(bp_options, command_body_text, {},false); + BreakpointOptions &bp_options, const char *command_body_text, + bool is_callback) { + return SetBreakpointCommandCallback(bp_options, command_body_text, {}, + /*uses_extra_args=*/false, is_callback); } // Set a Python one-liner as the callback for the breakpoint. Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( BreakpointOptions &bp_options, const char *command_body_text, - StructuredData::ObjectSP extra_args_sp, bool uses_extra_args) { + StructuredData::ObjectSP extra_args_sp, bool uses_extra_args, + bool is_callback) { auto data_up = std::make_unique<CommandDataPython>(extra_args_sp); // Split the command_body_text into lines, and pass that to // GenerateBreakpointCommandCallbackData. That will wrap the body in an @@ -1230,9 +1234,9 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( // That is what the callback will actually invoke. data_up->user_source.SplitIntoLines(command_body_text); - Status error = GenerateBreakpointCommandCallbackData(data_up->user_source, - data_up->script_source, - uses_extra_args); + Status error = GenerateBreakpointCommandCallbackData( + data_up->user_source, data_up->script_source, uses_extra_args, + is_callback); if (error.Success()) { auto baton_sp = std::make_shared<BreakpointOptions::CommandBaton>(std::move(data_up)); @@ -1245,7 +1249,8 @@ Status ScriptInterpreterPythonImpl::SetBreakpointCommandCallback( // Set a Python one-liner as the callback for the watchpoint. void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback( - WatchpointOptions *wp_options, const char *oneliner) { + WatchpointOptions *wp_options, const char *user_input, + bool is_callback) { auto data_up = std::make_unique<WatchpointOptions::CommandData>(); // It's necessary to set both user_source and script_source to the oneliner. @@ -1253,11 +1258,11 @@ void ScriptInterpreterPythonImpl::SetWatchpointCommandCallback( // command list) while the latter is used for Python to interpret during the // actual callback. - data_up->user_source.AppendString(oneliner); - data_up->script_source.assign(oneliner); + data_up->user_source.AppendString(user_input); + data_up->script_source.assign(user_input); - if (GenerateWatchpointCommandCallbackData(data_up->user_source, - data_up->script_source)) { + if (GenerateWatchpointCommandCallbackData( + data_up->user_source, data_up->script_source, is_callback)) { auto baton_sp = std::make_shared<WatchpointOptions::CommandBaton>(std::move(data_up)); wp_options->SetCallback( @@ -1277,7 +1282,8 @@ Status ScriptInterpreterPythonImpl::ExportFunctionDefinitionToInterpreter( } Status ScriptInterpreterPythonImpl::GenerateFunction(const char *signature, - const StringList &input) { + const StringList &input, + bool is_callback) { Status error; int num_lines = input.GetSize(); if (num_lines == 0) { @@ -1294,40 +1300,61 @@ Status ScriptInterpreterPythonImpl::GenerateFunction(const char *signature, StringList auto_generated_function; auto_generated_function.AppendString(signature); auto_generated_function.AppendString( - " global_dict = globals()"); // Grab the global dictionary + " global_dict = globals()"); // Grab the global dictionary auto_generated_function.AppendString( - " new_keys = internal_dict.keys()"); // Make a list of keys in the - // session dict + " new_keys = internal_dict.keys()"); // Make a list of keys in the + // session dict auto_generated_function.AppendString( - " old_keys = global_dict.keys()"); // Save list of keys in global dict + " old_keys = global_dict.keys()"); // Save list of keys in global dict auto_generated_function.AppendString( - " global_dict.update (internal_dict)"); // Add the session dictionary - // to the - // global dictionary. - - // Wrap everything up inside the function, increasing the indentation. - - auto_generated_function.AppendString(" if True:"); - for (int i = 0; i < num_lines; ++i) { - sstr.Clear(); - sstr.Printf(" %s", input.GetStringAtIndex(i)); - auto_generated_function.AppendString(sstr.GetData()); + " global_dict.update(internal_dict)"); // Add the session dictionary + // to the global dictionary. + + if (is_callback) { + // If the user input is a callback to a python function, make sure the input + // is only 1 line, otherwise appending the user input would break the + // generated wrapped function + if (num_lines == 1) { + sstr.Clear(); + sstr.Printf(" __return_val = %s", input.GetStringAtIndex(0)); + auto_generated_function.AppendString(sstr.GetData()); + } else { + return Status("ScriptInterpreterPythonImpl::GenerateFunction(is_callback=" + "true) = ERROR: python function is multiline."); + } + } else { + auto_generated_function.AppendString( + " __return_val = None"); // Initialize user callback return value. + auto_generated_function.AppendString( + " def __user_code():"); // Create a nested function that will wrap + // the user input. This is necessary to + // capture the return value of the user input + // and prevent early returns. + for (int i = 0; i < num_lines; ++i) { + sstr.Clear(); + sstr.Printf(" %s", input.GetStringAtIndex(i)); + auto_generated_function.AppendString(sstr.GetData()); + } + auto_generated_function.AppendString( + " __return_val = __user_code()"); // Call user code and capture + // return value } auto_generated_function.AppendString( - " for key in new_keys:"); // Iterate over all the keys from session - // dict + " for key in new_keys:"); // Iterate over all the keys from session + // dict + auto_generated_function.AppendString( + " internal_dict[key] = global_dict[key]"); // Update session dict + // values auto_generated_function.AppendString( - " internal_dict[key] = global_dict[key]"); // Update session dict - // values + " if key not in old_keys:"); // If key was not originally in + // global dict auto_generated_function.AppendString( - " if key not in old_keys:"); // If key was not originally in - // global dict + " del global_dict[key]"); // ...then remove key/value from + // global dict auto_generated_function.AppendString( - " del global_dict[key]"); // ...then remove key/value from - // global dict + " return __return_val"); // Return the user callback return value. // Verify that the results are valid Python. - error = ExportFunctionDefinitionToInterpreter(auto_generated_function); return error; @@ -1352,7 +1379,8 @@ bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction( sstr.Printf("def %s (valobj, internal_dict):", auto_generated_function_name.c_str()); - if (!GenerateFunction(sstr.GetData(), user_input).Success()) + if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/false) + .Success()) return false; // Store the name of the auto-generated function to be called. @@ -1376,7 +1404,8 @@ bool ScriptInterpreterPythonImpl::GenerateScriptAliasFunction( sstr.Printf("def %s (debugger, args, exe_ctx, result, internal_dict):", auto_generated_function_name.c_str()); - if (!GenerateFunction(sstr.GetData(), user_input).Success()) + if (!GenerateFunction(sstr.GetData(), user_input, /*is_callback=*/true) + .Success()) return false; // Store the name of the auto-generated function to be called. @@ -1434,7 +1463,7 @@ ScriptInterpreterPythonImpl::CreateFrameRecognizer(const char *class_name) { return StructuredData::GenericSP(); Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - PythonObject ret_val = LLDBSWIGPython_CreateFrameRecognizer( + PythonObject ret_val = SWIGBridge::LLDBSWIGPython_CreateFrameRecognizer( class_name, m_dictionary_name.c_str()); return StructuredData::GenericSP( @@ -1459,9 +1488,9 @@ lldb::ValueObjectListSP ScriptInterpreterPythonImpl::GetRecognizedArguments( if (!implementor.IsAllocated()) return ValueObjectListSP(); - PythonObject py_return( - PyRefType::Owned, - LLDBSwigPython_GetRecognizedArguments(implementor.get(), frame_sp)); + PythonObject py_return(PyRefType::Owned, + SWIGBridge::LLDBSwigPython_GetRecognizedArguments( + implementor.get(), frame_sp)); // if it fails, print the error but otherwise go on if (PyErr_Occurred()) { @@ -1475,7 +1504,8 @@ lldb::ValueObjectListSP ScriptInterpreterPythonImpl::GetRecognizedArguments( PyObject *item = result_list.GetItemAtIndex(i).get(); lldb::SBValue *sb_value_ptr = (lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(item); - auto valobj_sp = LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr); + auto valobj_sp = + SWIGBridge::LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr); if (valobj_sp) result->Append(valobj_sp); } @@ -1484,6 +1514,22 @@ lldb::ValueObjectListSP ScriptInterpreterPythonImpl::GetRecognizedArguments( return ValueObjectListSP(); } +ScriptedProcessInterfaceUP +ScriptInterpreterPythonImpl::CreateScriptedProcessInterface() { + return std::make_unique<ScriptedProcessPythonInterface>(*this); +} + +StructuredData::ObjectSP +ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject( + ScriptObject obj) { + void *ptr = const_cast<void *>(obj.GetPointer()); + PythonObject py_obj(PyRefType::Borrowed, static_cast<PyObject *>(ptr)); + if (!py_obj.IsValid() || py_obj.IsNone()) + return {}; + Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); + return py_obj.CreateStructuredObject(); +} + StructuredData::GenericSP ScriptInterpreterPythonImpl::OSPlugin_CreatePluginObject( const char *class_name, lldb::ProcessSP process_sp) { @@ -1494,7 +1540,7 @@ ScriptInterpreterPythonImpl::OSPlugin_CreatePluginObject( return StructuredData::GenericSP(); Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, Locker::FreeLock); - PythonObject ret_val = LLDBSWIGPythonCreateOSPlugin( + PythonObject ret_val = SWIGBridge::LLDBSWIGPythonCreateOSPlugin( class_name, m_dictionary_name.c_str(), process_sp); return StructuredData::GenericSP( @@ -1655,7 +1701,7 @@ StructuredData::ObjectSP ScriptInterpreterPythonImpl::CreateScriptedThreadPlan( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - PythonObject ret_val = LLDBSwigPythonCreateScriptedThreadPlan( + PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedThreadPlan( class_name, python_interpreter->m_dictionary_name.c_str(), args_data, error_str, thread_plan_sp); if (!ret_val) @@ -1674,7 +1720,7 @@ bool ScriptInterpreterPythonImpl::ScriptedThreadPlanExplainsStop( if (generic) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - explains_stop = LLDBSWIGPythonCallThreadPlan( + explains_stop = SWIGBridge::LLDBSWIGPythonCallThreadPlan( generic->GetValue(), "explains_stop", event, script_error); if (script_error) return true; @@ -1691,7 +1737,7 @@ bool ScriptInterpreterPythonImpl::ScriptedThreadPlanShouldStop( if (generic) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - should_stop = LLDBSWIGPythonCallThreadPlan( + should_stop = SWIGBridge::LLDBSWIGPythonCallThreadPlan( generic->GetValue(), "should_stop", event, script_error); if (script_error) return true; @@ -1708,8 +1754,8 @@ bool ScriptInterpreterPythonImpl::ScriptedThreadPlanIsStale( if (generic) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - is_stale = LLDBSWIGPythonCallThreadPlan(generic->GetValue(), "is_stale", - nullptr, script_error); + is_stale = SWIGBridge::LLDBSWIGPythonCallThreadPlan( + generic->GetValue(), "is_stale", (Event *)nullptr, script_error); if (script_error) return true; } @@ -1725,8 +1771,8 @@ lldb::StateType ScriptInterpreterPythonImpl::ScriptedThreadPlanGetRunState( if (generic) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - should_step = LLDBSWIGPythonCallThreadPlan( - generic->GetValue(), "should_step", nullptr, script_error); + should_step = SWIGBridge::LLDBSWIGPythonCallThreadPlan( + generic->GetValue(), "should_step", (Event *)nullptr, script_error); if (script_error) should_step = true; } @@ -1735,6 +1781,24 @@ lldb::StateType ScriptInterpreterPythonImpl::ScriptedThreadPlanGetRunState( return lldb::eStateRunning; } +bool +ScriptInterpreterPythonImpl::ScriptedThreadPlanGetStopDescription( + StructuredData::ObjectSP implementor_sp, lldb_private::Stream *stream, + bool &script_error) { + StructuredData::Generic *generic = nullptr; + if (implementor_sp) + generic = implementor_sp->GetAsGeneric(); + if (!generic) { + script_error = true; + return false; + } + Locker py_lock(this, + Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); + return SWIGBridge::LLDBSWIGPythonCallThreadPlan( + generic->GetValue(), "stop_description", stream, script_error); +} + + StructuredData::GenericSP ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver( const char *class_name, const StructuredDataImpl &args_data, @@ -1756,9 +1820,10 @@ ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - PythonObject ret_val = LLDBSwigPythonCreateScriptedBreakpointResolver( - class_name, python_interpreter->m_dictionary_name.c_str(), args_data, - bkpt_sp); + PythonObject ret_val = + SWIGBridge::LLDBSwigPythonCreateScriptedBreakpointResolver( + class_name, python_interpreter->m_dictionary_name.c_str(), args_data, + bkpt_sp); return StructuredData::GenericSP( new StructuredPythonObject(std::move(ret_val))); @@ -1771,7 +1836,7 @@ bool ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchCallback( if (implementor_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - should_continue = LLDBSwigPythonCallBreakpointResolver( + should_continue = SWIGBridge::LLDBSwigPythonCallBreakpointResolver( implementor_sp->GetValue(), "__callback__", sym_ctx); if (PyErr_Occurred()) { PyErr_Print(); @@ -1788,7 +1853,7 @@ ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchDepth( if (implementor_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - depth_as_int = LLDBSwigPythonCallBreakpointResolver( + depth_as_int = SWIGBridge::LLDBSwigPythonCallBreakpointResolver( implementor_sp->GetValue(), "__get_depth__", nullptr); if (PyErr_Occurred()) { PyErr_Print(); @@ -1828,7 +1893,7 @@ StructuredData::GenericSP ScriptInterpreterPythonImpl::CreateScriptedStopHook( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - PythonObject ret_val = LLDBSwigPythonCreateScriptedStopHook( + PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedStopHook( target_sp, class_name, python_interpreter->m_dictionary_name.c_str(), args_data, error); @@ -1848,7 +1913,7 @@ bool ScriptInterpreterPythonImpl::ScriptedStopHookHandleStop( lldb::ExecutionContextRefSP exc_ctx_ref_sp(new ExecutionContextRef(exc_ctx)); - bool ret_val = LLDBSwigPythonStopHookCallHandleStop( + bool ret_val = SWIGBridge::LLDBSwigPythonStopHookCallHandleStop( implementor_sp->GetValue(), exc_ctx_ref_sp, stream_sp); return ret_val; } @@ -1885,7 +1950,7 @@ StructuredData::DictionarySP ScriptInterpreterPythonImpl::GetDynamicSettings( Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); TargetSP target_sp(target->shared_from_this()); - auto setting = (PyObject *)LLDBSWIGPython_GetDynamicSetting( + auto setting = (PyObject *)SWIGBridge::LLDBSWIGPython_GetDynamicSetting( generic->GetValue(), setting_name, target_sp); if (!setting) @@ -1924,7 +1989,7 @@ ScriptInterpreterPythonImpl::CreateSyntheticScriptedProvider( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - PythonObject ret_val = LLDBSwigPythonCreateSyntheticProvider( + PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateSyntheticProvider( class_name, python_interpreter->m_dictionary_name.c_str(), valobj); return StructuredData::ObjectSP( @@ -1943,11 +2008,14 @@ ScriptInterpreterPythonImpl::CreateScriptCommandObject(const char *class_name) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - PythonObject ret_val = LLDBSwigPythonCreateCommandObject( + PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateCommandObject( class_name, m_dictionary_name.c_str(), debugger_sp); - return StructuredData::GenericSP( - new StructuredPythonObject(std::move(ret_val))); + if (ret_val.IsValid()) + return StructuredData::GenericSP( + new StructuredPythonObject(std::move(ret_val))); + else + return {}; } bool ScriptInterpreterPythonImpl::GenerateTypeScriptFunction( @@ -1965,8 +2033,8 @@ bool ScriptInterpreterPythonImpl::GenerateTypeSynthClass( } Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData( - StringList &user_input, std::string &output, - bool has_extra_args) { + StringList &user_input, std::string &output, bool has_extra_args, + bool is_callback) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines(); StreamString sstr; @@ -1985,7 +2053,7 @@ Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData( sstr.Printf("def %s (frame, bp_loc, internal_dict):", auto_generated_function_name.c_str()); - error = GenerateFunction(sstr.GetData(), user_input); + error = GenerateFunction(sstr.GetData(), user_input, is_callback); if (!error.Success()) return error; @@ -1995,7 +2063,7 @@ Status ScriptInterpreterPythonImpl::GenerateBreakpointCommandCallbackData( } bool ScriptInterpreterPythonImpl::GenerateWatchpointCommandCallbackData( - StringList &user_input, std::string &output) { + StringList &user_input, std::string &output, bool is_callback) { static uint32_t num_created_functions = 0; user_input.RemoveBlankLines(); StreamString sstr; @@ -2008,7 +2076,7 @@ bool ScriptInterpreterPythonImpl::GenerateWatchpointCommandCallbackData( sstr.Printf("def %s (frame, wp, internal_dict):", auto_generated_function_name.c_str()); - if (!GenerateFunction(sstr.GetData(), user_input).Success()) + if (!GenerateFunction(sstr.GetData(), user_input, is_callback).Success()) return false; // Store the name of the auto-generated function to be called. @@ -2047,7 +2115,7 @@ bool ScriptInterpreterPythonImpl::GetScriptedSummary( static Timer::Category func_cat("LLDBSwigPythonCallTypeScript"); Timer scoped_timer(func_cat, "LLDBSwigPythonCallTypeScript"); - ret_val = LLDBSwigPythonCallTypeScript( + ret_val = SWIGBridge::LLDBSwigPythonCallTypeScript( python_function_name, GetSessionDictionary().get(), valobj, &new_callee, options_sp, retval); } @@ -2071,7 +2139,7 @@ bool ScriptInterpreterPythonImpl::FormatterCallbackFunction( const char *python_function_name, TypeImplSP type_impl_sp) { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - return LLDBSwigPythonFormatterCallbackFunction( + return SWIGBridge::LLDBSwigPythonFormatterCallbackFunction( python_function_name, m_dictionary_name.c_str(), type_impl_sp); } @@ -2111,7 +2179,7 @@ bool ScriptInterpreterPythonImpl::BreakpointCallbackFunction( Locker::InitSession | Locker::NoSTDIN); Expected<bool> maybe_ret_val = - LLDBSwigPythonBreakpointCallbackFunction( + SWIGBridge::LLDBSwigPythonBreakpointCallbackFunction( python_function_name, python_interpreter->m_dictionary_name.c_str(), stop_frame_sp, bp_loc_sp, bp_option_data->m_extra_args); @@ -2172,7 +2240,7 @@ bool ScriptInterpreterPythonImpl::WatchpointCallbackFunction( Locker py_lock(python_interpreter, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPythonWatchpointCallbackFunction( + ret_val = SWIGBridge::LLDBSwigPythonWatchpointCallbackFunction( python_function_name, python_interpreter->m_dictionary_name.c_str(), stop_frame_sp, wp_sp); @@ -2202,7 +2270,7 @@ size_t ScriptInterpreterPythonImpl::CalculateNumChildren( { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPython_CalculateNumChildren(implementor, max); + ret_val = SWIGBridge::LLDBSwigPython_CalculateNumChildren(implementor, max); } return ret_val; @@ -2224,14 +2292,16 @@ lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetChildAtIndex( { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - PyObject *child_ptr = LLDBSwigPython_GetChildAtIndex(implementor, idx); + PyObject *child_ptr = + SWIGBridge::LLDBSwigPython_GetChildAtIndex(implementor, idx); if (child_ptr != nullptr && child_ptr != Py_None) { lldb::SBValue *sb_value_ptr = (lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(child_ptr); if (sb_value_ptr == nullptr) Py_XDECREF(child_ptr); else - ret_val = LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr); + ret_val = SWIGBridge::LLDBSWIGPython_GetValueObjectSPFromSBValue( + sb_value_ptr); } else { Py_XDECREF(child_ptr); } @@ -2257,7 +2327,7 @@ int ScriptInterpreterPythonImpl::GetIndexOfChildWithName( { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPython_GetIndexOfChildWithName(implementor, child_name); + ret_val = SWIGBridge::LLDBSwigPython_GetIndexOfChildWithName(implementor, child_name); } return ret_val; @@ -2280,7 +2350,8 @@ bool ScriptInterpreterPythonImpl::UpdateSynthProviderInstance( { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSwigPython_UpdateSynthProviderInstance(implementor); + ret_val = + SWIGBridge::LLDBSwigPython_UpdateSynthProviderInstance(implementor); } return ret_val; @@ -2303,8 +2374,8 @@ bool ScriptInterpreterPythonImpl::MightHaveChildrenSynthProviderInstance( { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = - LLDBSwigPython_MightHaveChildrenSynthProviderInstance(implementor); + ret_val = SWIGBridge::LLDBSwigPython_MightHaveChildrenSynthProviderInstance( + implementor); } return ret_val; @@ -2328,14 +2399,15 @@ lldb::ValueObjectSP ScriptInterpreterPythonImpl::GetSyntheticValue( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); PyObject *child_ptr = - LLDBSwigPython_GetValueSynthProviderInstance(implementor); + SWIGBridge::LLDBSwigPython_GetValueSynthProviderInstance(implementor); if (child_ptr != nullptr && child_ptr != Py_None) { lldb::SBValue *sb_value_ptr = (lldb::SBValue *)LLDBSWIGPython_CastPyObjectToSBValue(child_ptr); if (sb_value_ptr == nullptr) Py_XDECREF(child_ptr); else - ret_val = LLDBSWIGPython_GetValueObjectSPFromSBValue(sb_value_ptr); + ret_val = SWIGBridge::LLDBSWIGPython_GetValueObjectSPFromSBValue( + sb_value_ptr); } else { Py_XDECREF(child_ptr); } @@ -2406,7 +2478,7 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSWIGPythonRunScriptKeywordProcess( + ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordProcess( impl_function, m_dictionary_name.c_str(), process->shared_from_this(), output); if (!ret_val) @@ -2429,9 +2501,10 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - if (std::optional<std::string> result = LLDBSWIGPythonRunScriptKeywordThread( - impl_function, m_dictionary_name.c_str(), - thread->shared_from_this())) { + if (std::optional<std::string> result = + SWIGBridge::LLDBSWIGPythonRunScriptKeywordThread( + impl_function, m_dictionary_name.c_str(), + thread->shared_from_this())) { output = std::move(*result); return true; } @@ -2456,7 +2529,7 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( TargetSP target_sp(target->shared_from_this()); Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSWIGPythonRunScriptKeywordTarget( + ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordTarget( impl_function, m_dictionary_name.c_str(), target_sp, output); if (!ret_val) error.SetErrorString("python script evaluation failed"); @@ -2478,9 +2551,10 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - if (std::optional<std::string> result = LLDBSWIGPythonRunScriptKeywordFrame( - impl_function, m_dictionary_name.c_str(), - frame->shared_from_this())) { + if (std::optional<std::string> result = + SWIGBridge::LLDBSWIGPythonRunScriptKeywordFrame( + impl_function, m_dictionary_name.c_str(), + frame->shared_from_this())) { output = std::move(*result); return true; } @@ -2504,7 +2578,7 @@ bool ScriptInterpreterPythonImpl::RunScriptFormatKeyword( { Locker py_lock(this, Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN); - ret_val = LLDBSWIGPythonRunScriptKeywordValue( + ret_val = SWIGBridge::LLDBSWIGPythonRunScriptKeywordValue( impl_function, m_dictionary_name.c_str(), value->GetSP(), output); if (!ret_val) error.SetErrorString("python script evaluation failed"); @@ -2684,9 +2758,9 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( // if we are here, everything worked // call __lldb_init_module(debugger,dict) - if (!LLDBSwigPythonCallModuleInit(module_name.c_str(), - m_dictionary_name.c_str(), - m_debugger.shared_from_this())) { + if (!SWIGBridge::LLDBSwigPythonCallModuleInit( + module_name.c_str(), m_dictionary_name.c_str(), + m_debugger.shared_from_this())) { error.SetErrorString("calling __lldb_init_module failed"); return false; } @@ -2780,7 +2854,7 @@ bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( SynchronicityHandler synch_handler(debugger_sp, synchronicity); std::string args_str = args.str(); - ret_val = LLDBSwigPythonCallCommand( + ret_val = SWIGBridge::LLDBSwigPythonCallCommand( impl_function, m_dictionary_name.c_str(), debugger_sp, args_str.c_str(), cmd_retobj, exe_ctx_ref_sp); } @@ -2825,7 +2899,7 @@ bool ScriptInterpreterPythonImpl::RunScriptBasedCommand( SynchronicityHandler synch_handler(debugger_sp, synchronicity); std::string args_str = args.str(); - ret_val = LLDBSwigPythonCallCommandObject( + ret_val = SWIGBridge::LLDBSwigPythonCallCommandObject( static_cast<PyObject *>(impl_obj_sp->GetValue()), debugger_sp, args_str.c_str(), cmd_retobj, exe_ctx_ref_sp); } 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 f4875bfb8d18..01db6c520300 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -83,6 +83,9 @@ public: std::string &error_str, lldb::ThreadPlanSP thread_plan) override; + StructuredData::ObjectSP + CreateStructuredDataFromScriptObject(ScriptObject obj) override; + bool ScriptedThreadPlanExplainsStop(StructuredData::ObjectSP implementor_sp, Event *event, bool &script_error) override; @@ -97,6 +100,11 @@ public: ScriptedThreadPlanGetRunState(StructuredData::ObjectSP implementor_sp, bool &script_error) override; + bool + ScriptedThreadPlanGetStopDescription(StructuredData::ObjectSP implementor_sp, + lldb_private::Stream *s, + bool &script_error) override; + StructuredData::GenericSP CreateScriptedBreakpointResolver(const char *class_name, const StructuredDataImpl &args_data, @@ -124,6 +132,8 @@ public: GetRecognizedArguments(const StructuredData::ObjectSP &implementor, lldb::StackFrameSP frame_sp) override; + lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() override; + StructuredData::GenericSP OSPlugin_CreatePluginObject(const char *class_name, lldb::ProcessSP process_sp) override; @@ -186,16 +196,17 @@ public: lldb_private::CommandReturnObject &cmd_retobj, Status &error, const lldb_private::ExecutionContext &exe_ctx) override; - Status GenerateFunction(const char *signature, - const StringList &input) override; + Status GenerateFunction(const char *signature, const StringList &input, + bool is_callback) override; - Status GenerateBreakpointCommandCallbackData( - StringList &input, - std::string &output, - bool has_extra_args) override; + Status GenerateBreakpointCommandCallbackData(StringList &input, + std::string &output, + bool has_extra_args, + bool is_callback) override; bool GenerateWatchpointCommandCallbackData(StringList &input, - std::string &output) override; + std::string &output, + bool is_callback) override; bool GetScriptedSummary(const char *function_name, lldb::ValueObjectSP valobj, StructuredData::ObjectSP &callee_wrapper_sp, @@ -258,7 +269,8 @@ public: /// Set the callback body text into the callback for the breakpoint. Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, - const char *callback_body) override; + const char *callback_body, + bool is_callback) override; Status SetBreakpointCommandCallbackFunction( BreakpointOptions &bp_options, const char *function_name, @@ -272,11 +284,13 @@ public: Status SetBreakpointCommandCallback(BreakpointOptions &bp_options, const char *command_body_text, StructuredData::ObjectSP extra_args_sp, - bool uses_extra_args); + bool uses_extra_args, + bool is_callback); /// Set a one-liner as the callback for the watchpoint. void SetWatchpointCommandCallback(WatchpointOptions *wp_options, - const char *oneliner) override; + const char *user_input, + bool is_callback) override; const char *GetDictionaryName() { return m_dictionary_name.c_str(); } @@ -367,11 +381,18 @@ public: void LeaveSession(); - uint32_t IsExecutingPython() const { return m_lock_count > 0; } + uint32_t IsExecutingPython() { + std::lock_guard<std::mutex> guard(m_mutex); + return m_lock_count > 0; + } - uint32_t IncrementLockCount() { return ++m_lock_count; } + uint32_t IncrementLockCount() { + std::lock_guard<std::mutex> guard(m_mutex); + return ++m_lock_count; + } uint32_t DecrementLockCount() { + std::lock_guard<std::mutex> guard(m_mutex); if (m_lock_count > 0) --m_lock_count; return m_lock_count; @@ -411,6 +432,7 @@ public: bool m_pty_secondary_is_open; bool m_valid_session; uint32_t m_lock_count; + std::mutex m_mutex; PyThreadState *m_command_thread_state; }; @@ -423,10 +445,11 @@ public: ~IOHandlerPythonInterpreter() override = default; - ConstString GetControlSequence(char ch) override { + llvm::StringRef GetControlSequence(char ch) override { + static constexpr llvm::StringLiteral control_sequence("quit()\n"); if (ch == 'd') - return ConstString("quit()\n"); - return ConstString(); + return control_sequence; + return {}; } void Run() override { diff --git a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp index 9fbf50114694..a0c55874c70a 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPlatformPythonInterface.cpp @@ -44,7 +44,7 @@ StructuredData::GenericSP ScriptedPlatformPythonInterface::CreatePluginObject( lldb::ExecutionContextRefSP exe_ctx_ref_sp = std::make_shared<ExecutionContextRef>(exe_ctx); - PythonObject ret_val = LLDBSwigPythonCreateScriptedObject( + PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject( class_name.str().c_str(), m_interpreter.GetDictionaryName(), exe_ctx_ref_sp, args_impl, error_string); 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 6f087e8390ce..019924fa1971 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.cpp @@ -7,15 +7,17 @@ //===----------------------------------------------------------------------===// #include "lldb/Host/Config.h" +#if LLDB_ENABLE_PYTHON +// LLDB Python header must be included first +#include "lldb-python.h" +#endif +#include "lldb/Target/Process.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 "ScriptedProcessPythonInterface.h" @@ -46,7 +48,7 @@ StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject( lldb::ExecutionContextRefSP exe_ctx_ref_sp = std::make_shared<ExecutionContextRef>(exe_ctx); - PythonObject ret_val = LLDBSwigPythonCreateScriptedObject( + PythonObject ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject( class_name.str().c_str(), m_interpreter.GetDictionaryName(), exe_ctx_ref_sp, args_impl, error_string); @@ -56,26 +58,31 @@ StructuredData::GenericSP ScriptedProcessPythonInterface::CreatePluginObject( return m_object_instance_sp; } -Status ScriptedProcessPythonInterface::Launch() { - return GetStatusFromMethod("launch"); -} - -Status ScriptedProcessPythonInterface::Resume() { - return GetStatusFromMethod("resume"); -} - -bool ScriptedProcessPythonInterface::ShouldStop() { +StructuredData::DictionarySP ScriptedProcessPythonInterface::GetCapabilities() { Status error; - StructuredData::ObjectSP obj = Dispatch("is_alive", error); + StructuredData::DictionarySP dict = + Dispatch<StructuredData::DictionarySP>("get_capabilities", error); - if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, dict, error)) return {}; - return obj->GetBooleanValue(); + return dict; +} + +Status +ScriptedProcessPythonInterface::Attach(const ProcessAttachInfo &attach_info) { + lldb::ProcessAttachInfoSP attach_info_sp = + std::make_shared<ProcessAttachInfo>(attach_info); + return GetStatusFromMethod("attach", attach_info_sp); +} + +Status ScriptedProcessPythonInterface::Launch() { + return GetStatusFromMethod("launch"); } -Status ScriptedProcessPythonInterface::Stop() { - return GetStatusFromMethod("stop"); +Status ScriptedProcessPythonInterface::Resume() { + // When calling ScriptedProcess.Resume from lldb we should always stop. + return GetStatusFromMethod("resume", /*should_stop=*/true); } std::optional<MemoryRegionInfo> @@ -103,23 +110,20 @@ StructuredData::DictionarySP ScriptedProcessPythonInterface::GetThreadsInfo() { return dict; } -StructuredData::DictionarySP -ScriptedProcessPythonInterface::GetThreadWithID(lldb::tid_t tid) { - Status error; - StructuredData::ObjectSP obj = Dispatch("get_thread_with_id", error, tid); +bool ScriptedProcessPythonInterface::CreateBreakpoint(lldb::addr_t addr, + Status &error) { + Status py_error; + StructuredData::ObjectSP obj = + Dispatch("create_breakpoint", py_error, addr, error); + + // If there was an error on the python call, surface it to the user. + if (py_error.Fail()) + error = py_error; if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) return {}; - StructuredData::DictionarySP dict{obj->GetAsDictionary()}; - - return dict; -} - -StructuredData::DictionarySP -ScriptedProcessPythonInterface::GetRegistersForThread(lldb::tid_t tid) { - // TODO: Implement - return {}; + return obj->GetBooleanValue(); } lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( @@ -135,19 +139,29 @@ lldb::DataExtractorSP ScriptedProcessPythonInterface::ReadMemoryAtAddress( return data_sp; } +lldb::offset_t ScriptedProcessPythonInterface::WriteMemoryAtAddress( + lldb::addr_t addr, lldb::DataExtractorSP data_sp, Status &error) { + Status py_error; + StructuredData::ObjectSP obj = + Dispatch("write_memory_at_address", py_error, addr, data_sp, error); + + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) + return LLDB_INVALID_OFFSET; + + // If there was an error on the python call, surface it to the user. + if (py_error.Fail()) + error = py_error; + + return obj->GetUnsignedIntegerValue(LLDB_INVALID_OFFSET); +} + StructuredData::ArraySP ScriptedProcessPythonInterface::GetLoadedImages() { Status error; StructuredData::ArraySP array = Dispatch<StructuredData::ArraySP>("get_loaded_images", error); - if (!array || !array->IsValid() || error.Fail()) { - return ScriptedInterface::ErrorWithMessage<StructuredData::ArraySP>( - LLVM_PRETTY_FUNCTION, - llvm::Twine("Null or invalid object (" + - llvm::Twine(error.AsCString()) + llvm::Twine(").")) - .str(), - error); - } + if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, array, error)) + return {}; return array; } @@ -159,7 +173,7 @@ lldb::pid_t ScriptedProcessPythonInterface::GetProcessID() { if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) return LLDB_INVALID_PROCESS_ID; - return obj->GetIntegerValue(LLDB_INVALID_PROCESS_ID); + return obj->GetUnsignedIntegerValue(LLDB_INVALID_PROCESS_ID); } bool ScriptedProcessPythonInterface::IsAlive() { 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 6b4ee3021cfa..ff03eab07648 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedProcessPythonInterface.h @@ -29,13 +29,13 @@ public: StructuredData::DictionarySP args_sp, StructuredData::Generic *script_obj = nullptr) override; - Status Launch() override; + StructuredData::DictionarySP GetCapabilities() override; - Status Resume() override; + Status Attach(const ProcessAttachInfo &attach_info) override; - bool ShouldStop() override; + Status Launch() override; - Status Stop() override; + Status Resume() override; std::optional<MemoryRegionInfo> GetMemoryRegionContainingAddress(lldb::addr_t address, @@ -43,13 +43,15 @@ public: StructuredData::DictionarySP GetThreadsInfo() override; - StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) override; - - StructuredData::DictionarySP GetRegistersForThread(lldb::tid_t tid) override; + bool CreateBreakpoint(lldb::addr_t addr, Status &error) override; lldb::DataExtractorSP ReadMemoryAtAddress(lldb::addr_t address, size_t size, Status &error) override; + lldb::offset_t WriteMemoryAtAddress(lldb::addr_t addr, + lldb::DataExtractorSP data_sp, + Status &error) override; + StructuredData::ArraySP GetLoadedImages() override; lldb::pid_t GetProcessID() 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 789b39abf587..1e36a81fde54 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.cpp @@ -15,7 +15,6 @@ // LLDB Python header must be included first #include "lldb-python.h" -#include "SWIGPythonBridge.h" #include "ScriptInterpreterPythonImpl.h" #include "ScriptedPythonInterface.h" #include <optional> @@ -47,7 +46,7 @@ template <> Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>( python::PythonObject &p, Status &error) { if (lldb::SBError *sb_error = reinterpret_cast<lldb::SBError *>( - LLDBSWIGPython_CastPyObjectToSBError(p.get()))) + python::LLDBSWIGPython_CastPyObjectToSBError(p.get()))) return m_interpreter.GetStatusFromSBError(*sb_error); else error.SetErrorString("Couldn't cast lldb::SBError to lldb::Status."); @@ -60,7 +59,7 @@ lldb::DataExtractorSP ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( python::PythonObject &p, Status &error) { lldb::SBData *sb_data = reinterpret_cast<lldb::SBData *>( - LLDBSWIGPython_CastPyObjectToSBData(p.get())); + python::LLDBSWIGPython_CastPyObjectToSBData(p.get())); if (!sb_data) { error.SetErrorString( @@ -72,13 +71,59 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( } template <> +lldb::BreakpointSP +ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::BreakpointSP>( + python::PythonObject &p, Status &error) { + lldb::SBBreakpoint *sb_breakpoint = reinterpret_cast<lldb::SBBreakpoint *>( + python::LLDBSWIGPython_CastPyObjectToSBBreakpoint(p.get())); + + if (!sb_breakpoint) { + error.SetErrorString( + "Couldn't cast lldb::SBBreakpoint to lldb::BreakpointSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBBreakpoint(*sb_breakpoint); +} + +template <> +lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error) { + lldb::SBAttachInfo *sb_attach_info = reinterpret_cast<lldb::SBAttachInfo *>( + python::LLDBSWIGPython_CastPyObjectToSBAttachInfo(p.get())); + + if (!sb_attach_info) { + error.SetErrorString( + "Couldn't cast lldb::SBAttachInfo to lldb::ProcessAttachInfoSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBAttachInfo(*sb_attach_info); +} + +template <> +lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error) { + lldb::SBLaunchInfo *sb_launch_info = reinterpret_cast<lldb::SBLaunchInfo *>( + python::LLDBSWIGPython_CastPyObjectToSBLaunchInfo(p.get())); + + if (!sb_launch_info) { + error.SetErrorString( + "Couldn't cast lldb::SBLaunchInfo to lldb::ProcessLaunchInfoSP."); + return nullptr; + } + + return m_interpreter.GetOpaqueTypeFromSBLaunchInfo(*sb_launch_info); +} + +template <> std::optional<MemoryRegionInfo> ScriptedPythonInterface::ExtractValueFromPythonObject< std::optional<MemoryRegionInfo>>(python::PythonObject &p, Status &error) { lldb::SBMemoryRegionInfo *sb_mem_reg_info = reinterpret_cast<lldb::SBMemoryRegionInfo *>( - LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(p.get())); + python::LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(p.get())); if (!sb_mem_reg_info) { error.SetErrorString( 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 01dc07b49737..4d0645d18aca 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedPythonInterface.h @@ -113,8 +113,25 @@ protected: return {object}; } + python::PythonObject Transform(bool arg) { + // Boolean arguments need to be turned into python objects. + return python::PythonBoolean(arg); + } + python::PythonObject Transform(Status arg) { - return python::ToSWIGWrapper(arg); + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::ProcessAttachInfoSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::ProcessLaunchInfoSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); + } + + python::PythonObject Transform(lldb::DataExtractorSP arg) { + return python::SWIGBridge::ToSWIGWrapper(arg); } template <typename T, typename U> @@ -129,6 +146,19 @@ protected: original_arg = ExtractValueFromPythonObject<T>(transformed_arg, error); } + + void ReverseTransform(bool &original_arg, + python::PythonObject transformed_arg, Status &error) { + python::PythonBoolean boolean_arg = python::PythonBoolean( + python::PyRefType::Borrowed, transformed_arg.get()); + if (boolean_arg.IsValid()) + original_arg = boolean_arg.GetValue(); + else + error.SetErrorString( + llvm::formatv("{}: Invalid boolean argument.", LLVM_PRETTY_FUNCTION) + .str()); + } + template <std::size_t... I, typename... Args> auto TransformTuple(const std::tuple<Args...> &args, std::index_sequence<I...>) { @@ -199,6 +229,19 @@ Status ScriptedPythonInterface::ExtractValueFromPythonObject<Status>( python::PythonObject &p, Status &error); template <> +lldb::BreakpointSP +ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::BreakpointSP>( + python::PythonObject &p, Status &error); + +template <> +lldb::ProcessAttachInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessAttachInfoSP>(python::PythonObject &p, Status &error); + +template <> +lldb::ProcessLaunchInfoSP ScriptedPythonInterface::ExtractValueFromPythonObject< + lldb::ProcessLaunchInfoSP>(python::PythonObject &p, Status &error); + +template <> lldb::DataExtractorSP ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>( python::PythonObject &p, Status &error); 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 1b31ed2e5881..5603a1541314 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp @@ -46,7 +46,7 @@ StructuredData::GenericSP ScriptedThreadPythonInterface::CreatePluginObject( if (!script_obj) { lldb::ExecutionContextRefSP exe_ctx_ref_sp = std::make_shared<ExecutionContextRef>(exe_ctx); - ret_val = LLDBSwigPythonCreateScriptedObject( + ret_val = SWIGBridge::LLDBSwigPythonCreateScriptedObject( class_name.str().c_str(), m_interpreter.GetDictionaryName(), exe_ctx_ref_sp, args_impl, error_string); } else @@ -69,7 +69,7 @@ lldb::tid_t ScriptedThreadPythonInterface::GetThreadID() { if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) return LLDB_INVALID_THREAD_ID; - return obj->GetIntegerValue(LLDB_INVALID_THREAD_ID); + return obj->GetUnsignedIntegerValue(LLDB_INVALID_THREAD_ID); } std::optional<std::string> ScriptedThreadPythonInterface::GetName() { @@ -89,7 +89,7 @@ lldb::StateType ScriptedThreadPythonInterface::GetState() { if (!CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj, error)) return eStateInvalid; - return static_cast<StateType>(obj->GetIntegerValue(eStateInvalid)); + return static_cast<StateType>(obj->GetUnsignedIntegerValue(eStateInvalid)); } std::optional<std::string> ScriptedThreadPythonInterface::GetQueue() { |
